8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 21:23:03 +01:00

Added the equivalence operator. The major index optimizations are done.

Notes:
1) Some optimizations will follow after more deep analysis.
2) The syntax "==" is not yet agreed on. I'd prefer it to be changed.
This commit is contained in:
dimitr 2004-10-14 19:09:19 +00:00
parent 6dd8dcc3d1
commit 09c51110b4
9 changed files with 53 additions and 7 deletions

View File

@ -126,6 +126,7 @@
#define blr_user_name (unsigned char)44 /* added from gds.h */
#define blr_null (unsigned char)45
#define blr_equiv (unsigned char)46
#define blr_eql (unsigned char)47
#define blr_neq (unsigned char)48
#define blr_gtr (unsigned char)49

View File

@ -5044,6 +5044,7 @@ static jrd_nod* pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node
case nod_matches:
case nod_contains:
case nod_starts:
case nod_equiv:
case nod_eql:
case nod_neq:
case nod_geq:

View File

@ -19,7 +19,7 @@
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
* $Id: evl.cpp,v 1.113 2004-10-11 17:18:35 hvlad Exp $
* $Id: evl.cpp,v 1.114 2004-10-14 19:08:03 dimitr Exp $
*/
/*
@ -405,6 +405,7 @@ bool EVL_boolean(thread_db* tdbb, jrd_nod* node)
case nod_starts:
case nod_matches:
case nod_like:
case nod_equiv:
case nod_eql:
case nod_neq:
case nod_gtr:
@ -480,7 +481,25 @@ bool EVL_boolean(thread_db* tdbb, jrd_nod* node)
}
else
desc[1] = EVL_expr(tdbb, *ptr++);
// An equivalence operator evaluates to true when both operands
// are NULL and behaves like an equality operator otherwise.
// Note that this operator never sets req_null flag
if (node->nod_type == nod_equiv)
{
if ((flags & req_null) && (request->req_flags & req_null))
{
request->req_flags &= ~req_null;
return true;
}
else if ((flags & req_null) || (request->req_flags & req_null))
{
request->req_flags &= ~req_null;
return false;
}
}
// If either of expressions above returned NULL set req_null flag
// and return false
@ -770,6 +789,7 @@ bool EVL_boolean(thread_db* tdbb, jrd_nod* node)
return value;
}
case nod_equiv:
case nod_eql:
return (comparison == 0);
case nod_neq:

View File

@ -1614,7 +1614,8 @@ static jrd_nod* find(thread_db* tdbb, jrd_nod* node)
const USHORT blr_operator = (desc && !(request->req_flags & req_null)) ?
(USHORT) MOV_get_long(desc, 0) : MAX_USHORT;
if (blr_operator != blr_eql &&
if (blr_operator != blr_equiv &&
blr_operator != blr_eql &&
blr_operator != blr_leq &&
blr_operator != blr_lss &&
blr_operator != blr_geq &&

View File

@ -316,6 +316,7 @@ bool NAV_find_record(RecordSource* rsb,
}
// break; unreachable
case blr_equiv:
case blr_eql:
if (find_record(rsb, backwards ? RSE_get_last : RSE_get_first,
&key_value, find_key->nod_count, search_flags))

View File

@ -206,3 +206,4 @@ NODE(nod_asn_list, asn_list, "")
NODE(nod_dcl_cursor, declare_cursor, "DECLARE CURSOR")
NODE(nod_cursor_stmt, cursor_stmt, "CURSOR STATEMENT")
NODE(nod_equiv, equiv, " == ")

View File

@ -964,9 +964,9 @@ jrd_nod* OPT_make_index(thread_db* tdbb, OptimizerBlk* opt, jrd_rel* relation,
jrd_nod** lower = retrieval->irb_value;
jrd_nod** upper = retrieval->irb_value + idx->idx_count;
const OptimizerBlk::opt_segment* const end = opt->opt_segments + idx->idx_count;
OptimizerBlk::opt_segment* tail;
if (idx->idx_flags & idx_descending) {
OptimizerBlk::opt_segment* tail;
for (tail = opt->opt_segments; tail->opt_lower && tail < end; tail++)
*upper++ = tail->opt_lower;
for (tail = opt->opt_segments; tail->opt_upper && tail < end; tail++)
@ -974,7 +974,6 @@ jrd_nod* OPT_make_index(thread_db* tdbb, OptimizerBlk* opt, jrd_rel* relation,
retrieval->irb_generic |= irb_descending;
}
else {
OptimizerBlk::opt_segment* tail;
for (tail = opt->opt_segments; tail->opt_lower && tail < end; tail++)
*lower++ = tail->opt_lower;
for (tail = opt->opt_segments; tail->opt_upper && tail < end; tail++)
@ -985,9 +984,24 @@ jrd_nod* OPT_make_index(thread_db* tdbb, OptimizerBlk* opt, jrd_rel* relation,
retrieval->irb_upper_count =
(upper - retrieval->irb_value) - idx->idx_count;
bool equiv = false;
for (tail = opt->opt_segments; tail->opt_match && tail < end; tail++)
{
if (tail->opt_match->nod_type == nod_equiv)
{
equiv = true;
break;
}
}
// This index is never used for IS NULL, thus we can ignore NULLs
// already at index scan
retrieval->irb_generic |= irb_ignore_null_value_key;
// already at index scan. But this rule doesn't apply to nod_equiv
// which requires NULLs to be found in the index.
if (!equiv)
{
retrieval->irb_generic |= irb_ignore_null_value_key;
}
/* Check to see if this is really an equality retrieval */
@ -2886,6 +2900,7 @@ static bool expression_contains(const jrd_nod* node, NOD_T node_type)
case nod_matches:
case nod_contains:
case nod_starts:
case nod_equiv:
case nod_eql:
case nod_neq:
case nod_geq:
@ -3063,6 +3078,7 @@ static bool expression_contains_stream(const jrd_nod* node, UCHAR stream)
case nod_matches:
case nod_contains:
case nod_starts:
case nod_equiv:
case nod_eql:
case nod_neq:
case nod_geq:
@ -3226,6 +3242,7 @@ static bool expression_equal2(thread_db* tdbb, OptimizerBlk* opt,
case nod_multiply:
case nod_add2:
case nod_multiply2:
case nod_equiv:
case nod_eql:
case nod_neq:
case nod_and:
@ -6791,6 +6808,7 @@ static SSHORT match_index(thread_db* tdbb,
ptr->opt_upper = boolean->nod_arg[2];
ptr->opt_match = boolean;
break;
case nod_equiv:
case nod_eql:
ptr->opt_lower = ptr->opt_upper = value;
ptr->opt_match = boolean;
@ -6930,6 +6948,7 @@ static bool node_equality(const jrd_nod* node1, const jrd_nod* node2)
case nod_field:
return (node1->nod_arg[e_fld_stream] == node2->nod_arg[e_fld_stream]
&& node1->nod_arg[e_fld_id] == node2->nod_arg[e_fld_id]);
case nod_equiv:
case nod_eql:
if (node_equality(node1->nod_arg[0], node2->nod_arg[0])
&& node_equality(node1->nod_arg[1], node2->nod_arg[1]))

View File

@ -2447,6 +2447,7 @@ static jrd_nod* parse(thread_db* tdbb, CompilerScratch* csb, USHORT expected,
case blr_between:
*arg++ = parse(tdbb, csb, sub_type);
case blr_equiv:
case blr_eql:
case blr_neq:
case blr_geq:

View File

@ -137,6 +137,7 @@ static const VERB verbs[] =
PAIR2(nod_subtract, blr_subtract, 2, 2, VALUE, VALUE),
PAIR2(nod_total, blr_total, e_stat_length, 2, VALUE, VALUE),
PAIR(nod_value_if, blr_value_if, 3, 3, VALUE, OTHER),
PAIR(nod_equiv, blr_equiv, 2, 2, TYPE_BOOL, VALUE),
PAIR(nod_eql, blr_eql, 2, 2, TYPE_BOOL, VALUE),
PAIR(nod_neq, blr_neq, 2, 2, TYPE_BOOL, VALUE),
PAIR(nod_geq, blr_geq, 2, 2, TYPE_BOOL, VALUE),