mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 09:23:03 +01:00
another bugfix Alpha5 "no current record for fetch operation"
Added code so that more index-retrieval can be used. Cases where an LEFT OUTER JOIN messed-up the optimizer should be much lower. Example : SELECT * FROM SomeTable t1 LEFT JOIN AnotherTable t2 ON (t1.PK_Key = t2.FK_Key) JOIN AnotherTable t3 ON (t1.PK_Key = t3.FK_Key) This change fixed also BUG SF #219525.
This commit is contained in:
parent
7c121686fe
commit
aa638632a3
132
src/jrd/opt.cpp
132
src/jrd/opt.cpp
@ -36,6 +36,9 @@
|
|||||||
* which most are foreign_keys with a reference to a few records.
|
* which most are foreign_keys with a reference to a few records.
|
||||||
* 2002.11.01: Arno Brinkman: Added match_indices for better support of OR handling
|
* 2002.11.01: Arno Brinkman: Added match_indices for better support of OR handling
|
||||||
* in INNER JOIN (gen_join) statements.
|
* in INNER JOIN (gen_join) statements.
|
||||||
|
* 2002.12.15: Arno Brinkman: Added find_used_streams, so that inside opt_compile all the
|
||||||
|
* streams are marked active. This causes that more indices can be used for
|
||||||
|
* an retrieval. With this change BUG SF #219525 is solved too.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -101,6 +104,7 @@ static void find_best(TDBB, register OPT, USHORT, USHORT, UCHAR *, JRD_NOD,
|
|||||||
static JRD_NOD find_dbkey(JRD_NOD, USHORT, SLONG *);
|
static JRD_NOD find_dbkey(JRD_NOD, USHORT, SLONG *);
|
||||||
static USHORT find_order(TDBB, register OPT, UCHAR *, JRD_NOD);
|
static USHORT find_order(TDBB, register OPT, UCHAR *, JRD_NOD);
|
||||||
static void find_rsbs(RSB, LLS *, LLS *);
|
static void find_rsbs(RSB, LLS *, LLS *);
|
||||||
|
static void find_used_streams(RSB , UCHAR *);
|
||||||
static void form_rivers(TDBB, OPT, UCHAR *, LLS *, JRD_NOD *, JRD_NOD *, JRD_NOD);
|
static void form_rivers(TDBB, OPT, UCHAR *, LLS *, JRD_NOD *, JRD_NOD *, JRD_NOD);
|
||||||
static BOOLEAN form_river(TDBB, OPT, USHORT, UCHAR *, UCHAR *, LLS *, JRD_NOD *,
|
static BOOLEAN form_river(TDBB, OPT, USHORT, UCHAR *, UCHAR *, LLS *, JRD_NOD *,
|
||||||
JRD_NOD *, JRD_NOD);
|
JRD_NOD *, JRD_NOD);
|
||||||
@ -300,9 +304,9 @@ RSB OPT_compile(TDBB tdbb,
|
|||||||
#ifndef STACK_REDUCTION
|
#ifndef STACK_REDUCTION
|
||||||
UCHAR *p, *q, streams[MAX_STREAMS], beds[MAX_STREAMS],
|
UCHAR *p, *q, streams[MAX_STREAMS], beds[MAX_STREAMS],
|
||||||
*k, *b_end, *k_end, key_streams[MAX_STREAMS],
|
*k, *b_end, *k_end, key_streams[MAX_STREAMS],
|
||||||
local_streams[MAX_STREAMS];
|
local_streams[MAX_STREAMS], used_streams[MAX_STREAMS];
|
||||||
#else
|
#else
|
||||||
UCHAR *local_streams;
|
UCHAR *local_streams, *used_streams;
|
||||||
UCHAR *p, *q, *streams, *beds, *k, *b_end, *k_end, *key_streams;
|
UCHAR *p, *q, *streams, *beds, *k, *b_end, *k_end, *key_streams;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -344,6 +348,8 @@ RSB OPT_compile(TDBB tdbb,
|
|||||||
(UCHAR *) ALLOC_LIB_MEMORY((DWORD) (sizeof(UCHAR) * MAX_STREAMS));
|
(UCHAR *) ALLOC_LIB_MEMORY((DWORD) (sizeof(UCHAR) * MAX_STREAMS));
|
||||||
local_streams =
|
local_streams =
|
||||||
(UCHAR *) ALLOC_LIB_MEMORY((DWORD) (sizeof(UCHAR) * MAX_STREAMS));
|
(UCHAR *) ALLOC_LIB_MEMORY((DWORD) (sizeof(UCHAR) * MAX_STREAMS));
|
||||||
|
used_streams =
|
||||||
|
(UCHAR *) ALLOC_LIB_MEMORY((DWORD) (sizeof(UCHAR) * MAX_STREAMS));
|
||||||
opt_ = (OPT) ALLOC_LIB_MEMORY((DWORD) (sizeof(Opt)));
|
opt_ = (OPT) ALLOC_LIB_MEMORY((DWORD) (sizeof(Opt)));
|
||||||
if (streams == NULL || beds == NULL || key_streams == NULL ||
|
if (streams == NULL || beds == NULL || key_streams == NULL ||
|
||||||
local_streams == NULL || opt_ == NULL) {
|
local_streams == NULL || opt_ == NULL) {
|
||||||
@ -377,7 +383,7 @@ RSB OPT_compile(TDBB tdbb,
|
|||||||
if (rse->nod_flags & rse_stream)
|
if (rse->nod_flags & rse_stream)
|
||||||
opt_->opt_g_flags |= opt_g_stream;
|
opt_->opt_g_flags |= opt_g_stream;
|
||||||
|
|
||||||
beds[0] = streams[0] = key_streams[0] = 0;
|
beds[0] = streams[0] = key_streams[0] = used_streams[0] = 0;
|
||||||
conjunct_stack = rivers_stack = NULL;
|
conjunct_stack = rivers_stack = NULL;
|
||||||
conjunct_count = 0;
|
conjunct_count = 0;
|
||||||
|
|
||||||
@ -475,6 +481,7 @@ RSB OPT_compile(TDBB tdbb,
|
|||||||
river->riv_count = (UCHAR) i;
|
river->riv_count = (UCHAR) i;
|
||||||
river->riv_rsb = rsb;
|
river->riv_rsb = rsb;
|
||||||
MOVE_FAST(local_streams + 1, river->riv_streams, i);
|
MOVE_FAST(local_streams + 1, river->riv_streams, i);
|
||||||
|
find_used_streams(rsb, used_streams);
|
||||||
set_made_river(opt_, river);
|
set_made_river(opt_, river);
|
||||||
set_inactive(opt_, river);
|
set_inactive(opt_, river);
|
||||||
LLS_PUSH(river, &rivers_stack);
|
LLS_PUSH(river, &rivers_stack);
|
||||||
@ -562,11 +569,18 @@ RSB OPT_compile(TDBB tdbb,
|
|||||||
else
|
else
|
||||||
rse->rse_aggregate = aggregate = NULL;
|
rse->rse_aggregate = aggregate = NULL;
|
||||||
|
|
||||||
|
/* mark the previous used streams (sub-rse's) as active */
|
||||||
|
|
||||||
|
for (i = 1; i <= used_streams[0]; i++) {
|
||||||
|
csb->csb_rpt[used_streams[i]].csb_flags |= csb_active;
|
||||||
|
}
|
||||||
|
|
||||||
/* outer joins require some extra processing */
|
/* outer joins require some extra processing */
|
||||||
|
|
||||||
if (rse->rse_jointype != blr_inner)
|
if (rse->rse_jointype != blr_inner)
|
||||||
rsb = gen_outer(tdbb, opt_, rse, rivers_stack, &sort, &project);
|
rsb = gen_outer(tdbb, opt_, rse, rivers_stack, &sort, &project);
|
||||||
else {
|
else {
|
||||||
|
|
||||||
/* attempt to form joins in decreasing order of desirability */
|
/* attempt to form joins in decreasing order of desirability */
|
||||||
|
|
||||||
gen_join(tdbb, opt_, streams, &rivers_stack, &sort, &project,
|
gen_join(tdbb, opt_, streams, &rivers_stack, &sort, &project,
|
||||||
@ -595,8 +609,9 @@ RSB OPT_compile(TDBB tdbb,
|
|||||||
/* check index usage in all the base streams to ensure
|
/* check index usage in all the base streams to ensure
|
||||||
that any user-specified access plan is followed */
|
that any user-specified access plan is followed */
|
||||||
|
|
||||||
for (i = 1; i <= streams[0]; i++)
|
for (i = 1; i <= streams[0]; i++) {
|
||||||
check_indices(&csb->csb_rpt[streams[i]]);
|
check_indices(&csb->csb_rpt[streams[i]]);
|
||||||
|
}
|
||||||
|
|
||||||
if (project || sort) {
|
if (project || sort) {
|
||||||
/* Eliminate any duplicate dbkey streams */
|
/* Eliminate any duplicate dbkey streams */
|
||||||
@ -612,13 +627,15 @@ RSB OPT_compile(TDBB tdbb,
|
|||||||
|
|
||||||
/* Handle project clause, if present. */
|
/* Handle project clause, if present. */
|
||||||
|
|
||||||
if (project)
|
if (project) {
|
||||||
rsb = gen_sort(tdbb, opt_, beds, key_streams, rsb, project, TRUE);
|
rsb = gen_sort(tdbb, opt_, beds, key_streams, rsb, project, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle sort clause if present */
|
/* Handle sort clause if present */
|
||||||
|
|
||||||
if (sort)
|
if (sort) {
|
||||||
rsb = gen_sort(tdbb, opt_, beds, key_streams, rsb, sort, FALSE);
|
rsb = gen_sort(tdbb, opt_, beds, key_streams, rsb, sort, FALSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle first and/or skip. The skip MUST (if present)
|
/* Handle first and/or skip. The skip MUST (if present)
|
||||||
@ -627,11 +644,13 @@ RSB OPT_compile(TDBB tdbb,
|
|||||||
* gen_skip before gen_first.
|
* gen_skip before gen_first.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
if (rse->rse_skip)
|
if (rse->rse_skip) {
|
||||||
rsb = gen_skip(tdbb, opt_, rsb, rse->rse_skip);
|
rsb = gen_skip(tdbb, opt_, rsb, rse->rse_skip);
|
||||||
|
}
|
||||||
|
|
||||||
if (rse->rse_first)
|
if (rse->rse_first) {
|
||||||
rsb = gen_first(tdbb, opt_, rsb, rse->rse_first);
|
rsb = gen_first(tdbb, opt_, rsb, rse->rse_first);
|
||||||
|
}
|
||||||
|
|
||||||
/* release memory allocated for index descriptions */
|
/* release memory allocated for index descriptions */
|
||||||
|
|
||||||
@ -680,6 +699,7 @@ RSB OPT_compile(TDBB tdbb,
|
|||||||
csb->csb_rpt[stream].csb_idx_allocation = 0;
|
csb->csb_rpt[stream].csb_idx_allocation = 0;
|
||||||
}
|
}
|
||||||
#ifdef STACK_REDUCTION
|
#ifdef STACK_REDUCTION
|
||||||
|
FREE_LIB_MEMORY(used_streams);
|
||||||
FREE_LIB_MEMORY(local_streams);
|
FREE_LIB_MEMORY(local_streams);
|
||||||
FREE_LIB_MEMORY(key_streams);
|
FREE_LIB_MEMORY(key_streams);
|
||||||
FREE_LIB_MEMORY(beds);
|
FREE_LIB_MEMORY(beds);
|
||||||
@ -2888,6 +2908,93 @@ static void find_rsbs(RSB rsb, LLS * stream_list, LLS * rsb_list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void find_used_streams(RSB rsb, UCHAR * streams)
|
||||||
|
{
|
||||||
|
/**************************************
|
||||||
|
*
|
||||||
|
* f i n d _ u s e d _ s t r e a m s
|
||||||
|
*
|
||||||
|
**************************************
|
||||||
|
*
|
||||||
|
* Functional description
|
||||||
|
* Find all streams through the given rsb
|
||||||
|
* and add them to the stream list.
|
||||||
|
*
|
||||||
|
**************************************/
|
||||||
|
RSB *ptr, *end;
|
||||||
|
USHORT i, stream;
|
||||||
|
BOOLEAN found;
|
||||||
|
|
||||||
|
if (!(rsb)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
found = FALSE;
|
||||||
|
|
||||||
|
switch (rsb->rsb_type) {
|
||||||
|
|
||||||
|
case rsb_navigate:
|
||||||
|
stream = rsb->rsb_stream;
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case rsb_cross:
|
||||||
|
for (ptr = rsb->rsb_arg, end = ptr + rsb->rsb_count; ptr < end; ptr++) {
|
||||||
|
find_used_streams(*ptr, streams);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case rsb_union:
|
||||||
|
for (ptr = rsb->rsb_arg, end = ptr + rsb->rsb_count; ptr < end; ptr++) {
|
||||||
|
find_used_streams(*ptr, streams);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case rsb_merge:
|
||||||
|
for (ptr = rsb->rsb_arg, end = ptr + rsb->rsb_count * 2; ptr < end; ptr += 2) {
|
||||||
|
find_used_streams(*ptr, streams);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case rsb_left_cross:
|
||||||
|
find_used_streams(rsb->rsb_arg[RSB_LEFT_inner], streams);
|
||||||
|
find_used_streams(rsb->rsb_arg[RSB_LEFT_outer], streams);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case rsb_indexed:
|
||||||
|
stream = rsb->rsb_stream;
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case rsb_sequential:
|
||||||
|
stream = rsb->rsb_stream;
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* Shut up compiler warnings */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsb->rsb_next) {
|
||||||
|
find_used_streams(rsb->rsb_next, streams);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
found = FALSE;
|
||||||
|
for (i = 1; i <= streams[0]; i++) {
|
||||||
|
if (stream == streams[i]) {
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
streams[++streams[0]] = stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void form_rivers(TDBB tdbb,
|
static void form_rivers(TDBB tdbb,
|
||||||
OPT opt,
|
OPT opt,
|
||||||
UCHAR * streams,
|
UCHAR * streams,
|
||||||
@ -3942,9 +4049,12 @@ static RSB gen_retrieval(TDBB tdbb,
|
|||||||
if (!(tail->opt_flags & opt_matched)) {
|
if (!(tail->opt_flags & opt_matched)) {
|
||||||
/* Setting opt_lower and/or opt_upper values */
|
/* Setting opt_lower and/or opt_upper values */
|
||||||
node = tail->opt_conjunct;
|
node = tail->opt_conjunct;
|
||||||
if (match_index(tdbb, opt, stream, node, idx)) {
|
if (!(tail->opt_flags & opt_used) &&
|
||||||
matching_nodes[j++] = tail;
|
computable(csb, node, -1, (BOOLEAN) (inner_flag || outer_flag) ? TRUE : FALSE)) {
|
||||||
count = j;
|
if (match_index(tdbb, opt, stream, node, idx)) {
|
||||||
|
matching_nodes[j++] = tail;
|
||||||
|
count = j;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user