diff options
author | Alexander Barkov <bar@mariadb.com> | 2019-05-25 11:40:48 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2019-05-25 11:41:18 +0400 |
commit | ac93d7d674cd9955c940055d9777e98a1fbaf1cd (patch) | |
tree | 3c5adc1e030576cbf9bbd98741b737e32a5dba35 | |
parent | 0928596a8bd54c3ec85462eb4993464eac19f8f2 (diff) | |
download | mariadb-git-ac93d7d674cd9955c940055d9777e98a1fbaf1cd.tar.gz |
MDEV-19593 Split create_schema_table() into virtual methods in Type_handler
-rw-r--r-- | sql/field.h | 20 | ||||
-rw-r--r-- | sql/item.h | 41 | ||||
-rw-r--r-- | sql/sql_profile.h | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 728 | ||||
-rw-r--r-- | sql/sql_select.h | 7 | ||||
-rw-r--r-- | sql/sql_show.cc | 130 | ||||
-rw-r--r-- | sql/sql_type.cc | 190 | ||||
-rw-r--r-- | sql/sql_type.h | 90 | ||||
-rw-r--r-- | sql/table.h | 10 |
9 files changed, 750 insertions, 468 deletions
diff --git a/sql/field.h b/sql/field.h index ceb4a8bb93f..286265c6832 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1142,6 +1142,8 @@ public: { return Information_schema_character_attributes(); } + virtual void update_data_type_statistics(Data_type_statistics *st) const + { } /* Caller beware: sql_type can change str.Ptr, so check ptr() to see if it changed if you are using your own buffer @@ -3566,6 +3568,11 @@ public: my_decimal *val_decimal(my_decimal *); int cmp(const uchar *,const uchar *); void sort_string(uchar *buff,uint length); + void update_data_type_statistics(Data_type_statistics *st) const + { + st->m_fixed_string_count++; + st->m_fixed_string_total_length+= pack_length(); + } void sql_type(String &str) const; uint is_equal(Create_field *new_field); virtual uchar *pack(uchar *to, const uchar *from, @@ -3663,6 +3670,11 @@ public: !compression_method() == !from->compression_method() && length_bytes == ((Field_varstring*) from)->length_bytes; } + void update_data_type_statistics(Data_type_statistics *st) const + { + st->m_variable_string_count++; + st->m_variable_string_total_length+= pack_length(); + } int store(const char *to,size_t length,CHARSET_INFO *charset); using Field_str::store; double val_real(void); @@ -3869,6 +3881,10 @@ public: uint32 chars= octets / field_charset->mbminlen; return Information_schema_character_attributes(octets, chars); } + void update_data_type_statistics(Data_type_statistics *st) const + { + st->m_blob_count++; + } void make_send_field(Send_field *); Copy_func *get_copy_func(const Field *from) const { @@ -4346,6 +4362,10 @@ public: { return Information_schema_numeric_attributes(field_length); } + void update_data_type_statistics(Data_type_statistics *st) const + { + st->m_uneven_bit_length+= field_length & 7; + } uint size_of() const { return sizeof(*this); } int reset(void) { bzero(ptr, bytes_in_rec); diff --git a/sql/item.h b/sql/item.h index 45110265cd3..cb36475ecc0 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1506,7 +1506,6 @@ public: virtual Field *get_tmp_table_field() { return 0; } virtual Field *create_field_for_create_select(TABLE *table); - virtual Field *create_field_for_schema(THD *thd, TABLE *table); virtual const char *full_name() const { return name.str ? name.str : "???"; } const char *field_name_or_null() { return real_item()->type() == Item::FIELD_ITEM ? name.str : NULL; } @@ -4492,46 +4491,6 @@ public: }; -class Item_return_date_time :public Item_partition_func_safe_string -{ - enum_field_types date_time_field_type; -public: - Item_return_date_time(THD *thd, const LEX_CSTRING &name_arg, - enum_field_types field_type_arg, uint dec_arg= 0): - Item_partition_func_safe_string(thd, name_arg, - 0/*length is not important*/, - &my_charset_bin), - date_time_field_type(field_type_arg) - { decimals= dec_arg; } - const Type_handler *type_handler() const - { - return Type_handler::get_handler_by_field_type(date_time_field_type); - } -}; - - -class Item_blob :public Item_partition_func_safe_string -{ -public: - Item_blob(THD *thd, const LEX_CSTRING &name_arg, uint length): - Item_partition_func_safe_string(thd, name_arg, length, &my_charset_bin) - { } - enum Type type() const { return TYPE_HOLDER; } - const Type_handler *type_handler() const - { - return Type_handler::blob_type_handler(max_length); - } - const Type_handler *real_type_handler() const - { - // Should not be called, Item_blob is used for SHOW purposes only. - DBUG_ASSERT(0); - return &type_handler_varchar; - } - Field *create_field_for_schema(THD *thd, TABLE *table) - { return tmp_table_field_from_field_type(table); } -}; - - /** Item_empty_string -- is a utility class to put an item into List<Item> which is then used in protocol.send_result_set_metadata() when sending SHOW output to diff --git a/sql/sql_profile.h b/sql/sql_profile.h index 5b03acf59c0..7ec20f6aaa7 100644 --- a/sql/sql_profile.h +++ b/sql/sql_profile.h @@ -19,7 +19,7 @@ class Item; struct TABLE_LIST; class THD; -typedef struct st_field_info ST_FIELD_INFO; +struct ST_FIELD_INFO; typedef struct st_schema_table ST_SCHEMA_TABLE; extern ST_FIELD_INFO query_profile_statistics_info[]; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 28e4e6bd1f0..b0e15145bc1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -17461,42 +17461,6 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table) /** - Create field for information schema table. - - @param thd Thread handler - @param table Temporary table - @param item Item to create a field for - - @retval - 0 on error - @retval - new_created field -*/ - -Field *Item::create_field_for_schema(THD *thd, TABLE *table) -{ - if (field_type() == MYSQL_TYPE_VARCHAR) - { - Field *field; - if (max_length > MAX_FIELD_VARCHARLENGTH) - field= new (thd->mem_root) Field_blob(max_length, maybe_null, &name, - collation.collation); - else if (max_length > 0) - field= new (thd->mem_root) Field_varstring(max_length, maybe_null, &name, - table->s, - collation.collation); - else - field= new Field_null((uchar*) 0, 0, Field::NONE, &name, - collation.collation); - if (field) - field->init(table); - return field; - } - return tmp_table_field_from_field_type(table); -} - - -/** Create a temporary field for Item_field (or its descendant), either direct or referenced by an Item_ref. */ @@ -17749,6 +17713,91 @@ setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps) } +class Create_tmp_table: public Data_type_statistics +{ + // The following members are initialized only in start() + Field **m_from_field, **m_default_field; + KEY_PART_INFO *m_key_part_info; + uchar *m_group_buff, *m_bitmaps; + // The following members are initialized in ctor + uint m_alloced_field_count; + bool m_using_unique_constraint; + uint m_temp_pool_slot; + ORDER *m_group; + bool m_distinct; + bool m_save_sum_fields; + ulonglong m_select_options; + ha_rows m_rows_limit; + uint m_hidden_field_count; // Remove this eventually + uint m_group_null_items; + uint m_null_count; + uint m_hidden_uneven_bit_length; + uint m_hidden_null_count; +public: + Create_tmp_table(const TMP_TABLE_PARAM *param, + ORDER *group, bool distinct, bool save_sum_fields, + ulonglong select_options, ha_rows rows_limit) + :m_alloced_field_count(0), + m_using_unique_constraint(false), + m_temp_pool_slot(MY_BIT_NONE), + m_group(group), + m_distinct(distinct), + m_save_sum_fields(save_sum_fields), + m_select_options(select_options), + m_rows_limit(rows_limit), + m_hidden_field_count(param->hidden_field_count), + m_group_null_items(0), + m_null_count(0), + m_hidden_uneven_bit_length(0), + m_hidden_null_count(0) + { } + + void add_field(TABLE *table, Field *field, uint fieldnr, bool force_not_null_cols); + + TABLE *start(THD *thd, + TMP_TABLE_PARAM *param, + const LEX_CSTRING *table_alias); + + bool add_fields(THD *thd, TABLE *table, + TMP_TABLE_PARAM *param, List<Item> &fields); + + bool add_schema_fields(THD *thd, TABLE *table, + TMP_TABLE_PARAM *param, + const ST_SCHEMA_TABLE &schema_table, + const MY_BITMAP &bitmap); + + bool finalize(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, + bool do_not_open, bool keep_row_order); + void cleanup_on_failure(THD *thd, TABLE *table); +}; + + +void Create_tmp_table::add_field(TABLE *table, Field *field, uint fieldnr, bool force_not_null_cols) +{ + DBUG_ASSERT(!field->field_name.str || strlen(field->field_name.str) == field->field_name.length); + + if (force_not_null_cols) + { + field->flags|= NOT_NULL_FLAG; + field->null_ptr= NULL; + } + + if (!(field->flags & NOT_NULL_FLAG)) + m_null_count++; + + table->s->reclength+= field->pack_length(); + + // Assign it here, before update_data_type_statistics() changes m_blob_count + if (field->flags & BLOB_FLAG) + table->s->blob_field[m_blob_count]= fieldnr; + + table->field[fieldnr]= field; + field->field_index= fieldnr; + + field->update_data_type_statistics(this); +} + + /** Create a temp table according to a field list. @@ -17783,57 +17832,32 @@ setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps) inserted, the engine should preserve this order */ -TABLE * -create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, - ORDER *group, bool distinct, bool save_sum_fields, - ulonglong select_options, ha_rows rows_limit, - const LEX_CSTRING *table_alias, bool do_not_open, - bool keep_row_order) +TABLE *Create_tmp_table::start(THD *thd, + TMP_TABLE_PARAM *param, + const LEX_CSTRING *table_alias) { MEM_ROOT *mem_root_save, own_root; TABLE *table; TABLE_SHARE *share; - uint i,field_count,null_count,null_pack_length; uint copy_func_count= param->func_count; - uint hidden_null_count, hidden_null_pack_length, hidden_field_count; - uint blob_count,group_null_items, string_count; - uint temp_pool_slot=MY_BIT_NONE; - uint fieldnr= 0; - ulong reclength, string_total_length; - bool using_unique_constraint= false; - bool use_packed_rows= false; - bool not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS); char *tmpname,path[FN_REFLEN]; - uchar *pos, *group_buff, *bitmaps; - uchar *null_flags; - Field **reg_field, **from_field, **default_field; + Field **reg_field; uint *blob_field; - Copy_field *copy=0; - KEY *keyinfo; - KEY_PART_INFO *key_part_info; - Item **copy_func; - TMP_ENGINE_COLUMNDEF *recinfo; - /* - total_uneven_bit_length is uneven bit length for visible fields - hidden_uneven_bit_length is uneven bit length for hidden fields - */ - uint total_uneven_bit_length= 0, hidden_uneven_bit_length= 0; - bool force_copy_fields= param->force_copy_fields; /* Treat sum functions as normal ones when loose index scan is used. */ - save_sum_fields|= param->precomputed_group_by; - DBUG_ENTER("create_tmp_table"); + m_save_sum_fields|= param->precomputed_group_by; + DBUG_ENTER("Create_tmp_table::start"); DBUG_PRINT("enter", ("table_alias: '%s' distinct: %d save_sum_fields: %d " "rows_limit: %lu group: %d", table_alias->str, - (int) distinct, (int) save_sum_fields, - (ulong) rows_limit, MY_TEST(group))); + (int) m_distinct, (int) m_save_sum_fields, + (ulong) m_rows_limit, MY_TEST(m_group))); if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES)) - temp_pool_slot = bitmap_lock_set_next(&temp_pool); + m_temp_pool_slot = bitmap_lock_set_next(&temp_pool); - if (temp_pool_slot != MY_BIT_NONE) // we got a slot + if (m_temp_pool_slot != MY_BIT_NONE) // we got a slot sprintf(path, "%s-%lx-%i", tmp_file_prefix, - current_pid, temp_pool_slot); + current_pid, m_temp_pool_slot); else { /* if we run out of slots or we are not using tempool */ @@ -17848,12 +17872,12 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, fn_format(path, path, mysql_tmpdir, "", MY_REPLACE_EXT|MY_UNPACK_FILENAME); - if (group) + if (m_group) { - ORDER **prev= &group; + ORDER **prev= &m_group; if (!param->quick_group) - group=0; // Can't use group key - else for (ORDER *tmp=group ; tmp ; tmp=tmp->next) + m_group= 0; // Can't use group key + else for (ORDER *tmp= m_group ; tmp ; tmp= tmp->next) { /* Exclude found constant from the list */ if ((*tmp->item)->const_item()) @@ -17872,16 +17896,17 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, */ (*tmp->item)->marker=4; // Store null in key if ((*tmp->item)->too_big_for_varchar()) - using_unique_constraint= true; + m_using_unique_constraint= true; } if (param->group_length >= MAX_BLOB_WIDTH) - using_unique_constraint= true; - if (group) - distinct=0; // Can't use distinct + m_using_unique_constraint= true; + if (m_group) + m_distinct= 0; // Can't use distinct } - field_count=param->field_count+param->func_count+param->sum_func_count; - hidden_field_count=param->hidden_field_count; + m_alloced_field_count= param->field_count+param->func_count+param->sum_func_count; + DBUG_ASSERT(m_alloced_field_count); + const uint field_count= m_alloced_field_count; /* When loose index scan is employed as access method, it already @@ -17900,41 +17925,37 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, &table, sizeof(*table), &share, sizeof(*share), ®_field, sizeof(Field*) * (field_count+1), - &default_field, sizeof(Field*) * (field_count), + &m_default_field, sizeof(Field*) * (field_count), &blob_field, sizeof(uint)*(field_count+1), - &from_field, sizeof(Field*)*field_count, - ©_func, sizeof(*copy_func)*(copy_func_count+1), + &m_from_field, sizeof(Field*)*field_count, + ¶m->items_to_copy, + sizeof(param->items_to_copy[0])*(copy_func_count+1), ¶m->keyinfo, sizeof(*param->keyinfo), - &key_part_info, - sizeof(*key_part_info)*(param->group_parts+1), + &m_key_part_info, + sizeof(*m_key_part_info)*(param->group_parts+1), ¶m->start_recinfo, sizeof(*param->recinfo)*(field_count*2+4), &tmpname, (uint) strlen(path)+1, - &group_buff, (group && ! using_unique_constraint ? + &m_group_buff, (m_group && ! m_using_unique_constraint ? param->group_length : 0), - &bitmaps, bitmap_buffer_size(field_count)*6, + &m_bitmaps, bitmap_buffer_size(field_count)*6, NullS)) { - if (temp_pool_slot != MY_BIT_NONE) - bitmap_lock_clear_bit(&temp_pool, temp_pool_slot); DBUG_RETURN(NULL); /* purecov: inspected */ } /* Copy_field belongs to TMP_TABLE_PARAM, allocate it in THD mem_root */ - if (!(param->copy_field= copy= new (thd->mem_root) Copy_field[field_count])) + if (!(param->copy_field= new (thd->mem_root) Copy_field[field_count])) { - if (temp_pool_slot != MY_BIT_NONE) - bitmap_lock_clear_bit(&temp_pool, temp_pool_slot); free_root(&own_root, MYF(0)); /* purecov: inspected */ DBUG_RETURN(NULL); /* purecov: inspected */ } - param->items_to_copy= copy_func; strmov(tmpname, path); /* make table according to fields */ bzero((char*) table,sizeof(*table)); - bzero((char*) reg_field,sizeof(Field*)*(field_count+1)); - bzero((char*) default_field, sizeof(Field*) * (field_count)); - bzero((char*) from_field,sizeof(Field*)*field_count); + bzero((char*) reg_field, sizeof(Field*) * (field_count+1)); + bzero((char*) m_default_field, sizeof(Field*) * (field_count)); + bzero((char*) m_from_field, sizeof(Field*) * field_count); table->mem_root= own_root; mem_root_save= thd->mem_root; @@ -17945,7 +17966,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, table->reginfo.lock_type=TL_WRITE; /* Will be updated */ table->map=1; - table->temp_pool_slot = temp_pool_slot; + table->temp_pool_slot= m_temp_pool_slot; table->copy_blobs= 1; table->in_use= thd; table->no_rows_with_nulls= param->force_not_null_cols; @@ -17960,15 +17981,36 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, if (param->schema_table) share->db= INFORMATION_SCHEMA_NAME; - /* Calculate which type of fields we will store in the temporary table */ - - reclength= string_total_length= 0; - blob_count= string_count= null_count= hidden_null_count= group_null_items= 0; param->using_outer_summary_function= 0; + thd->mem_root= mem_root_save; + DBUG_RETURN(table); +} + + +bool Create_tmp_table::add_fields(THD *thd, + TABLE *table, + TMP_TABLE_PARAM *param, + List<Item> &fields) +{ + DBUG_ENTER("Create_tmp_table::add_fields"); + DBUG_ASSERT(table); + DBUG_ASSERT(table->field); + DBUG_ASSERT(table->s->blob_field); + DBUG_ASSERT(table->s->reclength == 0); + DBUG_ASSERT(table->s->fields == 0); + DBUG_ASSERT(table->s->blob_fields == 0); + + const bool not_all_columns= !(m_select_options & TMP_TABLE_ALL_COLUMNS); + uint fieldnr= 0; + TABLE_SHARE *share= table->s; + Item **copy_func= param->items_to_copy; + + MEM_ROOT *mem_root_save= thd->mem_root; + thd->mem_root= &table->mem_root; List_iterator_fast<Item> li(fields); Item *item; - Field **tmp_from_field=from_field; + Field **tmp_from_field= m_from_field; while ((item=li++)) { Item::Type type= item->type(); @@ -17995,14 +18037,14 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, continue; } } - if (item->const_item() && (int) hidden_field_count <= 0) + if (item->const_item() && (int) m_hidden_field_count <= 0) continue; // We don't have to store this } - if (type == Item::SUM_FUNC_ITEM && !group && !save_sum_fields) + if (type == Item::SUM_FUNC_ITEM && !m_group && !m_save_sum_fields) { /* Can't calc group yet */ Item_sum *sum_item= (Item_sum *) item; sum_item->result_field=0; - for (i=0 ; i < sum_item->get_arg_count() ; i++) + for (uint i= 0 ; i < sum_item->get_arg_count() ; i++) { Item *arg= sum_item->get_arg(i); if (!arg->const_item()) @@ -18010,49 +18052,30 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, Item *tmp_item; Field *new_field= create_tmp_field(table, arg, ©_func, - tmp_from_field, &default_field[fieldnr], - group != 0,not_all_columns, - distinct, false); + tmp_from_field, &m_default_field[fieldnr], + m_group != 0, not_all_columns, + m_distinct, false); if (!new_field) goto err; // Should be OOM - DBUG_ASSERT(!new_field->field_name.str || strlen(new_field->field_name.str) == new_field->field_name.length); tmp_from_field++; - reclength+=new_field->pack_length(); - if (new_field->flags & BLOB_FLAG) - { - *blob_field++= fieldnr; - blob_count++; - } - if (new_field->type() == MYSQL_TYPE_BIT) - total_uneven_bit_length+= new_field->field_length & 7; - *(reg_field++)= new_field; - if (new_field->real_type() == MYSQL_TYPE_STRING || - new_field->real_type() == MYSQL_TYPE_VARCHAR) - { - string_count++; - string_total_length+= new_field->pack_length(); - } + thd->mem_root= mem_root_save; if (!(tmp_item= new (thd->mem_root) Item_temptable_field(thd, new_field))) goto err; arg= sum_item->set_arg(i, thd, tmp_item); thd->mem_root= &table->mem_root; - if (param->force_not_null_cols) - { - new_field->flags|= NOT_NULL_FLAG; - new_field->null_ptr= NULL; - } + + add_field(table, new_field, fieldnr++, param->force_not_null_cols); + if (!(new_field->flags & NOT_NULL_FLAG)) { - null_count++; /* new_field->maybe_null() is still false, it will be changed below. But we have to setup Item_field correctly */ arg->maybe_null=1; } - new_field->field_index= fieldnr++; } } } @@ -18071,13 +18094,13 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, The test for item->marker == 4 is ensure we don't create a group-by key over a bit field as heap tables can't handle that. */ - Field *new_field= (param->schema_table) ? - item->create_field_for_schema(thd, table) : + DBUG_ASSERT(!param->schema_table); + Field *new_field= create_tmp_field(table, item, ©_func, - tmp_from_field, &default_field[fieldnr], - group != 0, - !force_copy_fields && - (not_all_columns || group !=0), + tmp_from_field, &m_default_field[fieldnr], + m_group != 0, + !param->force_copy_fields && + (not_all_columns || m_group !=0), /* If item->marker == 4 then we force create_tmp_field to create a 64-bit longs for BIT fields because HEAP @@ -18086,14 +18109,13 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, to be usable in this case too. */ item->marker == 4 || param->bit_fields_as_long, - force_copy_fields); + param->force_copy_fields); if (!new_field) { if (unlikely(thd->is_fatal_error)) goto err; // Got OOM continue; // Some kind of const item } - DBUG_ASSERT(!new_field->field_name.str || strlen(new_field->field_name.str) == new_field->field_name.length); if (type == Item::SUM_FUNC_ITEM) { Item_sum *agg_item= (Item_sum *) item; @@ -18120,82 +18142,92 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, agg_item->result_field= new_field; } tmp_from_field++; - if (param->force_not_null_cols) - { - new_field->flags|= NOT_NULL_FLAG; - new_field->null_ptr= NULL; - } - reclength+=new_field->pack_length(); - if (!(new_field->flags & NOT_NULL_FLAG)) - null_count++; - if (new_field->type() == MYSQL_TYPE_BIT) - total_uneven_bit_length+= new_field->field_length & 7; - if (new_field->flags & BLOB_FLAG) - { - *blob_field++= fieldnr; - blob_count++; - } - if (new_field->real_type() == MYSQL_TYPE_STRING || - new_field->real_type() == MYSQL_TYPE_VARCHAR) - { - string_count++; - string_total_length+= new_field->pack_length(); - } + add_field(table, new_field, fieldnr++, param->force_not_null_cols); if (item->marker == 4 && item->maybe_null) { - group_null_items++; + m_group_null_items++; new_field->flags|= GROUP_FLAG; } - new_field->field_index= fieldnr++; - *(reg_field++)= new_field; } - if (!--hidden_field_count) + if (!--m_hidden_field_count) { /* This was the last hidden field; Remember how many hidden fields could have null */ - hidden_null_count=null_count; + m_hidden_null_count= m_null_count; /* We need to update hidden_field_count as we may have stored group functions with constant arguments */ param->hidden_field_count= fieldnr; - null_count= 0; + m_null_count= 0; /* On last hidden field we store uneven bit length in - hidden_uneven_bit_length and proceed calculation of - uneven bits for visible fields into - total_uneven_bit_length variable. + m_hidden_uneven_bit_length and proceed calculation of + uneven bits for visible fields into m_uneven_bit_length. */ - hidden_uneven_bit_length= total_uneven_bit_length; - total_uneven_bit_length= 0; + m_hidden_uneven_bit_length= m_uneven_bit_length; + m_uneven_bit_length= 0; } } - DBUG_ASSERT(fieldnr == (uint) (reg_field - table->field)); - DBUG_ASSERT(field_count >= (uint) (reg_field - table->field)); - field_count= fieldnr; - *reg_field= 0; - *blob_field= 0; // End marker - share->fields= field_count; + share->fields= fieldnr; + share->blob_fields= m_blob_count; + table->field[fieldnr]= 0; // End marker + share->blob_field[m_blob_count]= 0; // End marker + copy_func[0]= 0; // End marker + param->func_count= (uint) (copy_func - param->items_to_copy); share->column_bitmap_size= bitmap_buffer_size(share->fields); + thd->mem_root= mem_root_save; + DBUG_RETURN(false); + +err: + thd->mem_root= mem_root_save; + DBUG_RETURN(true); +} + + +bool Create_tmp_table::finalize(THD *thd, + TABLE *table, + TMP_TABLE_PARAM *param, + bool do_not_open, bool keep_row_order) +{ + DBUG_ENTER("Create_tmp_table::finalize"); + DBUG_ASSERT(table); + + uint hidden_null_pack_length; + uint null_pack_length; + bool use_packed_rows= false; + uchar *pos; + uchar *null_flags; + KEY *keyinfo; + TMP_ENGINE_COLUMNDEF *recinfo; + TABLE_SHARE *share= table->s; + Copy_field *copy= param->copy_field; + + MEM_ROOT *mem_root_save= thd->mem_root; + thd->mem_root= &table->mem_root; + + DBUG_ASSERT(m_alloced_field_count >= share->fields); + DBUG_ASSERT(m_alloced_field_count >= share->blob_fields); + /* If result table is small; use a heap */ /* future: storage engine selection can be made dynamic? */ - if (blob_count || using_unique_constraint - || (thd->variables.big_tables && !(select_options & SELECT_SMALL_RESULT)) - || (select_options & TMP_TABLE_FORCE_MYISAM) + if (share->blob_fields || m_using_unique_constraint + || (thd->variables.big_tables && !(m_select_options & SELECT_SMALL_RESULT)) + || (m_select_options & TMP_TABLE_FORCE_MYISAM) || thd->variables.tmp_memory_table_size == 0) { share->db_plugin= ha_lock_engine(0, TMP_ENGINE_HTON); table->file= get_new_handler(share, &table->mem_root, share->db_type()); - if (group && + if (m_group && (param->group_parts > table->file->max_key_parts() || param->group_length > table->file->max_key_length())) - using_unique_constraint= true; + m_using_unique_constraint= true; } else { @@ -18212,35 +18244,33 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, goto err; } - if (!using_unique_constraint) - reclength+= group_null_items; // null flag is stored separately + if (!m_using_unique_constraint) + share->reclength+= m_group_null_items; // null flag is stored separately - share->blob_fields= blob_count; - if (blob_count == 0) + if (share->blob_fields == 0) { /* We need to ensure that first byte is not 0 for the delete link */ if (param->hidden_field_count) - hidden_null_count++; + m_hidden_null_count++; else - null_count++; + m_null_count++; } - hidden_null_pack_length= (hidden_null_count + 7 + - hidden_uneven_bit_length) / 8; + hidden_null_pack_length= (m_hidden_null_count + 7 + + m_hidden_uneven_bit_length) / 8; null_pack_length= (hidden_null_pack_length + - (null_count + total_uneven_bit_length + 7) / 8); - reclength+=null_pack_length; - if (!reclength) - reclength=1; // Dummy select + (m_null_count + m_uneven_bit_length + 7) / 8); + share->reclength+= null_pack_length; + if (!share->reclength) + share->reclength= 1; // Dummy select /* Use packed rows if there is blobs or a lot of space to gain */ - if (blob_count || - (string_total_length >= STRING_TOTAL_LENGTH_TO_PACK_ROWS && - (reclength / string_total_length <= RATIO_TO_PACK_ROWS || - string_total_length / string_count >= AVG_STRING_LENGTH_TO_PACK_ROWS))) + if (share->blob_fields || + (string_total_length() >= STRING_TOTAL_LENGTH_TO_PACK_ROWS && + (share->reclength / string_total_length() <= RATIO_TO_PACK_ROWS || + string_total_length() / string_count() >= AVG_STRING_LENGTH_TO_PACK_ROWS))) use_packed_rows= 1; - share->reclength= reclength; { - uint alloc_length=ALIGN_SIZE(reclength+MI_UNIQUE_HASH_LENGTH+1); + uint alloc_length= ALIGN_SIZE(share->reclength + MI_UNIQUE_HASH_LENGTH+1); share->rec_buff_length= alloc_length; if (!(table->record[0]= (uchar*) alloc_root(&table->mem_root, alloc_length*3))) @@ -18248,10 +18278,8 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, table->record[1]= table->record[0]+alloc_length; share->default_values= table->record[1]+alloc_length; } - copy_func[0]=0; // End marker - param->func_count= (uint)(copy_func - param->items_to_copy); - setup_tmp_table_column_bitmaps(table, bitmaps); + setup_tmp_table_column_bitmaps(table, m_bitmaps); recinfo=param->start_recinfo; null_flags=(uchar*) table->record[0]; @@ -18265,33 +18293,33 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, bfill(null_flags,null_pack_length,255); // Set null fields table->null_flags= (uchar*) table->record[0]; - share->null_fields= null_count+ hidden_null_count; + share->null_fields= m_null_count + m_hidden_null_count; share->null_bytes= share->null_bytes_for_compare= null_pack_length; } - null_count= (blob_count == 0) ? 1 : 0; - hidden_field_count=param->hidden_field_count; - for (i=0,reg_field=table->field; i < field_count; i++,reg_field++,recinfo++) + m_null_count= (share->blob_fields == 0) ? 1 : 0; + m_hidden_field_count= param->hidden_field_count; + for (uint i= 0; i < share->fields; i++, recinfo++) { - Field *field= *reg_field; + Field *field= table->field[i]; uint length; bzero((uchar*) recinfo,sizeof(*recinfo)); if (!(field->flags & NOT_NULL_FLAG)) { - recinfo->null_bit= (uint8)1 << (null_count & 7); - recinfo->null_pos= null_count/8; - field->move_field(pos,null_flags+null_count/8, - (uint8)1 << (null_count & 7)); - null_count++; + recinfo->null_bit= (uint8)1 << (m_null_count & 7); + recinfo->null_pos= m_null_count/8; + field->move_field(pos, null_flags + m_null_count/8, + (uint8)1 << (m_null_count & 7)); + m_null_count++; } else field->move_field(pos,(uchar*) 0,0); if (field->type() == MYSQL_TYPE_BIT) { /* We have to reserve place for extra bits among null bits */ - ((Field_bit*) field)->set_bit_ptr(null_flags + null_count / 8, - null_count & 7); - null_count+= (field->field_length & 7); + ((Field_bit*) field)->set_bit_ptr(null_flags + m_null_count / 8, + m_null_count & 7); + m_null_count+= (field->field_length & 7); } field->reset(); @@ -18299,14 +18327,14 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, Test if there is a default field value. The test for ->ptr is to skip 'offset' fields generated by initalize_tables */ - if (default_field[i] && default_field[i]->ptr) + if (m_default_field[i] && m_default_field[i]->ptr) { /* default_field[i] is set only in the cases when 'field' can inherit the default value that is defined for the field referred by the Item_field object from which 'field' has been created. */ - const Field *orig_field= default_field[i]; + const Field *orig_field= m_default_field[i]; /* Get the value from default_values */ if (orig_field->is_null_in_record(orig_field->table->s->default_values)) field->set_null(); @@ -18319,9 +18347,9 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, } } - if (from_field[i]) + if (m_from_field[i]) { /* Not a table Item */ - copy->set(field,from_field[i],save_sum_fields); + copy->set(field, m_from_field[i], m_save_sum_fields); copy++; } length=field->pack_length(); @@ -18340,14 +18368,14 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, else recinfo->type= FIELD_NORMAL; - if (!--hidden_field_count) - null_count=(null_count+7) & ~7; // move to next byte + if (!--m_hidden_field_count) + m_null_count= (m_null_count + 7) & ~7; // move to next byte // fix table name in field entry field->set_table_name(&table->alias); } - param->copy_field_end=copy; + param->copy_field_end= copy; param->recinfo= recinfo; // Pointer to after last field store_record(table,s->default_values); // Make empty default record @@ -18364,22 +18392,22 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, Push the LIMIT clause to the temporary table creation, so that we materialize only up to 'rows_limit' records instead of all result records. */ - set_if_smaller(share->max_rows, rows_limit); - param->end_write_records= rows_limit; + set_if_smaller(share->max_rows, m_rows_limit); + param->end_write_records= m_rows_limit; keyinfo= param->keyinfo; - if (group) + if (m_group) { DBUG_PRINT("info",("Creating group key in temporary table")); - table->group=group; /* Table is grouped by key */ - param->group_buff=group_buff; + table->group= m_group; /* Table is grouped by key */ + param->group_buff= m_group_buff; share->keys=1; - share->uniques= MY_TEST(using_unique_constraint); + 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=key_part_info; + keyinfo->key_part= m_key_part_info; keyinfo->flags=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY; keyinfo->ext_key_flags= keyinfo->flags; keyinfo->usable_key_parts=keyinfo->user_defined_key_parts= param->group_parts; @@ -18391,29 +18419,29 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, keyinfo->algorithm= HA_KEY_ALG_UNDEF; keyinfo->is_statistics_from_stat_tables= FALSE; keyinfo->name= group_key; - ORDER *cur_group= group; - for (; cur_group ; cur_group= cur_group->next, key_part_info++) + ORDER *cur_group= m_group; + for (; cur_group ; cur_group= cur_group->next, m_key_part_info++) { Field *field=(*cur_group->item)->get_tmp_table_field(); DBUG_ASSERT(field->table == table); bool maybe_null=(*cur_group->item)->maybe_null; - key_part_info->null_bit=0; - key_part_info->field= field; - key_part_info->fieldnr= field->field_index + 1; - if (cur_group == group) + m_key_part_info->null_bit=0; + m_key_part_info->field= field; + m_key_part_info->fieldnr= field->field_index + 1; + if (cur_group == m_group) field->key_start.set_bit(0); - key_part_info->offset= field->offset(table->record[0]); - key_part_info->length= (uint16) field->key_length(); - key_part_info->type= (uint8) field->key_type(); - key_part_info->key_type = - ((ha_base_keytype) key_part_info->type == HA_KEYTYPE_TEXT || - (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT1 || - (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT2) ? + m_key_part_info->offset= field->offset(table->record[0]); + m_key_part_info->length= (uint16) field->key_length(); + m_key_part_info->type= (uint8) field->key_type(); + m_key_part_info->key_type = + ((ha_base_keytype) m_key_part_info->type == HA_KEYTYPE_TEXT || + (ha_base_keytype) m_key_part_info->type == HA_KEYTYPE_VARTEXT1 || + (ha_base_keytype) m_key_part_info->type == HA_KEYTYPE_VARTEXT2) ? 0 : FIELDFLAG_BINARY; - key_part_info->key_part_flag= 0; - if (!using_unique_constraint) + m_key_part_info->key_part_flag= 0; + if (!m_using_unique_constraint) { - cur_group->buff=(char*) group_buff; + cur_group->buff=(char*) m_group_buff; if (maybe_null && !field->null_bit) { @@ -18428,9 +18456,9 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, } if (!(cur_group->field= field->new_key_field(thd->mem_root,table, - group_buff + + m_group_buff + MY_TEST(maybe_null), - key_part_info->length, + m_key_part_info->length, field->null_ptr, field->null_bit))) goto err; /* purecov: inspected */ @@ -18444,26 +18472,28 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, The NULL flag is updated in 'end_update()' and 'end_write()' */ keyinfo->flags|= HA_NULL_ARE_EQUAL; // def. that NULL == NULL - key_part_info->null_bit=field->null_bit; - key_part_info->null_offset= (uint) (field->null_ptr - + m_key_part_info->null_bit=field->null_bit; + m_key_part_info->null_offset= (uint) (field->null_ptr - (uchar*) table->record[0]); cur_group->buff++; // Pointer to field data - group_buff++; // Skipp null flag + m_group_buff++; // Skipp null flag } - group_buff+= cur_group->field->pack_length(); + m_group_buff+= cur_group->field->pack_length(); } - keyinfo->key_length+= key_part_info->length; + keyinfo->key_length+= m_key_part_info->length; } /* Ensure we didn't overrun the group buffer. The < is only true when some maybe_null fields was changed to be not null fields. */ - DBUG_ASSERT(using_unique_constraint || - group_buff <= param->group_buff + param->group_length); + DBUG_ASSERT(m_using_unique_constraint || + m_group_buff <= param->group_buff + param->group_length); } - if (distinct && field_count != param->hidden_field_count) + if (m_distinct && share->fields != param->hidden_field_count) { + uint i; + Field **reg_field; /* Create an unique key or an unique constraint over all columns that should be in the result. In the temporary table, there are @@ -18472,7 +18502,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, */ DBUG_PRINT("info",("hidden_field_count: %d", param->hidden_field_count)); - if (blob_count) + if (share->blob_fields) { /* Special mode for index creation in MyISAM used to support unique @@ -18483,21 +18513,21 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, } null_pack_length-=hidden_null_pack_length; keyinfo->user_defined_key_parts= - ((field_count-param->hidden_field_count)+ + ((share->fields - param->hidden_field_count)+ (share->uniques ? MY_TEST(null_pack_length) : 0)); keyinfo->ext_key_parts= keyinfo->user_defined_key_parts; keyinfo->usable_key_parts= keyinfo->user_defined_key_parts; table->distinct= 1; share->keys= 1; - if (!(key_part_info= (KEY_PART_INFO*) + if (!(m_key_part_info= (KEY_PART_INFO*) alloc_root(&table->mem_root, keyinfo->user_defined_key_parts * sizeof(KEY_PART_INFO)))) goto err; - bzero((void*) key_part_info, keyinfo->user_defined_key_parts * sizeof(KEY_PART_INFO)); + bzero((void*) m_key_part_info, keyinfo->user_defined_key_parts * sizeof(KEY_PART_INFO)); table->keys_in_use_for_query.set_bit(0); share->keys_in_use.set_bit(0); table->key_info= table->s->key_info= keyinfo; - keyinfo->key_part=key_part_info; + keyinfo->key_part= m_key_part_info; 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. @@ -18529,39 +18559,39 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, */ if (null_pack_length && share->uniques) { - key_part_info->null_bit=0; - key_part_info->offset=hidden_null_pack_length; - key_part_info->length=null_pack_length; - key_part_info->field= new Field_string(table->record[0], - (uint32) key_part_info->length, + m_key_part_info->null_bit=0; + m_key_part_info->offset=hidden_null_pack_length; + m_key_part_info->length=null_pack_length; + m_key_part_info->field= new Field_string(table->record[0], + (uint32) m_key_part_info->length, (uchar*) 0, (uint) 0, Field::NONE, &null_clex_str, &my_charset_bin); - if (!key_part_info->field) + if (!m_key_part_info->field) goto err; - key_part_info->field->init(table); - key_part_info->key_type=FIELDFLAG_BINARY; - key_part_info->type= HA_KEYTYPE_BINARY; - key_part_info->fieldnr= key_part_info->field->field_index + 1; - key_part_info++; + m_key_part_info->field->init(table); + m_key_part_info->key_type=FIELDFLAG_BINARY; + m_key_part_info->type= HA_KEYTYPE_BINARY; + m_key_part_info->fieldnr= m_key_part_info->field->field_index + 1; + m_key_part_info++; } /* Create a distinct key over the columns we are going to return */ - for (i=param->hidden_field_count, reg_field=table->field + i ; - i < field_count; - i++, reg_field++, key_part_info++) + for (i= param->hidden_field_count, reg_field= table->field + i ; + i < share->fields; + i++, reg_field++, m_key_part_info++) { - key_part_info->field= *reg_field; + m_key_part_info->field= *reg_field; (*reg_field)->flags |= PART_KEY_FLAG; - if (key_part_info == keyinfo->key_part) + if (m_key_part_info == keyinfo->key_part) (*reg_field)->key_start.set_bit(0); - key_part_info->null_bit= (*reg_field)->null_bit; - key_part_info->null_offset= (uint) ((*reg_field)->null_ptr - + m_key_part_info->null_bit= (*reg_field)->null_bit; + m_key_part_info->null_offset= (uint) ((*reg_field)->null_ptr - (uchar*) table->record[0]); - key_part_info->offset= (*reg_field)->offset(table->record[0]); - key_part_info->length= (uint16) (*reg_field)->pack_length(); - key_part_info->fieldnr= (*reg_field)->field_index + 1; + m_key_part_info->offset= (*reg_field)->offset(table->record[0]); + m_key_part_info->length= (uint16) (*reg_field)->pack_length(); + m_key_part_info->fieldnr= (*reg_field)->field_index + 1; /* TODO: The below method of computing the key format length of the key part is a copy/paste from opt_range.cc, and table.cc. @@ -18570,12 +18600,12 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, methods is supposed to compute the same length. If so, it might be reused. */ - key_part_info->store_length= key_part_info->length; + m_key_part_info->store_length= m_key_part_info->length; if ((*reg_field)->real_maybe_null()) { - key_part_info->store_length+= HA_KEY_NULL_LENGTH; - key_part_info->key_part_flag |= HA_NULL_PART; + m_key_part_info->store_length+= HA_KEY_NULL_LENGTH; + m_key_part_info->key_part_flag |= HA_NULL_PART; } if ((*reg_field)->type() == MYSQL_TYPE_BLOB || (*reg_field)->real_type() == MYSQL_TYPE_VARCHAR || @@ -18583,20 +18613,20 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, { if ((*reg_field)->type() == MYSQL_TYPE_BLOB || (*reg_field)->type() == MYSQL_TYPE_GEOMETRY) - key_part_info->key_part_flag|= HA_BLOB_PART; + m_key_part_info->key_part_flag|= HA_BLOB_PART; else - key_part_info->key_part_flag|= HA_VAR_LENGTH_PART; + m_key_part_info->key_part_flag|= HA_VAR_LENGTH_PART; - key_part_info->store_length+=HA_KEY_BLOB_LENGTH; + m_key_part_info->store_length+=HA_KEY_BLOB_LENGTH; } - keyinfo->key_length+= key_part_info->store_length; + keyinfo->key_length+= m_key_part_info->store_length; - key_part_info->type= (uint8) (*reg_field)->key_type(); - key_part_info->key_type = - ((ha_base_keytype) key_part_info->type == HA_KEYTYPE_TEXT || - (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT1 || - (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT2) ? + m_key_part_info->type= (uint8) (*reg_field)->key_type(); + m_key_part_info->key_type = + ((ha_base_keytype) m_key_part_info->type == HA_KEYTYPE_TEXT || + (ha_base_keytype) m_key_part_info->type == HA_KEYTYPE_VARTEXT1 || + (ha_base_keytype) m_key_part_info->type == HA_KEYTYPE_VARTEXT2) ? 0 : FIELDFLAG_BINARY; } } @@ -18611,7 +18641,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, if (!do_not_open) { if (instantiate_tmp_table(table, param->keyinfo, param->start_recinfo, - ¶m->recinfo, select_options)) + ¶m->recinfo, m_select_options)) goto err; } @@ -18620,14 +18650,108 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, thd->mem_root= mem_root_save; - DBUG_RETURN(table); + DBUG_RETURN(false); err: thd->mem_root= mem_root_save; - free_tmp_table(thd,table); /* purecov: inspected */ - if (temp_pool_slot != MY_BIT_NONE) - bitmap_lock_clear_bit(&temp_pool, temp_pool_slot); - DBUG_RETURN(NULL); /* purecov: inspected */ + DBUG_RETURN(true); /* purecov: inspected */ +} + + +bool Create_tmp_table::add_schema_fields(THD *thd, TABLE *table, + TMP_TABLE_PARAM *param, + const ST_SCHEMA_TABLE &schema_table, + const MY_BITMAP &bitmap) +{ + DBUG_ENTER("Create_tmp_table::add_schema_fields"); + DBUG_ASSERT(table); + DBUG_ASSERT(table->field); + DBUG_ASSERT(table->s->blob_field); + DBUG_ASSERT(table->s->reclength == 0); + DBUG_ASSERT(table->s->fields == 0); + DBUG_ASSERT(table->s->blob_fields == 0); + + TABLE_SHARE *share= table->s; + ST_FIELD_INFO *defs= schema_table.fields_info; + uint fieldnr; + MEM_ROOT *mem_root_save= thd->mem_root; + thd->mem_root= &table->mem_root; + + for (fieldnr= 0; defs[fieldnr].field_name; fieldnr++) + { + const ST_FIELD_INFO &def= defs[fieldnr]; + bool visible= bitmap_is_set(&bitmap, fieldnr); + Record_addr addr(def.field_flags & MY_I_S_MAYBE_NULL); + const Type_handler *h= Type_handler::get_handler_by_real_type(def.field_type); + Field *field= h->make_schema_field(table, addr, def, visible); + if (!field) + { + thd->mem_root= mem_root_save; + DBUG_RETURN(true); // EOM + } + field->init(table); + add_field(table, field, fieldnr, param->force_not_null_cols); + } + + share->fields= fieldnr; + share->blob_fields= m_blob_count; + table->field[fieldnr]= 0; // End marker + share->blob_field[m_blob_count]= 0; // End marker + param->func_count= 0; + share->column_bitmap_size= bitmap_buffer_size(share->fields); + + thd->mem_root= mem_root_save; + DBUG_RETURN(false); +} + + +void Create_tmp_table::cleanup_on_failure(THD *thd, TABLE *table) +{ + if (table) + free_tmp_table(thd, table); + if (m_temp_pool_slot != MY_BIT_NONE) + bitmap_lock_clear_bit(&temp_pool, m_temp_pool_slot); +} + + +TABLE *create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, + ORDER *group, bool distinct, bool save_sum_fields, + ulonglong select_options, ha_rows rows_limit, + const LEX_CSTRING *table_alias, bool do_not_open, + bool keep_row_order) +{ + TABLE *table; + Create_tmp_table maker(param, group, + distinct, save_sum_fields, select_options, rows_limit); + if (!(table= maker.start(thd, param, table_alias)) || + maker.add_fields(thd, table, param, fields) || + maker.finalize(thd, table, param, do_not_open, keep_row_order)) + { + maker.cleanup_on_failure(thd, table); + return NULL; + } + return table; +} + + +TABLE *create_tmp_table_for_schema(THD *thd, TMP_TABLE_PARAM *param, + const ST_SCHEMA_TABLE &schema_table, + const MY_BITMAP &bitmap, + longlong select_options, + const LEX_CSTRING &table_alias, + bool keep_row_order) +{ + TABLE *table; + Create_tmp_table maker(param, (ORDER *) NULL, false, false, + select_options, HA_POS_ERROR); + if (!(table= maker.start(thd, param, &table_alias)) || + maker.add_schema_fields(thd, table, param, schema_table, bitmap) || + maker.finalize(thd, table, param, false, keep_row_order)) + { + maker.cleanup_on_failure(thd, table); + return NULL; + } + return table; } diff --git a/sql/sql_select.h b/sql/sql_select.h index b7f870bf797..40a9ed303f7 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -2419,6 +2419,13 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ulonglong select_options, ha_rows rows_limit, const LEX_CSTRING *alias, bool do_not_open=FALSE, bool keep_row_order= FALSE); +TABLE *create_tmp_table_for_schema(THD *thd, TMP_TABLE_PARAM *param, + const ST_SCHEMA_TABLE &schema_table, + const MY_BITMAP &bitmap, + longlong select_options, + const LEX_CSTRING &alias, + bool keep_row_order); + void free_tmp_table(THD *thd, TABLE *entry); bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table, TMP_ENGINE_COLUMNDEF *start_recinfo, diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 3e049cfaae4..b82959b5c21 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -8164,13 +8164,11 @@ mark_all_fields_used_in_query(THD *thd, TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) { uint field_count; - Item *item, *all_items; + Item *all_items; TABLE *table; - List<Item> field_list; ST_SCHEMA_TABLE *schema_table= table_list->schema_table; ST_FIELD_INFO *fields_info= schema_table->fields_info; ST_FIELD_INFO *fields; - MEM_ROOT *mem_root= thd->mem_root; MY_BITMAP bitmap; my_bitmap_map *buf; DBUG_ENTER("create_schema_table"); @@ -8189,120 +8187,6 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) mark_all_fields_used_in_query(thd, fields_info, &bitmap, all_items); - for (field_count=0; fields_info->field_name; fields_info++) - { - switch (fields_info->field_type) { - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONGLONG: - case MYSQL_TYPE_INT24: - if (!(item= new (mem_root) - Item_return_int(thd, fields_info->field_name, - fields_info->field_length, - fields_info->field_type, - fields_info->value))) - { - DBUG_RETURN(0); - } - item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED); - break; - case MYSQL_TYPE_DATE: - if (!(item=new (mem_root) - Item_return_date_time(thd, fields_info->get_name(), - fields_info->field_type))) - DBUG_RETURN(0); - break; - case MYSQL_TYPE_TIME: - if (!(item=new (mem_root) - Item_return_date_time(thd, fields_info->get_name(), - fields_info->field_type))) - DBUG_RETURN(0); - break; - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_DATETIME: - if (!(item=new (mem_root) - Item_return_date_time(thd, fields_info->get_name(), - fields_info->field_type, - fields_info->field_length))) - DBUG_RETURN(0); - item->decimals= fields_info->field_length; - break; - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - if ((item= new (mem_root) - Item_float(thd, fields_info->field_name, 0.0, - NOT_FIXED_DEC, - fields_info->field_length)) == NULL) - DBUG_RETURN(NULL); - break; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_NEWDECIMAL: - if (!(item= new (mem_root) - Item_decimal(thd, (longlong) fields_info->value, false))) - { - DBUG_RETURN(0); - } - /* - Create a type holder, as we want the type of the item to defined - the type of the object, not the value - */ - if (!(item= new (mem_root) Item_type_holder(thd, item))) - DBUG_RETURN(0); - item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED); - item->decimals= fields_info->field_length%10; - item->max_length= (fields_info->field_length/100)%100; - if (item->unsigned_flag == 0) - item->max_length+= 1; - if (item->decimals > 0) - item->max_length+= 1; - item->set_name(thd, fields_info->get_name()); - break; - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_BLOB: - if (bitmap_is_set(&bitmap, field_count)) - { - if (!(item= new (mem_root) - Item_blob(thd, fields_info->get_name(), - fields_info->field_length))) - { - DBUG_RETURN(0); - } - } - else - { - if (!(item= new (mem_root) - Item_empty_string(thd, "", 0, system_charset_info))) - { - DBUG_RETURN(0); - } - item->set_name(thd, fields_info->get_name()); - } - break; - default: - { - bool show_field; - /* Don't let unimplemented types pass through. Could be a grave error. */ - DBUG_ASSERT(fields_info->field_type == MYSQL_TYPE_STRING); - - show_field= bitmap_is_set(&bitmap, field_count); - if (!(item= new (mem_root) - Item_empty_string(thd, "", - show_field ? fields_info->field_length : 0, - system_charset_info))) - { - DBUG_RETURN(0); - } - item->set_name(thd, fields_info->get_name()); - break; - } - } - field_list.push_back(item, thd->mem_root); - item->maybe_null= (fields_info->field_flags & MY_I_S_MAYBE_NULL); - field_count++; - } TMP_TABLE_PARAM *tmp_table_param = (TMP_TABLE_PARAM*) (thd->alloc(sizeof(TMP_TABLE_PARAM))); tmp_table_param->init(); @@ -8311,11 +8195,13 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) tmp_table_param->schema_table= 1; SELECT_LEX *select_lex= table_list->select_lex; bool keep_row_order= is_show_command(thd); - if (!(table= create_tmp_table(thd, tmp_table_param, - field_list, (ORDER*) 0, 0, 0, - (select_lex->options | thd->variables.option_bits | - TMP_TABLE_ALL_COLUMNS), HA_POS_ERROR, - &table_list->alias, false, keep_row_order))) + if (!(table= create_tmp_table_for_schema(thd, tmp_table_param, + *schema_table, bitmap, + (select_lex->options | + thd->variables.option_bits | + TMP_TABLE_ALL_COLUMNS), + table_list->alias, + keep_row_order))) DBUG_RETURN(0); my_bitmap_map* bitmaps= (my_bitmap_map*) thd->alloc(bitmap_buffer_size(field_count)); diff --git a/sql/sql_type.cc b/sql/sql_type.cc index f5b8b2e530d..71677f847d9 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -3436,6 +3436,196 @@ Field *Type_handler_set::make_table_field(const LEX_CSTRING *name, attr.collation); } + +/*************************************************************************/ + +Field *Type_handler_float::make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const +{ + Lex_cstring name(def.field_name); + return new (table->in_use->mem_root) + Field_float(addr.ptr(), def.field_length, + addr.null_ptr(), addr.null_bit(), + Field::NONE, &name, + (uint8) NOT_FIXED_DEC, + 0/*zerofill*/, def.unsigned_flag()); +} + + +Field *Type_handler_double::make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const +{ + Lex_cstring name(def.field_name); + return new (table->in_use->mem_root) + Field_double(addr.ptr(), def.field_length, + addr.null_ptr(), addr.null_bit(), + Field::NONE, &name, + (uint8) NOT_FIXED_DEC, + 0/*zerofill*/, def.unsigned_flag()); +} + + +Field *Type_handler_decimal_result::make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const +{ + Lex_cstring name(def.field_name); + uint dec= def.field_length % 10; + uint prec= (def.field_length / 100) % 100; + DBUG_ASSERT(dec <= DECIMAL_MAX_SCALE); + uint32 len= my_decimal_precision_to_length(prec, dec, def.unsigned_flag()); + return new (table->in_use->mem_root) + Field_new_decimal(addr.ptr(), len, addr.null_ptr(), addr.null_bit(), + Field::NONE, &name, + (uint8) dec, 0/*zerofill*/, def.unsigned_flag()); +} + + +Field *Type_handler_blob_common::make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const +{ + Lex_cstring name(def.field_name); + if (show_field) + { + return new (table->in_use->mem_root) + Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(), + Field::NONE, &name, table->s, + length_bytes(), + &my_charset_bin); + } + else + return new (table->in_use->mem_root) + Field_null(addr.ptr(), 0, Field::NONE, &name, &my_charset_bin); +} + + +Field *Type_handler_string::make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const +{ + DBUG_ASSERT(def.field_length); + Lex_cstring name(def.field_name); + uint32 octet_length= (uint32) def.field_length * 3; + if (def.field_length * 3 > MAX_FIELD_VARCHARLENGTH) + { + Field *field= new (table->in_use->mem_root) + Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(), Field::NONE, + &name, table->s, 4, system_charset_info); + if (field) + field->field_length= octet_length; + return field; + } + else if (show_field) + { + return new (table->in_use->mem_root) + Field_varstring(addr.ptr(), octet_length, + HA_VARCHAR_PACKLENGTH(octet_length), + addr.null_ptr(), addr.null_bit(), + Field::NONE, &name, + table->s, system_charset_info); + } + else + return new (table->in_use->mem_root) + Field_null(addr.ptr(), 0, Field::NONE, &name, system_charset_info); +} + + +Field *Type_handler_tiny::make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const +{ + Lex_cstring name(def.field_name); + return new (table->in_use->mem_root) + Field_tiny(addr.ptr(), def.field_length, + addr.null_ptr(), addr.null_bit(), Field::NONE, &name, + 0/*zerofill*/, def.unsigned_flag()); +} + + +Field *Type_handler_short::make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const +{ + Lex_cstring name(def.field_name); + return new (table->in_use->mem_root) + Field_short(addr.ptr(), def.field_length, + addr.null_ptr(), addr.null_bit(), Field::NONE, &name, + 0/*zerofill*/, def.unsigned_flag()); +} + + +Field *Type_handler_long::make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const +{ + Lex_cstring name(def.field_name); + return new (table->in_use->mem_root) + Field_long(addr.ptr(), def.field_length, + addr.null_ptr(), addr.null_bit(), Field::NONE, &name, + 0/*zerofill*/, def.unsigned_flag()); +} + + +Field *Type_handler_longlong::make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const +{ + Lex_cstring name(def.field_name); + return new (table->in_use->mem_root) + Field_longlong(addr.ptr(), def.field_length, + addr.null_ptr(), addr.null_bit(), Field::NONE, &name, + 0/*zerofill*/, def.unsigned_flag()); +} + + +Field *Type_handler_date_common::make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const +{ + Lex_cstring name(def.field_name); + return new (table->in_use->mem_root) + Field_newdate(addr.ptr(), addr.null_ptr(), addr.null_bit(), + Field::NONE, &name); +} + + +Field *Type_handler_time_common::make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const +{ + Lex_cstring name(def.field_name); + return new_Field_time(table->in_use->mem_root, + addr.ptr(), addr.null_ptr(), addr.null_bit(), + Field::NONE, &name, def.fsp()); +} + + +Field *Type_handler_datetime_common::make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const +{ + Lex_cstring name(def.field_name); + return new_Field_datetime(table->in_use->mem_root, + addr.ptr(), addr.null_ptr(), addr.null_bit(), + Field::NONE, &name, def.fsp()); +} + + /*************************************************************************/ /* diff --git a/sql/sql_type.h b/sql/sql_type.h index 6d9d802913f..06b72dd7d27 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -81,6 +81,7 @@ struct TABLE; struct SORT_FIELD_ATTR; class Vers_history_point; class Virtual_column_info; +struct ST_FIELD_INFO; #define my_charset_numeric my_charset_latin1 @@ -110,6 +111,34 @@ enum scalar_comparison_op }; +class Data_type_statistics +{ +public: + uint m_uneven_bit_length; + uint m_fixed_string_total_length; + uint m_fixed_string_count; + uint m_variable_string_total_length; + uint m_variable_string_count; + uint m_blob_count; + Data_type_statistics() + :m_uneven_bit_length(0), + m_fixed_string_total_length(0), + m_fixed_string_count(0), + m_variable_string_total_length(0), + m_variable_string_count(0), + m_blob_count(0) + { } + uint string_count() const + { + return m_fixed_string_count + m_variable_string_count; + } + uint string_total_length() const + { + return m_fixed_string_total_length + m_variable_string_total_length; + } +}; + + class Native: public Binary_string { public: @@ -3422,6 +3451,14 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + virtual Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const + { + DBUG_ASSERT(0); + return NULL; + } virtual Field * make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, @@ -4192,6 +4229,10 @@ public: } bool subquery_type_allows_materialization(const Item *inner, const Item *outer) const; + Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const; Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const; void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, Sort_param *param) const; @@ -4759,6 +4800,10 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, @@ -4804,6 +4849,10 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, @@ -4849,6 +4898,10 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, @@ -4909,6 +4962,10 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, @@ -5108,6 +5165,10 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, @@ -5156,6 +5217,10 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, @@ -5188,6 +5253,10 @@ public: { return MYSQL_TIMESTAMP_TIME; } + Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const; Item_literal *create_literal_item(THD *thd, const char *str, size_t length, CHARSET_INFO *cs, bool send_error) const; Item *create_typecast_item(THD *thd, Item *item, @@ -5353,6 +5422,10 @@ public: { return true; } + Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const; Item_literal *create_literal_item(THD *thd, const char *str, size_t length, CHARSET_INFO *cs, bool send_error) const; Item *create_typecast_item(THD *thd, Item *item, @@ -5446,6 +5519,10 @@ public: { return true; } + Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const; Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const; void Column_definition_implicit_upgrade(Column_definition *c) const; @@ -5817,6 +5894,10 @@ public: const Record_addr &addr, const Type_all_attributes &attr, TABLE *table) const; + Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, @@ -5925,6 +6006,7 @@ class Type_handler_blob_common: public Type_handler_longstr { public: virtual ~Type_handler_blob_common() { } + virtual uint length_bytes() const= 0; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; const Type_handler *type_handler_for_tmp_table(const Item *item) const @@ -5955,6 +6037,10 @@ public: Item **items, uint nitems) const; void Item_param_setup_conversion(THD *thd, Item_param *) const; + Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const; Field *make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, @@ -5970,6 +6056,7 @@ class Type_handler_tiny_blob: public Type_handler_blob_common static const Name m_name_tinyblob; public: virtual ~Type_handler_tiny_blob() {} + uint length_bytes() const { return 1; } const Name name() const { return m_name_tinyblob; } enum_field_types field_type() const { return MYSQL_TYPE_TINY_BLOB; } uint32 calc_pack_length(uint32 length) const; @@ -5986,6 +6073,7 @@ class Type_handler_medium_blob: public Type_handler_blob_common static const Name m_name_mediumblob; public: virtual ~Type_handler_medium_blob() {} + uint length_bytes() const { return 3; } const Name name() const { return m_name_mediumblob; } enum_field_types field_type() const { return MYSQL_TYPE_MEDIUM_BLOB; } uint32 calc_pack_length(uint32 length) const; @@ -6002,6 +6090,7 @@ class Type_handler_long_blob: public Type_handler_blob_common static const Name m_name_longblob; public: virtual ~Type_handler_long_blob() {} + uint length_bytes() const { return 4; } const Name name() const { return m_name_longblob; } enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; } uint32 calc_pack_length(uint32 length) const; @@ -6020,6 +6109,7 @@ class Type_handler_blob: public Type_handler_blob_common static const Name m_name_blob; public: virtual ~Type_handler_blob() {} + uint length_bytes() const { return 2; } const Name name() const { return m_name_blob; } enum_field_types field_type() const { return MYSQL_TYPE_BLOB; } uint32 calc_pack_length(uint32 length) const; diff --git a/sql/table.h b/sql/table.h index f41bcb30c2b..de52d6d8395 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1670,7 +1670,7 @@ bool fk_modifies_child(enum_fk_option opt); #define OPEN_FRM_ONLY 1U // open FRM file only #define OPEN_FULL_TABLE 2U // open FRM,MYD, MYI files -typedef struct st_field_info +struct ST_FIELD_INFO { /** This is used as column name. @@ -1712,7 +1712,13 @@ typedef struct st_field_info { return LEX_CSTRING({old_name, strlen(old_name)}); } -} ST_FIELD_INFO; + bool unsigned_flag() const { return field_flags & MY_I_S_UNSIGNED; } + uint fsp() const + { + DBUG_ASSERT(field_length <= TIME_SECOND_PART_DIGITS); + return field_length; + } +}; struct TABLE_LIST; |