From e6909de7f7a91b800d10c8eb67db32dd874e0f84 Mon Sep 17 00:00:00 2001 From: dimitr Date: Sat, 31 Oct 2009 06:25:01 +0000 Subject: [PATCH] Wipe out the SCROLLABLE_CURSORS code + minor cleanup. Also, surfaced scrollability for PSQL cursors (without internal support yet). --- src/jrd/Optimizer.cpp | 11 +- src/jrd/WindowRsb.cpp | 4 +- src/jrd/blr.h | 72 ++-- src/jrd/btn.cpp | 65 --- src/jrd/btn.h | 8 - src/jrd/btr.cpp | 159 +------ src/jrd/btr_proto.h | 5 - src/jrd/cmp.cpp | 59 +-- src/jrd/dpm.epp | 93 +---- src/jrd/dpm_proto.h | 6 +- src/jrd/evl.cpp | 36 +- src/jrd/exe.cpp | 330 +-------------- src/jrd/exe.h | 42 +- src/jrd/exe_proto.h | 3 - src/jrd/gds.cpp | 10 +- src/jrd/idx.cpp | 6 +- src/jrd/inf.cpp | 5 - src/jrd/jrd.cpp | 36 +- src/jrd/jrd_proto.h | 11 +- src/jrd/nav.cpp | 493 ++-------------------- src/jrd/nav_proto.h | 6 +- src/jrd/nod.h | 1 - src/jrd/opt.cpp | 54 +-- src/jrd/par.cpp | 38 +- src/jrd/req.h | 7 - src/jrd/rse.cpp | 868 +++------------------------------------ src/jrd/rse.h | 48 +-- src/jrd/rse_proto.h | 5 +- src/jrd/scroll_cursors.h | 87 ---- src/jrd/sort.cpp | 635 ++-------------------------- src/jrd/sort.h | 9 - src/jrd/sort_proto.h | 7 - src/jrd/validation.cpp | 1 - src/jrd/vio.cpp | 21 +- src/jrd/vio_proto.h | 6 +- src/jrd/why.cpp | 178 +------- src/jrd/why_proto.h | 19 - 37 files changed, 255 insertions(+), 3189 deletions(-) delete mode 100644 src/jrd/scroll_cursors.h diff --git a/src/jrd/Optimizer.cpp b/src/jrd/Optimizer.cpp index ee5a8c1d61..91afeaa7f7 100644 --- a/src/jrd/Optimizer.cpp +++ b/src/jrd/Optimizer.cpp @@ -729,14 +729,7 @@ USHORT OPT_nav_rsb_size(RecordSource* rsb, USHORT key_length, USHORT size) * **************************************/ DEV_BLKCHK(rsb, type_rsb); -#ifdef SCROLLABLE_CURSORS - // allocate extra impure area to hold the current key, - // plus an upper and lower bound key value, for a total - // of three times the key length for the index - size += sizeof(struct irsb_nav) + 3 * key_length; -#else size += sizeof(struct irsb_nav) + 2 * key_length; -#endif size = FB_ALIGN(size, FB_ALIGNMENT); // make room for an idx structure to describe the index // that was used to generate this rsb @@ -1348,9 +1341,7 @@ RecordSource* OptimizerRetrieval::generateNavigation() } // check to see if the fields in the sort match the fields in the index - // in the exact same order--we used to check for ascending/descending prior - // to SCROLLABLE_CURSORS, but now descending sorts can use ascending indices - // and vice versa. + // in the exact same order bool usableIndex = true; index_desc::idx_repeat* idx_tail = idx->idx_rpt; diff --git a/src/jrd/WindowRsb.cpp b/src/jrd/WindowRsb.cpp index 114a5b2e62..7bc9b697b9 100644 --- a/src/jrd/WindowRsb.cpp +++ b/src/jrd/WindowRsb.cpp @@ -72,7 +72,7 @@ void WindowRsb::open(thread_db* tdbb) SET_TDBB(tdbb); RSE_open(tdbb, next); - RSE_internal_get_record(tdbb, next, NULL, RSE_get_forward); + RSE_internal_get_record(tdbb, next, NULL); RSE_close(tdbb, next); RSE_open(tdbb, next->rsb_next); @@ -91,7 +91,7 @@ bool WindowRsb::get(thread_db* tdbb) { SET_TDBB(tdbb); - if (!RSE_internal_get_record(tdbb, next->rsb_next, NULL, RSE_get_forward)) + if (!RSE_internal_get_record(tdbb, next->rsb_next, NULL)) return false; jrd_nod* node = (jrd_nod*) next->rsb_arg[0]; diff --git a/src/jrd/blr.h b/src/jrd/blr.h index f294c05da0..af2cb798aa 100644 --- a/src/jrd/blr.h +++ b/src/jrd/blr.h @@ -120,9 +120,9 @@ #define blr_maximum (unsigned char)29 #define blr_minimum (unsigned char)30 #define blr_total (unsigned char)31 -/* count 2 -#define blr_count2 32 -*/ + +// unused codes: 32..33 + #define blr_add (unsigned char)34 #define blr_subtract (unsigned char)35 #define blr_multiply (unsigned char)36 @@ -133,7 +133,6 @@ #define blr_parameter2 (unsigned char)41 #define blr_from (unsigned char)42 #define blr_via (unsigned char)43 -#define blr_parameter2_old (unsigned char)44 /* Confusion */ #define blr_user_name (unsigned char)44 /* added from gds.h */ #define blr_null (unsigned char)45 @@ -156,8 +155,7 @@ #define blr_unique (unsigned char)62 #define blr_like (unsigned char)63 -//#define blr_stream (unsigned char)65 -//#define blr_set_index (unsigned char)66 +// unused codes: 64..66 #define blr_rse (unsigned char)67 #define blr_first (unsigned char)68 @@ -174,6 +172,8 @@ #define blr_aggregate (unsigned char)79 #define blr_join_type (unsigned char)80 +// unused codes: 81..82 + #define blr_agg_count (unsigned char)83 #define blr_agg_max (unsigned char)84 #define blr_agg_min (unsigned char)85 @@ -189,6 +189,8 @@ #define blr_agg_total_distinct (unsigned char)95 #define blr_agg_average_distinct (unsigned char)96 +// unused codes: 97..99 + #define blr_function (unsigned char)100 #define blr_gen_id (unsigned char)101 #define blr_prot_mask (unsigned char)102 @@ -198,31 +200,16 @@ #define blr_matching2 (unsigned char)106 #define blr_index (unsigned char)107 #define blr_ansi_like (unsigned char)108 -//#define blr_bookmark (unsigned char)109 -//#define blr_crack (unsigned char)110 -//#define blr_force_crack (unsigned char)111 -#define blr_seek (unsigned char)112 -//#define blr_find (unsigned char)113 +#define blr_scrollable (unsigned char) 109 -/* these indicate directions for blr_seek and blr_find */ - -#define blr_continue (unsigned char)0 -#define blr_forward (unsigned char)1 -#define blr_backward (unsigned char)2 -#define blr_bof_forward (unsigned char)3 -#define blr_eof_backward (unsigned char)4 - -//#define blr_lock_relation (unsigned char)114 -//#define blr_lock_record (unsigned char)115 -//#define blr_set_bookmark (unsigned char)116 -//#define blr_get_bookmark (unsigned char)117 +// unused codes: 110..117 #define blr_run_count (unsigned char)118 /* changed from 88 to avoid conflict with blr_parameter3 */ #define blr_rs_stream (unsigned char)119 #define blr_exec_proc (unsigned char)120 -//#define blr_begin_range (unsigned char)121 -//#define blr_end_range (unsigned char)122 -//#define blr_delete_range (unsigned char)123 + +// unused codes: 121..123 + #define blr_procedure (unsigned char)124 #define blr_pid (unsigned char)125 #define blr_exec_pid (unsigned char)126 @@ -232,13 +219,13 @@ #define blr_error_handler (unsigned char)130 #define blr_cast (unsigned char)131 -//#define blr_release_lock (unsigned char)132 -//#define blr_release_locks (unsigned char)133 + +// unused codes: 132..133 + #define blr_start_savepoint (unsigned char)134 #define blr_end_savepoint (unsigned char)135 -//#define blr_find_dbkey (unsigned char)136 -//#define blr_range_relation (unsigned char)137 -//#define blr_delete_ranges (unsigned char)138 + +// unused codes: 136..138 #define blr_plan (unsigned char)139 /* access plan items */ #define blr_merge (unsigned char)140 @@ -250,20 +237,21 @@ #define blr_relation2 (unsigned char)146 #define blr_rid2 (unsigned char)147 -//#define blr_reset_stream (unsigned char)148 -//#define blr_release_bookmark (unsigned char)149 + +// unused codes: 148..149 #define blr_set_generator (unsigned char)150 #define blr_ansi_any (unsigned char)151 /* required for NULL handling */ #define blr_exists (unsigned char)152 /* required for NULL handling */ -//#define blr_cardinality (unsigned char)153 + +// unused codes: 153 #define blr_record_version (unsigned char)154 /* get tid of record */ #define blr_stall (unsigned char)155 /* fake server stall */ -//#define blr_seek_no_warn (unsigned char)156 -//#define blr_find_dbkey_version (unsigned char)157 /* find dbkey with record version */ +// unused codes: 156..157 + #define blr_ansi_all (unsigned char)158 /* required for NULL handling */ #define blr_extract (unsigned char)159 @@ -298,6 +286,8 @@ #define blr_agg_list_distinct (unsigned char)171 #define blr_modify2 (unsigned char)172 +// unused codes: 173 + /* FB 1.0 specific BLR */ #define blr_current_role (unsigned char)174 @@ -344,6 +334,16 @@ #define blr_cursor_open (unsigned char)0 #define blr_cursor_close (unsigned char)1 #define blr_cursor_fetch (unsigned char)2 +#define blr_cursor_fetch_scroll (unsigned char)3 + +/* scroll options */ + +#define blr_scroll_forward (unsigned char)0 +#define blr_scroll_backward (unsigned char)1 +#define blr_scroll_bof (unsigned char)2 +#define blr_scroll_eof (unsigned char)3 +#define blr_scroll_absolute (unsigned char)4 +#define blr_scroll_relative (unsigned char)5 /* FB 2.1 specific BLR */ diff --git a/src/jrd/btn.cpp b/src/jrd/btn.cpp index 188060aef6..77df524c0e 100644 --- a/src/jrd/btn.cpp +++ b/src/jrd/btn.cpp @@ -400,46 +400,6 @@ bool keyEquality(USHORT length, const UCHAR* data, const IndexNode* indexNode) } -#ifdef SCROLLABLE_CURSORS -UCHAR* lastNode(btree_page* page, exp_index_buf* expanded_page, btree_exp** expanded_node) -{ -/************************************** - * - * l a s t N o d e - * - ************************************** - * - * Functional description - * Find the last node on a page. Used when walking - * down the right side of an index tree. - * - **************************************/ - - // the last expanded node is always at the end of the page - // minus the size of a btree_exp, since there is always an extra - // btree_exp node with zero-length tail at the end of the page - btree_exp* enode = (btree_exp*) ((UCHAR*) expanded_page + expanded_page->exp_length - BTX_SIZE); - - // starting at the end of the page, find the - // first node that is not an end marker - UCHAR* pointer = ((UCHAR*) page + page->btr_length); - const UCHAR flags = page->btr_header.pag_flags; - IndexNode node; - while (true) - { - pointer = previousNode(/*&node,*/ pointer, /*flags,*/ &enode); - if (!node.isEndBucket && !node.isEndLevel) - { - if (expanded_node) { - *expanded_node = enode; - } - return node.nodePointer; - } - } -} -#endif - - UCHAR* nextNode(IndexNode* node, UCHAR* pointer, UCHAR flags, btree_exp** expanded_node) { @@ -467,31 +427,6 @@ UCHAR* nextNode(IndexNode* node, UCHAR* pointer, } -#ifdef SCROLLABLE_CURSORS -UCHAR* previousNode(/*IndexNode* node,*/ UCHAR* pointer, - /*UCHAR flags,*/ btree_exp** expanded_node) -{ -/************************************** - * - * p r e v i o u s N o d e - * - ************************************** - * - * Functional description - * Find the previous node on a page. Used when walking - * an index backwards. - * - **************************************/ - - pointer = (pointer - (*expanded_node)->btx_btr_previous_length); - - *expanded_node = (btree_exp*) ((UCHAR*) *expanded_node - (*expanded_node)->btx_previous_length); - - return pointer; -} -#endif - - UCHAR* readJumpInfo(IndexJumpInfo* jumpInfo, UCHAR* pagePointer) { /************************************** diff --git a/src/jrd/btn.h b/src/jrd/btn.h index afd9726fc8..df514437a7 100644 --- a/src/jrd/btn.h +++ b/src/jrd/btn.h @@ -87,16 +87,8 @@ namespace BTreeNode { bool keyEquality(USHORT length, const UCHAR* data, const Ods::IndexNode* indexNode); -#ifdef SCROLLABLE_CURSORS - UCHAR* lastNode(Ods::btree_page* page, exp_index_buf* expanded_page, btree_exp** expanded_node); -#endif - UCHAR* nextNode(Ods::IndexNode* node, UCHAR* pointer, UCHAR flags, btree_exp** expanded_node); -#ifdef SCROLLABLE_CURSORS - UCHAR* previousNode(/*Ods::IndexNode* node,*/ UCHAR* pointer, - /*UCHAR flags,*/ btree_exp** expanded_node); -#endif //void quad_put(SLONG value, UCHAR *data); diff --git a/src/jrd/btr.cpp b/src/jrd/btr.cpp index db42b8d8d2..04d9865059 100644 --- a/src/jrd/btr.cpp +++ b/src/jrd/btr.cpp @@ -638,11 +638,7 @@ void BTR_evaluate(thread_db* tdbb, IndexRetrieval* retrieval, RecordBitmap** bit lower.key_length = 0; upper.key_flags = 0; upper.key_length = 0; - btree_page* page = BTR_find_page(tdbb, retrieval, &window, &idx, &lower, &upper -#ifdef SCROLLABLE_CURSORS - , false -#endif - ); + btree_page* page = BTR_find_page(tdbb, retrieval, &window, &idx, &lower, &upper); const bool descending = (idx.idx_flags & idx_descending); bool skipLowerKey = (retrieval->irb_generic & irb_exclude_lower); @@ -812,12 +808,7 @@ btree_page* BTR_find_page(thread_db* tdbb, WIN* window, index_desc* idx, temporary_key* lower, - temporary_key* upper -#ifdef SCROLLABLE_CURSORS - , - const bool backwards -#endif - ) + temporary_key* upper) { /************************************** * @@ -890,13 +881,8 @@ btree_page* BTR_find_page(thread_db* tdbb, const bool ignoreNulls = ((idx->idx_count == 1) && !(idx->idx_flags & idx_descending) && (retrieval->irb_generic & irb_ignore_null_value_key) && !(retrieval->irb_lower_count)); -#ifdef SCROLLABLE_CURSORS - const bool firstData = - ((!backwards && retrieval->irb_lower_count) || (!backwards && ignoreNulls) || - (backwards && retrieval->irb_upper_count)); -#else const bool firstData = (retrieval->irb_lower_count || ignoreNulls); -#endif + if (firstData) { // Make a temporary key with length 1 and zero byte, this will return @@ -910,12 +896,7 @@ btree_page* BTR_find_page(thread_db* tdbb, { while (true) { -#ifdef SCROLLABLE_CURSORS - const temporary_key* tkey = - backwards ? upper : (ignoreNulls ? &firstNotNullKey : lower); -#else const temporary_key* tkey = ignoreNulls ? &firstNotNullKey : lower; -#endif const SLONG number = find_page(page, tkey, idx->idx_flags, NO_VALUE, (retrieval->irb_generic & (irb_starting | irb_partial))); if (number != END_BUCKET) @@ -935,36 +916,13 @@ btree_page* BTR_find_page(thread_db* tdbb, { UCHAR* pointer; const UCHAR* const endPointer = (UCHAR*) page + page->btr_length; -#ifdef SCROLLABLE_CURSORS - if (backwards) { - pointer = BTR_last_node(page, NAV_expand_index(window, 0), 0); - } - else -#endif - { - pointer = BTreeNode::getPointerFirstNode(page); - } - + pointer = BTreeNode::getPointerFirstNode(page); pointer = BTreeNode::readNode(&node, pointer, page->btr_header.pag_flags, false); // Check if pointer is still valid if (pointer > endPointer) { BUGCHECK(204); // msg 204 index inconsistent } page = (btree_page*) CCH_HANDOFF(tdbb, window, node.pageNumber, LCK_read, pag_index); - - // make sure that we are actually on the last page on this - // level when scanning in the backward direction -#ifdef SCROLLABLE_CURSORS - if (backwards) - { - while (page->btr_sibling) - { - page = (btree_page*) CCH_HANDOFF(tdbb, window, page->btr_sibling, - LCK_read, pag_index); - } - } -#endif - } } @@ -1412,109 +1370,6 @@ USHORT BTR_key_length(thread_db* tdbb, jrd_rel* relation, index_desc* idx) } -#ifdef SCROLLABLE_CURSORS -UCHAR* BTR_last_node(btree_page* page, exp_index_buf* expanded_page, btree_exp** expanded_node) -{ -/************************************** - * - * B T R _ l a s t _ n o d e - * - ************************************** - * - * Functional description - * Find the last node on a page. Used when walking - * down the right side of an index tree. - * - **************************************/ - - // the last expanded node is always at the end of the page - // minus the size of a btree_exp, since there is always an extra - // btree_exp node with zero-length tail at the end of the page - btree_exp* enode = (btree_exp*) ((UCHAR*)expanded_page + expanded_page->exp_length - BTX_SIZE); - - // starting at the end of the page, find the - // first node that is not an end marker - UCHAR* pointer = ((UCHAR*)page + page->btr_length); - const UCHAR flags = page->btr_header.pag_flags; - IndexNode node; - while (true) - { - pointer = BTreeNode::previousNode(/*&node,*/ pointer, /*flags,*/ &enode); - if (!node.isEndBucket && !node.isEndLevel) - { - if (expanded_node) { - *expanded_node = enode; - } - return node.nodePointer; - } - } -} -#endif - - -#ifdef SCROLLABLE_CURSORS -btree_page* BTR_left_handoff(thread_db* tdbb, WIN* window, btree_page* page, SSHORT lock_level) -{ -/************************************** - * - * B T R _ l e f t _ h a n d o f f - * - ************************************** - * - * Functional description - * Handoff a btree page to the left. This is more difficult than a - * right handoff because we have to traverse pages without handing - * off locks. (A lock handoff to the left while someone was handing - * off to the right could result in deadlock.) - * - **************************************/ - - SET_TDBB(tdbb); - const Database* dbb = tdbb->getDatabase(); - CHECK_DBB(dbb); - - const PageNumber original_page(window->win_page); - const SLONG left_sibling = page->btr_left_sibling; - - CCH_RELEASE(tdbb, window); - window->win_page = left_sibling; - page = (btree_page*) CCH_FETCH(tdbb, window, lock_level, pag_index); - - SLONG sibling = page->btr_sibling; - if (sibling == original_page) { - return page; - } - - // Since we are not handing off pages, a page could split before we get to it. - // To detect this case, fetch the left sibling pointer and then handoff right - // sibling pointers until we reach the page to the left of the page passed - // to us. - - while (sibling != original_page) - { - page = (btree_page*) CCH_HANDOFF(tdbb, window, page->btr_sibling, lock_level, pag_index); - sibling = page->btr_sibling; - } - WIN fix_win(original_page); - btree_page* fix_page = (btree_page*) CCH_FETCH(tdbb, &fix_win, LCK_write, pag_index); - - // if someone else already fixed it, just return - if (fix_page->btr_left_sibling == window->win_page) - { - CCH_RELEASE(tdbb, &fix_win); - return page; - } - - CCH_MARK(tdbb, &fix_win); - fix_page->btr_left_sibling = window->win_page; - - CCH_RELEASE(tdbb, &fix_win); - - return page; -} -#endif - - USHORT BTR_lookup(thread_db* tdbb, jrd_rel* relation, USHORT id, index_desc* buffer, RelationPages* relPages) { @@ -3446,11 +3301,7 @@ static SLONG fast_load(thread_db* tdbb, // Get the next record in sorted order. UCHAR* record; - SORT_get(tdbb, sort_handle, reinterpret_cast(&record) -#ifdef SCROLLABLE_CURSORS - , RSE_get_forward -#endif - ); + SORT_get(tdbb, sort_handle, reinterpret_cast(&record)); if (!record) { break; diff --git a/src/jrd/btr_proto.h b/src/jrd/btr_proto.h index 1777d07a60..c0d46d9c2d 100644 --- a/src/jrd/btr_proto.h +++ b/src/jrd/btr_proto.h @@ -41,13 +41,8 @@ bool BTR_description(Jrd::thread_db*, Jrd::jrd_rel*, Ods::index_root_page*, Jrd: DSC* BTR_eval_expression(Jrd::thread_db*, Jrd::index_desc*, Jrd::Record*, bool&); void BTR_evaluate(Jrd::thread_db*, Jrd::IndexRetrieval*, Jrd::RecordBitmap**, Jrd::RecordBitmap*); UCHAR* BTR_find_leaf(Ods::btree_page*, Jrd::temporary_key*, UCHAR*, USHORT*, bool, bool); -#ifdef SCROLLABLE_CURSORS -Ods::btree_page* BTR_find_page(Jrd::thread_db*, Jrd::IndexRetrieval*, Jrd::win*, Jrd::index_desc*, - Jrd::temporary_key*, Jrd::temporary_key*, const bool); -#else Ods::btree_page* BTR_find_page(Jrd::thread_db*, Jrd::IndexRetrieval*, Jrd::win*, Jrd::index_desc*, Jrd::temporary_key*, Jrd::temporary_key*); -#endif void BTR_insert(Jrd::thread_db*, Jrd::win*, Jrd::index_insertion*); Jrd::idx_e BTR_key(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::Record*, Jrd::index_desc*, Jrd::temporary_key*, Jrd::idx_null_state*, const bool); diff --git a/src/jrd/cmp.cpp b/src/jrd/cmp.cpp index 661208cfc0..92171ecd1c 100644 --- a/src/jrd/cmp.cpp +++ b/src/jrd/cmp.cpp @@ -998,9 +998,6 @@ void CMP_get_desc(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node, DSC* des case nod_count: case nod_gen_id: case nod_lock_state: -#ifdef SCROLLABLE_CURSORS - case nod_seek: -#endif desc->dsc_dtype = dtype_long; desc->dsc_length = sizeof(SLONG); desc->dsc_scale = 0; @@ -2191,10 +2188,6 @@ jrd_req* CMP_make_request(thread_db* tdbb, CompilerScratch* csb, bool internal_f request->req_flags |= req_blr_version4; } -#ifdef SCROLLABLE_CURSORS - request->req_async_message = csb->csb_async_message; -#endif - // Take out existence locks on resources used in request. This is // a little complicated since relation locks MUST be taken before // index locks. @@ -4042,10 +4035,9 @@ jrd_nod* CMP_pass1(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node) return (jrd_nod*) pass1_rse(tdbb, csb, (RecordSelExpr*) node); case nod_cursor_stmt: - if ((UCHAR) (IPTR) node->nod_arg[e_cursor_stmt_op] == blr_cursor_fetch) { - node->nod_arg[e_cursor_stmt_seek] = CMP_pass1(tdbb, csb, node->nod_arg[e_cursor_stmt_seek]); - node->nod_arg[e_cursor_stmt_into] = CMP_pass1(tdbb, csb, node->nod_arg[e_cursor_stmt_into]); - } + node->nod_arg[e_cursor_stmt_scroll_op] = CMP_pass1(tdbb, csb, node->nod_arg[e_cursor_stmt_scroll_op]); + node->nod_arg[e_cursor_stmt_scroll_val] = CMP_pass1(tdbb, csb, node->nod_arg[e_cursor_stmt_scroll_val]); + node->nod_arg[e_cursor_stmt_into] = CMP_pass1(tdbb, csb, node->nod_arg[e_cursor_stmt_into]); break; case nod_max: @@ -4689,9 +4681,6 @@ static RecordSelExpr* pass1_rse(thread_db* tdbb, jrd_nod* skip = rse->rse_skip; jrd_nod* plan = rse->rse_plan; const bool writelock = rse->rse_writelock; -#ifdef SCROLLABLE_CURSORS - jrd_nod* async_message = rse->rse_async_message; -#endif // zip thru RecordSelExpr expanding views and inner joins jrd_nod** arg = rse->rse_relation; @@ -4765,13 +4754,6 @@ static RecordSelExpr* pass1_rse(thread_db* tdbb, rse->rse_writelock = writelock; -#ifdef SCROLLABLE_CURSORS - if (async_message) { - rse->rse_async_message = CMP_pass1(tdbb, csb, async_message); - csb->csb_async_message = rse->rse_async_message; - } -#endif - // we are no longer in the scope of this RecordSelExpr csb->csb_current_nodes.pop(); @@ -5289,33 +5271,19 @@ jrd_nod* CMP_pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node, j case nod_for: rse_node = node->nod_arg[e_for_re]; rsb_ptr = (RecordSource**) & node->nod_arg[e_for_rsb]; -#ifdef SCROLLABLE_CURSORS - csb->csb_current_rse = rse_node; -#endif break; case nod_dcl_cursor: rse_node = node->nod_arg[e_dcl_cursor_rse]; rsb_ptr = (RecordSource**) & node->nod_arg[e_dcl_cursor_rsb]; -#ifdef SCROLLABLE_CURSORS - csb->csb_current_rse = rse_node; -#endif break; case nod_cursor_stmt: - if ((UCHAR) (IPTR) node->nod_arg[e_cursor_stmt_op] == blr_cursor_fetch) { - CMP_pass2(tdbb, csb, node->nod_arg[e_cursor_stmt_seek], node); - CMP_pass2(tdbb, csb, node->nod_arg[e_cursor_stmt_into], node); - } + CMP_pass2(tdbb, csb, node->nod_arg[e_cursor_stmt_scroll_op], node); + CMP_pass2(tdbb, csb, node->nod_arg[e_cursor_stmt_scroll_val], node); + CMP_pass2(tdbb, csb, node->nod_arg[e_cursor_stmt_into], node); break; -#ifdef SCROLLABLE_CURSORS - case nod_seek: - // store the RecordSelExpr in whose scope we are defined - node->nod_arg[e_seek_rse] = (jrd_nod*) csb->csb_current_rse; - break; -#endif - case nod_max: case nod_min: case nod_count: @@ -5598,9 +5566,6 @@ jrd_nod* CMP_pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node, j case nod_current_timestamp: case nod_current_date: case nod_derived_expr: -#ifdef SCROLLABLE_CURSORS - case nod_seek: -#endif { dsc descriptor_a; CMP_get_desc(tdbb, csb, node, &descriptor_a); @@ -5846,11 +5811,6 @@ static void pass2_rse(thread_db* tdbb, CompilerScratch* csb, RecordSelExpr* rse) plan_check(csb, rse); } -#ifdef SCROLLABLE_CURSORS - if (rse->rse_async_message) { - CMP_pass2(tdbb, csb, rse->rse_async_message, 0); - } -#endif csb->csb_current_nodes.pop(); } @@ -6193,6 +6153,10 @@ static RecordSource* post_rse(thread_db* tdbb, CompilerScratch* csb, RecordSelEx rsb->rsb_flags |= rsb_singular; } + if (rse->nod_flags & rse_scrollable) { + rsb->rsb_flags |= rsb_scrollable; + } + // mark all the substreams as inactive jrd_nod** ptr = rse->rse_relation; @@ -6212,9 +6176,6 @@ static RecordSource* post_rse(thread_db* tdbb, CompilerScratch* csb, RecordSelEx } csb->csb_fors.push(rsb); -#ifdef SCROLLABLE_CURSORS - rse->rse_rsb = rsb; -#endif return rsb; } diff --git a/src/jrd/dpm.epp b/src/jrd/dpm.epp index 59123ee4c4..d001978bee 100644 --- a/src/jrd/dpm.epp +++ b/src/jrd/dpm.epp @@ -1530,9 +1530,6 @@ punt: bool DPM_next(thread_db* tdbb, record_param* rpb, USHORT lock_type, -#ifdef SCROLLABLE_CURSORS - bool backwards, -#endif bool onepage) { /************************************** @@ -1570,40 +1567,7 @@ bool DPM_next(thread_db* tdbb, // Find starting point -#ifdef SCROLLABLE_CURSORS - if (backwards) - { - if (rpb->rpb_number.isEmpty()) - return false; - - if (!rpb->rpb_number.isBof()) { - rpb->rpb_number.decrement(); - } - else - { - /* if the stream was just opened, assume we want to start - at the end of the stream, so compute the last theoretically - possible rpb_number and go down from there. - For now, we must force a scan to make sure that we get - the last pointer page: this should be changed to use - a coordination mechanism (probably using a shared lock) - to keep apprised of when a pointer page gets added */ - - DPM_scan_pages(tdbb); - const vcl* vector = relPages->rel_pages; - if (!vector) { - return false; - } - const size_t pp_sequence = vector->count(); - rpb->rpb_number.setValue( - ((SINT64) pp_sequence) * dbb->dbb_dp_per_pp * dbb->dbb_max_records - 1); - } - } - else -#endif - { - rpb->rpb_number.increment(); - } + rpb->rpb_number.increment(); SSHORT slot, line; USHORT pp_sequence; @@ -1625,12 +1589,6 @@ bool DPM_next(thread_db* tdbb, BUGCHECK(249); // msg 249 pointer page vanished from DPM_next } -#ifdef SCROLLABLE_CURSORS - if (backwards && slot >= ppage->ppg_count) { - slot = ppage->ppg_count - 1; - } -#endif - for (; slot >= 0 && slot < ppage->ppg_count;) { const SLONG page_number = ppage->ppg_page[slot]; @@ -1640,11 +1598,7 @@ bool DPM_next(thread_db* tdbb, // Perform sequential prefetch of relation's data pages. // This may need more work for scrollable cursors. -#ifdef SCROLLABLE_CURSORS - if (!onepage && !line && !backwards) -#else if (!onepage && !line) -#endif { if (!(slot % dbb->dbb_prefetch_sequence)) { @@ -1669,19 +1623,7 @@ bool DPM_next(thread_db* tdbb, const data_page* dpage = (data_page*) CCH_HANDOFF(tdbb, window, page_number, lock_type, pag_data); -#ifdef SCROLLABLE_CURSORS - if (backwards && line >= dpage->dpg_count) { - line = dpage->dpg_count - 1; - } -#endif - - for (; line >= 0 && line < dpage->dpg_count; -#ifdef SCROLLABLE_CURSORS - backwards ? line-- : line++ -#else - ++line -#endif - ) + for (; line >= 0 && line < dpage->dpg_count; ++line) { if (get_header(window, line, rpb) && !(rpb->rpb_flags & (rpb_blob | rpb_chained | rpb_fragment))) @@ -1725,35 +1667,14 @@ bool DPM_next(thread_db* tdbb, return false; } -#ifdef SCROLLABLE_CURSORS - if (backwards) - { - slot--; - line = dbb->dbb_max_records - 1; - } - else -#endif - { - slot++; - line = 0; - } + slot++; + line = 0; } const UCHAR flags = ppage->ppg_header.pag_flags; -#ifdef SCROLLABLE_CURSORS - if (backwards) - { - pp_sequence--; - slot = ppage->ppg_count - 1; - line = dbb->dbb_max_records - 1; - } - else -#endif - { - pp_sequence++; - slot = 0; - line = 0; - } + pp_sequence++; + slot = 0; + line = 0; if (window->win_flags & WIN_large_scan) { CCH_RELEASE_TAIL(tdbb, window); diff --git a/src/jrd/dpm_proto.h b/src/jrd/dpm_proto.h index c6275108b9..2bc280a9a9 100644 --- a/src/jrd/dpm_proto.h +++ b/src/jrd/dpm_proto.h @@ -56,11 +56,7 @@ void DPM_fetch_fragment(Jrd::thread_db*, Jrd::record_param*, USHORT); SINT64 DPM_gen_id(Jrd::thread_db*, SLONG, bool, SINT64); bool DPM_get(Jrd::thread_db*, Jrd::record_param*, SSHORT); ULONG DPM_get_blob(Jrd::thread_db*, Jrd::blb*, RecordNumber, bool, SLONG); -bool DPM_next(Jrd::thread_db*, Jrd::record_param*, USHORT, -#ifdef SCROLLABLE_CURSORS - bool, -#endif - bool); +bool DPM_next(Jrd::thread_db*, Jrd::record_param*, USHORT, bool); void DPM_pages(Jrd::thread_db*, SSHORT, int, ULONG, SLONG); SLONG DPM_prefetch_bitmap(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::PageBitmap*, SLONG); void DPM_scan_pages(Jrd::thread_db*); diff --git a/src/jrd/evl.cpp b/src/jrd/evl.cpp index f3e09158a5..1060427369 100644 --- a/src/jrd/evl.cpp +++ b/src/jrd/evl.cpp @@ -170,14 +170,6 @@ const SINT64 ISC_TICKS_PER_DAY = SECONDS_PER_DAY * ISC_TIME_SECONDS_PRECISION; const SCHAR DIALECT_3_TIMESTAMP_SCALE = -9; const SCHAR DIALECT_1_TIMESTAMP_SCALE = 0; -#ifdef SCROLLABLE_CURSORS -static const rse_get_mode g_RSE_get_mode = RSE_get_next; -#else -static const rse_get_mode g_RSE_get_mode = RSE_get_forward; -#endif - - - dsc* EVL_assign_to(thread_db* tdbb, jrd_nod* node) { @@ -640,7 +632,7 @@ bool EVL_boolean(thread_db* tdbb, jrd_nod* node) } } RSE_open(tdbb, select); - value = RSE_get_record(tdbb, select, g_RSE_get_mode); + value = RSE_get_record(tdbb, select); RSE_close(tdbb, select); if (node->nod_type == nod_any) request->req_flags &= ~req_null; @@ -750,10 +742,10 @@ bool EVL_boolean(thread_db* tdbb, jrd_nod* node) RecordSource* urs = reinterpret_cast(node->nod_arg[e_any_rsb]); RSE_open(tdbb, urs); - value = RSE_get_record(tdbb, urs, g_RSE_get_mode); + value = RSE_get_record(tdbb, urs); if (value) { - value = !RSE_get_record(tdbb, urs, g_RSE_get_mode); + value = !RSE_get_record(tdbb, urs); } RSE_close(tdbb, urs); request->req_flags &= ~req_null; @@ -1534,7 +1526,7 @@ USHORT EVL_group(thread_db* tdbb, RecordSource* rsb, jrd_nod* const node, USHORT if ((state == 0) || (state == 3)) { RSE_open(tdbb, rsb); - if (!RSE_get_record(tdbb, rsb, g_RSE_get_mode)) + if (!RSE_get_record(tdbb, rsb)) { if (group) { fini_agg_distinct(tdbb, node); @@ -1767,7 +1759,7 @@ USHORT EVL_group(thread_db* tdbb, RecordSource* rsb, jrd_nod* const node, USHORT if (state == 2) break; - if (!RSE_get_record(tdbb, rsb, g_RSE_get_mode)) + if (!RSE_get_record(tdbb, rsb)) { state = 2; } @@ -2970,11 +2962,7 @@ static void compute_agg_distinct(thread_db* tdbb, jrd_nod* node) while (true) { UCHAR* data; - SORT_get(tdbb, asb_impure->iasb_sort_handle, reinterpret_cast(&data) -#ifdef SCROLLABLE_CURSORS - , RSE_get_forward -#endif - ); + SORT_get(tdbb, asb_impure->iasb_sort_handle, reinterpret_cast(&data)); if (data == NULL) { /* we are done, close the sort */ @@ -3341,7 +3329,7 @@ static dsc* eval_statistical(thread_db* tdbb, jrd_nod* node, impure_value* impur { case nod_count: flag = 0; - while (RSE_get_record(tdbb, rsb, g_RSE_get_mode)) + while (RSE_get_record(tdbb, rsb)) { ++impure->vlu_misc.vlu_long; } @@ -3350,7 +3338,7 @@ static dsc* eval_statistical(thread_db* tdbb, jrd_nod* node, impure_value* impur /* case nod_count2: flag = 0; - while (RSE_get_record(tdbb, rsb, g_RSE_get_mode)) + while (RSE_get_record(tdbb, rsb)) { EVL_expr(tdbb, node->nod_arg[e_stat_value]); if (!(request->req_flags & req_null)) { @@ -3362,7 +3350,7 @@ static dsc* eval_statistical(thread_db* tdbb, jrd_nod* node, impure_value* impur case nod_min: case nod_max: - while (RSE_get_record(tdbb, rsb, g_RSE_get_mode)) + while (RSE_get_record(tdbb, rsb)) { dsc* value = EVL_expr(tdbb, node->nod_arg[e_stat_value]); if (request->req_flags & req_null) { @@ -3379,7 +3367,7 @@ static dsc* eval_statistical(thread_db* tdbb, jrd_nod* node, impure_value* impur break; case nod_from: - if (RSE_get_record(tdbb, rsb, g_RSE_get_mode)) + if (RSE_get_record(tdbb, rsb)) { desc = EVL_expr(tdbb, node->nod_arg[e_stat_value]); } @@ -3395,7 +3383,7 @@ static dsc* eval_statistical(thread_db* tdbb, jrd_nod* node, impure_value* impur case nod_average: /* total or average with dialect-1 semantics */ case nod_total: - while (RSE_get_record(tdbb, rsb, g_RSE_get_mode)) + while (RSE_get_record(tdbb, rsb)) { desc = EVL_expr(tdbb, node->nod_arg[e_stat_value]); if (request->req_flags & req_null) { @@ -3424,7 +3412,7 @@ static dsc* eval_statistical(thread_db* tdbb, jrd_nod* node, impure_value* impur break; case nod_average2: /* average with dialect-3 semantics */ - while (RSE_get_record(tdbb, rsb, g_RSE_get_mode)) + while (RSE_get_record(tdbb, rsb)) { desc = EVL_expr(tdbb, node->nod_arg[e_stat_value]); if (request->req_flags & req_null) diff --git a/src/jrd/exe.cpp b/src/jrd/exe.cpp index 4a9b94b8df..bccd961cdc 100644 --- a/src/jrd/exe.cpp +++ b/src/jrd/exe.cpp @@ -208,10 +208,6 @@ static jrd_nod* modify(thread_db*, jrd_nod*, SSHORT); static jrd_nod* receive_msg(thread_db*, jrd_nod*); static void release_blobs(thread_db*, jrd_req*); static void release_proc_save_points(jrd_req*); -#ifdef SCROLLABLE_CURSORS -static jrd_nod* seek_rse(thread_db*, jrd_req*, jrd_nod*); -static void seek_rsb(thread_db*, jrd_req*, RecordSource*, USHORT, SLONG); -#endif static jrd_nod* selct(thread_db*, jrd_nod*); static void set_error(thread_db*, const xcp_repeat*, jrd_nod*); static jrd_nod* stall(thread_db*, jrd_nod*); @@ -238,12 +234,6 @@ const int POST_TRIG = 2; const size_t MAX_STACK_TRACE = 2048; -#ifdef SCROLLABLE_CURSORS -static const rse_get_mode g_RSE_get_mode = RSE_get_next; -#else -static const rse_get_mode g_RSE_get_mode = RSE_get_forward; -#endif - void EXE_assignment(thread_db* tdbb, jrd_nod* node) { @@ -762,11 +752,7 @@ void EXE_receive(thread_db* tdbb, execute_looper(tdbb, request, transaction, jrd_req::req_sync); else { - if (request->req_message->nod_type == nod_stall -#ifdef SCROLLABLE_CURSORS - || request->req_flags & req_fetch_required -#endif - ) + if (request->req_message->nod_type == nod_stall) { execute_looper(tdbb, request, transaction, jrd_req::req_sync); } @@ -840,42 +826,6 @@ void EXE_receive(thread_db* tdbb, } -#ifdef SCROLLABLE_CURSORS -void EXE_seek(thread_db* tdbb, jrd_req* request, USHORT direction, ULONG offset) -{ -/************************************** - * - * E X E _ s e e k - * - ************************************** - * - * Functional description - * Seek a given request in a particular direction - * for offset records. - * - **************************************/ - SET_TDBB(tdbb); - DEV_BLKCHK(request, type_req); - -/* loop through all RSEs in the request, - and describe the rsb tree for that rsb; - go backwards because items were popped - off the stack backwards */ - -/* find the top-level rsb in the request and seek it */ - - for (SLONG i = request->req_fors.getCount() - 1; i >= 0; i--) - { - RecordSource* rsb = request->req_fors[i]; - if (rsb) { - seek_rsb(tdbb, request, rsb, direction, offset); - break; - } - } -} -#endif - - void EXE_send(thread_db* tdbb, jrd_req* request, USHORT msg, @@ -904,40 +854,9 @@ void EXE_send(thread_db* tdbb, jrd_nod* message; jrd_nod* node; -#ifdef SCROLLABLE_CURSORS -/* look for an asynchronous send message--if such - a message was defined, we allow the user to send - us a message at any time during request execution */ - jrd_nod* save_next = NULL; - jrd_nod* save_message = NULL; - jrd_req::req_s save_operation = jrd_req::req_evaluate; - - if ((message = request->req_async_message) && (node = message->nod_arg[e_send_message]) && - (msg == (USHORT)(ULONG) node->nod_arg[e_msg_number])) - { - /* save the current state of the request so we can go - back to what was interrupted */ - - save_operation = request->req_operation; - save_message = request->req_message; - save_next = request->req_next; - - request->req_operation = jrd_req::req_receive; - request->req_message = node; - request->req_next = message->nod_arg[e_send_statement]; - - /* indicate that we are processing an asynchronous message */ - - request->req_flags |= req_async_processing; - } - else { -#endif - if (request->req_operation != jrd_req::req_receive) - ERR_post(Arg::Gds(isc_req_sync)); - node = request->req_message; -#ifdef SCROLLABLE_CURSORS - } -#endif + if (request->req_operation != jrd_req::req_receive) + ERR_post(Arg::Gds(isc_req_sync)); + node = request->req_message; jrd_tra* transaction = request->req_transaction; const bool external = request->req_procedure && request->req_procedure->prc_external; @@ -1029,18 +948,6 @@ void EXE_send(thread_db* tdbb, if (!external) execute_looper(tdbb, request, transaction, jrd_req::req_proceed); - -#ifdef SCROLLABLE_CURSORS - if (save_next) { - /* if the message was sent asynchronously, restore all the - previous values so that whatever we were trying to do when - the message came in is what we do next */ - - request->req_operation = save_operation; - request->req_message = save_message; - request->req_next = save_next; - } -#endif } @@ -2205,7 +2112,7 @@ jrd_nod* EXE_looper(thread_db* tdbb, jrd_req* request, jrd_nod* in_node) break; } case jrd_req::req_sync: - if (RSE_get_record(tdbb, (RecordSource*) node->nod_arg[e_for_rsb], g_RSE_get_mode)) + if (RSE_get_record(tdbb, (RecordSource*) node->nod_arg[e_for_rsb])) { node = node->nod_arg[e_for_statement]; request->req_operation = jrd_req::req_evaluate; @@ -2281,6 +2188,7 @@ jrd_nod* EXE_looper(thread_db* tdbb, jrd_req* request, jrd_nod* in_node) node = node->nod_parent; break; case blr_cursor_fetch: + case blr_cursor_fetch_scroll: switch (request->req_operation) { case jrd_req::req_evaluate: @@ -2292,13 +2200,8 @@ jrd_nod* EXE_looper(thread_db* tdbb, jrd_req* request, jrd_nod* in_node) ERR_post(Arg::Gds(isc_stream_eof)); } request->req_records_affected.clear(); - // perform preliminary navigation, if specified - if (node->nod_arg[e_cursor_stmt_seek]) { - node = node->nod_arg[e_cursor_stmt_seek]; - break; - } // fetch one record - if (RSE_get_record(tdbb, rsb, g_RSE_get_mode)) + if (RSE_get_record(tdbb, rsb)) { node = node->nod_arg[e_cursor_stmt_into]; request->req_operation = jrd_req::req_evaluate; @@ -2804,12 +2707,6 @@ jrd_nod* EXE_looper(thread_db* tdbb, jrd_req* request, jrd_nod* in_node) } break; -#ifdef SCROLLABLE_CURSORS - case nod_seek: - node = seek_rse(tdbb, request, node); - break; -#endif - case nod_set_generator: case nod_set_generator2: if (request->req_operation == jrd_req::req_evaluate) @@ -2949,11 +2846,7 @@ jrd_nod* EXE_looper(thread_db* tdbb, jrd_req* request, jrd_nod* in_node) // request unless we are in the middle of processing an // asynchronous message - if (in_node->nod_type != nod_stmt_expr && !node -#ifdef SCROLLABLE_CURSORS - && !(request->req_flags & req_async_processing) -#endif - ) + if (in_node->nod_type != nod_stmt_expr && !node) { // Close active cursors if (request->req_cursors) @@ -3408,213 +3301,6 @@ static void release_proc_save_points(jrd_req* request) } -#ifdef SCROLLABLE_CURSORS -static jrd_nod* seek_rse(thread_db* tdbb, jrd_req* request, jrd_nod* node) -{ -/************************************** - * - * s e e k _ r s e - * - ************************************** - * - * Functional description - * Execute a nod_seek, which specifies - * a direction and offset in which to - * scroll a record selection expression. - * - **************************************/ - SET_TDBB(tdbb); - DEV_BLKCHK(node, type_nod); - - if (request->req_operation == jrd_req::req_proceed) - { - /* get input arguments */ - - const dsc* desc = EVL_expr(tdbb, node->nod_arg[e_seek_direction]); - const USHORT direction = (desc && !(request->req_flags & req_null)) ? - MOV_get_long(desc, 0) : MAX_USHORT; - - desc = EVL_expr(tdbb, node->nod_arg[e_seek_offset]); - const SLONG offset = (desc && !(request->req_flags & req_null)) ? MOV_get_long(desc, 0) : 0; - - RecordSelExpr* rse = (RecordSelExpr*) node->nod_arg[e_seek_rse]; - - seek_rsb(tdbb, request, rse->rse_rsb, direction, offset); - - request->req_operation = jrd_req::req_return; - } - - return node->nod_parent; -} -#endif - - -#ifdef SCROLLABLE_CURSORS -static void seek_rsb(thread_db* tdbb, - jrd_req* request, RecordSource* rsb, USHORT direction, SLONG offset) -{ -/************************************** - * - * s e e k _ r s b - * - ************************************** - * - * Functional description - * Allow scrolling through a stream as defined - * by the input rsb. Handles multiple seeking. - * Uses RSE_get_record() to do the actual work. - * - **************************************/ - SET_TDBB(tdbb); - DEV_BLKCHK(rsb, type_rsb); - irsb* impure = (IRSB) ((UCHAR *) request + rsb->rsb_impure); - -/* look past any boolean to the actual stream */ - - if (rsb->rsb_type == rsb_boolean) - { - seek_rsb(tdbb, request, rsb->rsb_next, direction, offset); - - /* set the backwards flag */ - - const irsb* next_impure = (IRSB) ((UCHAR *) request + rsb->rsb_next->rsb_impure); - - if (next_impure->irsb_flags & irsb_last_backwards) - impure->irsb_flags |= irsb_last_backwards; - else - impure->irsb_flags &= ~irsb_last_backwards; - return; - } - -/* do simple boundary checking for bof and eof */ - - switch (direction) - { - case blr_forward: - if (impure->irsb_flags & irsb_eof) - ERR_post(Arg::Gds(isc_stream_eof)); - break; - - case blr_backward: - if (impure->irsb_flags & irsb_bof) - ERR_post(Arg::Gds(isc_stream_bof)); - break; - - case blr_bof_forward: - case blr_eof_backward: - break; - - default: - // was: BUGCHECK(232); - // replaced with this error to be consistent with find() - ERR_post(Arg::Gds(isc_invalid_direction)); - } - -/* the actual offset to seek may be one less because the next time - through the blr_for loop we will seek one record--flag the fact - that a fetch is required on this stream in case it doesn't happen - (for example when GPRE generates BLR which does not stall prior to - the blr_for, as DSQL does) */ - - if (offset > 0) - switch (direction) - { - case blr_forward: - case blr_bof_forward: - if (!(impure->irsb_flags & irsb_last_backwards)) { - offset--; - if (!(impure->irsb_flags & irsb_bof)) - request->req_flags |= req_fetch_required; - } - break; - - case blr_backward: - case blr_eof_backward: - if (impure->irsb_flags & irsb_last_backwards) { - offset--; - if (!(impure->irsb_flags & irsb_eof)) - request->req_flags |= req_fetch_required; - } - break; - } - -/* now do the actual seek */ - - switch (direction) - { - case blr_forward: /* go forward from the current location */ - - /* the rsb_backwards flag is used to indicate the direction to seek in; - this is sticky in the sense that after the user has seek'ed in the - backward direction, the next retrieval from a blr_for loop will also - be in the backward direction--this allows us to continue scrolling - without constantly sending messages to the engine */ - - impure->irsb_flags &= ~irsb_last_backwards; - - while (offset) { - offset--; - if (!RSE_get_record(tdbb, rsb, RSE_get_next)) - break; - } - break; - - case blr_backward: /* go backward from the current location */ - - impure->irsb_flags |= irsb_last_backwards; - - while (offset) { - offset--; - if (!RSE_get_record(tdbb, rsb, RSE_get_next)) - break; - } - break; - - case blr_bof_forward: /* go forward from the beginning of the stream */ - - RSE_close(tdbb, rsb); - RSE_open(tdbb, rsb); - - impure->irsb_flags &= ~irsb_last_backwards; - - while (offset) { - offset--; - if (!RSE_get_record(tdbb, rsb, RSE_get_next)) - break; - } - break; - - case blr_eof_backward: /* go backward from the end of the stream */ - - RSE_close(tdbb, rsb); - RSE_open(tdbb, rsb); - - /* if this is a stream type which uses bof and eof flags, - reverse the sense of bof and eof in this case */ - - if (impure->irsb_flags & irsb_bof) { - impure->irsb_flags &= ~irsb_bof; - impure->irsb_flags |= irsb_eof; - } - - impure->irsb_flags |= irsb_last_backwards; - - while (offset) { - offset--; - if (!RSE_get_record(tdbb, rsb, RSE_get_next)) - break; - } - break; - - default: - // Should never go here, because of the boundary - // check above, but anyway... - BUGCHECK(232); - } -} -#endif - - static jrd_nod* selct(thread_db* tdbb, jrd_nod* node) { /************************************** diff --git a/src/jrd/exe.h b/src/jrd/exe.h index b07c06ebeb..1759fa45aa 100644 --- a/src/jrd/exe.h +++ b/src/jrd/exe.h @@ -134,9 +134,6 @@ public: USHORT rse_count; USHORT rse_jointype; // inner, left, full bool rse_writelock; -#ifdef SCROLLABLE_CURSORS - RecordSource* rse_rsb; -#endif jrd_nod* rse_first; jrd_nod* rse_skip; jrd_nod* rse_boolean; @@ -145,17 +142,13 @@ public: jrd_nod* rse_aggregate; // singleton aggregate for optimizing to index jrd_nod* rse_plan; // user-specified access plan VarInvariantArray *rse_invariants; // Invariant nodes bound to top-level RSE -#ifdef SCROLLABLE_CURSORS - jrd_nod* rse_async_message; // asynchronous message to send for scrolling -#endif jrd_nod* rse_relation[1]; }; -// First one is obsolete: was used for PC_ENGINE -//const int rse_stream = 1; // flags RecordSelExpr-type node as a blr_stream type -const int rse_singular = 2; // flags RecordSelExpr-type node as from a singleton select -const int rse_variant = 4; // flags RecordSelExpr as variant (not invariant?) +const int rse_scrollable = 1; // flags RSE as a scrollable cursor +const int rse_singular = 2; // flags RSE as a singleton select +const int rse_variant = 4; // flags RSE as variant (not invariant?) // Number of nodes may fit into nod_arg of normal node to get to rse_relation const size_t rse_delta = (sizeof(RecordSelExpr) - sizeof(jrd_nod)) / sizeof(jrd_nod::blk_repeat_type); @@ -461,14 +454,6 @@ const int e_cast_iteminfo = 2; const int e_cast_length = 3; -// CVC: These belong to SCROLLABLE_CURSORS, but I can't mark them with the macro -// because e_seek_length is used in blrtable.h. -const int e_seek_offset = 0; // for seeking through a stream -const int e_seek_direction = 1; -const int e_seek_rse = 2; -const int e_seek_length = 3; - - // This is for the plan node const int e_retrieve_relation = 0; const int e_retrieve_access_type = 1; @@ -496,11 +481,12 @@ const int e_dcl_cursor_number = 2; const int e_dcl_cursor_rsb = 3; const int e_dcl_cursor_length = 4; -const int e_cursor_stmt_op = 0; -const int e_cursor_stmt_number = 1; -const int e_cursor_stmt_seek = 2; -const int e_cursor_stmt_into = 3; -const int e_cursor_stmt_length = 4; +const int e_cursor_stmt_op = 0; +const int e_cursor_stmt_number = 1; +const int e_cursor_stmt_scroll_op = 2; +const int e_cursor_stmt_scroll_val = 3; +const int e_cursor_stmt_into = 4; +const int e_cursor_stmt_length = 5; const int e_strlen_value = 0; const int e_strlen_type = 1; @@ -808,10 +794,6 @@ public: : /*csb_node(0), csb_variables(0), csb_dependencies(0), -#ifdef SCROLLABLE_CURSORS - csb_current_rse(0), - csb_async_message(0), -#endif csb_count(0), csb_n_stream(0), csb_msg_number(0), @@ -879,12 +861,6 @@ public: Firebird::Array csb_invariants; // stack of invariant nodes Firebird::Array csb_current_nodes; // RecordSelExpr's and other invariant // candidates within whose scope we are -#ifdef SCROLLABLE_CURSORS - RecordSelExpr* csb_current_rse; // this holds the RecordSelExpr currently being processed; - // unlike the current_rses stack, it references any - // expanded view RecordSelExpr - jrd_nod* csb_async_message; // asynchronous message to send to request -#endif USHORT csb_n_stream; // Next available stream USHORT csb_msg_number; // Highest used message number SLONG csb_impure; // Next offset into impure area diff --git a/src/jrd/exe_proto.h b/src/jrd/exe_proto.h index 8314d2e169..b45337345f 100644 --- a/src/jrd/exe_proto.h +++ b/src/jrd/exe_proto.h @@ -44,9 +44,6 @@ void EXE_receive(Jrd::thread_db*, Jrd::jrd_req*, USHORT, USHORT, UCHAR*, bool = void EXE_send(Jrd::thread_db*, Jrd::jrd_req*, USHORT, USHORT, const UCHAR*); void EXE_start(Jrd::thread_db*, Jrd::jrd_req*, Jrd::jrd_tra*); void EXE_unwind(Jrd::thread_db*, Jrd::jrd_req*); -#ifdef SCROLLABLE_CURSORS -void EXE_seek(Jrd::thread_db*, Jrd::jrd_req*, USHORT, ULONG); -#endif void EXE_verb_cleanup(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction); namespace Jrd diff --git a/src/jrd/gds.cpp b/src/jrd/gds.cpp index 96a9089078..60848fd16c 100644 --- a/src/jrd/gds.cpp +++ b/src/jrd/gds.cpp @@ -3449,13 +3449,11 @@ static void blr_print_verb(gds_ctl* control, SSHORT level) case op_cursor_stmt: blr_operator = blr_print_byte(control); blr_print_word(control); - if (blr_operator == blr_cursor_fetch) + offset = blr_print_line(control, (SSHORT) offset); + if (blr_operator == blr_cursor_fetch_scroll) { -#ifdef SCROLLABLE_CURSORS - if (control->ctl_blr_reader.peekByte() == blr_seek) { - blr_print_verb(control, level); - } -#endif + blr_print_verb(control, level); + blr_print_verb(control, level); } offset = blr_print_line(control, (SSHORT) offset); break; diff --git a/src/jrd/idx.cpp b/src/jrd/idx.cpp index 936d96f750..08df0f574c 100644 --- a/src/jrd/idx.cpp +++ b/src/jrd/idx.cpp @@ -348,11 +348,7 @@ void IDX_create_index(thread_db* tdbb, // Loop thru the relation computing index keys. If there are old versions, find them, too. temporary_key key; - while (DPM_next(tdbb, &primary, LCK_read, -#ifdef SCROLLABLE_CURSORS - false, -#endif - false)) + while (DPM_next(tdbb, &primary, LCK_read, false)) { if (!VIO_garbage_collect(tdbb, &primary, transaction)) continue; diff --git a/src/jrd/inf.cpp b/src/jrd/inf.cpp index ab46f769d1..aaa73aeb91 100644 --- a/src/jrd/inf.cpp +++ b/src/jrd/inf.cpp @@ -397,13 +397,8 @@ void INF_database_info(const UCHAR* items, * base_level represents what the server 'knows' */ STUFF(p, 1); /* Count */ -#ifdef SCROLLABLE_CURSORS - UPDATE WITH VERSION OF SERVER SUPPORTING - SCROLLABLE CURSORS STUFF(p, 5); /* base level of scrollable cursors */ -#else /* IB_MAJOR_VER is defined as a character string */ STUFF(p, DBSERVER_BASE_LEVEL); /* base level of current version */ -#endif length = p - buffer; break; diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 57362a5863..dacc0e59e8 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -2799,12 +2799,7 @@ ISC_STATUS GDS_RECEIVE(ISC_STATUS* user_status, USHORT msg_type, USHORT msg_length, SCHAR* msg, - SSHORT level -#ifdef SCROLLABLE_CURSORS - , USHORT direction, - ULONG offset -#endif - ) + SSHORT level) { /************************************** * @@ -2826,11 +2821,7 @@ ISC_STATUS GDS_RECEIVE(ISC_STATUS* user_status, check_database(tdbb); check_transaction(tdbb, request->req_transaction); - JRD_receive(tdbb, request, msg_type, msg_length, reinterpret_cast(msg), level -#ifdef SCROLLABLE_CURSORS - , direction, offset -#endif - ); + JRD_receive(tdbb, request, msg_type, msg_length, reinterpret_cast(msg), level); } catch (const Exception& ex) { @@ -3841,11 +3832,7 @@ ISC_STATUS GDS_DSQL_EXECUTE_IMMEDIATE(ISC_STATUS* user_status, ISC_STATUS GDS_DSQL_FETCH(ISC_STATUS* user_status, dsql_req** stmt_handle, USHORT blr_length, const SCHAR* blr, - USHORT /*msg_type*/, USHORT msg_length, SCHAR* dsql_msg_buf -#ifdef SCROLLABLE_CURSORS - , USHORT direction, SLONG offset -#endif - ) + USHORT /*msg_type*/, USHORT msg_length, SCHAR* dsql_msg_buf) { ISC_STATUS return_code = FB_SUCCESS; @@ -3859,11 +3846,7 @@ ISC_STATUS GDS_DSQL_FETCH(ISC_STATUS* user_status, check_database(tdbb); return_code = DSQL_fetch(tdbb, statement, blr_length, reinterpret_cast(blr), - /*msg_type,*/ msg_length, reinterpret_cast(dsql_msg_buf) -#ifdef SCROLLABLE_CURSORS - , direction, offset -#endif - ); + /*msg_type,*/ msg_length, reinterpret_cast(dsql_msg_buf)); } catch (const Exception& ex) { @@ -6340,11 +6323,7 @@ void JRD_ddl(thread_db* tdbb, /*Jrd::Attachment* attachment,*/ jrd_tra* transact void JRD_receive(thread_db* tdbb, jrd_req* request, USHORT msg_type, USHORT msg_length, - UCHAR* msg, SSHORT level -#ifdef SCROLLABLE_CURSORS - , USHORT direction, ULONG offset -#endif - ) + UCHAR* msg, SSHORT level) { /************************************** * @@ -6358,11 +6337,6 @@ void JRD_receive(thread_db* tdbb, jrd_req* request, USHORT msg_type, USHORT msg_ **************************************/ verify_request_synchronization(request, level); -#ifdef SCROLLABLE_CURSORS - if (direction) - EXE_seek(tdbb, request, direction, offset); -#endif - EXE_receive(tdbb, request, msg_type, msg_length, msg, true); check_autocommit(request, tdbb); diff --git a/src/jrd/jrd_proto.h b/src/jrd/jrd_proto.h index 9070eed909..e1e404eb2b 100644 --- a/src/jrd/jrd_proto.h +++ b/src/jrd/jrd_proto.h @@ -104,12 +104,7 @@ ISC_STATUS jrd8_execute(ISC_STATUS*, Jrd::jrd_tra**, Jrd::dsql_req**, USHORT, co ISC_STATUS jrd8_execute_immediate(ISC_STATUS*, Jrd::Attachment**, Jrd::jrd_tra**, USHORT, const TEXT*, USHORT, USHORT, const SCHAR*, USHORT, USHORT, const SCHAR*, USHORT, SCHAR*, USHORT, USHORT, SCHAR*); -#ifdef SCROLLABLE_CURSORS -ISC_STATUS jrd8_fetch(ISC_STATUS*, Jrd::dsql_req**, USHORT, const SCHAR*, USHORT, USHORT, SCHAR*, - USHORT, SLONG); -#else ISC_STATUS jrd8_fetch(ISC_STATUS*, Jrd::dsql_req**, USHORT, const SCHAR*, USHORT, USHORT, SCHAR*); -#endif // SCROLLABLE_CURSORS ISC_STATUS jrd8_free_statement(ISC_STATUS*, Jrd::dsql_req**, USHORT); ISC_STATUS jrd8_insert(ISC_STATUS*, Jrd::dsql_req**, USHORT, const SCHAR*, USHORT, USHORT, const SCHAR*); ISC_STATUS jrd8_prepare(ISC_STATUS*, Jrd::jrd_tra**, Jrd::dsql_req**, USHORT, const TEXT*, @@ -143,11 +138,7 @@ void JRD_autocommit_ddl(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction); void JRD_ddl(Jrd::thread_db* tdbb, /*Jrd::Attachment* attachment,*/ Jrd::jrd_tra* transaction, USHORT ddl_length, const UCHAR* ddl, const Firebird::string& sqlText); void JRD_receive(Jrd::thread_db* tdbb, Jrd::jrd_req* request, USHORT msg_type, USHORT msg_length, - UCHAR* msg, SSHORT level -#ifdef SCROLLABLE_CURSORS - , USHORT direction, ULONG offset -#endif - ); + UCHAR* msg, SSHORT level); void JRD_request_info(Jrd::thread_db* tdbb, Jrd::jrd_req* request, SSHORT level, SSHORT item_length, const UCHAR* items, SLONG buffer_length, UCHAR* buffer); void JRD_start(Jrd::thread_db* tdbb, Jrd::jrd_req* request, Jrd::jrd_tra* transaction, SSHORT level); diff --git a/src/jrd/nav.cpp b/src/jrd/nav.cpp index 04408f40d5..f2d22b8996 100644 --- a/src/jrd/nav.cpp +++ b/src/jrd/nav.cpp @@ -56,96 +56,19 @@ using namespace Jrd; static int compare_keys(const index_desc*, const UCHAR*, USHORT, const temporary_key*, USHORT); -#ifdef SCROLLABLE_CURSORS -static void expand_index(WIN *); -#endif static btree_exp* find_current(exp_index_buf*, Ods::btree_page*, const UCHAR*); static bool find_saved_node(thread_db* tdbb, RecordSource*, IRSB_NAV, WIN*, UCHAR**); -static UCHAR* get_position(thread_db*, RecordSource*, IRSB_NAV, WIN *, rse_get_mode, btree_exp**); +static UCHAR* get_position(thread_db*, RecordSource*, IRSB_NAV, WIN *, btree_exp**); static bool get_record(thread_db* tdbb, RecordSource*, IRSB_NAV, record_param*, temporary_key*, bool); static void init_fetch(IRSB_NAV); -static UCHAR* nav_open(thread_db* tdbb, RecordSource*, IRSB_NAV, WIN *, rse_get_mode); //, btree_exp**); +static UCHAR* nav_open(thread_db* tdbb, RecordSource*, IRSB_NAV, WIN *); static void set_page(IRSB_NAV impure, WIN* window); static void set_position(IRSB_NAV, record_param*, WIN*, const UCHAR*, btree_exp*, const UCHAR*, USHORT); static bool setup_bitmaps(thread_db* tdbb, RecordSource*, IRSB_NAV); -#ifdef SCROLLABLE_CURSORS -exp_index_buf* NAV_expand_index(WIN * window, IRSB_NAV impure) -{ -/************************************** - * - * N A V _ e x p a n d _ i n d e x - * - ************************************** - * - * Functional description - * Given a window with a btree leaf page loaded into it, - * expand the index page into a form that facilitates walking - * backward through it. Each node's data is decompressed. - * Since the prefix field is not needed, it contains an offset to - * the prior node. - * - * If an impure pointer is passed, set the current node on the - * expanded page to match that on the corresponding btree page. - * - **************************************/ - - // allocate the expanded page to allow room for all nodes fully expanded, - // plus leave room for an extra node with zero-length tail - // (note that the difference in size of a btree_exp node versus a btree_nod node could - // be deducted, but there is no easy way to get the no. of nodes on page) */ - - // if the right version of expanded page is available, there - // is no work to be done - exp_index_buf* expanded_page = window->win_expanded_buffer; - if (expanded_page && (expanded_page->exp_incarnation == CCH_get_incarnation(window))) - { - return expanded_page; - } - - // If different incarnation, reallocate the page - if (expanded_page) { - ALL_free(expanded_page); - } - - Ods::btree_page* page = (Ods::btree_page*) window->win_buffer; - - expanded_page = (exp_index_buf*) ALL_malloc(EXP_SIZE + page->btr_prefix_total + - (SLONG) page->btr_length + BTX_SIZE, ERR_jmp); - window->win_expanded_buffer = expanded_page; - expanded_page->exp_incarnation = -1; - - expand_index(window); - - if (!impure) { - return expanded_page; - } - - // go through the nodes on the original page and reposition - UCHAR* pointer = BTreeNode::getPointerFirstNode(page); - const UCHAR* const endPointer = ((UCHAR*) page + page->btr_length); - btree_exp* expanded_node = (btree_exp*) expanded_page->exp_nodes; - const UCHAR* current_pointer = ((UCHAR*) page + impure->irsb_nav_offset); - - impure->irsb_nav_expanded_offset = -1; - - Ods::IndexNode node; - while (pointer < endPointer) - { - if (pointer == current_pointer) { - impure->irsb_nav_expanded_offset = (UCHAR*) expanded_node - (UCHAR*) expanded_page; - } - pointer = BTreeNode::nextNode(pointer, &expanded_node); - } - - return expanded_page; -} -#endif - - bool NAV_get_record(thread_db* tdbb, RecordSource* rsb, - IRSB_NAV impure, record_param* rpb, rse_get_mode direction) + IRSB_NAV impure, record_param* rpb) { /************************************** * @@ -154,57 +77,20 @@ bool NAV_get_record(thread_db* tdbb, RecordSource* rsb, ************************************** * * Functional description - * Get a record from a stream, either in - * the forward or backward direction, or the - * current record. This routine must set - * BOF or EOF properly. + * Get a record from a stream. * **************************************/ SET_TDBB(tdbb); -#ifdef SCROLLABLE_CURSORS - // before we do anything, check for the case where an ascending index - // was used to optimize a descending sort, or a descending index was - // used to optimize an ascending sort--in either case, we need to flip - // the nominal direction of navigation - if (rsb->rsb_flags & rsb_descending) - { - if (direction == RSE_get_forward) { - direction = RSE_get_backward; - } - else if (direction == RSE_get_backward) { - direction = RSE_get_forward; - } - } -#endif - init_fetch(impure); index_desc* idx = (index_desc*) ((SCHAR*) impure + (IPTR) rsb->rsb_arg[RSB_NAV_idx_offset]); - // The bitmap is only valid when we are continuing on in one - // direction. It is of no help when we change direction, - // and so we need to reset in that case. -#ifdef SCROLLABLE_CURSORS - if (((impure->irsb_flags & irsb_backwards) && direction != RSE_get_backward) || - (!(impure->irsb_flags & irsb_backwards) && direction != RSE_get_forward)) - { - RecordBitmap::reset(impure->irsb_nav_records_visited); - } - - if (direction == RSE_get_forward) { - impure->irsb_flags &= ~irsb_backwards; - } - else if (direction == RSE_get_backward) { - impure->irsb_flags |= irsb_backwards; - } -#endif - // find the last fetched position from the index const USHORT pageSpaceID = rpb->rpb_relation->getPages(tdbb)->rel_pg_space_id; WIN window(pageSpaceID, impure->irsb_nav_page); btree_exp* expanded_next = NULL; - UCHAR* nextPointer = get_position(tdbb, rsb, impure, &window, direction, &expanded_next); + UCHAR* nextPointer = get_position(tdbb, rsb, impure, &window, &expanded_next); if (!nextPointer) return false; temporary_key key; @@ -214,31 +100,13 @@ bool NAV_get_record(thread_db* tdbb, RecordSource* rsb, // set the upper (or lower) limit for navigational retrieval temporary_key upper; -#ifdef SCROLLABLE_CURSORS - temporary_key lower; -#endif - if ((direction == RSE_get_forward) && retrieval->irb_upper_count) + if (retrieval->irb_upper_count) { upper.key_length = impure->irsb_nav_upper_length; -#ifdef SCROLLABLE_CURSORS - memcpy(upper.key_data, - (impure->irsb_nav_data + (2 * (SLONG) rsb->rsb_arg[RSB_NAV_key_length])), - upper.key_length); -#else memcpy(upper.key_data, (impure->irsb_nav_data + (IPTR) rsb->rsb_arg[RSB_NAV_key_length]), upper.key_length); -#endif } -#ifdef SCROLLABLE_CURSORS - else if ((direction == RSE_get_backward) && retrieval->irb_lower_count) - { - lower.key_length = impure->irsb_nav_lower_length; - memcpy(lower.key_data, - (impure->irsb_nav_data + (IPTR) rsb->rsb_arg[RSB_NAV_key_length]), - lower.key_length); - } -#endif // In the case of a DISTINCT, we must detect whether the key changed since the last // time a record was returned from the rsb. It is not good enough to know whether the @@ -278,56 +146,22 @@ bool NAV_get_record(thread_db* tdbb, RecordSource* rsb, number = node.recordNumber; } -#ifdef SCROLLABLE_CURSORS - // in the backwards case, check to make sure we haven't hit the - // beginning of a page, and if so fetch the left sibling page. - if (direction == RSE_get_backward) + if (node.isEndLevel) + break; + + if (node.isEndBucket) { - if (pointer < BTreeNode::getPointerFirstNode(page)) - { - exp_index_buf* expanded_page = window.win_expanded_buffer; - - if (!page->btr_left_sibling) - { - impure->irsb_flags |= irsb_bof; - break; - } - - page = BTR_left_handoff(tdbb, &window, page, LCK_read); - expanded_page = NAV_expand_index(&window, 0); - nextPointer = BTR_last_node(page, expanded_page, &expanded_next); - - page_changed = true; - continue; - } - } - else - // In the forwards case, check for end of page. If we find - // it, do a simple handoff to the right sibling page. -#endif - { - if (node.isEndLevel) - { -#ifdef SCROLLABLE_CURSORS - impure->irsb_flags |= irsb_eof; -#endif - break; - } - if (node.isEndBucket) - { - page = (Ods::btree_page*) window.win_buffer; - page = (Ods::btree_page*) CCH_HANDOFF(tdbb, &window, page->btr_sibling, - LCK_read, pag_index); - nextPointer = BTreeNode::getPointerFirstNode(page); - exp_index_buf* expanded_page = window.win_expanded_buffer; - if (expanded_page) { - expanded_next = (btree_exp*) expanded_page->exp_nodes; - } - - page_changed = true; - continue; + page = (Ods::btree_page*) window.win_buffer; + page = (Ods::btree_page*) CCH_HANDOFF(tdbb, &window, page->btr_sibling, + LCK_read, pag_index); + nextPointer = BTreeNode::getPointerFirstNode(page); + exp_index_buf* expanded_page = window.win_expanded_buffer; + if (expanded_page) { + expanded_next = (btree_exp*) expanded_page->exp_nodes; } + page_changed = true; + continue; } // In the project (DISTINCT) case, we need to determine if the key has changed @@ -368,22 +202,13 @@ bool NAV_get_record(thread_db* tdbb, RecordSource* rsb, key.key_length = node.length + node.prefix; // Make sure we haven't hit the upper (or lower) limit. - if ((direction == RSE_get_forward) && retrieval->irb_upper_count && + if (retrieval->irb_upper_count && compare_keys(idx, key.key_data, key.key_length, &upper, retrieval->irb_generic & (irb_descending | irb_partial | irb_starting)) > 0) { break; } -#ifdef SCROLLABLE_CURSORS - if ((direction == RSE_get_backward) && retrieval->irb_lower_count && - compare_keys(idx, key.key_data, key.key_length, &lower, - retrieval->irb_generic & (irb_descending | irb_partial | irb_starting)) < 0) - { - break; - } -#endif - // skip this record if: // 1) there is an inversion tree for this index and this record // is not in the bitmap for the inversion, or @@ -396,20 +221,9 @@ bool NAV_get_record(thread_db* tdbb, RecordSource* rsb, RecordBitmap::test(impure->irsb_nav_records_visited, number.getValue()) || ((rsb->rsb_flags & rsb_project) && !(impure->irsb_flags & irsb_key_changed))) { -#ifdef SCROLLABLE_CURSORS - if (direction == RSE_get_backward) - { - nextPointer = BTreeNode::previousNode(/*&node,*/ pointer, /*flags,*/ &expanded_node); - expanded_next = expanded_node; - continue; - } -#endif - if (direction == RSE_get_forward) - { - nextPointer = BTreeNode::nextNode(&node, pointer, flags, &expanded_node); - expanded_next = expanded_node; - continue; - } + nextPointer = BTreeNode::nextNode(&node, pointer, flags, &expanded_node); + expanded_next = expanded_node; + continue; } // reset the current navigational position in the index @@ -422,7 +236,7 @@ bool NAV_get_record(thread_db* tdbb, RecordSource* rsb, return true; } - nextPointer = get_position(tdbb, rsb, impure, &window, direction, &expanded_next); + nextPointer = get_position(tdbb, rsb, impure, &window, &expanded_next); if (!nextPointer) return false; } @@ -554,72 +368,6 @@ static int compare_keys(const index_desc* idx, } -#ifdef SCROLLABLE_CURSORS -static void expand_index(WIN * window) -{ -/************************************** - * - * e x p a n d _ i n d e x - * - ************************************** - * - * Functional description - * Given a window with a btree leaf page loaded into it, - * expand the index page into a form that facilitates walking - * backward through it. Each node's data is decompressed. - * Since the prefix field is not needed, it contains an offset to - * the prior node. - * - **************************************/ - Ods::btree_page* page = (Ods::btree_page*) window->win_buffer; - exp_index_buf* expanded_page = window->win_expanded_buffer; - expanded_page->exp_incarnation = CCH_get_incarnation(window); - - // go through the nodes on the original page and expand them - temporary_key key; - btree_exp* expanded_node = (btree_exp*) expanded_page->exp_nodes; - bool priorPointer = false; - UCHAR* pointer = BTreeNode::getPointerFirstNode(page); - const UCHAR* const endPointer = ((UCHAR*) page + page->btr_length); - - const UCHAR flags = page->btr_header.pag_flags; - Ods::IndexNode node, priorNode; - - while (pointer < endPointer) - { - - if (!priorPointer) { - pointer = BTreeNode::readNode(&node, pointer, flags, true); - } - - memcpy(key.key_data + node.prefix, node.data, node.length); - memcpy(expanded_node->btx_data, key.key_data, node.length + node.prefix); - - // point back to the prior nodes on the expanded page and the btree page - expanded_node->btx_btr_previous_length = - priorPointer ? BTreeNode::getLeafNodeSize(&priorNode, flags) : 0; - expanded_node->btx_previous_length = - priorPointer ? priorNode.length + priorNode.prefix : 0; - - priorPointer = true; - priorNode = node; - pointer = BTreeNode::nextNode(&node, pointer, flags, &expanded_node); - } - - // insert one additional expanded node to keep track of the length of the - // last node on page--this is necessary because the end of bucket marker - // contains the length and key of the first node on the next page - expanded_node->btx_btr_previous_length = - priorPointer ? BTreeNode::getLeafNodeSize(&priorNode, flags) : 0; - expanded_node->btx_previous_length = - priorPointer ? priorNode.length + priorNode.prefix : 0; - - expanded_page->exp_length = - (UCHAR*) expanded_node - (UCHAR*) expanded_page + BTX_SIZE; -} -#endif - - static btree_exp* find_current(exp_index_buf* expanded_page, Ods::btree_page* page, const UCHAR* current_pointer) { @@ -742,7 +490,7 @@ static UCHAR* get_position(thread_db* tdbb, RecordSource* rsb, IRSB_NAV impure, WIN* window, - rse_get_mode direction, btree_exp** expanded_node) + btree_exp** expanded_node) { /************************************** * @@ -759,14 +507,10 @@ static UCHAR* get_position(thread_db* tdbb, **************************************/ SET_TDBB(tdbb); - // If this is the first time, start at the beginning (or the end) -#ifdef SCROLLABLE_CURSORS - if (!window->win_page.getPageNum() || impure->irsb_flags & (irsb_bof | irsb_eof)) -#else + // If this is the first time, start at the beginning if (!window->win_page.getPageNum()) -#endif { - return nav_open(tdbb, rsb, impure, window, direction); //, expanded_node); + return nav_open(tdbb, rsb, impure, window); } exp_index_buf* expanded_page = NULL; @@ -774,15 +518,6 @@ static UCHAR* get_position(thread_db* tdbb, // Re-fetch page and get incarnation counter Ods::btree_page* page = (Ods::btree_page*) CCH_FETCH(tdbb, window, LCK_read, pag_index); -#ifdef SCROLLABLE_CURSORS - // we must ensure that if we are going backwards, we always - // have an expanded buffer (and a valid position on that page) - if (direction == RSE_get_backward) { - NAV_expand_index(window, impure); - } - expanded_page = window->win_expanded_buffer; -#endif - UCHAR* pointer = 0; const UCHAR flags = page->btr_header.pag_flags; const SLONG incarnation = CCH_get_incarnation(window); @@ -807,28 +542,15 @@ static UCHAR* get_position(thread_db* tdbb, } // The new way of doing things is to have the current - // nav_offset be the last node fetched. Go forward or - // backward from that point accordingly. -#ifdef SCROLLABLE_CURSORS - if (direction == RSE_get_backward) - { - pointer = BTreeNode::previousNode(/*&node,*/ pointer, /*flags,*/ expanded_node); - //node = (btree_nod*) BTR_previous_node( (UCHAR*)node, expanded_node); - } - else -#endif - { - if (direction == RSE_get_forward) - pointer = BTreeNode::nextNode(&node, pointer, flags, expanded_node); - } - return pointer; + // nav_offset be the last node fetched. + return BTreeNode::nextNode(&node, pointer, flags, expanded_node); } // Page is presumably changed. If there is a previous // stored position in the page, go back to it if possible. CCH_RELEASE(tdbb, window); if (!impure->irsb_nav_page) { - return nav_open(tdbb, rsb, impure, window, direction); //, expanded_node); + return nav_open(tdbb, rsb, impure, window); } const bool found = find_saved_node(tdbb, rsb, impure, window, &pointer); @@ -836,41 +558,16 @@ static UCHAR* get_position(thread_db* tdbb, if (pointer) { *expanded_node = find_current(window->win_expanded_buffer, page, pointer); -#ifdef SCROLLABLE_CURSORS - if (direction == RSE_get_backward) + if (found) { - pointer = BTreeNode::previousNode(/*&node,*/ pointer, /*flags,*/ expanded_node); - //node = (btree_nod*) BTR_previous_node((UCHAR*) node, expanded_node); - } - else -#endif - { - if (direction == RSE_get_forward && found) - { - // in the forward case, seek to the next node only if we found - // the actual node on page; if we did not find it, we are already - // at the next node (such as when the node is garbage collected) - pointer = BTreeNode::nextNode(&node, pointer, flags, expanded_node); - } + // in the forward case, seek to the next node only if we found + // the actual node on page; if we did not find it, we are already + // at the next node (such as when the node is garbage collected) + pointer = BTreeNode::nextNode(&node, pointer, flags, expanded_node); } return pointer; } -#ifdef SCROLLABLE_CURSORS - // As a last resort, return the first (or last if backwards) - // node on the page. The sparse bitmap will prevent us from - // seeing records we have already visited before. - if (direction == RSE_get_backward) - { - expanded_page = NAV_expand_index(window, 0); - return BTR_last_node(page, expanded_page, expanded_node); - } - - if (expanded_page = window->win_expanded_buffer) { - *expanded_node = (btree_exp*) expanded_page->exp_nodes; - } -#endif - return BTreeNode::getPointerFirstNode(page); } @@ -908,14 +605,6 @@ static bool get_record(thread_db* tdbb, RecordSource* rsb, IRSB_NAV impure, tdbb->getAttachment()->att_flags |= ATT_no_cleanup; // HACK } -#ifdef SCROLLABLE_CURSORS - // the attempt to get a record, whether successful or not, takes - // us off bof or eof (otherwise we will keep trying to retrieve - // the first record) - - impure->irsb_flags &= ~(irsb_bof | irsb_eof); -#endif - result = VIO_get(tdbb, rpb, request->req_transaction, request->req_pool); temporary_key value; @@ -978,7 +667,7 @@ static void init_fetch(IRSB_NAV impure) static UCHAR* nav_open(thread_db* tdbb, RecordSource* rsb, IRSB_NAV impure, - WIN* window, rse_get_mode direction) //, btree_exp** expanded_node) + WIN* window) { /************************************** * @@ -999,100 +688,30 @@ static UCHAR* nav_open(thread_db* tdbb, set_page(impure, NULL); impure->irsb_nav_length = 0; -#ifdef SCROLLABLE_CURSORS - if (direction == RSE_get_forward) { - impure->irsb_flags |= irsb_bof; - } - else if (direction == RSE_get_backward) { - impure->irsb_flags |= irsb_eof; - } -#endif - // Find the starting leaf page jrd_nod* retrieval_node = (jrd_nod*) rsb->rsb_arg[RSB_NAV_index]; IndexRetrieval* retrieval = (IndexRetrieval*) retrieval_node->nod_arg[e_idx_retrieval]; index_desc* idx = (index_desc*) ((SCHAR *) impure + (IPTR) rsb->rsb_arg[RSB_NAV_idx_offset]); temporary_key lower, upper; -#ifdef SCROLLABLE_CURSORS - Ods::btree_page* page = BTR_find_page(tdbb, retrieval, window, idx, &lower, &upper, - (direction == RSE_get_backward)); -#else Ods::btree_page* page = BTR_find_page(tdbb, retrieval, window, idx, &lower, &upper); -#endif set_page(impure, window); - -#ifdef SCROLLABLE_CURSORS - // store the upper and lower bounds for the search in the impure area for the rsb - if (retrieval->irb_lower_count) - { - impure->irsb_nav_lower_length = lower.key_length; - memcpy((impure->irsb_nav_data + (SLONG) rsb->rsb_arg[RSB_NAV_key_length]), - lower.key_data, - lower.key_length); - } - + // find the upper limit for the search + temporary_key* limit_ptr = NULL; if (retrieval->irb_upper_count) { impure->irsb_nav_upper_length = upper.key_length; - memcpy((impure->irsb_nav_data + (2 * (SLONG) rsb->rsb_arg[RSB_NAV_key_length])), + memcpy((impure->irsb_nav_data + (IPTR) rsb->rsb_arg[RSB_NAV_key_length]), upper.key_data, upper.key_length); } - - // find the limit the search needs to begin with, if any - temporary_key* limit_ptr = NULL; - if (direction == RSE_get_forward) - { - if (retrieval->irb_lower_count) - limit_ptr = &lower; + if (retrieval->irb_lower_count) { + limit_ptr = &lower; } - else - { - if (retrieval->irb_upper_count) - limit_ptr = &upper; - } -#else - - // find the upper limit for the search (or lower for backwards) - temporary_key* limit_ptr = NULL; - if (direction == RSE_get_forward) - { - if (retrieval->irb_upper_count) - { - impure->irsb_nav_upper_length = upper.key_length; - memcpy((impure->irsb_nav_data + (IPTR) rsb->rsb_arg[RSB_NAV_key_length]), - upper.key_data, - upper.key_length); - } - if (retrieval->irb_lower_count) { - limit_ptr = &lower; - } - } - else - { - fb_assert(direction == RSE_get_forward); - if (retrieval->irb_lower_count) - { - impure->irsb_nav_lower_length = lower.key_length; - memcpy((impure->irsb_nav_data + (IPTR) rsb->rsb_arg[RSB_NAV_key_length]), - lower.key_data, - lower.key_length); - } - if (retrieval->irb_upper_count) { - limit_ptr = &upper; - } - } -#endif // If there is a starting descriptor, search down index to starting position. // This may involve sibling buckets if splits are in progress. If there - // isn't a starting descriptor, walk down the left side of the index (or the - // right side if backwards). - -#ifdef SCROLLABLE_CURSORS - exp_index_buf* expanded_page = 0; -#endif + // isn't a starting descriptor, walk down the left side of the index. UCHAR* pointer = NULL; if (limit_ptr) @@ -1110,38 +729,10 @@ static UCHAR* nav_open(thread_db* tdbb, BTreeNode::readNode(&node, pointer, page->btr_header.pag_flags, true); impure->irsb_nav_length = node.prefix + node.length; - -#ifdef SCROLLABLE_CURSORS - // ensure that if we are going backward, there is an expanded page - if (direction == RSE_get_backward && !window->win_expanded_buffer) - NAV_expand_index(window, 0); - - // now find our current location on the expanded page - if (expanded_node && (expanded_page = window->win_expanded_buffer)) { - *expanded_node = find_current(expanded_page, page, pointer); - } -#endif } -#ifdef SCROLLABLE_CURSORS - else if (direction == RSE_get_backward) - { - expanded_page = NAV_expand_index(window, 0); - pointer = BTR_last_node(page, expanded_page, expanded_node); - } -#endif else { - pointer = BTreeNode::getPointerFirstNode(page); - -#ifdef SCROLLABLE_CURSORS - if (expanded_node && (expanded_page = window->win_expanded_buffer)) { - *expanded_node = (btree_exp*) expanded_page->exp_nodes; - } - else { - *expanded_node = NULL; - } -#endif } return pointer; diff --git a/src/jrd/nav_proto.h b/src/jrd/nav_proto.h index 7fe63d8efa..458b8dfcf5 100644 --- a/src/jrd/nav_proto.h +++ b/src/jrd/nav_proto.h @@ -36,11 +36,7 @@ namespace Jrd { struct irsb_nav; } -#ifdef SCROLLABLE_CURSORS -exp_index_buf* NAV_expand_index(Jrd::win*, Jrd::irsb_nav*); -#endif -bool NAV_get_record(Jrd::thread_db* tdbb, Jrd::RecordSource*, Jrd::irsb_nav*, - Jrd::record_param*, Jrd::rse_get_mode); +bool NAV_get_record(Jrd::thread_db* tdbb, Jrd::RecordSource*, Jrd::irsb_nav*, Jrd::record_param*); #endif // JRD_NAV_PROTO_H diff --git a/src/jrd/nod.h b/src/jrd/nod.h index 4f1f58bc0d..c7f35ead1e 100644 --- a/src/jrd/nod.h +++ b/src/jrd/nod.h @@ -111,7 +111,6 @@ NODE(nod_asn_list, asn_list, "") NODE(nod_asb, AggregateSort, "") NODE(nod_relation, relation, "") NODE(nod_rse, RecordSelExpr, "") - NODE(nod_seek, seek, "") NODE(nod_sort, sort, "") NODE(nod_union, union, "") NODE(nod_aggregate, aggregate, "") diff --git a/src/jrd/opt.cpp b/src/jrd/opt.cpp index 8e1ebb431b..cf8ab5a5bf 100644 --- a/src/jrd/opt.cpp +++ b/src/jrd/opt.cpp @@ -130,12 +130,7 @@ static RecordSource* gen_first(thread_db*, OptimizerBlk*, RecordSource*, jrd_nod static void gen_join(thread_db*, OptimizerBlk*, const UCHAR*, RiverStack&, jrd_nod**, jrd_nod**, jrd_nod*); static RecordSource* gen_navigation(thread_db*, OptimizerBlk*, USHORT, jrd_rel*, VaryingString*, index_desc*, jrd_nod**); -#ifdef SCROLLABLE_CURSORS -static RecordSource* gen_nav_rsb(thread_db*, OptimizerBlk*, USHORT, jrd_rel*, VaryingString*, - index_desc*, rse_get_mode); -#else static RecordSource* gen_nav_rsb(thread_db*, OptimizerBlk*, USHORT, jrd_rel*, VaryingString*, index_desc*); -#endif static RecordSource* gen_outer(thread_db*, OptimizerBlk*, RecordSelExpr*, RiverStack&, jrd_nod**, jrd_nod**); static RecordSource* gen_procedure(thread_db*, OptimizerBlk*, jrd_nod*); static RecordSource* gen_residual_boolean(thread_db*, OptimizerBlk*, RecordSource*); @@ -4527,13 +4522,7 @@ static RecordSource* gen_navigation(thread_db* tdbb, } // check to see if the fields in the sort match the fields in the index - // in the exact same order--we used to check for ascending/descending prior - // to SCROLLABLE_CURSORS, but now descending sorts can use ascending indices - // and vice versa. -#ifdef SCROLLABLE_CURSORS - rse_get_mode mode; - rse_get_mode last_mode = RSE_get_next; -#endif + // in the exact same order index_desc::idx_repeat* idx_tail = idx->idx_rpt; jrd_nod** ptr = sort->nod_arg; @@ -4559,30 +4548,12 @@ static RecordSource* gen_navigation(thread_db* tdbb, (temp == rse_nulls_last && !ptr[sort->nod_count]))) || // for ODS10 and earlier indices always placed nulls at the end of dataset (dbb->dbb_ods_version < ODS_VERSION11 && temp == rse_nulls_first) -#ifndef SCROLLABLE_CURSORS || (ptr[sort->nod_count] && !(idx->idx_flags & idx_descending)) - || (!ptr[sort->nod_count] && (idx->idx_flags & idx_descending)) -#endif - ) + || (!ptr[sort->nod_count] && (idx->idx_flags & idx_descending))) { return NULL; } -#ifdef SCROLLABLE_CURSORS - // determine whether we ought to navigate backwards or forwards through - // the index--we can't allow navigating one index in two different directions - // on two different fields at the same time! - mode = ((ptr[sort->nod_count] && !(idx->idx_flags & idx_descending)) || - (!ptr[sort->nod_count] && (idx->idx_flags & idx_descending))) ? - RSE_get_backward : RSE_get_forward; - if (last_mode == RSE_get_next) { - last_mode = mode; - } - else if (last_mode != mode) { - return NULL; - } -#endif - dsc desc; CMP_get_desc(tdbb, opt->opt_csb, node, &desc); @@ -4603,21 +4574,13 @@ static RecordSource* gen_navigation(thread_db* tdbb, // a navigational rsb for it. *sort_ptr = NULL; idx->idx_runtime_flags |= idx_navigate; - return gen_nav_rsb(tdbb, opt, stream, relation, alias, idx -#ifdef SCROLLABLE_CURSORS - , mode -#endif - ); + return gen_nav_rsb(tdbb, opt, stream, relation, alias, idx); } static RecordSource* gen_nav_rsb(thread_db* tdbb, OptimizerBlk* opt, - USHORT stream, jrd_rel* relation, VaryingString* alias, index_desc* idx -#ifdef SCROLLABLE_CURSORS - , rse_get_mode mode -#endif - ) + USHORT stream, jrd_rel* relation, VaryingString* alias, index_desc* idx) { /************************************** * @@ -4644,15 +4607,6 @@ static RecordSource* gen_nav_rsb(thread_db* tdbb, rsb->rsb_arg[RSB_NAV_index] = (RecordSource*) OPT_make_index(tdbb, opt, relation, idx); rsb->rsb_arg[RSB_NAV_key_length] = (RecordSource*) (IPTR) key_length; -#ifdef SCROLLABLE_CURSORS - // indicate that the index needs to be navigated in a mirror-image - // fashion; that when the user wants to go backwards we actually go - // forwards and vice versa - if (mode == RSE_get_backward) { - rsb->rsb_flags |= rsb_descending; - } -#endif - const USHORT size = OPT_nav_rsb_size(rsb, key_length, 0); rsb->rsb_impure = CMP_impure(opt->opt_csb, size); return rsb; diff --git a/src/jrd/par.cpp b/src/jrd/par.cpp index 2db8b08bd4..8159eb34de 100644 --- a/src/jrd/par.cpp +++ b/src/jrd/par.cpp @@ -2415,19 +2415,6 @@ static jrd_nod* par_rse(thread_db* tdbb, CompilerScratch* csb, SSHORT rse_op) rse->rse_writelock = true; break; -#ifdef SCROLLABLE_CURSORS - /* if a receive is seen here, then it is intended to be an asynchronous - receive which can happen at any time during the scope of the RecordSelExpr-- - this is intended to be a more efficient mechanism for scrolling through - a record stream, to prevent having to send a message to the engine - for each record */ - - case blr_receive: - csb->csb_blr_reader.seekBackward(1); - rse->rse_async_message = PAR_parse_node(tdbb, csb, STATEMENT); - break; -#endif - default: if (op == (UCHAR) blr_end) { @@ -3038,12 +3025,15 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected) node->nod_arg[e_for_stall] = PAR_parse_node(tdbb, csb, STATEMENT); if (csb->csb_blr_reader.peekByte() == (UCHAR) blr_rse || - csb->csb_blr_reader.peekByte() == (UCHAR) blr_singular) + csb->csb_blr_reader.peekByte() == (UCHAR) blr_singular || + csb->csb_blr_reader.peekByte() == (UCHAR) blr_scrollable) { node->nod_arg[e_for_re] = PAR_parse_node(tdbb, csb, TYPE_RSE); } else + { node->nod_arg[e_for_re] = par_rse(tdbb, csb, blr_operator); + } node->nod_arg[e_for_statement] = PAR_parse_node(tdbb, csb, sub_type); break; @@ -3070,11 +3060,11 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected) case blr_cursor_open: case blr_cursor_close: break; + case blr_cursor_fetch_scroll: + node->nod_arg[e_cursor_stmt_scroll_op] = PAR_parse_node(tdbb, csb, VALUE); + node->nod_arg[e_cursor_stmt_scroll_val] = PAR_parse_node(tdbb, csb, VALUE); + // FALL INTO case blr_cursor_fetch: -#ifdef SCROLLABLE_CURSORS - if (csb->csb_blr_reader.peekByte() == blr_seek) - node->nod_arg[e_cursor_stmt_seek] = PAR_parse_node(tdbb, csb, STATEMENT); -#endif csb->csb_g_flags |= csb_reuse_context; node->nod_arg[e_cursor_stmt_into] = PAR_parse_node(tdbb, csb, STATEMENT); csb->csb_g_flags &= ~csb_reuse_context; @@ -3094,6 +3084,11 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected) ((RecordSelExpr*) node)->nod_flags |= rse_singular; break; + case blr_scrollable: + node = PAR_parse_node(tdbb, csb, TYPE_RSE); + ((RecordSelExpr*) node)->nod_flags |= rse_scrollable; + break; + case blr_relation: case blr_rid: case blr_relation2: @@ -3381,13 +3376,6 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected) node->nod_arg[e_stat_default] = PAR_parse_node(tdbb, csb, VALUE); break; -#ifdef SCROLLABLE_CURSORS - case blr_seek: - node->nod_arg[e_seek_direction] = PAR_parse_node(tdbb, csb, VALUE); - node->nod_arg[e_seek_offset] = PAR_parse_node(tdbb, csb, VALUE); - break; -#endif - case blr_init_variable: { n = csb->csb_blr_reader.getWord(); diff --git a/src/jrd/req.h b/src/jrd/req.h index 17160dda80..a31cafc30f 100644 --- a/src/jrd/req.h +++ b/src/jrd/req.h @@ -231,9 +231,6 @@ public: //vec* req_variables; // Vector of variables, if any CVC: UNUSED ResourceList req_resources; // Resources (relations and indices) jrd_nod* req_message; // Current message for send/receive -#ifdef SCROLLABLE_CURSORS - jrd_nod* req_async_message; // Asynchronous message (used in scrolling) -#endif jrd_prc* req_procedure; // procedure, if any Firebird::MetaName req_trg_name; // name of request (trigger), if any //USHORT req_length; // message length for send/receive @@ -338,11 +335,7 @@ const size_t REQ_SIZE = sizeof(jrd_req) - sizeof(jrd_req::blk_repeat_type); const ULONG req_active = 0x1L; const ULONG req_stall = 0x2L; const ULONG req_leave = 0x4L; -#ifdef SCROLLABLE_CURSORS -const ULONG req_async_processing= 0x8L; -#endif const ULONG req_null = 0x10L; -//const ULONG req_broken = 0x20L; const ULONG req_abort = 0x40L; const ULONG req_internal = 0x80L; const ULONG req_warning = 0x100L; diff --git a/src/jrd/rse.cpp b/src/jrd/rse.cpp index fc245eac09..aaf086c430 100644 --- a/src/jrd/rse.cpp +++ b/src/jrd/rse.cpp @@ -87,26 +87,12 @@ static void close_merge(thread_db*, RecordSource*, irsb_mrg*); static void close_procedure(thread_db*, RecordSource*); static SSHORT compare(thread_db*, jrd_nod*, jrd_nod*); static SSHORT compare_longs(const SLONG*, const SLONG*, USHORT); -#ifdef SCROLLABLE_CURSORS -static bool fetch_record(thread_db*, RecordSource*, USHORT, rse_get_mode); -static bool get_merge_join(thread_db*, RecordSource*, irsb_mrg*, rse_get_mode); -static bool get_merge_fetch(thread_db*, RecordSource*, SSHORT, rse_get_mode); -static SLONG get_merge_record(thread_db*, RecordSource*, irsb_mrg::irsb_mrg_repeat*, rse_get_mode); -static UCHAR *get_sort(thread_db*, RecordSource*, rse_get_mode); -static void resynch_merge(thread_db*, RecordSource*, irsb_mrg*, rse_get_mode); -static void unget_sort(thread_db*, RecordSource*, UCHAR *); -#else static bool fetch_record(thread_db*, RecordSource*, USHORT); static bool get_merge_join(thread_db*, RecordSource*, irsb_mrg*); static bool get_merge_fetch(thread_db*, RecordSource*, SSHORT); static SLONG get_merge_record(thread_db*, RecordSource*, irsb_mrg::irsb_mrg_repeat *); static UCHAR *get_sort(thread_db*, RecordSource*); -#endif -#ifdef SCROLLABLE_CURSORS -static bool fetch_left(thread_db*, RecordSource*, IRSB, rse_get_mode); -#else static bool fetch_left(thread_db*, RecordSource*, IRSB); -#endif static UCHAR* get_merge_data(thread_db*, merge_file*, SLONG); static bool get_procedure(thread_db*, RecordSource*, irsb_procedure*, record_param*); static bool get_union(thread_db*, RecordSource*, IRSB); @@ -272,7 +258,7 @@ void RSE_close(thread_db* tdbb, RecordSource* rsb) } -bool RSE_get_record(thread_db* tdbb, RecordSource* rsb, rse_get_mode mode) +bool RSE_get_record(thread_db* tdbb, RecordSource* rsb) { /************************************** * @@ -282,7 +268,6 @@ bool RSE_get_record(thread_db* tdbb, RecordSource* rsb, rse_get_mode mode) * * Functional description * External entrypoint for RSE_internal_get_record(). - * Handle the "stickiness" of directionality. * Check whether we need to count records * retrieved at the top level of the rsb tree. * @@ -291,18 +276,6 @@ bool RSE_get_record(thread_db* tdbb, RecordSource* rsb, rse_get_mode mode) jrd_req* request = tdbb->getRequest(); IRSB impure = (IRSB) ((UCHAR*) request + rsb->rsb_impure); -#ifdef SCROLLABLE_CURSORS -/* The mode RSE_get_next is a generic mode which requests that - we continue on in the last direction we were going. Oblige - by converting the mode to the appropriate direction. */ - - if (mode == RSE_get_next) - { - mode = (impure->irsb_flags & irsb_last_backwards) ? RSE_get_backward : RSE_get_forward; - } - request->req_flags &= ~req_fetch_required; -#endif - impure->irsb_flags |= irsb_eof; /* Turn off the flag so that records at a @@ -312,7 +285,7 @@ bool RSE_get_record(thread_db* tdbb, RecordSource* rsb, rse_get_mode mode) request->req_flags &= ~req_count_records; bool result; - while ( (result = RSE_internal_get_record(tdbb, rsb, NULL, mode)) ) + while ( (result = RSE_internal_get_record(tdbb, rsb, NULL)) ) { if (rsb->rsb_flags & rsb_writelock) { @@ -322,14 +295,17 @@ bool RSE_get_record(thread_db* tdbb, RecordSource* rsb, rse_get_mode mode) RecordSource* table_rsb = rsb; // Skip nodes without streams - while (table_rsb->rsb_type == rsb_boolean || table_rsb->rsb_type == rsb_sort || - table_rsb->rsb_type == rsb_first || table_rsb->rsb_type == rsb_skip) + while (table_rsb->rsb_type == rsb_boolean || + table_rsb->rsb_type == rsb_sort || + table_rsb->rsb_type == rsb_first || + table_rsb->rsb_type == rsb_skip) { table_rsb = table_rsb->rsb_next; } // Raise error if we cannot lock this kind of stream - if (table_rsb->rsb_type != rsb_sequential && table_rsb->rsb_type != rsb_indexed && + if (table_rsb->rsb_type != rsb_sequential && + table_rsb->rsb_type != rsb_indexed && table_rsb->rsb_type != rsb_navigate) { ERR_post(Arg::Gds(isc_record_lock_not_supp)); @@ -417,12 +393,6 @@ void RSE_open(thread_db* tdbb, RecordSource* rsb) case rsb_navigate: case rsb_sequential: -#ifdef SCROLLABLE_CURSORS - if (rsb->rsb_type == rsb_navigate) { - impure->irsb_flags |= irsb_bof; - impure->irsb_flags &= ~irsb_eof; - } -#endif if (rsb->rsb_type == rsb_sequential) { Database* dbb = tdbb->getDatabase(); @@ -462,10 +432,6 @@ void RSE_open(thread_db* tdbb, RecordSource* rsb) return; case rsb_sort: -#ifdef SCROLLABLE_CURSORS - impure->irsb_flags |= irsb_bof; - impure->irsb_flags &= ~irsb_eof; -#endif // dimitr: we can avoid reading and sorting the entire // record set, if there's actually nothing to return if (first_records) { @@ -727,11 +693,7 @@ static SSHORT compare_longs(const SLONG* p, const SLONG* q, USHORT count) } -static bool fetch_record(thread_db* tdbb, RecordSource* rsb, USHORT n -#ifdef SCROLLABLE_CURSORS - , rse_get_mode mode -#endif - ) +static bool fetch_record(thread_db* tdbb, RecordSource* rsb, USHORT n) { /************************************** * @@ -753,13 +715,7 @@ static bool fetch_record(thread_db* tdbb, RecordSource* rsb, USHORT n RecordSource* sub_rsb = rsb->rsb_arg[n]; - if (RSE_internal_get_record(tdbb, sub_rsb, NULL -#ifdef SCROLLABLE_CURSORS - , mode -#else - , RSE_get_forward -#endif - )) + if (RSE_internal_get_record(tdbb, sub_rsb, NULL)) { return true; } @@ -771,23 +727,13 @@ static bool fetch_record(thread_db* tdbb, RecordSource* rsb, USHORT n while (true) { RSE_close(tdbb, sub_rsb); - if (n == 0 || !fetch_record(tdbb, rsb, n - 1 -#ifdef SCROLLABLE_CURSORS - , mode -#endif - )) + if (n == 0 || !fetch_record(tdbb, rsb, n - 1)) { return false; } RSE_open(tdbb, sub_rsb); - if (RSE_internal_get_record(tdbb, sub_rsb, NULL -#ifdef SCROLLABLE_CURSORS - , mode -#else - , RSE_get_forward -#endif - )) + if (RSE_internal_get_record(tdbb, sub_rsb, NULL)) { return true; } @@ -795,164 +741,6 @@ static bool fetch_record(thread_db* tdbb, RecordSource* rsb, USHORT n } -#ifdef SCROLLABLE_CURSORS -static bool fetch_left(thread_db* tdbb, RecordSource* rsb, IRSB impure, rse_get_mode mode) -{ -/************************************** - * - * f e t c h _ l e f t ( I B _ V 4 _ 1 ) - * - ************************************** - * - * Functional description - * Get records for a left outer join. Records are read - * from the left sub-stream when the right sub-stream is - * dry or when it is not yet open. When the left - * sub-stream's boolean is true, open the right sub-stream - * and read a record. When the right sub-stream becomes dry, - * close it, and if nothing has been joined to the left - * sub-stream's current record, join a null valued right - * sub-stream record. When the left sub-stream is dry, - * the outer join is finished, so return false. - * - **************************************/ - SET_TDBB(tdbb); - - fb_assert(rsb->rsb_type == rsb_left_cross); - -/* loop through the outer join in either the forward or the backward direction; - the various modes indicate what state of the join we are in */ - - while (true) - { - if (!(impure->irsb_flags & irsb_join_full)) - { - /* mustread indicates to get the next record from the outer stream */ - - if (impure->irsb_flags & irsb_mustread) - { - if (!RSE_internal_get_record(tdbb, rsb->rsb_arg[RSB_LEFT_outer], NULL, mode)) - { - if (mode == RSE_get_backward) - return false; - - if (!rsb->rsb_left_inner_streams) - return false; - - /* We have a full outer join. Open up the inner stream - one more time. */ - - RSE_close(tdbb, rsb->rsb_arg[RSB_LEFT_outer]); - impure->irsb_flags |= irsb_join_full; - RSE_open(tdbb, rsb->rsb_arg[RSB_LEFT_inner]); - continue; - } - - /* check if the outer record qualifies for the boolean */ - - if (rsb->rsb_arg[RSB_LEFT_boolean] && - !EVL_boolean(tdbb, (jrd_nod*) rsb->rsb_arg[RSB_LEFT_boolean])) - { - /* The boolean pertaining to the left sub-stream is false - so just join sub-stream to a null valued right sub-stream */ - join_to_nulls(tdbb, rsb->rsb_left_streams); - return true; - } - - impure->irsb_flags &= ~(irsb_mustread | irsb_joined); - impure->irsb_flags |= irsb_in_opened; - RSE_open(tdbb, rsb->rsb_arg[RSB_LEFT_inner]); - } - - /* fetch records from the inner stream until exhausted */ - - while (RSE_internal_get_record(tdbb, rsb->rsb_arg[RSB_LEFT_inner], NULL, mode)) - { - if (!rsb->rsb_arg[RSB_LEFT_inner_boolean] || - EVL_boolean(tdbb, (jrd_nod*) rsb->rsb_arg[RSB_LEFT_inner_boolean])) - { - impure->irsb_flags |= irsb_joined; - return true; - } - } - - /* out of inner records, go back to reading the next outer record */ - - RSE_close(tdbb, rsb->rsb_arg[RSB_LEFT_inner]); - impure->irsb_flags |= irsb_mustread; - - /* The right stream did not have any matching records. Join - the left stream to a null valued right sub-stream */ - - if (!(impure->irsb_flags & irsb_joined)) { - join_to_nulls(tdbb, rsb->rsb_left_streams); - return true; - } - } - else - { - /* Continue with a full outer join. */ - - RecordSource* full = rsb->rsb_arg[RSB_LEFT_inner]; - full = (full->rsb_type == rsb_boolean) ? full->rsb_next : full; - - if (impure->irsb_flags & irsb_in_opened) - { - /* The inner stream was opened at some point. If it doesn't have a - boolean, then all of its records have been returned. Otherwise, - find the records that haven't been. */ - bool found; - do { - if (!RSE_internal_get_record(tdbb, full, NULL, mode)) { - if (mode == RSE_get_forward) - return false; - - goto return_to_outer; - } - - RSE_open(tdbb, rsb->rsb_arg[RSB_LEFT_outer]); - while (found = RSE_internal_get_record(tdbb, rsb->rsb_arg[RSB_LEFT_outer], NULL, mode)) - { - if ( - (!rsb->rsb_arg[RSB_LEFT_boolean] || - EVL_boolean(tdbb, (jrd_nod*) rsb->rsb_arg[RSB_LEFT_boolean])) && - (!rsb->rsb_arg[RSB_LEFT_inner_boolean] || - EVL_boolean(tdbb, (jrd_nod*) rsb->rsb_arg[RSB_LEFT_inner_boolean])) && - (full == rsb->rsb_arg[RSB_LEFT_inner] || - EVL_boolean(tdbb, (jrd_nod*) rsb->rsb_arg[RSB_LEFT_inner]->rsb_arg[0]))) - { - break; - } - } - RSE_close(tdbb, rsb->rsb_arg[RSB_LEFT_outer]); - } while (found); - } - else if (!RSE_internal_get_record(tdbb, full, NULL, mode)) - { - if (mode == RSE_get_forward) - return false; - - goto return_to_outer; - } - - join_to_nulls(tdbb, rsb->rsb_left_inner_streams); - return true; - -return_to_outer: - impure->irsb_flags &= ~(irsb_join_full | irsb_in_opened); - impure->irsb_flags |= irsb_mustread; - RSE_close(tdbb, rsb->rsb_arg[RSB_LEFT_inner]); - RSE_close(tdbb, rsb->rsb_arg[RSB_LEFT_outer]); - RSE_open(tdbb, rsb->rsb_arg[RSB_LEFT_outer]); - } - } - -/* NOTREACHED */ - return true; -} -#else - - static bool fetch_left(thread_db* tdbb, RecordSource* rsb, IRSB impure) { /************************************** @@ -981,7 +769,7 @@ static bool fetch_left(thread_db* tdbb, RecordSource* rsb, IRSB impure) { if (impure->irsb_flags & irsb_mustread) { - if (!RSE_internal_get_record(tdbb, rsb->rsb_arg[RSB_LEFT_outer], NULL, RSE_get_forward)) + if (!RSE_internal_get_record(tdbb, rsb->rsb_arg[RSB_LEFT_outer], NULL)) { if (rsb->rsb_left_inner_streams->isEmpty()) return false; @@ -1007,7 +795,7 @@ static bool fetch_left(thread_db* tdbb, RecordSource* rsb, IRSB impure) RSE_open(tdbb, rsb->rsb_arg[RSB_LEFT_inner]); } - while (RSE_internal_get_record(tdbb, rsb->rsb_arg[RSB_LEFT_inner], NULL, RSE_get_forward)) + while (RSE_internal_get_record(tdbb, rsb->rsb_arg[RSB_LEFT_inner], NULL)) { if (!rsb->rsb_arg[RSB_LEFT_inner_boolean] || EVL_boolean(tdbb, (jrd_nod*) rsb->rsb_arg[RSB_LEFT_inner_boolean])) @@ -1041,10 +829,10 @@ static bool fetch_left(thread_db* tdbb, RecordSource* rsb, IRSB impure) find the records that haven't been. */ bool found; do { - if (!RSE_internal_get_record(tdbb, full, NULL, RSE_get_forward)) + if (!RSE_internal_get_record(tdbb, full, NULL)) return false; RSE_open(tdbb, rsb->rsb_arg[RSB_LEFT_outer]); - while ( (found = RSE_internal_get_record(tdbb, rsb->rsb_arg[RSB_LEFT_outer], NULL, RSE_get_forward)) ) + while ( (found = RSE_internal_get_record(tdbb, rsb->rsb_arg[RSB_LEFT_outer], NULL)) ) { if ((!rsb->rsb_arg[RSB_LEFT_boolean] || EVL_boolean(tdbb, (jrd_nod*) rsb->rsb_arg[RSB_LEFT_boolean])) && @@ -1059,14 +847,13 @@ static bool fetch_left(thread_db* tdbb, RecordSource* rsb, IRSB impure) RSE_close(tdbb, rsb->rsb_arg[RSB_LEFT_outer]); } while (found); } - else if (!RSE_internal_get_record(tdbb, full, NULL, RSE_get_forward)) + else if (!RSE_internal_get_record(tdbb, full, NULL)) return false; join_to_nulls(tdbb, rsb->rsb_left_inner_streams); return true; } -#endif static UCHAR *get_merge_data(thread_db* tdbb, merge_file* mfb, SLONG record) @@ -1094,101 +881,6 @@ static UCHAR *get_merge_data(thread_db* tdbb, merge_file* mfb, SLONG record) } -#ifdef SCROLLABLE_CURSORS -static bool get_merge_fetch(thread_db* tdbb, - RecordSource* rsb, SSHORT stream, rse_get_mode mode) -{ -/************************************** - * - * g e t _ m e r g e _ f e t c h ( I B _ V 4 _ 1 ) - * - ************************************** - * - * Functional description - * Cycle through all the records of equal key - * in all the substreams of a sort-merge. - * - **************************************/ - SET_TDBB(tdbb); - - irsb_mrg* impure = (irsb_mrg*) ((UCHAR*) tdbb->getRequest() + rsb->rsb_impure); - irsb_mrg::irsb_mrg_repeat* tail = impure->irsb_mrg_rpt + stream; - const SSHORT m = tail->irsb_mrg_order; - tail = impure->irsb_mrg_rpt + m; - RecordSource* sub_rsb = rsb->rsb_arg[2 * m]; - -/* go forward or backward to the next record */ - - SLONG record = tail->irsb_mrg_equal_current; - - if (((mode == RSE_get_backward) && !(impure->irsb_flags & irsb_backwards)) || - ((mode == RSE_get_forward) && (impure->irsb_flags & irsb_backwards))) - { - --record; - } - else - ++record; -//} CVC: Misplaced ending brace - -/* if there is a record waiting for us, use it; - otherwise proceed recursively from right to left - through the substreams, getting the next record - in the equality group */ - - if (record < tail->irsb_mrg_equal || record > tail->irsb_mrg_equal_end) - { - /* if we get to the first stream and there is no next record, - we have exhausted the equality group, so return */ - - if (stream == 0) - { - /* in the case where we are stepping off the end of the equivalence - group in a direction other than the direction in which we entered - it, we have a problem; the sort streams are positioned at the other - end of the equivalence group, so we need to resynch them */ - - if (((mode == RSE_get_backward) && !(impure->irsb_flags & irsb_backwards)) || - ((mode == RSE_get_forward) && (impure->irsb_flags & irsb_backwards))) - { - resynch_merge(tdbb, rsb, impure, mode); - } - - return false; - } - - /* we have exhausted the equivalent records in this stream, - so get the next record in the next leftmost stream */ - - if (!get_merge_fetch(tdbb, rsb, stream - 1, mode)) - return false; - - /* we are incrementing (or decrementing) the next leftmost stream, - so we need to start at the beginning (or end) of this stream - (and recursively all the streams to the right of this one) */ - - if (((mode == RSE_get_backward) && !(impure->irsb_flags & irsb_backwards)) || - ((mode == RSE_get_forward) && (impure->irsb_flags & irsb_backwards))) - { - record = tail->irsb_mrg_equal_end; - } - else - record = tail->irsb_mrg_equal; - } - - /* indicate the last record fetched */ - - tail->irsb_mrg_equal_current = record; - - /* copy out the data from this sort merge block to the - current record in the record parameter block */ - - merge_file* mfb = &tail->irsb_mrg_file; - map_sort_data(tdbb, tdbb->getRequest(), (SortMap*) sub_rsb->rsb_arg[0], - get_merge_data(tdbb, mfb, record)); - - return true; -} -#else static bool get_merge_fetch(thread_db* tdbb, RecordSource* rsb, SSHORT stream) { /************************************** @@ -1227,218 +919,8 @@ static bool get_merge_fetch(thread_db* tdbb, RecordSource* rsb, SSHORT stream) return true; } -#endif -#ifdef SCROLLABLE_CURSORS -static bool get_merge_join(thread_db* tdbb, - RecordSource* rsb, irsb_mrg* impure, rse_get_mode mode) -{ -/************************************** - * - * g e t _ m e r g e _ j o i n - * - ************************************** - * - * Functional description - * Get the next tuple from a sort/merge join. - * - **************************************/ - SET_TDBB(tdbb); - jrd_req* request = tdbb->getRequest(); - const RecordSource* const* const end = rsb->rsb_arg + rsb->rsb_count * 2; - -/* If there is a group of equivalent records already formed, - fetch the next record from it */ - - if (get_merge_fetch(tdbb, rsb, rsb->rsb_count - 1, mode)) - return true; - -/* We are done with the current equivalence group, - so we need to generate a new one. If backwards - is specified, we will fetch all the records in - the backward direction, so the backwards flag indicates - that all the equivalent records were fetched in the - backward direction. This will effectively reverse the - direction we traverse the equivalent records in response - to a scroll request. */ - - if (mode == RSE_get_backward) - impure->irsb_flags |= irsb_backwards; - else - impure->irsb_flags &= ~irsb_backwards; - -/* Increment (or decrement) each stream one record. If any comes - up dry, we are at the end. */ - - RecordSource** ptr; - RecordSource** highest_ptr = rsb->rsb_arg; - irsb_mrg::irsb_mrg_repeat* tail; - for (ptr = rsb->rsb_arg, tail = impure->irsb_mrg_rpt; ptr < end; ptr += 2, tail++) - { - RecordSource* sort_rsb = *ptr; - SortMap* map = (SortMap*) sort_rsb->rsb_arg[0]; - merge_file* mfb = &tail->irsb_mrg_file; - - /* reset equality group record positions */ - - tail->irsb_mrg_equal = 0; - tail->irsb_mrg_equal_current = 0; - tail->irsb_mrg_equal_end = 0; - - /* If there is a record waiting, use it. Otherwise get another */ - - SLONG record = tail->irsb_mrg_last_fetched; - if (record >= 0) - { - tail->irsb_mrg_last_fetched = -1; - const UCHAR* const last_data = get_merge_data(tdbb, mfb, record); - mfb->mfb_current_block = 0; - UCHAR* const first_data = get_merge_data(tdbb, mfb, 0); - if (first_data != last_data) - memcpy(first_data, last_data, map->smb_length); - mfb->mfb_equal_records = 1; - record = 0; - } - else - { - mfb->mfb_current_block = 0; - mfb->mfb_equal_records = 0; - if ((record = get_merge_record(tdbb, sort_rsb, tail, mode)) < 0) - return false; - } - - /* Map data into target records and do comparison */ - - map_sort_data(tdbb, request, map, get_merge_data(tdbb, mfb, record)); - const int result = compare(tdbb, (jrd_nod*) highest_ptr[1], (jrd_nod*) ptr[1]); - if (ptr != highest_ptr) - { - if (((result > 0) && (impure->irsb_flags & irsb_backwards)) || - ((result < 0) && ~(impure->irsb_flags & irsb_backwards))) - { - highest_ptr = ptr; - } - } - } - -/* Loop thru the streams advancing each up to (or down to) the target value. - If any exceeds the target value, there is no match so start over. */ - - for (;;) - { - for (ptr = rsb->rsb_arg, tail = impure->irsb_mrg_rpt; ptr < end; ptr += 2, tail++) - { - if (highest_ptr != ptr) - { - int result; - while (result = compare(tdbb, (jrd_nod*) highest_ptr[1], (jrd_nod*) ptr[1])) - { - if (((result > 0) && (impure->irsb_flags & irsb_backwards)) || - ((result < 0) && ~(impure->irsb_flags & irsb_backwards))) - { - highest_ptr = ptr; - goto recycle; - } - RecordSource* sort_rsb = *ptr; - merge_file* mfb = &tail->irsb_mrg_file; - mfb->mfb_current_block = 0; - mfb->mfb_equal_records = 0; - - /* get the new record, which is both the beginning and end of - the equal queue for the moment */ - - const SLONG record = get_merge_record(tdbb, sort_rsb, tail, mode); - if (record < 0) - return false; - map_sort_data(tdbb, request, (SortMap*) sort_rsb->rsb_arg[0], - get_merge_data(tdbb, mfb, record)); - } - } - } - - break; - recycle:; - } - -/* Finally compute equality group for each stream in sort/merge */ - - for (ptr = rsb->rsb_arg, tail = impure->irsb_mrg_rpt; ptr < end; ptr += 2, tail++) - { - RecordSource* sort_rsb = *ptr; - SortMap* map = (SortMap*) sort_rsb->rsb_arg[0]; - merge_file* mfb = &tail->irsb_mrg_file; - Firebird::HalfStaticArray key; - ULONG* const first_data = key.getBuffer(map->smb_key_length); - const ULONG key_length = map->smb_key_length * sizeof(ULONG); - memcpy(first_data, get_merge_data(tdbb, mfb, 0), key_length); - - SLONG record; - while ((record = get_merge_record(tdbb, sort_rsb, tail, mode)) >= 0) - { - if (compare_longs((const SLONG*) first_data, - (const SLONG*) get_merge_data(tdbb, mfb, record), - map->smb_key_length)) - { - tail->irsb_mrg_last_fetched = record; - break; - } - - tail->irsb_mrg_equal_end = record; - } - - if (mfb->mfb_current_block) - write_merge_block(tdbb, mfb, mfb->mfb_current_block); - } - -/* Optimize cross product of equivalence groups by ordering the streams - from left (outermost) to right (innermost) by descending cardinality - of merge blocks. This ordering will vary for each set of equivalence - groups and cannot be statically assigned by the optimizer. */ - - typedef Firebird::Stack ImrStack; - ImrStack best_tails; - - tail = impure->irsb_mrg_rpt; - for (const irsb_mrg::irsb_mrg_repeat* const tail_end = tail + rsb->rsb_count; - tail < tail_end; tail++) - { - ULONG most_blocks = 0; - irsb_mrg::irsb_mrg_repeat* best_tail = NULL; - for (irsb_mrg::irsb_mrg_repeat* tail2 = impure->irsb_mrg_rpt; tail2 < tail_end; tail2++) - { - ImrStack::iterator stack(best_tails); - for (; stack.hasData(); ++stack) - { - if (stack.object() == tail2) - { - break; - } - } - if (stack.hasData()) { - continue; - } - merge_file* mfb = &tail2->irsb_mrg_file; - ULONG blocks = mfb->mfb_equal_records / mfb->mfb_blocking_factor; - if (++blocks > most_blocks) { - most_blocks = blocks; - best_tail = tail2; - } - } - - best_tails.push(best_tail); - tail->irsb_mrg_order = best_tail - impure->irsb_mrg_rpt; - } - - /* - while (best_tails) { - LLS_POP(&best_tails); - } - */ - - return true; -} -#else static bool get_merge_join(thread_db* tdbb, RecordSource* rsb, irsb_mrg* impure) { /************************************** @@ -1622,15 +1104,10 @@ static bool get_merge_join(thread_db* tdbb, RecordSource* rsb, irsb_mrg* impure) return true; } -#endif static SLONG get_merge_record(thread_db* tdbb, - RecordSource* rsb, irsb_mrg::irsb_mrg_repeat * impure -#ifdef SCROLLABLE_CURSORS -, rse_get_mode mode -#endif - ) + RecordSource* rsb, irsb_mrg::irsb_mrg_repeat * impure) { /************************************** * @@ -1645,11 +1122,7 @@ static SLONG get_merge_record(thread_db* tdbb, **************************************/ SET_TDBB(tdbb); - UCHAR* sort_data = get_sort(tdbb, rsb -#ifdef SCROLLABLE_CURSORS - , mode -#endif - ); + UCHAR* sort_data = get_sort(tdbb, rsb); if (!sort_data) return -1; @@ -1670,12 +1143,6 @@ static SLONG get_merge_record(thread_db* tdbb, memcpy(merge_data, sort_data, map->smb_length); ++mfb->mfb_equal_records; -#ifdef SCROLLABLE_CURSORS -/* fix up the sort data in case we need to retrieve it again */ - - unget_sort(tdbb, rsb, sort_data); -#endif - return record; } @@ -1770,8 +1237,7 @@ static bool get_procedure(thread_db* tdbb, bool RSE_internal_get_record(thread_db* tdbb, RecordSource* rsb, - RecordSource* parent_rsb, - rse_get_mode mode) + RecordSource* parent_rsb) { /************************************** * @@ -1781,9 +1247,6 @@ bool RSE_internal_get_record(thread_db* tdbb, * * Functional description * Get a record from an open record stream. - * The mode parameter specifies whether to - * go forward one record, go backward one - * record, or fetch the current record. * **************************************/ SET_TDBB(tdbb); @@ -1810,34 +1273,10 @@ bool RSE_internal_get_record(thread_db* tdbb, record_param* rpb = &request->req_rpb[rsb->rsb_stream]; -#ifdef SCROLLABLE_CURSORS -/* do bof and eof handling for streams which may be navigated */ - - if (rsb->rsb_type == rsb_sequential || rsb->rsb_type == rsb_navigate || rsb->rsb_type == rsb_sort) - { - if (((mode == RSE_get_forward) && (impure->irsb_flags & irsb_eof)) || - ((mode == RSE_get_backward) && (impure->irsb_flags & irsb_bof))) - { - return false; - } - } -#endif - switch (rsb->rsb_type) { case rsb_sequential: -#ifdef SCROLLABLE_CURSORS - if (impure->irsb_flags & irsb_bof) - { - rpb->rpb_number.setValue(BOF_NUMBER); - } -#endif - - if (!VIO_next_record(tdbb, rpb, /*rsb,*/ request->req_transaction, request->req_pool, -#ifdef SCROLLABLE_CURSORS - (mode == RSE_get_backward), -#endif - false)) + if (!VIO_next_record(tdbb, rpb, /*rsb,*/ request->req_transaction, request->req_pool, false)) { rpb->rpb_number.setValid(false); return false; @@ -1857,9 +1296,7 @@ bool RSE_internal_get_record(thread_db* tdbb, bool result = false; // NS: Original code was the following: - // while (SBM_next(*bitmap, &rpb->rpb_number, mode)) - // We assume mode = RSE_get_forward because we do not support - // scrollable cursors at the moment. + // while (SBM_next(*bitmap, &rpb->rpb_number)) if (rpb->rpb_number.isBof() ? bitmap->getFirst() : bitmap->getNext()) { do @@ -1868,8 +1305,7 @@ bool RSE_internal_get_record(thread_db* tdbb, #ifdef SUPERSERVER_V2 /* Prefetch next set of data pages from bitmap. */ - if (rpb->rpb_number > ((irsb_index*) impure)->irsb_prefetch_number && - (mode == RSE_get_forward)) + if (rpb->rpb_number > ((irsb_index*) impure)->irsb_prefetch_number) { ((irsb_index*) impure)->irsb_prefetch_number = DPM_prefetch_bitmap(tdbb, rpb->rpb_relation, *bitmap, rpb->rpb_number); @@ -1894,13 +1330,7 @@ bool RSE_internal_get_record(thread_db* tdbb, } case rsb_navigate: -#ifdef SCROLLABLE_CURSORS - if (impure->irsb_flags & irsb_bof) - { - rpb->rpb_number.setValue(BOF_NUMBER); - } -#endif - if (!NAV_get_record(tdbb, rsb, (IRSB_NAV) impure, rpb, mode)) + if (!NAV_get_record(tdbb, rsb, (IRSB_NAV) impure, rpb)) { rpb->rpb_number.setValid(false); return false; @@ -1962,7 +1392,7 @@ bool RSE_internal_get_record(thread_db* tdbb, any_null = false; any_true = false; - while (RSE_internal_get_record(tdbb, rsb->rsb_next, rsb, mode)) + while (RSE_internal_get_record(tdbb, rsb->rsb_next, rsb)) { if (EVL_boolean(tdbb, (jrd_nod*) rsb->rsb_arg[0])) { @@ -2024,7 +1454,7 @@ bool RSE_internal_get_record(thread_db* tdbb, ANY is true */ result = false; - while (RSE_internal_get_record(tdbb, rsb->rsb_next, rsb, mode)) + while (RSE_internal_get_record(tdbb, rsb->rsb_next, rsb)) { if (EVL_boolean(tdbb, (jrd_nod*) rsb->rsb_arg[0])) { result = true; @@ -2053,7 +1483,7 @@ bool RSE_internal_get_record(thread_db* tdbb, NOT ALL is true */ any_false = false; - while (RSE_internal_get_record(tdbb, rsb->rsb_next, rsb, mode)) + while (RSE_internal_get_record(tdbb, rsb->rsb_next, rsb)) { request->req_flags &= ~req_null; @@ -2102,7 +1532,7 @@ bool RSE_internal_get_record(thread_db* tdbb, ALL is true */ any_false = false; - while (RSE_internal_get_record(tdbb, rsb->rsb_next, rsb, mode)) + while (RSE_internal_get_record(tdbb, rsb->rsb_next, rsb)) { request->req_flags &= ~req_null; @@ -2144,7 +1574,7 @@ bool RSE_internal_get_record(thread_db* tdbb, bool flag = false; result = false; - while (RSE_internal_get_record(tdbb, rsb->rsb_next, rsb, mode)) + while (RSE_internal_get_record(tdbb, rsb->rsb_next, rsb)) { if (EVL_boolean(tdbb, (jrd_nod*) rsb->rsb_arg[0])) { result = true; @@ -2180,95 +1610,33 @@ bool RSE_internal_get_record(thread_db* tdbb, *******/ case rsb_first: - switch (mode) + if (((irsb_first_n*) impure)->irsb_count <= 0) { - case RSE_get_forward: - if (((irsb_first_n*) impure)->irsb_count <= 0) - { - invalidate_child_rpbs(tdbb, rsb); - return false; - } - ((irsb_first_n*) impure)->irsb_count--; - if (!RSE_internal_get_record(tdbb, rsb->rsb_next, NULL, mode)) - return false; - break; - -#ifdef SCROLLABLE_CURSORS - case RSE_get_current: - if (((irsb_first_n*) impure)->irsb_count <= 0) - { - invalidate_child_rpbs(tdbb, rsb); - return false; - } - if (!RSE_internal_get_record(tdbb, rsb->rsb_next, NULL, mode)) - return false; - break; - - case RSE_get_backward: - ((irsb_first_n*) impure)->irsb_count++; - if (!RSE_internal_get_record(tdbb, rsb->rsb_next, NULL, mode)) - return false; - break; -#endif + invalidate_child_rpbs(tdbb, rsb); + return false; } + ((irsb_first_n*) impure)->irsb_count--; + if (!RSE_internal_get_record(tdbb, rsb->rsb_next, NULL)) + return false; break; case rsb_skip: { irsb_skip_n* skip = (irsb_skip_n*) impure; - switch (mode) - { -#ifdef SCROLLABLE_CURSORS - case RSE_get_backward: - if (skip->irsb_count > 0) - { - invalidate_child_rpbs(tdbb, rsb); - return false; - } - if (skip->irsb_count == 0) - { - skip->irsb_count++; - if (RSE_internal_get_record(tdbb, rsb->rsb_next, NULL, mode)) - invalidate_child_rpbs(tdbb, rsb); - return false; - } - skip->irsb_count++; - if (!RSE_internal_get_record(tdbb, rsb->rsb_next, NULL, mode)) - return false; - break; - - case RSE_get_current: - if (skip->irsb_count >= 1) - { - invalidate_child_rpbs(tdbb, rsb); - return false; - } - if (!RSE_internal_get_record(tdbb, rsb->rsb_next, NULL, mode)) - return false; - break; -#endif - - case RSE_get_forward: - while (skip->irsb_count > 1) { - skip->irsb_count--; - if (!RSE_internal_get_record(tdbb, rsb->rsb_next, NULL, mode)) - return false; - } + while (skip->irsb_count > 1) { skip->irsb_count--; - if (!RSE_internal_get_record(tdbb, rsb->rsb_next, NULL, mode)) + if (!RSE_internal_get_record(tdbb, rsb->rsb_next, NULL)) return false; - break; } + skip->irsb_count--; + if (!RSE_internal_get_record(tdbb, rsb->rsb_next, NULL)) + return false; } break; case rsb_merge: - if (!get_merge_join(tdbb, rsb, (irsb_mrg*) impure -#ifdef SCROLLABLE_CURSORS - , mode -#endif - )) + if (!get_merge_join(tdbb, rsb, (irsb_mrg*) impure)) { return false; } @@ -2286,35 +1654,12 @@ bool RSE_internal_get_record(thread_db* tdbb, case rsb_sort: { UCHAR* data; - -#ifdef SCROLLABLE_CURSORS - /* any attempt to get a record takes us off of bof or eof */ - - impure->irsb_flags &= ~(irsb_bof | irsb_eof); -#endif - - if (!(data = get_sort(tdbb, rsb -#ifdef SCROLLABLE_CURSORS - , mode -#endif - ))) + if (!(data = get_sort(tdbb, rsb))) { -#ifdef SCROLLABLE_CURSORS - if (mode == RSE_get_forward) - impure->irsb_flags |= irsb_eof; - else - impure->irsb_flags |= irsb_bof; -#endif return false; } map_sort_data(tdbb, request, (SortMap*) rsb->rsb_arg[0], data); - -#ifdef SCROLLABLE_CURSORS - /* fix up the sort data in case we need to retrieve it again */ - - unget_sort(tdbb, rsb, data); -#endif } break; @@ -2323,11 +1668,7 @@ bool RSE_internal_get_record(thread_db* tdbb, for (USHORT i = 0; i < rsb->rsb_count; i++) { RSE_open(tdbb, rsb->rsb_arg[i]); - if (!fetch_record(tdbb, rsb, i -#ifdef SCROLLABLE_CURSORS - , mode -#endif - )) + if (!fetch_record(tdbb, rsb, i)) { return false; } @@ -2342,11 +1683,7 @@ bool RSE_internal_get_record(thread_db* tdbb, if (rsb->rsb_flags & rsb_project) { - if (!fetch_record(tdbb, rsb, 0 -#ifdef SCROLLABLE_CURSORS - , mode -#endif - )) + if (!fetch_record(tdbb, rsb, 0)) { return false; } @@ -2358,11 +1695,7 @@ bool RSE_internal_get_record(thread_db* tdbb, else if (rsb->rsb_count == 0) return false; - else if (!fetch_record(tdbb, rsb, rsb->rsb_count - 1 -#ifdef SCROLLABLE_CURSORS - , mode -#endif - )) + else if (!fetch_record(tdbb, rsb, rsb->rsb_count - 1)) { return false; } @@ -2408,11 +1741,7 @@ bool RSE_internal_get_record(thread_db* tdbb, break; case rsb_left_cross: - if (!fetch_left(tdbb, rsb, impure -#ifdef SCROLLABLE_CURSORS - , mode -#endif - )) + if (!fetch_left(tdbb, rsb, impure)) { return false; } @@ -2437,7 +1766,7 @@ bool RSE_internal_get_record(thread_db* tdbb, { push_rpbs(tdbb, request, rsb); impure->irsb_flags |= irsb_checking_singular; - if (RSE_internal_get_record(tdbb, rsb, parent_rsb, mode)) { + if (RSE_internal_get_record(tdbb, rsb, parent_rsb)) { impure->irsb_flags &= ~irsb_checking_singular; ERR_post(Arg::Gds(isc_sing_select_err)); } @@ -2450,11 +1779,7 @@ bool RSE_internal_get_record(thread_db* tdbb, } -static UCHAR *get_sort(thread_db* tdbb, RecordSource* rsb -#ifdef SCROLLABLE_CURSORS - , rse_get_mode mode -#endif - ) +static UCHAR *get_sort(thread_db* tdbb, RecordSource* rsb) { /************************************** * @@ -2476,11 +1801,7 @@ static UCHAR *get_sort(thread_db* tdbb, RecordSource* rsb ran out of records. This is known in the trade as "end of file." */ ULONG* data = 0; -#ifdef SCROLLABLE_CURSORS - SORT_get(tdbb, impure->irsb_sort_handle, &data, mode); -#else SORT_get(tdbb, impure->irsb_sort_handle, &data); -#endif return reinterpret_cast(data); } @@ -2503,7 +1824,7 @@ static bool get_union(thread_db* tdbb, RecordSource* rsb, IRSB impure) /* March thru the sub-streams (tributaries?) looking for a record */ - while (!RSE_internal_get_record(tdbb, *rsb_ptr, NULL, RSE_get_forward)) + while (!RSE_internal_get_record(tdbb, *rsb_ptr, NULL)) { RSE_close(tdbb, *rsb_ptr); impure->irsb_count += 2; @@ -2907,7 +2228,7 @@ static void open_sort(thread_db* tdbb, RecordSource* rsb, irsb_sort* impure) //, dsc to, temp; - while (RSE_internal_get_record(tdbb, rsb->rsb_next, NULL, RSE_get_forward)) + while (RSE_internal_get_record(tdbb, rsb->rsb_next, NULL)) { records++; @@ -3433,67 +2754,6 @@ static void restore_record(record_param* rpb) } -#ifdef SCROLLABLE_CURSORS -static void resynch_merge(thread_db* tdbb, - RecordSource* rsb, irsb_mrg* impure, rse_get_mode mode) -{ -/************************************** - * - * r e s y n c h _ m e r g e - * - ************************************** - * - * Functional description - * We are in trouble because we stepped off - * an equivalence group in a direction different - * than that which we entered it. We need to - * "back up" each substream by an amount equal - * to the number of records in the grouping. - * - **************************************/ - SET_TDBB(tdbb); - jrd_req* request = tdbb->getRequest(); - - const RecordSource* const* const end = rsb->rsb_arg + rsb->rsb_count * 2; - RecordSource** ptr = rsb->rsb_arg; - for (irsb_mrg::irsb_mrg_repeat* tail = impure->irsb_mrg_rpt; ptr < end; ptr += 2, tail++) - { - RecordSource* sort_rsb = *ptr; - merge_file* mfb = &tail->irsb_mrg_file; - - /* increment (or decrement) past each record in the substream - which has been stored in the merge equivalence group; assume - the actual count is one less, unless an additional record - was stored in the "last_fetched" field */ - - SLONG records = mfb->mfb_equal_records; - if (records) - --records; - - for (; records; --records) - { - /* failure of this operation should never happen, - but if it does give an error */ - - UCHAR* data = get_sort(tdbb, sort_rsb, mode); - if (!data) - ERR_post(Arg::Gds(isc_stream_eof)); - - /* do an "unget" to fix up the sort record for re-retrieval */ - - unget_sort(tdbb, sort_rsb, data); - } - - /* null out the "last fetched" record, since this is not the - next record we want to retrieve anymore--we are headed in - the opposite direction */ - - tail->irsb_mrg_last_fetched = -1; - } -} -#endif - - static void save_record(thread_db* tdbb, record_param* rpb) { /************************************** @@ -3534,32 +2794,6 @@ static void save_record(thread_db* tdbb, record_param* rpb) } -#ifdef SCROLLABLE_CURSORS -static void unget_sort(thread_db* tdbb, RecordSource* rsb, UCHAR* data) -{ -/************************************** - * - * u n g e t _ s o r t - * - ************************************** - * - * Functional description - * Fix up the sort data in case we need to re-retrieve - * it. This was initiated because of the need to navigate - * through the sort, and the fact that retrieving the sort - * data is destructive to the sort data (diddles it). - * - **************************************/ - SET_TDBB(tdbb); - jrd_req* request = tdbb->getRequest(); - - irsb_sort* impure = (irsb_sort*) ((UCHAR *) request + rsb->rsb_impure); - - SORT_diddle_key(data, impure->irsb_sort_handle, true); -} -#endif - - static void write_merge_block(thread_db* tdbb, merge_file* mfb, ULONG block) { /************************************** @@ -3691,7 +2925,7 @@ bool RSBRecurse::get(thread_db* tdbb, RecordSource* rsb, irsb_recurse* irsb) // Get the data -- if there is none go back one level and when // there isn't a previous level, we're done - while (!RSE_internal_get_record(tdbb, *rsb_ptr, NULL, RSE_get_forward)) + while (!RSE_internal_get_record(tdbb, *rsb_ptr, NULL)) { if (irsb->irsb_level == 1) { diff --git a/src/jrd/rse.h b/src/jrd/rse.h index 153dbc677a..08bc057144 100644 --- a/src/jrd/rse.h +++ b/src/jrd/rse.h @@ -121,11 +121,10 @@ public: // bits for the rsb_flags field const USHORT rsb_singular = 1; // singleton select, expect 0 or 1 records -//const USHORT rsb_stream_type = 2; // rsb is for stream type request, PC_ENGINE -const USHORT rsb_descending = 4; // an ascending index is being used for a descending sort or vice versa -const USHORT rsb_project = 8; // projection on this stream is requested -const USHORT rsb_writelock = 16; // records should be locked for writing -const USHORT rsb_recursive = 32; // this rsb is a sub_rsb of recursive rsb +const USHORT rsb_scrollable = 2; // scrollable cursor +const USHORT rsb_project = 4; // projection on this stream is requested +const USHORT rsb_writelock = 8; // records should be locked for writing +const USHORT rsb_recursive = 16; // this rsb is a sub_rsb of recursive rsb // special argument positions within the RecordSource @@ -298,23 +297,12 @@ const ULONG irsb_first = 1; const ULONG irsb_joined = 2; // set in left join when current record has been joined to something const ULONG irsb_mustread = 4; // set in left join when must read a record from left stream const ULONG irsb_open = 8; // indicated rsb is open -#ifdef SCROLLABLE_CURSORS -const ULONG irsb_backwards = 16; // backwards navigation has been performed on this stream -#endif -const ULONG irsb_in_opened = 32; // set in outer join when inner stream has been opened -const ULONG irsb_join_full = 64; // set in full join when left join has completed -const ULONG irsb_checking_singular = 128; // fetching to verify singleton select -const ULONG irsb_singular_processed = 256; // singleton stream already delivered one record -#ifdef SCROLLABLE_CURSORS -const ULONG irsb_last_backwards = 512; // rsb was last scrolled in the backward direction -const ULONG irsb_bof = 1024; // rsb is at beginning of stream -const ULONG irsb_eof = 2048; // rsb is at end of stream -#endif -const ULONG irsb_key_changed = 4096; // key has changed since record last returned from rsb -// The below flag duplicates the one from the disabled SCROLLABLE_CURSORS -// implementation, but it's used slightly differently (at the top RSB levels). -// To be renamed if the SCROLLABLE_CURSORS code will ever be enabled. -const ULONG irsb_eof = 8192; // rsb is at end of stream +const ULONG irsb_in_opened = 16; // set in outer join when inner stream has been opened +const ULONG irsb_join_full = 32; // set in full join when left join has completed +const ULONG irsb_checking_singular = 64; // fetching to verify singleton select +const ULONG irsb_singular_processed = 128; // singleton stream already delivered one record +const ULONG irsb_key_changed = 256; // key has changed since record last returned from rsb +const ULONG irsb_eof = 512; // rsb is at end of stream // Sort map block @@ -462,22 +450,6 @@ public: UCHAR riv_streams[1]; // actual streams }; - -// types for navigating through a stream - -enum rse_get_mode -{ - RSE_get_forward -#ifdef SCROLLABLE_CURSORS - , - RSE_get_backward, - RSE_get_current, - RSE_get_first, - RSE_get_last, - RSE_get_next -#endif -}; - } //namespace Jrd #endif // JRD_RSE_H diff --git a/src/jrd/rse_proto.h b/src/jrd/rse_proto.h index 742d979799..7409791a62 100644 --- a/src/jrd/rse_proto.h +++ b/src/jrd/rse_proto.h @@ -34,9 +34,8 @@ namespace Jrd { } void RSE_close(Jrd::thread_db*, Jrd::RecordSource*); -bool RSE_get_record(Jrd::thread_db*, Jrd::RecordSource*, Jrd::rse_get_mode); -bool RSE_internal_get_record(Jrd::thread_db*, Jrd::RecordSource*, Jrd::RecordSource*, - Jrd::rse_get_mode); +bool RSE_get_record(Jrd::thread_db*, Jrd::RecordSource*); +bool RSE_internal_get_record(Jrd::thread_db*, Jrd::RecordSource*, Jrd::RecordSource*); void RSE_open(Jrd::thread_db*, Jrd::RecordSource*); #endif // JRD_RSE_PROTO_H diff --git a/src/jrd/scroll_cursors.h b/src/jrd/scroll_cursors.h deleted file mode 100644 index 6c0a106a6f..0000000000 --- a/src/jrd/scroll_cursors.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * MODULE: scroll_cursors.h - * DESCRIPTION: OSRI entrypoints and defines for SCROLLABLE_CURSORS - * - * The contents of this file are subject to the Interbase Public - * License Version 1.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy - * of the License at http://www.Inprise.com/IPL.html - * - * Software distributed under the License is distributed on an - * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express - * or implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code was created by Inprise Corporation - * and its predecessors. Portions created by Inprise Corporation are - * Copyright (C) Inprise Corporation. - * - * All Rights Reserved. - * Contributor(s): ______________________________________. - */ - -#ifndef JRD_SCROLL_CURSORS_H -#define JRD_SCROLL_CURSORS_H - -/* ALL THE FOLLOWING DEFINITIONS HAVE BEEN TAKEN OUT OF JRD/IBASE.H - WHEN SCROLLABLE_CURSORS ARE TOTALLY IMPLEMENTED, THE FOLLOWING - DEFINITIONS NEED TO BE PUT IN THE PROPER INCLUDE FILE. - - This was done so that IB 5.0 customers do not see any functions - they are not supposed to see. - As per Engg. team's decision on 23-Sep-1997 -*/ - -#ifdef SCROLLABLE_CURSORS -ISC_STATUS ISC_EXPORT isc_dsql_fetch2(ISC_STATUS *, - isc_stmt_handle *, - unsigned short, - XSQLDA *, - unsigned short, signed long); -#endif - -#ifdef SCROLLABLE_CURSORS -ISC_STATUS ISC_EXPORT isc_dsql_fetch2_m(ISC_STATUS*, - isc_stmt_handle*, - unsigned short, - const char*, - unsigned short, - unsigned short, - char*, - unsigned short, signed long); -#endif - -#ifdef SCROLLABLE_CURSORS -ISC_STATUS ISC_EXPORT isc_embed_dsql_fetch2(ISC_STATUS*, - char*, - unsigned short, - XSQLDA*, - unsigned short, signed long); -#endif - -#ifdef SCROLLABLE_CURSORS -ISC_STATUS ISC_EXPORT isc_receive2(ISC_STATUS *, - isc_req_handle *, - short, - short, - void *, - short, unsigned short, unsigned long); -#endif - -/****** Add the following commented lines in the #else part of.. -#else __cplusplus || __STDC__ -ISC_STATUS ISC_EXPORT isc_receive2(); -******/ - -/****************************************/ -/* Scroll direction for isc_dsql_fetch2 */ -/****************************************/ - -const int isc_fetch_next = 0; -const int isc_fetch_prior = 1; -const int isc_fetch_first = 2; -const int isc_fetch_last = 3; -const int isc_fetch_absolute = 4; -const int isc_fetch_relative = 5; - -#endif /* JRD_SCROLL_CURSORS_H */ diff --git a/src/jrd/sort.cpp b/src/jrd/sort.cpp index 2daf07657d..b6895098c9 100644 --- a/src/jrd/sort.cpp +++ b/src/jrd/sort.cpp @@ -124,12 +124,8 @@ static ULONG high_key[] = MAX_ULONG, MAX_ULONG, MAX_ULONG, MAX_ULONG, MAX_ULONG, MAX_ULONG, MAX_ULONG, MAX_ULONG }; -#ifdef SCROLLABLE_CURSORS -static sort_record* get_merge(merge_control*, sort_context*, rse_get_mode); -#else static void diddle_key(UCHAR*, sort_context*, bool); static sort_record* get_merge(merge_control*, sort_context*); -#endif static ULONG allocate_memory(sort_context*, ULONG, ULONG, bool); static void init(sort_context*); @@ -157,355 +153,6 @@ static void check_file(const sort_context*, const run_control*); static const char* const SCRATCH = "fb_sort_"; -#ifdef SCROLLABLE_CURSORS -#ifdef WORDS_BIGENDIAN -void SORT_diddle_key(UCHAR* record, sort_context* scb, bool direction) -{ -/************************************** - * - * S O R T _ d i d d l e _ k e y ( n o n - V A X ) - * - ************************************** - * - * Functional description - * Perform transformation between the natural form of a record - * and a form that can be sorted in unsigned comparison order. - * - * direction - true for SORT_put() and false for SORT_get() - * - **************************************/ - const sort_key_def* key = scb->scb_description; - for (const sort_key_def* const end = key + scb->scb_keys; key < end; key++) - { - UCHAR* p = record + key->skd_offset; - USHORT n = key->skd_length; - bool complement = key->skd_flags & SKD_descending; - - switch (key->skd_dtype) - { - case SKD_ulong: - case SKD_ushort: - case SKD_bytes: - break; - - // Stash embedded control info for non-fixed data types in the sort - // record and zap it so that it doesn't interfere with collation - - case SKD_varying: - if (direction) - { - USHORT& vlen = ((vary*) p)->vary_length; - if (!(scb->scb_flags & scb_sorted)) - { - *((USHORT*) (record + key->skd_vary_offset)) = vlen; - const UCHAR fill_char = (key->skd_flags & SKD_binary) ? 0 : ASCII_SPACE; - UCHAR* fill_pos = p + sizeof(USHORT) + vlen; - const USHORT fill = n - sizeof(USHORT) - vlen; - if (fill) - memset(fill_pos, fill_char, fill); - } - vlen = 0; - } - break; - - case SKD_cstring: - if (direction) - { - const UCHAR fill_char = (key->skd_flags & SKD_binary) ? 0 : ASCII_SPACE; - if (!(scb->scb_flags & scb_sorted)) - { - const USHORT l = strlen(reinterpret_cast(p)); - *((USHORT*) (record + key->skd_vary_offset)) = l; - UCHAR* fill_pos = p + l; - const USHORT fill = n - l; - if (fill) - memset(fill_pos, fill_char, fill); - } - else - { - const USHORT l = *((USHORT*) (record + key->skd_vary_offset)); - *(p + l) = fill_char; - } - } - break; - - case SKD_text: - break; - - case SKD_float: - case SKD_double: - { - const USHORT flag = (direction || !complement) ? (direction ? TRUE : FALSE) : TRUE; - if (flag ^ (*p >> 7)) - *p ^= 1 << 7; - else - complement = !complement; - break; - } - - case SKD_long: - case SKD_short: - case SKD_quad: - case SKD_timestamp1: - case SKD_timestamp2: - case SKD_sql_time: - case SKD_sql_date: - case SKD_int64: - *p ^= 1 << 7; - break; - - default: - fb_assert(false); - break; - } - if (complement && n) - do { - *p++ ^= -1; - } while (--n); - - // Flatter but don't complement control info for non-fixed - // data types when restoring the data - - if (key->skd_dtype == SKD_varying && !direction) - { - p = record + key->skd_offset; - ((vary*) p)->vary_length = *((USHORT*) (record + key->skd_vary_offset)); - } - - if (key->skd_dtype == SKD_cstring && !direction) - { - p = record + key->skd_offset; - const USHORT l = *((USHORT*) (record + key->skd_vary_offset)); - *(p + l) = 0; - } - } -} - - -#else -void SORT_diddle_key(UCHAR* record, sort_context* scb, bool direction) -{ -/************************************** - * - * S O R T _ d i d d l e _ k e y ( V A X ) - * - ************************************** - * - * Functional description - * Perform transformation between the natural form of a record - * and a form that can be sorted in unsigned comparison order. - * - * direction - true for SORT_put() and false for SORT_get() - * - **************************************/ - UCHAR c1; - SSHORT longs, flag; - ULONG lw; - - const sort_key_def* key = scb->scb_description; - for (const sort_key_def* const end = key + scb->scb_keys; key < end; key++) - { - BLOB_PTR* p = (BLOB_PTR*) record + key->skd_offset; - USHORT* wp = (USHORT*) p; - SORTP* lwp = (SORTP*) p; - bool complement = key->skd_flags & SKD_descending; - USHORT n = ROUNDUP(key->skd_length, sizeof(SLONG)); - - switch (key->skd_dtype) - { - case SKD_timestamp1: - case SKD_timestamp2: - case SKD_sql_date: - case SKD_sql_time: - p[3] ^= 1 << 7; - break; - - case SKD_ulong: - case SKD_ushort: - break; - - case SKD_text: - case SKD_bytes: - case SKD_cstring: - case SKD_varying: - - // Stash embedded control info for non-fixed data types in the sort - // record and zap it so that it doesn't interfere with collation - - if (key->skd_dtype == SKD_varying && direction) - { - USHORT& vlen = ((vary*) p)->vary_length; - if (!(scb->scb_flags & scb_sorted)) - { - *((USHORT*) (record + key->skd_vary_offset)) = vlen; - const UCHAR fill_char = (key->skd_flags & SKD_binary) ? 0 : ASCII_SPACE; - UCHAR* fill_pos = p + sizeof(USHORT) + vlen; - const USHORT fill = n - sizeof(USHORT) - vlen; - if (fill) - memset(fill_pos, fill_char, fill); - } - vlen = 0; - } - - if (key->skd_dtype == SKD_cstring && direction) - { - const UCHAR fill_char = (key->skd_flags & SKD_binary) ? 0 : ASCII_SPACE; - if (!(scb->scb_flags & scb_sorted)) - { - const USHORT l = strlen(reinterpret_cast(p)); - *((USHORT*) (record + key->skd_vary_offset)) = l; - UCHAR* fill_pos = p + l; - const USHORT fill = n - l; - if (fill) - memset(fill_pos, fill_char, fill); - } - else - { - USHORT l = *((USHORT*) (record + key->skd_vary_offset)); - *(p + l) = fill_char; - } - } - - longs = n >> SHIFTLONG; - while (--longs >= 0) - { - c1 = p[3]; - p[3] = *p; - *p++ = c1; - c1 = p[1]; - p[1] = *p; - *p = c1; - p += 3; - } - p = (BLOB_PTR*) wp; - break; - - case SKD_short: - p[1] ^= 1 << 7; - break; - - case SKD_long: - p[3] ^= 1 << 7; - break; - - case SKD_quad: - p[7] ^= 1 << 7; - break; - - case SKD_int64: - - // INT64's fit in TWO LONGS, and hence the SWAP has to happen - // here for the right order comparison using DO_32_COMPARE - - if (!direction) - SWAP_LONGS(lwp[0], lwp[1], lw); - - p[7] ^= 1 << 7; - - if (direction) - SWAP_LONGS(lwp[0], lwp[1], lw); - break; - -#ifdef IEEE - case SKD_double: - if (!direction) - { - lw = lwp[0]; - lwp[0] = lwp[1]; - lwp[1] = lw; - } - flag = (direction || !complement) ? direction : TRUE; - if (flag ^ (p[7] >> 7)) - p[7] ^= 1 << 7; - else - complement = !complement; - if (direction) - { - lw = lwp[0]; - lwp[0] = lwp[1]; - lwp[1] = lw; - } - break; - - case SKD_float: - flag = (direction || !complement) ? direction : TRUE; - if (flag ^ (p[3] >> 7)) - p[3] ^= 1 << 7; - else - complement = !complement; - break; - -#else // IEEE - case SKD_double: - w = wp[2]; - wp[2] = wp[3]; - wp[3] = w; - - case SKD_d_float: - case SKD_float: - if (!direction) - { - if (complement) - { - if (p[3] & 1 << 7) - complement = !complement; - else - p[3] ^= 1 << 7; - } - else - { - if (p[3] & 1 << 7) - p[3] ^= 1 << 7; - else - complement = !complement; - } - } - w = wp[0]; - wp[0] = wp[1]; - wp[1] = w; - if (direction) - { - if (p[3] & 1 << 7) - complement = !complement; - else - p[3] ^= 1 << 7; - } - break; -#endif // IEEE - - default: - fb_assert(false); - break; - } - - if (complement && n) - { - do { - *p++ ^= -1; - } while (--n); - } - - // Flatter but don't complement control info for non-fixed - // data types when restoring the data - - if (key->skd_dtype == SKD_varying && !direction) - { - p = (BLOB_PTR*) record + key->skd_offset; - ((vary*) p)->vary_length = *((USHORT*) (record + key->skd_vary_offset)); - } - - if (key->skd_dtype == SKD_cstring && !direction) - { - p = (BLOB_PTR*) record + key->skd_offset; - USHORT l = *((USHORT*) (record + key->skd_vary_offset)); - *(p + l) = 0; - } - } -} -#endif -#endif - - void SORT_fini(sort_context* scb) { /************************************** @@ -571,99 +218,6 @@ void SORT_fini(sort_context* scb) } -#ifdef SCROLLABLE_CURSORS -void SORT_get(thread_db* tdbb, sort_context* scb, ULONG** record_address, rse_get_mode mode) -{ -/************************************** - * - * S O R T _ g e t ( I B _ V 4 _ 1 ) - * - ************************************** - * - * Functional description - * Get a record from sort (in order, of course). - * The address of the record is returned in - * If the stream is exhausted, SORT_get puts NULL in . - * - **************************************/ - sort_record* record = NULL; - - // If there were runs, get the records from the merge - // tree. Otherwise everything fit in memory. - - if (scb->scb_merge) - record = get_merge(scb->scb_merge, scb, mode); - else - switch (mode) - { - case RSE_get_forward: - if (scb->scb_flags & scb_initialized) - scb->scb_flags &= ~scb_initialized; - - while (true) - { - if (scb->scb_next_pointer > scb->scb_last_pointer) - { - record = NULL; - break; - } - if (record = *scb->scb_next_pointer++) - break; - } - break; - - case RSE_get_backward: - if (scb->scb_flags & scb_initialized) - { - scb->scb_flags &= ~scb_initialized; - scb->scb_next_pointer = scb->scb_last_pointer + 1; - } - else - { - // By definition, the next pointer is on the next record, - // so we have to go back one to get to the last fetched record. - // This is easier than changing the sense of the next pointer. - - scb->scb_next_pointer--; - if (scb->scb_next_pointer <= scb->scb_first_pointer + 1) - { - record = NULL; - scb->scb_next_pointer++; - break; - } - } - - while (true) - { - scb->scb_next_pointer--; - if (scb->scb_next_pointer <= scb->scb_first_pointer) - { - record = NULL; - scb->scb_next_pointer++; - break; - } - if (record = *scb->scb_next_pointer) - break; - } - - // Reset next pointer to one greater than the last fetched - - scb->scb_next_pointer++; - break; - - default: - fb_assert(FALSE); - break; - } - - if (record) - SORT_diddle_key((UCHAR*) record->sort_record_key, scb, false); - - *record_address = (ULONG*) record; - - tdbb->bumpStats(RuntimeStatistics::SORT_GETS); -} -#else void SORT_get(thread_db* tdbb, sort_context* scb, ULONG** record_address) { /************************************** @@ -723,7 +277,6 @@ void SORT_get(thread_db* tdbb, sort_context* scb, ULONG** record_address) status.raise(); } } -#endif sort_context* SORT_init(Database* dbb, @@ -884,11 +437,7 @@ void SORT_put(thread_db* tdbb, sort_context* scb, ULONG** record_address) if (record != (SR*) scb->scb_end_memory) { -#ifdef SCROLLABLE_CURSORS - SORT_diddle_key((UCHAR*) (record->sr_sort_record.sort_record_key), scb, true); -#else diddle_key((UCHAR*) (record->sr_sort_record.sort_record_key), scb, true); -#endif } // If there isn't room for the record, sort and write the run. @@ -925,9 +474,7 @@ void SORT_put(thread_db* tdbb, sort_context* scb, ULONG** record_address) // Move key_id into *scb->scb_next_pointer and then // increment scb->scb_next_pointer *scb->scb_next_pointer++ = reinterpret_cast(record->sr_sort_record.sort_record_key); -#ifndef SCROLLABLE_CURSORS scb->scb_records++; -#endif *record_address = (ULONG*) record->sr_sort_record.sort_record_key; tdbb->bumpStats(RuntimeStatistics::SORT_PUTS); @@ -945,12 +492,7 @@ void SORT_put(thread_db* tdbb, sort_context* scb, ULONG** record_address) } -#ifdef SCROLLABLE_CURSORS -void -#else -FB_UINT64 -#endif -SORT_read_block(TempSpace* tmp_space, FB_UINT64 seek, BLOB_PTR* address, ULONG length) +FB_UINT64 SORT_read_block(TempSpace* tmp_space, FB_UINT64 seek, BLOB_PTR* address, ULONG length) { /************************************** * @@ -964,9 +506,7 @@ SORT_read_block(TempSpace* tmp_space, FB_UINT64 seek, BLOB_PTR* address, ULONG l **************************************/ const size_t bytes = tmp_space->read(seek, address, length); fb_assert(bytes == length); -#ifndef SCROLLABLE_CURSORS return seek + bytes; -#endif } @@ -993,11 +533,7 @@ void SORT_sort(thread_db* tdbb, sort_context* scb) { if (scb->scb_last_record != (SR*) scb->scb_end_memory) { -#ifdef SCROLLABLE_CURSORS - SORT_diddle_key((UCHAR*) KEYOF(scb->scb_last_record), scb, true); -#else diddle_key((UCHAR*) KEYOF(scb->scb_last_record), scb, true); -#endif } // If there aren't any runs, things fit nicely in memory. Just sort the mess @@ -1005,13 +541,7 @@ void SORT_sort(thread_db* tdbb, sort_context* scb) if (!scb->scb_runs) { sort(scb); -#ifdef SCROLLABLE_CURSORS - scb->scb_last_pointer = scb->scb_next_pointer - 1; -#endif scb->scb_next_pointer = scb->scb_first_pointer + 1; -#ifdef SCROLLABLE_CURSORS - scb->scb_flags |= scb_initialized; -#endif scb->scb_flags |= scb_sorted; tdbb->bumpStats(RuntimeStatistics::SORTS); return; @@ -1212,7 +742,6 @@ FB_UINT64 SORT_write_block(TempSpace* tmp_space, FB_UINT64 seek, BLOB_PTR* addre } -#ifndef SCROLLABLE_CURSORS #ifdef WORDS_BIGENDIAN static void diddle_key(UCHAR* record, sort_context* scb, bool direction) { @@ -1559,14 +1088,9 @@ static void diddle_key(UCHAR* record, sort_context* scb, bool direction) } } #endif -#endif -static sort_record* get_merge(merge_control* merge, sort_context* scb -#ifdef SCROLLABLE_CURSORS - , rse_get_mode mode -#endif - ) +static sort_record* get_merge(merge_control* merge, sort_context* scb) { /************************************** * @@ -1581,11 +1105,7 @@ static sort_record* get_merge(merge_control* merge, sort_context* scb SORTP *p; // no more than 1 SORTP* to a line SORTP *q; // no more than 1 SORTP* to a line ULONG l; -#ifdef SCROLLABLE_CURSORS - ULONG space_available, data_remaining; -#else ULONG n; -#endif sort_record* record = NULL; bool eof = false; @@ -1601,12 +1121,7 @@ static sort_record* get_merge(merge_control* merge, sort_context* scb // check for end-of-file condition in either direction -#ifdef SCROLLABLE_CURSORS - if ((mode == RSE_get_backward && run->run_records >= run->run_max_records - 1) || - (mode == RSE_get_forward && run->run_records == 0)) -#else if (run->run_records == 0) -#endif { record = (sort_record*) - 1; eof = true; @@ -1617,83 +1132,28 @@ static sort_record* get_merge(merge_control* merge, sort_context* scb // Find the appropriate record in the buffer to return -#ifdef SCROLLABLE_CURSORS - if (mode == RSE_get_forward) + if ((record = (sort_record*) run->run_record) < + (sort_record*) run->run_end_buffer) { run->run_record = reinterpret_cast(NEXT_RUN_RECORD(run->run_record)); -#endif - - if ((record = (sort_record*) run->run_record) < - (sort_record*) run->run_end_buffer) - { -#ifndef SCROLLABLE_CURSORS - run->run_record = reinterpret_cast(NEXT_RUN_RECORD(run->run_record)); -#endif - --run->run_records; - continue; - } -#ifndef SCROLLABLE_CURSORS - // There are records remaining, but the buffer is full. - // Read a buffer full. - - l = (ULONG) ((BLOB_PTR*) run->run_end_buffer - (BLOB_PTR*) run->run_buffer); - n = run->run_records * scb->scb_longs * sizeof(ULONG); - l = MIN(l, n); - run->run_seek = - SORT_read_block(scb->scb_space, run->run_seek, (UCHAR*) run->run_buffer, l); -#else - } - else - { - run->run_record = reinterpret_cast(PREV_RUN_RECORD(run->run_record)); - if ((record = (sort_record*) run->run_record) >= - reinterpret_cast(run->run_buffer)) - { - ++run->run_records; - continue; - } - } - - // There are records remaining, but we have stepped over the - // edge of the cache. Read the next buffer full of records. - - fb_assert((BLOB_PTR*) run->run_end_buffer > (BLOB_PTR*) run->run_buffer); - - space_available = (ULONG) ((BLOB_PTR*) run->run_end_buffer - (BLOB_PTR*) run->run_buffer); - if (mode == RSE_get_forward) - data_remaining = run->run_records * scb->scb_longs * sizeof(ULONG); - else - data_remaining = - (run->run_max_records - run->run_records) * scb->scb_longs * sizeof(ULONG); - l = MIN(space_available, data_remaining); - - if (mode == RSE_get_forward) - run->run_seek += run->run_cached; - else - run->run_seek -= l; - - SORT_read_block(scb->scb_space, run->run_seek, (UCHAR*) run->run_buffer, l); - run->run_cached = l; - - if (mode == RSE_get_forward) - { -#endif - record = reinterpret_cast(run->run_buffer); -#ifndef SCROLLABLE_CURSORS - run->run_record = - reinterpret_cast(NEXT_RUN_RECORD(record)); -#endif --run->run_records; -#ifdef SCROLLABLE_CURSORS - } - else - { - record = reinterpret_cast(PREV_RUN_RECORD(run->run_end_buffer)); - ++run->run_records; + continue; } - run->run_record = (sort_record*) record; -#endif + // There are records remaining, but the buffer is full. + // Read a buffer full. + + l = (ULONG) ((BLOB_PTR*) run->run_end_buffer - (BLOB_PTR*) run->run_buffer); + n = run->run_records * scb->scb_longs * sizeof(ULONG); + l = MIN(l, n); + run->run_seek = + SORT_read_block(scb->scb_space, run->run_seek, (UCHAR*) run->run_buffer, l); + + record = reinterpret_cast(run->run_buffer); + run->run_record = + reinterpret_cast(NEXT_RUN_RECORD(record)); + --run->run_records; + continue; } @@ -1766,32 +1226,19 @@ static sort_record* get_merge(merge_control* merge, sort_context* scb if (l == 0 && scb->scb_dup_callback) { -#ifdef SCROLLABLE_CURSORS - SORT_diddle_key((UCHAR*) merge->mrg_record_a, scb, false); - SORT_diddle_key((UCHAR*) merge->mrg_record_b, scb, false); -#else diddle_key((UCHAR*) merge->mrg_record_a, scb, false); diddle_key((UCHAR*) merge->mrg_record_b, scb, false); -#endif + if ((*scb->scb_dup_callback) ((const UCHAR*) merge->mrg_record_a, (const UCHAR*) merge->mrg_record_b, scb->scb_dup_callback_arg)) { merge->mrg_record_a = NULL; -#ifdef SCROLLABLE_CURSORS - SORT_diddle_key((UCHAR*) merge->mrg_record_b, scb, true); -#else diddle_key((UCHAR*) merge->mrg_record_b, scb, true); -#endif continue; } -#ifdef SCROLLABLE_CURSORS - SORT_diddle_key((UCHAR*) merge->mrg_record_a, scb, true); - SORT_diddle_key((UCHAR*) merge->mrg_record_b, scb, true); -#else diddle_key((UCHAR*) merge->mrg_record_a, scb, true); diddle_key((UCHAR*) merge->mrg_record_b, scb, true); -#endif } if (l == 0) @@ -1801,11 +1248,7 @@ static sort_record* get_merge(merge_control* merge, sort_context* scb DO_32_COMPARE(p, q, l); } -#ifdef SCROLLABLE_CURSORS - if (mode == RSE_get_forward && p[-1] < q[-1]) -#else if (p[-1] < q[-1]) -#endif { record = merge->mrg_record_a; merge->mrg_record_a = NULL; @@ -2110,11 +1553,7 @@ static void merge_runs(sort_context* scb, USHORT n) CHECK_FILE2(scb, &temp_run); const sort_record* p; -#ifdef SCROLLABLE_CURSORS - while (p = get_merge(merge, scb, RSE_get_forward)) -#else while ( (p = get_merge(merge, scb)) ) -#endif { if (q >= (sort_record*) temp_run.run_end_buffer) { @@ -2128,9 +1567,6 @@ static void merge_runs(sort_context* scb, USHORT n) } while (--count); ++temp_run.run_records; } -#ifdef SCROLLABLE_CURSORS - temp_run.run_max_records = temp_run.run_records; -#endif // Write the tail of the new run and return any unused space @@ -2153,11 +1589,8 @@ static void merge_runs(sort_context* scb, USHORT n) // Remove run from list of in-use run blocks run = scb->scb_runs; scb->scb_runs = run->run_next; -#ifdef SCROLLABLE_CURSORS - seek = run->run_seek + run->run_cached - run->run_size; -#else seek = run->run_seek - run->run_size; -#endif + // Free the sort file space associated with the run scb->scb_space->releaseSpace(seek, run->run_size); @@ -2546,19 +1979,7 @@ static void put_run(sort_context* scb) // Re-arrange records in physical order so they can be dumped in a single write // operation -#ifdef SCROLLABLE_CURSORS - run->run_records = run->run_max_records = order(scb); - run->run_cached = 0; - - // Write records to scratch file. Keep track of the number of bytes - // written, etc. - - run->run_size = run->run_records * (scb->scb_longs - SIZEOF_SR_BCKPTR_IN_LONGS) * sizeof(ULONG); - run->run_seek = scb->scb_space->allocateSpace(run->run_size); - SORT_write_block(scb->scb_space, run->run_seek, (UCHAR*) scb->scb_last_record, run->run_size); -#else order_and_save(scb); -#endif } @@ -2642,26 +2063,20 @@ static void sort(sort_context* scb) DO_32_COMPARE(p, q, l); if (l == 0) { -#ifdef SCROLLABLE_CURSORS - SORT_diddle_key((UCHAR*) *i, scb, false); - SORT_diddle_key((UCHAR*) *j, scb, false); -#else diddle_key((UCHAR*) *i, scb, false); diddle_key((UCHAR*) *j, scb, false); -#endif + if ((*scb->scb_dup_callback) ((const UCHAR*) *i, (const UCHAR*) *j, scb->scb_dup_callback_arg)) { ((SORTP***) (*i))[BACK_OFFSET] = NULL; *i = NULL; } else -#ifdef SCROLLABLE_CURSORS - SORT_diddle_key((UCHAR*) *i, scb, true); - SORT_diddle_key((UCHAR*) *j, scb, true); -#else + { diddle_key((UCHAR*) *i, scb, true); + } + diddle_key((UCHAR*) *j, scb, true); -#endif } } } diff --git a/src/jrd/sort.h b/src/jrd/sort.h index aabe58af4c..483d9271ba 100644 --- a/src/jrd/sort.h +++ b/src/jrd/sort.h @@ -196,15 +196,9 @@ struct run_control run_merge_hdr run_header; run_control* run_next; // Next (actually last) run ULONG run_records; // Records (remaining) in run -#ifdef SCROLLABLE_CURSORS - ULONG run_max_records; // total number of records in run -#endif USHORT run_depth; // Number of "elementary" runs FB_UINT64 run_seek; // Offset in file of run FB_UINT64 run_size; // Length of run in work file -#ifdef SCROLLABLE_CURSORS - FB_UINT64 run_cached; // amount of cached data from run file -#endif sort_record* run_record; // Next record in run SORTP* run_buffer; // Run buffer SORTP* run_end_buffer; // End of buffer @@ -242,9 +236,6 @@ struct sort_context SR* scb_last_record; // Address of last record sort_record** scb_first_pointer; // Memory for sort sort_record** scb_next_pointer; // Address for next pointer -#ifdef SCROLLABLE_CURSORS - sort_record** scb_last_pointer; // Address for last pointer in block -#endif //USHORT scb_length; // Record length. Unused. USHORT scb_longs; // Length of record in longwords ULONG scb_keys; // Number of keys diff --git a/src/jrd/sort_proto.h b/src/jrd/sort_proto.h index 98e8206098..b522531522 100644 --- a/src/jrd/sort_proto.h +++ b/src/jrd/sort_proto.h @@ -32,15 +32,8 @@ namespace Jrd { class SortOwner; } -#ifdef SCROLLABLE_CURSORS -void SORT_diddle_key(UCHAR*, Jrd::sort_context*, bool); -void SORT_get(Jrd::thread_db*, Jrd::sort_context*, ULONG**, Jrd::rse_get_mode); -void SORT_read_block(TempSpace*, FB_UINT64, BLOB_PTR*, ULONG); -#else void SORT_get(Jrd::thread_db*, Jrd::sort_context*, ULONG**); FB_UINT64 SORT_read_block(TempSpace*, FB_UINT64, BLOB_PTR*, ULONG); -#endif - void SORT_fini(Jrd::sort_context*); Jrd::sort_context* SORT_init(Jrd::Database*, Jrd::SortOwner*, USHORT, USHORT, USHORT, const Jrd::sort_key_def*, diff --git a/src/jrd/validation.cpp b/src/jrd/validation.cpp index 57196a5422..90a5d8cd15 100644 --- a/src/jrd/validation.cpp +++ b/src/jrd/validation.cpp @@ -941,7 +941,6 @@ static void garbage_collect(thread_db* tdbb, vdr* control) // Dump verbose output of all the pages fetched if (VAL_debug_level >= 2) { - // We are assuming RSE_get_forward if (control->vdr_page_bitmap->getFirst()) { do { diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index 5dbae9d064..fdbb96b972 100644 --- a/src/jrd/vio.cpp +++ b/src/jrd/vio.cpp @@ -2454,9 +2454,6 @@ bool VIO_next_record(thread_db* tdbb, //RecordSource* rsb, jrd_tra* transaction, MemoryPool* pool, -#ifdef SCROLLABLE_CURSORS - bool backwards, -#endif bool onepage) { /************************************** @@ -2496,11 +2493,7 @@ bool VIO_next_record(thread_db* tdbb, #endif do { - if (!DPM_next(tdbb, rpb, lock_type, -#ifdef SCROLLABLE_CURSORS - backwards, -#endif - onepage)) + if (!DPM_next(tdbb, rpb, lock_type, onepage)) { return false; } @@ -2948,11 +2941,7 @@ bool VIO_sweep(thread_db* tdbb, jrd_tra* transaction) relation->rel_garbage->clear(); } #endif - while (VIO_next_record(tdbb, &rpb, /*NULL,*/ transaction, 0, -#ifdef SCROLLABLE_CURSORS - false, -#endif - false)) + while (VIO_next_record(tdbb, &rpb, /*NULL,*/ transaction, 0, false)) { CCH_RELEASE(tdbb, &rpb.getWindow(tdbb)); if (relation->rel_flags & REL_deleting) { @@ -4075,11 +4064,7 @@ static THREAD_ENTRY_DECLARE garbage_collector(THREAD_ENTRY_PARAM arg) // Attempt to garbage collect all records on the data page. - while (VIO_next_record(tdbb, &rpb, /*NULL,*/ transaction, NULL, -#ifdef SCROLLABLE_CURSORS - false, -#endif - true)) + while (VIO_next_record(tdbb, &rpb, /*NULL,*/ transaction, NULL, true)) { CCH_RELEASE(tdbb, &rpb.getWindow(tdbb)); diff --git a/src/jrd/vio_proto.h b/src/jrd/vio_proto.h index d698853299..7d5e92be68 100644 --- a/src/jrd/vio_proto.h +++ b/src/jrd/vio_proto.h @@ -57,11 +57,7 @@ void VIO_merge_proc_sav_points(Jrd::thread_db*, Jrd::jrd_tra*, Jrd::Savepoint**) bool VIO_writelock(Jrd::thread_db*, Jrd::record_param*, Jrd::RecordSource*, Jrd::jrd_tra*); void VIO_modify(Jrd::thread_db*, Jrd::record_param*, Jrd::record_param*, Jrd::jrd_tra*); bool VIO_next_record(Jrd::thread_db*, Jrd::record_param*, /*Jrd::RecordSource*,*/ Jrd::jrd_tra*, - MemoryPool*, -#ifdef SCROLLABLE_CURSORS - bool, -#endif - bool); + MemoryPool*, bool); Jrd::Record* VIO_record(Jrd::thread_db*, Jrd::record_param*, const Jrd::Format*, MemoryPool*); void VIO_refetch_record(Jrd::thread_db*, Jrd::record_param*, Jrd::jrd_tra*); void VIO_start_save_point(Jrd::thread_db*, Jrd::jrd_tra*); diff --git a/src/jrd/why.cpp b/src/jrd/why.cpp index 7282be9c39..89c07d93ca 100644 --- a/src/jrd/why.cpp +++ b/src/jrd/why.cpp @@ -96,9 +96,6 @@ #include "../common/classes/FpeControl.h" #include "../jrd/constants.h" #include "../jrd/ThreadStart.h" -#ifdef SCROLLABLE_CURSORS -#include "../jrd/blr.h" -#endif #ifdef HAVE_ERRNO_H #include @@ -1089,11 +1086,6 @@ namespace #define GDS_QUE_EVENTS isc_que_events #define GDS_RECONNECT isc_reconnect_transaction #define GDS_RECEIVE isc_receive - -#ifdef SCROLLABLE_CURSORS -#define GDS_RECEIVE2 isc_receive2 -#endif - #define GDS_RELEASE_REQUEST isc_release_request #define GDS_REQUEST_INFO isc_request_info #define GDS_ROLLBACK isc_rollback_transaction @@ -3155,71 +3147,6 @@ ISC_STATUS API_ROUTINE GDS_DSQL_FETCH(ISC_STATUS* user_status, } -#ifdef SCROLLABLE_CURSORS -ISC_STATUS API_ROUTINE GDS_DSQL_FETCH2(ISC_STATUS* user_status, - FB_API_HANDLE* stmt_handle, - USHORT dialect, - XSQLDA* sqlda, - USHORT direction, - SLONG offset) -{ -/************************************** - * - * i s c _ d s q l _ f e t c h 2 - * - ************************************** - * - * Functional description - * Fetch next record from a dynamic SQL cursor - * - **************************************/ - Status status(user_status); - - try - { - if (!sqlda) - { - status_exception::raise(Arg::Gds(isc_dsql_sqlda_err)); - } - - Statement statement = translate(stmt_handle); - - statement->checkPrepared(); - sqlda_sup& dasup = statement->das; - - USHORT blr_length, msg_type, msg_length; - - if (UTLD_parse_sqlda(status, &dasup, &blr_length, &msg_type, &msg_length, - dialect, sqlda, DASUP_CLAUSE_select)) - { - return status[1]; - } - - ISC_STATUS s = GDS_DSQL_FETCH2_M(status, stmt_handle, blr_length, - dasup.dasup_clauses[DASUP_CLAUSE_select].dasup_blr, - 0, msg_length, - dasup.dasup_clauses[DASUP_CLAUSE_select].dasup_msg, - direction, offset); - if (s && s != 101) - { - return s; - } - - if (UTLD_parse_sqlda(status, &dasup, NULL, NULL, NULL, dialect, sqlda, DASUP_CLAUSE_select)) - { - return status[1]; - } - } - catch (const Exception& e) - { - e.stuff_exception(status); - } - - return status[1]; -} -#endif - - ISC_STATUS API_ROUTINE GDS_DSQL_FETCH_M(ISC_STATUS* user_status, FB_API_HANDLE* stmt_handle, USHORT blr_length, @@ -3248,12 +3175,7 @@ ISC_STATUS API_ROUTINE GDS_DSQL_FETCH_M(ISC_STATUS* user_status, ISC_STATUS s = CALL(PROC_DSQL_FETCH, statement->implementation) (status, &statement->handle, blr_length, blr, - msg_type, msg_length, msg -#ifdef SCROLLABLE_CURSORS - , - (USHORT) 0, (ULONG) 1 -#endif // SCROLLABLE_CURSORS - ); + msg_type, msg_length, msg); if (s == 100 || s == 101) { @@ -3269,55 +3191,6 @@ ISC_STATUS API_ROUTINE GDS_DSQL_FETCH_M(ISC_STATUS* user_status, } -#ifdef SCROLLABLE_CURSORS -ISC_STATUS API_ROUTINE GDS_DSQL_FETCH2_M(ISC_STATUS* user_status, - FB_API_HANDLE* stmt_handle, - USHORT blr_length, - SCHAR* blr, - USHORT msg_type, - USHORT msg_length, - SCHAR* msg, - USHORT direction, - SLONG offset) -{ -/************************************** - * - * i s c _ d s q l _ f e t c h 2 _ m - * - ************************************** - * - * Functional description - * Fetch next record from a dynamic SQL cursor - * - **************************************/ - Status status(user_status); - - try - { - Statement statement = translate(stmt_handle); - YEntry entryGuard(statement); - - ISC_STATUS s = - CALL(PROC_DSQL_FETCH, statement->implementation) (status, &statement->handle, - blr_length, blr, - msg_type, msg_length, msg, - direction, offset); - - if (s == 100 || s == 101) - { - return s; - } - } - catch (const Exception& e) - { - e.stuff_exception(status); - } - - return status[1]; -} -#endif - - ISC_STATUS API_ROUTINE GDS_DSQL_FREE(ISC_STATUS* user_status, FB_API_HANDLE* stmt_handle, USHORT option) @@ -4161,12 +4034,6 @@ ISC_STATUS API_ROUTINE GDS_RECEIVE(ISC_STATUS* user_status, * Get a record from the host program. * **************************************/ - -#ifdef SCROLLABLE_CURSORS - return GDS_RECEIVE2(user_status, req_handle, msg_type, msg_length, - msg, level, (USHORT) blr_continue, /* means continue in same direction as before */ - (ULONG) 1); -#else Status status(user_status); try @@ -4184,52 +4051,9 @@ ISC_STATUS API_ROUTINE GDS_RECEIVE(ISC_STATUS* user_status, } return status[1]; -#endif } -#ifdef SCROLLABLE_CURSORS -ISC_STATUS API_ROUTINE GDS_RECEIVE2(ISC_STATUS* user_status, - FB_API_HANDLE* req_handle, - USHORT msg_type, - USHORT msg_length, - SCHAR* msg, - SSHORT level, - USHORT direction, - ULONG offset) -{ -/************************************** - * - * i s c _ r e c e i v e 2 - * - ************************************** - * - * Functional description - * Scroll through the request output stream, - * then get a record from the host program. - * - **************************************/ - Status status(user_status); - - try - { - Request request = translate(req_handle); - YEntry entryGuard(request); - - CALL(PROC_RECEIVE, request->implementation) (status, &request->handle, - msg_type, msg_length, msg, - level, direction, offset); - } - catch (const Exception& e) - { - e.stuff_exception(status); - } - - return status[1]; -} -#endif - - ISC_STATUS API_ROUTINE GDS_RECONNECT(ISC_STATUS* user_status, FB_API_HANDLE* db_handle, FB_API_HANDLE* tra_handle, diff --git a/src/jrd/why_proto.h b/src/jrd/why_proto.h index 0458db866e..16d6d7a0a1 100644 --- a/src/jrd/why_proto.h +++ b/src/jrd/why_proto.h @@ -74,17 +74,8 @@ ISC_STATUS API_ROUTINE isc_dsql_exec_immed3_m(ISC_STATUS*, FB_API_HANDLE*, const SCHAR*, USHORT, SCHAR*, USHORT, USHORT, SCHAR*); ISC_STATUS API_ROUTINE isc_dsql_fetch(ISC_STATUS*, FB_API_HANDLE*, USHORT, const XSQLDA*); -#ifdef SCROLLABLE_CURSORS -ISC_STATUS API_ROUTINE isc_dsql_fetch2(ISC_STATUS*, FB_API_HANDLE*, USHORT, - XSQLDA*, USHORT, SLONG); -#endif ISC_STATUS API_ROUTINE isc_dsql_fetch_m(ISC_STATUS*, FB_API_HANDLE*, USHORT, SCHAR*, USHORT, USHORT, SCHAR*); -#ifdef SCROLLABLE_CURSORS -ISC_STATUS API_ROUTINE isc_dsql_fetch2_m(ISC_STATUS*, FB_API_HANDLE*, USHORT, - SCHAR*, USHORT, USHORT, SCHAR*, - USHORT, SLONG); -#endif ISC_STATUS API_ROUTINE isc_dsql_free_statement(ISC_STATUS*, FB_API_HANDLE*, USHORT); ISC_STATUS API_ROUTINE isc_dsql_insert(ISC_STATUS*, FB_API_HANDLE*, USHORT, XSQLDA*); ISC_STATUS API_ROUTINE isc_dsql_insert_m(ISC_STATUS*, FB_API_HANDLE*, USHORT, @@ -108,11 +99,6 @@ ISC_STATUS API_ROUTINE isc_dsql_sql_info(ISC_STATUS*, FB_API_HANDLE*, SSHORT, //ISC_STATUS API_ROUTINE isc_que_events(ISC_STATUS*, FB_API_HANDLE*, SLONG*, // USHORT, const UCHAR*, // FPTR_EVENT_CALLBACK, void*); -//#ifdef SCROLLABLE_CURSORS -//ISC_STATUS API_ROUTINE isc_receive2(ISC_STATUS*, FB_API_HANDLE*, USHORT, -// USHORT, SCHAR*, SSHORT, USHORT, -// ULONG); -//#endif //ISC_STATUS API_ROUTINE isc_rollback_transaction(ISC_STATUS*, FB_API_HANDLE*); //ISC_STATUS API_ROUTINE_VARARG isc_start_transaction(ISC_STATUS*, // FB_API_HANDLE*, SSHORT, @@ -191,11 +177,6 @@ ISC_STATUS API_ROUTINE isc_que_events(ISC_STATUS*, FB_API_HANDLE*, SLONG*, USHOR ISC_STATUS API_ROUTINE isc_receive(ISC_STATUS*, FB_API_HANDLE*, USHORT, USHORT, SCHAR*, SSHORT); -#ifdef SCROLLABLE_CURSORS -ISC_STATUS API_ROUTINE isc_receive2(ISC_STATUS*, FB_API_HANDLE*, USHORT, USHORT, SCHAR*, - SSHORT, USHORT, ULONG); -#endif - ISC_STATUS API_ROUTINE isc_reconnect_transaction(ISC_STATUS*, FB_API_HANDLE*, FB_API_HANDLE*, SSHORT, const UCHAR*);