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

1) Fixed wrong ALL results in the ODS11 optimizer.

2) Fixed SF #527681 -- Strange/Inconsistent query results
This commit is contained in:
dimitr 2006-05-17 19:15:41 +00:00
parent 1c0ad0e6ce
commit 8c66a4883a
4 changed files with 104 additions and 25 deletions

View File

@ -1182,10 +1182,14 @@ InversionCandidate* OptimizerRetrieval::generateInversion(RecordSource** rsb)
tail += optimizer->opt_base_parent_conjuncts;
}
for (; tail < opt_end; tail++) {
if (tail->opt_conjunct_flags & opt_conjunct_matched) {
continue;
}
jrd_nod* const node = tail->opt_conjunct_node;
if (!(tail->opt_conjunct_flags & opt_conjunct_used) &&
tail->opt_conjunct_node && (tail->opt_conjunct_node->nod_type != nod_or))
node && (node->nod_type != nod_or))
{
matchOnIndexes(&indexScratches, tail->opt_conjunct_node, 1);
matchOnIndexes(&indexScratches, node, 1);
}
}
getInversionCandidates(&inversions, &indexScratches, 1);
@ -1201,12 +1205,16 @@ InversionCandidate* OptimizerRetrieval::generateInversion(RecordSource** rsb)
tail += optimizer->opt_base_parent_conjuncts;
}
for (; tail < opt_end; tail++) {
if (tail->opt_conjunct_flags & opt_conjunct_matched) {
continue;
}
jrd_nod* const node = tail->opt_conjunct_node;
if (!(tail->opt_conjunct_flags & opt_conjunct_used) &&
tail->opt_conjunct_node && (tail->opt_conjunct_node->nod_type == nod_or))
node && (node->nod_type == nod_or))
{
invCandidate = matchOnIndexes(&indexScratches, tail->opt_conjunct_node, 1);
invCandidate = matchOnIndexes(&indexScratches, node, 1);
if (invCandidate) {
invCandidate->boolean = tail->opt_conjunct_node;
invCandidate->boolean = node;
inversions.add(invCandidate);
}
}
@ -2255,6 +2263,17 @@ bool OptimizerRetrieval::matchBoolean(IndexScratch* indexScratch,
}
}
// check datatypes to ensure that the index scan is guaranteed
// to deliver correct results
if (value) {
dsc desc1, desc2;
CMP_get_desc(tdbb, optimizer->opt_csb, match, &desc1);
CMP_get_desc(tdbb, optimizer->opt_csb, value, &desc2);
if (!BTR_types_comparable(desc1, desc2))
return false;
}
// match the field to an index, if possible, and save the value to be matched
// as either the lower or upper bound for retrieval, or both

View File

@ -256,6 +256,25 @@ USHORT BTR_all(thread_db* tdbb,
}
void BTR_complement_key(temporary_key* key)
{
/**************************************
*
* B T R _ c o m p l e m e n t _ k e y
*
**************************************
*
* Functional description
* Negate a key for descending index.
*
**************************************/
UCHAR* p = key->key_data;
for (const UCHAR* const end = p + key->key_length; p < end; p++) {
*p ^= -1;
}
}
void BTR_create(thread_db* tdbb,
jrd_rel* relation,
index_desc* idx,
@ -2019,6 +2038,54 @@ void BTR_selectivity(thread_db* tdbb, const jrd_rel* relation, USHORT id,
}
bool BTR_types_comparable(const dsc& target, const dsc& source)
{
/**************************************
*
* B T R _ t y p e s _ c o m p a r a b l e
*
**************************************
*
* Functional description
* Return whether two datatypes are comparable in terms of the CVT rules.
* The purpose is to ensure that compress() converts datatypes in the same
* direction as CVT2_compare(), thus causing index scans to always deliver
* the same results as the generic boolean evaluation.
*
**************************************/
if (DTYPE_IS_TEXT(target.dsc_dtype))
{
// should we also check for the INTL stuff here?
return (DTYPE_IS_TEXT(source.dsc_dtype));
}
else if (DTYPE_IS_NUMERIC(target.dsc_dtype))
{
return (DTYPE_IS_TEXT(source.dsc_dtype) ||
DTYPE_IS_NUMERIC(source.dsc_dtype));
}
else if (target.dsc_dtype == dtype_sql_date)
{
return (DTYPE_IS_TEXT(source.dsc_dtype) ||
source.dsc_dtype == dtype_sql_date);
}
else if (target.dsc_dtype == dtype_sql_time)
{
return (DTYPE_IS_TEXT(source.dsc_dtype) ||
source.dsc_dtype == dtype_sql_time);
}
else if (target.dsc_dtype == dtype_timestamp)
{
return (DTYPE_IS_TEXT(source.dsc_dtype) ||
DTYPE_IS_DATE(source.dsc_dtype));
}
else
{
fb_assert(DTYPE_IS_BLOB(target.dsc_dtype));
return false;
}
}
static SLONG add_node(thread_db* tdbb,
WIN * window,
index_insertion* insertion,
@ -2134,25 +2201,6 @@ static SLONG add_node(thread_db* tdbb,
}
void BTR_complement_key(temporary_key* key)
{
/**************************************
*
* B T R _ c o m p l e m e n t _ k e y
*
**************************************
*
* Functional description
* Negate a key for descending index.
*
**************************************/
UCHAR* p = key->key_data;
for (const UCHAR* const end = p + key->key_length; p < end; p++) {
*p ^= -1;
}
}
static void compress(thread_db* tdbb,
const dsc* desc,
temporary_key* key,

View File

@ -33,6 +33,7 @@ struct btree_exp;
struct exp_index_buf;
USHORT BTR_all(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::IndexDescAlloc**);
void BTR_complement_key(Jrd::temporary_key*);
void BTR_create(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::index_desc*, USHORT, Jrd::sort_context*, Jrd::SelectivityList&);
void BTR_delete_index(Jrd::thread_db*, Jrd::win*, USHORT);
//USHORT BTR_delete_node(Jrd::thread_db*, Ods::btree_page*, USHORT);
@ -55,7 +56,7 @@ bool BTR_next_index(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::jrd_tra*, Jrd::index_de
void BTR_remove(Jrd::thread_db*, Jrd::win*, Jrd::index_insertion*);
void BTR_reserve_slot(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::jrd_tra*, Jrd::index_desc*);
void BTR_selectivity(Jrd::thread_db*, const Jrd::jrd_rel*, USHORT, Jrd::SelectivityList&);
void BTR_complement_key(Jrd::temporary_key*);
bool BTR_types_comparable(const dsc& target, const dsc& source);
#endif // JRD_BTR_PROTO_H

View File

@ -6803,6 +6803,17 @@ static int match_index(thread_db* tdbb,
}
}
/* check datatypes to ensure that the index scan is guaranteed
to deliver correct results */
if (value) {
dsc desc1, desc2;
CMP_get_desc(tdbb, opt->opt_csb, match, &desc1);
CMP_get_desc(tdbb, opt->opt_csb, value, &desc2);
if (!BTR_types_comparable(desc1, desc2))
return 0;
}
/* match the field to an index, if possible, and save the value to be matched
as either the lower or upper bound for retrieval, or both */