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:
parent
1c2c7b2ff9
commit
46c115411a
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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];
|
||||
};
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user