summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc212
1 files changed, 115 insertions, 97 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 9c665bf5df0..048f101c046 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -21410,12 +21410,13 @@ bool Create_tmp_table::finalize(THD *thd,
table->group= m_group; /* Table is grouped by key */
param->group_buff= m_group_buff;
share->keys=1;
- share->uniques= MY_TEST(m_using_unique_constraint);
table->key_info= table->s->key_info= keyinfo;
table->keys_in_use_for_query.set_bit(0);
share->keys_in_use.set_bit(0);
keyinfo->key_part= m_key_part_info;
keyinfo->flags=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
+ if (m_using_unique_constraint)
+ keyinfo->flags|= HA_UNIQUE_HASH;
keyinfo->ext_key_flags= keyinfo->flags;
keyinfo->usable_key_parts=keyinfo->user_defined_key_parts=
param->group_parts;
@@ -21514,6 +21515,7 @@ bool Create_tmp_table::finalize(THD *thd,
*/
DBUG_PRINT("info",("hidden_field_count: %d", param->hidden_field_count));
+ keyinfo->flags= 0;
if (m_blobs_count[distinct])
{
/*
@@ -21521,10 +21523,11 @@ bool Create_tmp_table::finalize(THD *thd,
indexes on blobs with arbitrary length. Such indexes cannot be
used for lookups.
*/
- share->uniques= 1;
+ keyinfo->flags|= HA_UNIQUE_HASH;
}
keyinfo->user_defined_key_parts= m_field_count[distinct] +
- (share->uniques ? MY_TEST(null_pack_length[distinct]) : 0);
+ ((keyinfo->flags & HA_UNIQUE_HASH) ?
+ MY_TEST(null_pack_length[distinct]) : 0);
keyinfo->ext_key_parts= keyinfo->user_defined_key_parts;
keyinfo->usable_key_parts= keyinfo->user_defined_key_parts;
table->distinct= 1;
@@ -21539,7 +21542,8 @@ bool Create_tmp_table::finalize(THD *thd,
share->keys_in_use.set_bit(0);
table->key_info= table->s->key_info= keyinfo;
keyinfo->key_part= m_key_part_info;
- keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL | HA_BINARY_PACK_KEY | HA_PACK_KEY;
+ keyinfo->flags|= (HA_NOSAME | HA_NULL_ARE_EQUAL | HA_BINARY_PACK_KEY |
+ HA_PACK_KEY);
keyinfo->ext_key_flags= keyinfo->flags;
keyinfo->key_length= 0; // Will compute the sum of the parts below.
keyinfo->name= distinct_key;
@@ -21568,7 +21572,7 @@ bool Create_tmp_table::finalize(THD *thd,
blobs can distinguish NULL from 0. This extra field is not needed
when we do not use UNIQUE indexes for blobs.
*/
- if (null_pack_length[distinct] && share->uniques)
+ if (null_pack_length[distinct] && (keyinfo->flags & HA_UNIQUE_HASH))
{
m_key_part_info->null_bit=0;
m_key_part_info->offset= null_pack_base[distinct];
@@ -21986,113 +21990,125 @@ bool open_tmp_table(TABLE *table)
*/
-bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
+bool create_internal_tmp_table(TABLE *table, KEY *org_keyinfo,
TMP_ENGINE_COLUMNDEF *start_recinfo,
TMP_ENGINE_COLUMNDEF **recinfo,
ulonglong options)
{
int error;
- MARIA_KEYDEF keydef;
+ MARIA_KEYDEF *keydefs= 0, *keydef;
MARIA_UNIQUEDEF uniquedef;
TABLE_SHARE *share= table->s;
MARIA_CREATE_INFO create_info;
+ bool use_unique= false;
DBUG_ENTER("create_internal_tmp_table");
if (share->keys)
{ // Get keys for ni_create
- bool using_unique_constraint=0;
- HA_KEYSEG *seg= (HA_KEYSEG*) alloc_root(&table->mem_root,
- sizeof(*seg) * keyinfo->user_defined_key_parts);
- if (!seg)
- goto err;
+ HA_KEYSEG *seg;
+ DBUG_ASSERT(share->key_parts);
- bzero(seg, sizeof(*seg) * keyinfo->user_defined_key_parts);
- /*
- Note that a similar check is performed during
- subquery_types_allow_materialization. See MDEV-7122 for more details as
- to why. Whenever this changes, it must be updated there as well, for
- all tmp_table engines.
- */
- if (keyinfo->key_length > table->file->max_key_length() ||
- keyinfo->user_defined_key_parts > table->file->max_key_parts() ||
- share->uniques)
- {
- if (!share->uniques && !(keyinfo->flags & HA_NOSAME))
- {
- my_error(ER_INTERNAL_ERROR, MYF(0),
- "Using too big key for internal temp tables");
- DBUG_RETURN(1);
- }
-
- /* Can't create a key; Make a unique constraint instead of a key */
- share->keys= 0;
- share->key_parts= share->ext_key_parts= 0;
- share->uniques= 1;
- using_unique_constraint=1;
- bzero((char*) &uniquedef,sizeof(uniquedef));
- uniquedef.keysegs=keyinfo->user_defined_key_parts;
- uniquedef.seg=seg;
- uniquedef.null_are_equal=1;
+ if (!(multi_alloc_root(&table->mem_root,
+ &seg, sizeof(*seg) * share->key_parts,
+ &keydefs, sizeof(*keydefs) * share->keys,
+ NullS)))
+ goto err;
+ keydef= keydefs;
- /* Create extra column for hash value */
- bzero((uchar*) *recinfo,sizeof(**recinfo));
- (*recinfo)->type= FIELD_CHECK;
- (*recinfo)->length= MARIA_UNIQUE_HASH_LENGTH;
- (*recinfo)++;
+ bzero(seg, sizeof(*seg) * share->key_parts);
- /* Avoid warnings from valgrind */
- bzero(table->record[0]+ share->reclength, MARIA_UNIQUE_HASH_LENGTH);
- bzero(share->default_values+ share->reclength, MARIA_UNIQUE_HASH_LENGTH);
- share->reclength+= MARIA_UNIQUE_HASH_LENGTH;
- }
- else
- {
- /* Create a key */
- bzero((char*) &keydef,sizeof(keydef));
- keydef.flag= keyinfo->flags & HA_NOSAME;
- keydef.keysegs= keyinfo->user_defined_key_parts;
- keydef.seg= seg;
- }
- for (uint i=0; i < keyinfo->user_defined_key_parts ; i++,seg++)
+ /* Note that share->keys may change in the loop ! */
+ for (KEY *keyinfo= org_keyinfo, *end_keyinfo= keyinfo + share->keys;
+ keyinfo < end_keyinfo ;
+ keyinfo++)
{
- Field *field=keyinfo->key_part[i].field;
- seg->flag= 0;
- seg->language= field->charset()->number;
- seg->length= keyinfo->key_part[i].length;
- seg->start= keyinfo->key_part[i].offset;
- if (field->flags & BLOB_FLAG)
+ /*
+ Note that a similar check is performed during
+ subquery_types_allow_materialization. See MDEV-7122 for more details as
+ to why. Whenever this changes, it must be updated there as well, for
+ all tmp_table engines.
+ */
+ if (keyinfo->key_length > table->file->max_key_length() ||
+ keyinfo->user_defined_key_parts > table->file->max_key_parts() ||
+ (keyinfo->flags & HA_UNIQUE_HASH))
{
- seg->type=
- ((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
- HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
- seg->bit_start= (uint8)(field->pack_length() -
- portable_sizeof_char_ptr);
- seg->flag= HA_BLOB_PART;
- seg->length=0; // Whole blob in unique constraint
+ if (!(keyinfo->flags & (HA_NOSAME | HA_UNIQUE_HASH)))
+ {
+ my_error(ER_INTERNAL_ERROR, MYF(0),
+ "Using too big key for internal temp tables");
+ DBUG_RETURN(1);
+ }
+ /* Can't create a key; Make a unique constraint instead of a key */
+ share->keys--;
+ share->key_parts-= keyinfo->user_defined_key_parts;
+ share->ext_key_parts-= keyinfo->ext_key_parts;
+ use_unique= true;
+ bzero((char*) &uniquedef,sizeof(uniquedef));
+ uniquedef.keysegs= keyinfo->user_defined_key_parts;
+ uniquedef.seg=seg;
+ uniquedef.null_are_equal=1;
+ keyinfo->flags|= HA_UNIQUE_HASH;
+ keyinfo->algorithm= HA_KEY_ALG_UNIQUE_HASH;
+
+ /* Create extra column for hash value */
+ bzero((uchar*) *recinfo,sizeof(**recinfo));
+ (*recinfo)->type= FIELD_CHECK;
+ (*recinfo)->length= MARIA_UNIQUE_HASH_LENGTH;
+ (*recinfo)++;
+
+ /* Avoid warnings from valgrind */
+ bzero(table->record[0]+ share->reclength, MARIA_UNIQUE_HASH_LENGTH);
+ bzero(share->default_values+ share->reclength,
+ MARIA_UNIQUE_HASH_LENGTH);
+ share->reclength+= MARIA_UNIQUE_HASH_LENGTH;
}
else
{
- seg->type= keyinfo->key_part[i].type;
- /* Tell handler if it can do suffic space compression */
- if (field->real_type() == MYSQL_TYPE_STRING &&
- keyinfo->key_part[i].length > 32)
- seg->flag|= HA_SPACE_PACK;
- }
- if (!(field->flags & NOT_NULL_FLAG))
- {
- seg->null_bit= field->null_bit;
- seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]);
- /*
- We are using a GROUP BY on something that contains NULL
- In this case we have to tell Aria that two NULL should
- on INSERT be regarded at the same value
- */
- if (!using_unique_constraint)
- keydef.flag|= HA_NULL_ARE_EQUAL;
+ /* Create a key */
+ bzero((char*) keydef,sizeof(*keydef));
+ /*
+ We are using a GROUP BY on something that contains NULL
+ In this case we have to tell Aria that two NULL should
+ on INSERT be regarded at the same value.
+ */
+ keydef->flag= (keyinfo->flags & HA_NOSAME) | HA_NULL_ARE_EQUAL;
+ keydef->keysegs= keyinfo->user_defined_key_parts;
+ keydef->seg= seg;
+ keydef++;
+ }
+ for (uint i=0; i < keyinfo->user_defined_key_parts ; i++,seg++)
+ {
+ Field *field=keyinfo->key_part[i].field;
+ seg->flag= 0;
+ seg->language= field->charset()->number;
+ seg->length= keyinfo->key_part[i].length;
+ seg->start= keyinfo->key_part[i].offset;
+ if (field->flags & BLOB_FLAG)
+ {
+ seg->type=
+ ((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
+ HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
+ seg->bit_start= (uint8)(field->pack_length() -
+ portable_sizeof_char_ptr);
+ seg->flag= HA_BLOB_PART;
+ seg->length=0; // Whole blob in unique constraint
+ }
+ else
+ {
+ seg->type= keyinfo->key_part[i].type;
+ /* Tell handler if it can do suffic space compression */
+ if (field->real_type() == MYSQL_TYPE_STRING &&
+ keyinfo->key_part[i].length > 32)
+ seg->flag|= HA_SPACE_PACK;
+ }
+ if (!(field->flags & NOT_NULL_FLAG))
+ {
+ seg->null_bit= field->null_bit;
+ seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]);
+ }
}
- }
- if (share->keys)
keyinfo->index_flags= table->file->index_flags(0, 0, 1);
+ }
}
bzero((char*) &create_info,sizeof(create_info));
create_info.data_file_length= table->in_use->variables.tmp_disk_table_size;
@@ -22138,8 +22154,8 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
}
if (unlikely((error= maria_create(share->path.str, file_type, share->keys,
- &keydef, (uint) (*recinfo-start_recinfo),
- start_recinfo, share->uniques, &uniquedef,
+ keydefs, (uint) (*recinfo-start_recinfo),
+ start_recinfo, use_unique, &uniquedef,
&create_info, create_flags))))
{
table->file->print_error(error,MYF(0)); /* purecov: inspected */
@@ -22191,7 +22207,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
/* Create internal MyISAM temporary table */
-bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
+bool create_internal_tmp_table(TABLE *table, KEY *org_keyinfo,
TMP_ENGINE_COLUMNDEF *start_recinfo,
TMP_ENGINE_COLUMNDEF **recinfo,
ulonglong options)
@@ -22206,11 +22222,12 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
{ // Get keys for ni_create
bool using_unique_constraint=0;
HA_KEYSEG *seg= (HA_KEYSEG*) alloc_root(&table->mem_root,
- sizeof(*seg) * keyinfo->user_defined_key_parts);
+ sizeof(*seg) *
+ share->user_defined_key_parts);
if (!seg)
goto err;
- bzero(seg, sizeof(*seg) * keyinfo->user_defined_key_parts);
+ bzero(seg, sizeof(*seg) * share->user_defined_key_parts);
/*
Note that a similar check is performed during
subquery_types_allow_materialization. See MDEV-7122 for more details as
@@ -22546,7 +22563,7 @@ void set_postjoin_aggr_write_func(JOIN_TAB *tab)
Note for MyISAM tmp tables: if uniques is true keys won't be
created.
*/
- if (table->s->keys && !table->s->uniques)
+ if (table->s->keys && !table->s->have_unique_constraint())
{
DBUG_PRINT("info",("Using end_update"));
aggr->set_write_func(end_update);
@@ -22856,6 +22873,8 @@ bool instantiate_tmp_table(TABLE *table, KEY *keyinfo,
TMP_ENGINE_COLUMNDEF **recinfo,
ulonglong options)
{
+ DBUG_ASSERT(table->s->keys == 0 || table->key_info == keyinfo);
+ DBUG_ASSERT(table->s->keys <= 1);
if (table->s->db_type() == TMP_ENGINE_HTON)
{
/*
@@ -24768,7 +24787,6 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_RETURN(NESTED_LOOP_ERROR); // Not a table_is_full error
if (is_duplicate)
goto end;
- table->s->uniques=0; // To ensure rows are the same
}
if (++join_tab->send_records >=
join_tab->tmp_table_param->end_write_records &&