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

Fixed CORE-1254 - Problem with DISTINCT and insensitive collations

This commit is contained in:
asfernandes 2008-02-09 15:19:21 +00:00
parent 1c2c7b2ff9
commit 46c115411a
3 changed files with 56 additions and 13 deletions

View File

@ -1705,11 +1705,29 @@ USHORT EVL_group(thread_db* tdbb, RecordSource* rsb, jrd_nod *const node, USHORT
impure_agg_sort* asb_impure =
(impure_agg_sort*) ((SCHAR *) request + asb->nod_impure);
UCHAR* data;
SORT_put(tdbb, asb_impure->iasb_sort_handle,
reinterpret_cast<ULONG**>(&data));
MOVE_CLEAR(data, ROUNDUP_LONG(asb->asb_key_desc->skd_length));
asb->asb_desc.dsc_address = data;
SORT_put(tdbb, asb_impure->iasb_sort_handle, reinterpret_cast<ULONG**>(&data));
MOVE_CLEAR(data, asb->asb_length);
if (asb->asb_intl)
{
// convert to an international byte array
dsc to;
to.dsc_dtype = dtype_text;
to.dsc_flags = 0;
to.dsc_sub_type = 0;
to.dsc_scale = 0;
to.dsc_ttype() = ttype_sort_key;
to.dsc_length = asb->asb_key_desc[0].skd_length;
to.dsc_address = data;
INTL_string_to_key(tdbb, INTL_TEXT_TO_INDEX(desc->getTextType()),
desc, &to, INTL_KEY_SORT);
}
asb->asb_desc.dsc_address = data +
(asb->asb_intl ? asb->asb_key_desc[1].skd_offset : 0);
MOV_move(tdbb, desc, &asb->asb_desc);
break;
}
@ -3000,7 +3018,8 @@ static void compute_agg_distinct(thread_db* tdbb, jrd_nod* node)
break;
}
desc->dsc_address = data;
desc->dsc_address = data + (asb->asb_intl ? asb->asb_key_desc[1].skd_offset : 0);
switch (node->nod_type) {
case nod_agg_total_distinct:
case nod_agg_average_distinct:
@ -3828,7 +3847,7 @@ static void init_agg_distinct(thread_db* tdbb, const jrd_nod* node)
asb_impure->iasb_sort_handle =
SORT_init(tdbb, ROUNDUP_LONG(asb->asb_length),
1, 1, sort_key, reject_duplicate, 0, 0);
(asb->asb_intl ? 2 : 1), 1, sort_key, reject_duplicate, 0, 0);
}

View File

@ -190,6 +190,7 @@ public:
USHORT nod_count;
dsc asb_desc;
USHORT asb_length;
bool asb_intl;
sort_key_def* asb_key_desc; /* for the aggregate */
UCHAR asb_key_data[1];
};

View File

@ -3960,11 +3960,6 @@ static RecordSource* gen_aggregate(thread_db* tdbb, OptimizerBlk* opt, jrd_nod*
(from->nod_type == nod_agg_average_distinct) ||
(from->nod_type == nod_agg_list_distinct))
{
const USHORT count = asb_delta + 1 +
(sizeof(sort_key_def) + sizeof(jrd_nod**) - 1) / sizeof(jrd_nod**);
AggregateSort* asb = (AggregateSort*) PAR_make_node(tdbb, count);
asb->nod_type = nod_asb;
asb->nod_count = 0;
// Build the sort key definition. Turn cstrings into varying text.
CMP_get_desc(tdbb, csb, from->nod_arg[0], desc);
if (desc->dsc_dtype == dtype_cstring) {
@ -3972,8 +3967,36 @@ static RecordSource* gen_aggregate(thread_db* tdbb, OptimizerBlk* opt, jrd_nod*
desc->dsc_length++;
}
bool asb_intl = desc->isText() && desc->getTextType() != ttype_none &&
desc->getTextType() != ttype_binary && desc->getTextType() != ttype_ascii;
const USHORT count = asb_delta + 1 +
((sizeof(sort_key_def) + sizeof(jrd_nod**)) * (asb_intl ? 2 : 1) - 1) / sizeof(jrd_nod**);
AggregateSort* asb = (AggregateSort*) PAR_make_node(tdbb, count);
asb->nod_type = nod_asb;
asb->asb_intl = asb_intl;
asb->nod_count = 0;
sort_key_def* sort_key = asb->asb_key_desc = (sort_key_def*) asb->asb_key_data;
sort_key->skd_offset = 0;
if (asb_intl)
{
const USHORT key_length = ROUNDUP(INTL_key_length(tdbb,
INTL_TEXT_TO_INDEX(desc->getTextType()), desc->getStringLength()), sizeof(SINT64));
sort_key->skd_dtype = SKD_bytes;
sort_key->skd_flags = SKD_ascending;
sort_key->skd_length = key_length;
sort_key->skd_offset = 0;
sort_key->skd_vary_offset = 0;
++sort_key;
asb->asb_length = sort_key->skd_offset = key_length;
}
else
asb->asb_length = 0;
fb_assert(desc->dsc_dtype < FB_NELEM(sort_dtypes));
sort_key->skd_dtype = sort_dtypes[desc->dsc_dtype];
if (!sort_key->skd_dtype) {
@ -3988,11 +4011,11 @@ static RecordSource* gen_aggregate(thread_db* tdbb, OptimizerBlk* opt, jrd_nod*
if (desc->dsc_dtype == dtype_varying)
{
// allocate space to store varying length
sort_key->skd_vary_offset = ROUNDUP(desc->dsc_length, sizeof(SLONG));
sort_key->skd_vary_offset = sort_key->skd_offset + ROUNDUP(desc->dsc_length, sizeof(SLONG));
asb->asb_length = sort_key->skd_vary_offset + sizeof(USHORT);
}
else
asb->asb_length = sort_key->skd_length;
asb->asb_length += sort_key->skd_length;
sort_key->skd_flags = SKD_ascending;
asb->nod_impure = CMP_impure(csb, sizeof(impure_agg_sort));