summaryrefslogtreecommitdiff
path: root/sql/table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/table.cc')
-rw-r--r--sql/table.cc190
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;