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:
parent
6dd8dcc3d1
commit
09c51110b4
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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 &&
|
||||
|
@ -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))
|
||||
|
@ -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, " == ")
|
||||
|
@ -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]))
|
||||
|
@ -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:
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user