diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_subselect.cc | 2 | ||||
-rw-r--r-- | sql/opt_subselect.cc | 6 | ||||
-rw-r--r-- | sql/sql_select.cc | 212 | ||||
-rw-r--r-- | sql/sql_show.cc | 1 | ||||
-rw-r--r-- | sql/table.h | 13 |
5 files changed, 132 insertions, 102 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 80228917210..3adc65008e0 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -5266,7 +5266,7 @@ bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id) //fprintf(stderr, "Q: %s\n", current_thd->query()); DBUG_ASSERT(0); DBUG_ASSERT( - tmp_table->s->uniques || + (tmp_table->key_info->flags & HA_UNIQUE_HASH) || tmp_table->key_info->key_length >= tmp_table->file->max_key_length() || tmp_table->key_info->user_defined_key_parts > tmp_table->file->max_key_parts()); diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 1d0b1ff1874..94adae02a17 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -4903,11 +4903,13 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd) { DBUG_PRINT("info",("Creating group key in temporary table")); share->keys=1; - share->uniques= MY_TEST(using_unique_constraint); table->key_info= share->key_info= keyinfo; keyinfo->key_part=key_part_info; - keyinfo->flags=HA_NOSAME; + keyinfo->flags= HA_NOSAME | (using_unique_constraint ? HA_UNIQUE_HASH : 0); + keyinfo->ext_key_flags= keyinfo->flags; keyinfo->usable_key_parts= keyinfo->user_defined_key_parts= 1; + keyinfo->ext_key_parts= 1; + share->key_parts= 1; keyinfo->key_length=0; keyinfo->rec_per_key=0; keyinfo->algorithm= HA_KEY_ALG_UNDEF; 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 && diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1a99f6f0bae..fa95aa66b0f 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -8841,7 +8841,6 @@ bool optimize_schema_tables_memory_usage(List<TABLE_LIST> &tables) TMP_TABLE_PARAM *p= table_list->schema_table_param; TMP_ENGINE_COLUMNDEF *from_recinfo, *to_recinfo; DBUG_ASSERT(table->s->keys == 0); - DBUG_ASSERT(table->s->uniques == 0); uchar *cur= table->field[0]->ptr; /* first recinfo could be a NULL bitmap, not an actual Field */ diff --git a/sql/table.h b/sql/table.h index c67a5783c89..3874ccacb9a 100644 --- a/sql/table.h +++ b/sql/table.h @@ -853,7 +853,18 @@ struct TABLE_SHARE uint keys, key_parts; uint ext_key_parts; /* Total number of key parts in extended keys */ uint max_key_length, max_unique_length; - uint uniques; /* Number of UNIQUE index */ + + /* + Older versions had TABLE_SHARE::uniques but now it is replaced with + per-index HA_UNIQUE_HASH flag + */ + bool have_unique_constraint() const + { + for (uint i=0; i < keys; i++) + if (key_info[i].flags & HA_UNIQUE_HASH) + return true; + return false; + } uint db_create_options; /* Create options from database */ uint db_options_in_use; /* Options in use */ uint db_record_offset; /* if HA_REC_IN_SEQ */ |