diff options
Diffstat (limited to 'sql/table.cc')
-rw-r--r-- | sql/table.cc | 190 |
1 files changed, 125 insertions, 65 deletions
diff --git a/sql/table.cc b/sql/table.cc index aa85b296399..e6878c42ea2 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -17,7 +17,7 @@ /* Some general useful functions */ -#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */ +#include "mariadb.h" /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" #include "table.h" #include "key.h" // find_ref_key @@ -43,6 +43,7 @@ #include "rpl_filter.h" #include "sql_cte.h" #include "ha_sequence.h" +#include "sql_show.h" /* For MySQL 5.7 virtual fields */ #define MYSQL57_GENERATED_FIELD 128 @@ -217,31 +218,26 @@ static uchar *get_field_name(Field **buff, size_t *length, Returns pointer to '.frm' extension of the file name. SYNOPSIS - fn_rext() + fn_frm_ext() name file name DESCRIPTION Checks file name part starting with the rightmost '.' character, and returns it if it is equal to '.frm'. - TODO - It is a good idea to get rid of this function modifying the code - to garantee that the functions presently calling fn_rext() always - get arguments in the same format: either with '.frm' or without '.frm'. - RETURN VALUES - Pointer to the '.frm' extension. If there is no extension, - or extension is not '.frm', pointer at the end of file name. + Pointer to the '.frm' extension or NULL if not a .frm file */ -char *fn_rext(char *name) +const char *fn_frm_ext(const char *name) { - char *res= strrchr(name, '.'); + const char *res= strrchr(name, '.'); if (res && !strcmp(res, reg_ext)) return res; - return name + strlen(name); + return 0; } + TABLE_CATEGORY get_table_category(const LEX_CSTRING *db, const LEX_CSTRING *name) { @@ -251,30 +247,18 @@ TABLE_CATEGORY get_table_category(const LEX_CSTRING *db, if (is_infoschema_db(db->str, db->length)) return TABLE_CATEGORY_INFORMATION; - if ((db->length == PERFORMANCE_SCHEMA_DB_NAME.length) && - (my_strcasecmp(system_charset_info, - PERFORMANCE_SCHEMA_DB_NAME.str, - db->str) == 0)) + if (lex_string_eq(&PERFORMANCE_SCHEMA_DB_NAME, db) == 0) return TABLE_CATEGORY_PERFORMANCE; - if ((db->length == MYSQL_SCHEMA_NAME.length) && - (my_strcasecmp(system_charset_info, - MYSQL_SCHEMA_NAME.str, - db->str) == 0)) + if (lex_string_eq(&MYSQL_SCHEMA_NAME, db) == 0) { if (is_system_table_name(name->str, name->length)) return TABLE_CATEGORY_SYSTEM; - if ((name->length == GENERAL_LOG_NAME.length) && - (my_strcasecmp(system_charset_info, - GENERAL_LOG_NAME.str, - name->str) == 0)) + if (lex_string_eq(&GENERAL_LOG_NAME, name) == 0) return TABLE_CATEGORY_LOG; - if ((name->length == SLOW_LOG_NAME.length) && - (my_strcasecmp(system_charset_info, - SLOW_LOG_NAME.str, - name->str) == 0)) + if (lex_string_eq(&SLOW_LOG_NAME, name) == 0) return TABLE_CATEGORY_LOG; } @@ -328,8 +312,13 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name, share->normalized_path.length= path_length; share->table_category= get_table_category(& share->db, & share->table_name); share->open_errno= ENOENT; - /* The following will be fixed in open_table_from_share */ - share->cached_row_logging_check= 1; + /* The following will be updated in open_table_from_share */ + share->can_do_row_logging= 1; + if (share->table_category == TABLE_CATEGORY_LOG) + share->no_replicate= 1; + if (my_strnncoll(table_alias_charset, (uchar*) db, 6, + (const uchar*) "mysql", 6) == 0) + share->not_usable_by_query_cache= 1; init_sql_alloc(&share->stats_cb.mem_root, TABLE_ALLOC_BLOCK_SIZE, 0, MYF(0)); @@ -402,8 +391,8 @@ void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key, share->normalized_path.str= (char*) path; share->path.length= share->normalized_path.length= strlen(path); share->frm_version= FRM_VER_CURRENT; - - share->cached_row_logging_check= 0; // No row logging + share->not_usable_by_query_cache= 1; + share->can_do_row_logging= 0; // No row logging /* table_map_id is also used for MERGE tables to suppress repeated @@ -1173,13 +1162,15 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, uint db_create_options, keys, key_parts, n_length; uint com_length, null_bit_pos, UNINIT_VAR(mysql57_vcol_null_bit_pos), bitmap_count; uint i; + uint field_additional_property_length= 0; bool use_hash, mysql57_null_bits= 0; char *keynames, *names, *comment_pos; const uchar *forminfo, *extra2; const uchar *frm_image_end = frm_image + frm_length; uchar *record, *null_flags, *null_pos, *mysql57_vcol_null_pos= 0; const uchar *disk_buff, *strpos; - ulong pos, record_offset; + const uchar *field_properties= NULL; + ulong pos, record_offset; ulong rec_buff_length; handler *handler_file= 0; KEY *keyinfo; @@ -1233,7 +1224,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (*extra2 != '/') // old frm had '/' there { const uchar *e2end= extra2 + len; - while (extra2 + 3 < e2end) + while (extra2 + 3 <= e2end) { uchar type= *extra2++; size_t length= *extra2++; @@ -1291,6 +1282,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } #endif /*HAVE_SPATIAL*/ break; + case EXTRA2_FIELD_FLAGS: + field_properties = extra2; + field_additional_property_length= length; + break; default: /* abort frm parsing if it's an unknown but important extra2 value */ if (type >= EXTRA2_ENGINE_IMPORTANT) @@ -1607,8 +1602,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, memcpy(record, frm_image + record_offset, share->reclength); disk_buff= frm_image + pos + FRM_FORMINFO_SIZE; - share->fields= uint2korr(forminfo+258); + if (field_properties && field_additional_property_length != share->fields) + goto err; pos= uint2korr(forminfo+260); /* Length of all screens */ n_length= uint2korr(forminfo+268); interval_count= uint2korr(forminfo+270); @@ -1619,6 +1615,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, vcol_screen_length= uint2korr(forminfo+286); share->virtual_fields= share->default_expressions= share->field_check_constraints= share->default_fields= 0; + share->visible_fields= 0; share->stored_fields= share->fields; if (forminfo[46] != (uchar)255) { @@ -1990,6 +1987,15 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, reg_field->field_index= i; reg_field->comment=comment; reg_field->vcol_info= vcol_info; + if(field_properties!=NULL) + { + uint temp= *field_properties++; + reg_field->field_visibility= f_visibility(temp); + } + if (reg_field->field_visibility == USER_DEFINED_INVISIBLE) + status_var_increment(thd->status_var.feature_invisible_columns); + if (reg_field->field_visibility == NOT_INVISIBLE) + share->visible_fields++; if (field_type == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag)) { null_bits_are_used= 1; @@ -2125,18 +2131,18 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, for (uint key=0 ; key < keys ; key++,keyinfo++) { uint usable_parts= 0; - keyinfo->name=(char*) share->keynames.type_names[key]; - keyinfo->name_length= strlen(keyinfo->name); + keyinfo->name.str= share->keynames.type_names[key]; + keyinfo->name.length= strlen(keyinfo->name.str); keyinfo->cache_name= (uchar*) alloc_root(&share->mem_root, share->table_cache_key.length+ - keyinfo->name_length + 1); + keyinfo->name.length + 1); if (keyinfo->cache_name) // If not out of memory { uchar *pos= keyinfo->cache_name; memcpy(pos, share->table_cache_key.str, share->table_cache_key.length); - memcpy(pos + share->table_cache_key.length, keyinfo->name, - keyinfo->name_length+1); + memcpy(pos + share->table_cache_key.length, keyinfo->name.str, + keyinfo->name.length+1); } if (ext_key_parts > share->key_parts && key) @@ -2239,6 +2245,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, field= key_part->field= share->field[key_part->fieldnr-1]; key_part->type= field->key_type(); + if (field->field_visibility > USER_DEFINED_INVISIBLE) + keyinfo->flags |= HA_INVISIBLE_KEY; if (field->null_ptr) { key_part->null_offset=(uint) ((uchar*) field->null_ptr - @@ -2955,6 +2963,14 @@ unpack_vcol_info_from_frm(THD *thd, MEM_ROOT *mem_root, TABLE *table, if (error) goto end; + if (lex.current_select->table_list.first[0].next_global) + { + /* We are using NEXT VALUE FOR sequence. Remember table name for open */ + TABLE_LIST *sequence= lex.current_select->table_list.first[0].next_global; + sequence->next_global= table->internal_tables; + table->internal_tables= sequence; + } + vcol_storage.vcol_info->set_vcol_type(vcol->get_vcol_type()); vcol_storage.vcol_info->stored_in_db= vcol->stored_in_db; vcol_storage.vcol_info->name= vcol->name; @@ -3377,24 +3393,20 @@ partititon_err: outparam->mark_columns_used_by_check_constraints(); - if (share->table_category == TABLE_CATEGORY_LOG) - { - outparam->no_replicate= TRUE; - } - else if (outparam->file) + if (db_stat) { + /* Set some flags in share on first open of the table */ handler::Table_flags flags= outparam->file->ha_table_flags(); - outparam->no_replicate= ! MY_TEST(flags & (HA_BINLOG_STMT_CAPABLE - | HA_BINLOG_ROW_CAPABLE)) - || MY_TEST(flags & HA_HAS_OWN_BINLOGGING); - } - else - { - outparam->no_replicate= FALSE; + if (! MY_TEST(flags & (HA_BINLOG_STMT_CAPABLE | + HA_BINLOG_ROW_CAPABLE)) || + MY_TEST(flags & HA_HAS_OWN_BINLOGGING)) + share->no_replicate= TRUE; + if (outparam->file->table_cache_type() & HA_CACHE_TBL_NOCACHE) + share->not_usable_by_query_cache= TRUE; } - if (outparam->no_replicate || !binlog_filter->db_ok(outparam->s->db.str)) - outparam->s->cached_row_logging_check= 0; // No row based replication + if (share->no_replicate || !binlog_filter->db_ok(share->db.str)) + share->can_do_row_logging= 0; // No row based replication /* Increment the opened_tables counter, only when open flags set. */ if (db_stat) @@ -5124,7 +5136,6 @@ int TABLE::verify_constraints(bool ignore_failure) return(VIEW_CHECK_OK); } - /* Find table in underlying tables by mask and check that only this table belong to given mask @@ -6289,11 +6300,6 @@ void TABLE::mark_columns_needed_for_delete() need_signal= true; } } - if (check_constraints) - { - mark_check_constraint_columns_for_read(); - need_signal= true; - } if (need_signal) file->column_bitmaps_signal(); @@ -6653,6 +6659,58 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl) DBUG_RETURN(bitmap_updated); } + +/** + Check if a virtual not stored column field is in read set + + @retval FALSE No virtual not stored column is used + @retval TRUE At least one virtual not stored column is used +*/ + +bool TABLE::check_virtual_columns_marked_for_read() +{ + if (vfield) + { + Field **vfield_ptr; + for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++) + { + Field *tmp_vfield= *vfield_ptr; + if (bitmap_is_set(read_set, tmp_vfield->field_index) && + !tmp_vfield->vcol_info->stored_in_db) + return TRUE; + } + } + return FALSE; +} + + +/** + Check if a stored virtual column field is marked for write + + This can be used to check if any column that is part of a virtual + stored column is changed + + @retval FALSE No stored virtual column is used + @retval TRUE At least one stored virtual column is used +*/ + +bool TABLE::check_virtual_columns_marked_for_write() +{ + if (vfield) + { + Field **vfield_ptr; + for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++) + { + Field *tmp_vfield= *vfield_ptr; + if (bitmap_is_set(write_set, tmp_vfield->field_index) && + tmp_vfield->vcol_info->stored_in_db) + return TRUE; + } + } + return FALSE; +} + + /* Mark fields used by check constraints. This is done once for the TABLE_SHARE the first time the table is opened. @@ -6710,6 +6768,7 @@ void TABLE::mark_default_fields_for_write(bool is_insert) DBUG_VOID_RETURN; } + void TABLE::move_fields(Field **ptr, const uchar *to, const uchar *from) { my_ptrdiff_t diff= to - from; @@ -6916,7 +6975,8 @@ bool TABLE::add_tmp_key(uint key, uint key_parts, if (unique) keyinfo->flags|= HA_NOSAME; sprintf(buf, "key%i", key); - if (!(keyinfo->name= strdup_root(&mem_root, buf))) + keyinfo->name.length= strlen(buf); + if (!(keyinfo->name.str= strmake_root(&mem_root, buf, keyinfo->name.length))) return TRUE; keyinfo->rec_per_key= (ulong*) alloc_root(&mem_root, sizeof(ulong)*key_parts); @@ -8260,8 +8320,8 @@ Item* TABLE_LIST::build_pushable_cond_for_table(THD *thd, Item *cond) if (!(item->used_tables() == tab_map)) continue; Item_func_eq *eq= 0; - Item *left_item_clone= left_item->build_clone(thd, thd->mem_root); - Item *right_item_clone= item->build_clone(thd, thd->mem_root); + Item *left_item_clone= left_item->build_clone(thd); + Item *right_item_clone= item->build_clone(thd); if (left_item_clone && right_item_clone) { left_item_clone->set_item_equal(NULL); @@ -8291,7 +8351,7 @@ Item* TABLE_LIST::build_pushable_cond_for_table(THD *thd, Item *cond) return new_cond; } else if (cond->get_extraction_flag() != NO_EXTRACTION_FL) - return cond->build_clone(thd, thd->mem_root); + return cond->build_clone(thd); return 0; } @@ -8316,7 +8376,7 @@ Field *TABLE::find_field_by_name(LEX_CSTRING *str) const for (Field **tmp= field; *tmp; tmp++) { if ((*tmp)->field_name.length == length && - !my_strcasecmp(system_charset_info, (*tmp)->field_name.str, str->str)) + !lex_string_cmp(system_charset_info, &(*tmp)->field_name, str)) return *tmp; } return NULL; |