summaryrefslogtreecommitdiff
path: root/sql/table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/table.cc')
-rw-r--r--sql/table.cc724
1 files changed, 485 insertions, 239 deletions
diff --git a/sql/table.cc b/sql/table.cc
index d5dfc414792..025612ca87b 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
- Copyright (c) 2008, 2020, MariaDB
+ Copyright (c) 2008, 2021, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,9 +25,9 @@
// primary_key_name
#include "sql_parse.h" // free_items
#include "strfunc.h" // unhex_type2
-#include "sql_partition.h" // mysql_unpack_partition,
+#include "ha_partition.h" // PART_EXT
+ // mysql_unpack_partition,
// fix_partition_func, partition_info
-#include "sql_acl.h" // *_ACL, acl_getroot_no_password
#include "sql_base.h"
#include "create_options.h"
#include "sql_trigger.h"
@@ -70,6 +70,8 @@ struct extra2_fields
LEX_CUSTRING field_flags;
LEX_CUSTRING system_period;
LEX_CUSTRING application_period;
+ LEX_CUSTRING field_data_type_info;
+ LEX_CUSTRING without_overlaps;
void reset()
{ bzero((void*)this, sizeof(*this)); }
};
@@ -277,7 +279,8 @@ TABLE_CATEGORY get_table_category(const LEX_CSTRING *db,
DBUG_ASSERT(name != NULL);
#ifdef WITH_WSREP
- if (my_strcasecmp(system_charset_info, db->str, "mysql") == 0 &&
+ if (db->str &&
+ my_strcasecmp(system_charset_info, db->str, "mysql") == 0 &&
my_strcasecmp(system_charset_info, name->str, "wsrep_streaming_log") == 0)
{
return TABLE_CATEGORY_INFORMATION;
@@ -286,7 +289,7 @@ TABLE_CATEGORY get_table_category(const LEX_CSTRING *db,
if (is_infoschema_db(db))
return TABLE_CATEGORY_INFORMATION;
- if (lex_string_eq(&PERFORMANCE_SCHEMA_DB_NAME, db))
+ if (is_perfschema_db(db))
return TABLE_CATEGORY_PERFORMANCE;
if (lex_string_eq(&MYSQL_SCHEMA_NAME, db))
@@ -336,7 +339,8 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name,
path_length= build_table_filename(path, sizeof(path) - 1,
db, table_name, "", 0);
- init_sql_alloc(&mem_root, "table_share", TABLE_ALLOC_BLOCK_SIZE, 0, MYF(0));
+ init_sql_alloc(key_memory_table_share, &mem_root, TABLE_ALLOC_BLOCK_SIZE, 0,
+ MYF(0));
if (multi_alloc_root(&mem_root,
&share, sizeof(*share),
&key_buff, key_length,
@@ -359,11 +363,10 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name,
if (share->table_category == TABLE_CATEGORY_LOG)
share->no_replicate= 1;
if (key_length > 6 &&
- my_strnncoll(table_alias_charset, (const uchar*) key, 6,
- (const uchar*) "mysql", 6) == 0)
+ table_alias_charset->strnncoll(key, 6, "mysql", 6) == 0)
share->not_usable_by_query_cache= 1;
- init_sql_alloc(&share->stats_cb.mem_root, "share_stats",
+ init_sql_alloc(PSI_INSTRUMENT_ME, &share->stats_cb.mem_root,
TABLE_ALLOC_BLOCK_SIZE, 0, MYF(0));
memcpy((char*) &share->mem_root, (char*) &mem_root, sizeof(mem_root));
@@ -425,8 +428,9 @@ void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key,
This can't be MY_THREAD_SPECIFIC for slaves as they are freed
during cleanup() from Relay_log_info::close_temporary_tables()
*/
- init_sql_alloc(&share->mem_root, "tmp_table_share", TABLE_ALLOC_BLOCK_SIZE,
- 0, MYF(thd->slave_thread ? 0 : MY_THREAD_SPECIFIC));
+ init_sql_alloc(key_memory_table_share, &share->mem_root,
+ TABLE_ALLOC_BLOCK_SIZE, 0,
+ MYF(thd->slave_thread ? 0 : MY_THREAD_SPECIFIC));
share->table_category= TABLE_CATEGORY_TEMPORARY;
share->tmp_table= INTERNAL_TMP_TABLE;
share->db.str= (char*) key;
@@ -626,9 +630,13 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags)
path);
if (flags & GTS_FORCE_DISCOVERY)
{
+ const char *path2= share->normalized_path.str;
DBUG_ASSERT(flags & GTS_TABLE);
DBUG_ASSERT(flags & GTS_USE_DISCOVERY);
- mysql_file_delete_with_symlink(key_file_frm, path, "", MYF(0));
+ /* Delete .frm and .par files */
+ mysql_file_delete_with_symlink(key_file_frm, path2, reg_ext, MYF(0));
+ mysql_file_delete_with_symlink(key_file_partition_ddl_log, path2, PAR_EXT,
+ MYF(0));
file= -1;
}
else
@@ -686,7 +694,8 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags)
frmlen= uint4korr(head+10);
set_if_smaller(frmlen, FRM_MAX_SIZE); // safety
- if (!(buf= (uchar*)my_malloc(frmlen, MYF(MY_THREAD_SPECIFIC|MY_WME))))
+ if (!(buf= (uchar*)my_malloc(PSI_INSTRUMENT_ME, frmlen,
+ MYF(MY_THREAD_SPECIFIC|MY_WME))))
goto err;
memcpy(buf, head, sizeof(head));
@@ -987,6 +996,38 @@ void Column_definition_attributes::frm_unpack_basic(const uchar *buff)
}
+void Column_definition_attributes::frm_pack_numeric_with_dec(uchar *buff) const
+{
+ DBUG_ASSERT(f_decimals(pack_flag) == 0);
+ uint tmp_pack_flag= pack_flag | (decimals << FIELDFLAG_DEC_SHIFT);
+ int2store(buff + 3, length);
+ int2store(buff + 8, tmp_pack_flag);
+ buff[10]= (uchar) unireg_check;
+}
+
+
+bool
+Column_definition_attributes::frm_unpack_numeric_with_dec(TABLE_SHARE *share,
+ const uchar *buff)
+{
+ frm_unpack_basic(buff);
+ decimals= f_decimals(pack_flag);
+ pack_flag&= ~FIELDFLAG_DEC_MASK;
+ return frm_unpack_charset(share, buff);
+}
+
+
+bool
+Column_definition_attributes::frm_unpack_temporal_with_dec(TABLE_SHARE *share,
+ uint intlen,
+ const uchar *buff)
+{
+ frm_unpack_basic(buff);
+ decimals= temporal_dec(intlen);
+ return frm_unpack_charset(share, buff);
+}
+
+
void Column_definition_attributes::frm_pack_charset(uchar *buff) const
{
buff[11]= (uchar) (charset->number >> 8);
@@ -1100,7 +1141,6 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
Field **vfield_ptr= table->vfield;
Field **dfield_ptr= table->default_field;
Virtual_column_info **check_constraint_ptr= table->check_constraints;
- sql_mode_t saved_mode= thd->variables.sql_mode;
Query_arena backup_arena;
Virtual_column_info *vcol= 0;
StringBuffer<MAX_FIELD_WIDTH> expr_str;
@@ -1127,7 +1167,8 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
thd->stmt_arena= table->expr_arena;
thd->update_charset(&my_charset_utf8mb4_general_ci, table->s->table_charset);
expr_str.append(&parse_vcol_keyword);
- thd->variables.sql_mode &= ~(MODE_NO_BACKSLASH_ESCAPES | MODE_EMPTY_STRING_IS_NULL);
+ Sql_mode_instant_remove sms(thd, MODE_NO_BACKSLASH_ESCAPES |
+ MODE_EMPTY_STRING_IS_NULL);
while (pos < end)
{
@@ -1228,10 +1269,10 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
for (key_index= 0; key_index < table->s->keys; key_index++)
{
key=table->key_info + key_index;
- parts= key->user_defined_key_parts;
+ parts= key->user_defined_key_parts;
if (key->key_part[parts].fieldnr == field->field_index + 1)
- break;
- }
+ break;
+ }
if (!key || key->algorithm != HA_KEY_ALG_LONG_HASH)
goto end;
KEY_PART_INFO *keypart;
@@ -1310,7 +1351,6 @@ end:
thd->stmt_arena= backup_stmt_arena_ptr;
if (save_character_set_client)
thd->update_charset(save_character_set_client, save_collation);
- thd->variables.sql_mode= saved_mode;
DBUG_RETURN(res);
}
@@ -1484,6 +1524,14 @@ static size_t extra2_read_len(const uchar **extra2, const uchar *extra2_end)
return length;
}
+static
+bool read_extra2_section_once(const uchar *extra2, size_t len, LEX_CUSTRING *section)
+{
+ if (section->str)
+ return true;
+ *section= {extra2, len};
+ return false;
+}
static
bool read_extra2(const uchar *frm_image, size_t len, extra2_fields *fields)
@@ -1503,6 +1551,8 @@ bool read_extra2(const uchar *frm_image, size_t len, extra2_fields *fields)
size_t length= extra2_read_len(&extra2, e2end);
if (!length)
DBUG_RETURN(true);
+
+ bool fail= false;
switch (type) {
case EXTRA2_TABLEDEF_VERSION:
if (fields->version.str) // see init_from_sql_statement_string()
@@ -1517,43 +1567,38 @@ bool read_extra2(const uchar *frm_image, size_t len, extra2_fields *fields)
}
break;
case EXTRA2_ENGINE_TABLEOPTS:
- if (fields->options.str)
- DBUG_RETURN(true);
- fields->options.str= extra2;
- fields->options.length= length;
+ fail= read_extra2_section_once(extra2, length, &fields->options);
break;
case EXTRA2_DEFAULT_PART_ENGINE:
fields->engine.set((const char*)extra2, length);
break;
case EXTRA2_GIS:
- if (fields->gis.str)
- DBUG_RETURN(true);
- fields->gis.str= extra2;
- fields->gis.length= length;
+ fail= read_extra2_section_once(extra2, length, &fields->gis);
break;
case EXTRA2_PERIOD_FOR_SYSTEM_TIME:
- if (fields->system_period.str || length != 2 * frm_fieldno_size)
- DBUG_RETURN(true);
- fields->system_period.str = extra2;
- fields->system_period.length= length;
+ fail= read_extra2_section_once(extra2, length, &fields->system_period)
+ || length != 2 * frm_fieldno_size;
break;
case EXTRA2_FIELD_FLAGS:
- if (fields->field_flags.str)
- DBUG_RETURN(true);
- fields->field_flags.str= extra2;
- fields->field_flags.length= length;
+ fail= read_extra2_section_once(extra2, length, &fields->field_flags);
break;
case EXTRA2_APPLICATION_TIME_PERIOD:
- if (fields->application_period.str)
- DBUG_RETURN(true);
- fields->application_period.str= extra2;
- fields->application_period.length= length;
+ fail= read_extra2_section_once(extra2, length, &fields->application_period);
+ break;
+ case EXTRA2_PERIOD_WITHOUT_OVERLAPS:
+ fail= read_extra2_section_once(extra2, length, &fields->without_overlaps);
+ break;
+ case EXTRA2_FIELD_DATA_TYPE_INFO:
+ fail= read_extra2_section_once(extra2, length, &fields->field_data_type_info);
break;
default:
/* abort frm parsing if it's an unknown but important extra2 value */
if (type >= EXTRA2_ENGINE_IMPORTANT)
DBUG_RETURN(true);
}
+ if (fail)
+ DBUG_RETURN(true);
+
extra2+= length;
}
if (extra2 != e2end)
@@ -1563,9 +1608,92 @@ bool read_extra2(const uchar *frm_image, size_t len, extra2_fields *fields)
}
+class Field_data_type_info_array
+{
+public:
+ class Elem
+ {
+ LEX_CSTRING m_type_info;
+ public:
+ void set(const LEX_CSTRING &type_info)
+ {
+ m_type_info= type_info;
+ }
+ const LEX_CSTRING &type_info() const
+ {
+ return m_type_info;
+ }
+ };
+private:
+ Elem *m_array;
+ uint m_count;
+ bool alloc(MEM_ROOT *root, uint count)
+ {
+ DBUG_ASSERT(!m_array);
+ DBUG_ASSERT(!m_count);
+ size_t nbytes= sizeof(Elem) * count;
+ if (!(m_array= (Elem*) alloc_root(root, nbytes)))
+ return true;
+ m_count= count;
+ bzero((void*) m_array, nbytes);
+ return false;
+ }
+ static uint32 read_length(uchar **pos, const uchar *end)
+ {
+ ulonglong num= safe_net_field_length_ll(pos, end - *pos);
+ if (num > UINT_MAX32)
+ return 0;
+ return (uint32) num;
+ }
+ static bool read_string(LEX_CSTRING *to, uchar **pos, const uchar *end)
+ {
+ to->length= read_length(pos, end);
+ if (*pos + to->length > end)
+ return true; // Not enough data
+ to->str= (const char *) *pos;
+ *pos+= to->length;
+ return false;
+ }
+public:
+ Field_data_type_info_array()
+ :m_array(NULL), m_count(0)
+ { }
+ uint count() const
+ {
+ return m_count;
+ }
+ const Elem& element(uint i) const
+ {
+ DBUG_ASSERT(i < m_count);
+ return m_array[i];
+ }
+ bool parse(MEM_ROOT *root, uint count, LEX_CUSTRING &image)
+ {
+ const uchar *pos= image.str;
+ const uchar *end= pos + image.length;
+ if (alloc(root, count))
+ return true;
+ for (uint i= 0; i < count && pos < end; i++)
+ {
+ LEX_CSTRING type_info;
+ uint fieldnr= read_length((uchar**) &pos, end);
+ if ((fieldnr == 0 && i > 0) || fieldnr >= count)
+ return true; // Bad data
+ if (read_string(&type_info, (uchar**) &pos, end) || type_info.length == 0)
+ return true; // Bad data
+ m_array[fieldnr].set(type_info);
+ }
+ return pos < end; // Error if some data is still left
+ }
+};
+
+
/**
Read data from a binary .frm file image into a TABLE_SHARE
+ @param write Write the .frm and .par file. These are not created if
+ the function returns an error.
+
@note
frm bytes at the following offsets are unused in MariaDB 10.0:
@@ -1576,12 +1704,13 @@ bool read_extra2(const uchar *frm_image, size_t len, extra2_fields *fields)
42..46 are unused since 5.0 (were for RAID support)
Also, there're few unused bytes in forminfo.
-
*/
int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
const uchar *frm_image,
- size_t frm_length)
+ size_t frm_length,
+ const uchar *par_image,
+ size_t par_length)
{
TABLE_SHARE *share= this;
uint new_frm_ver, field_pack_length, new_field_pack_flag;
@@ -1615,23 +1744,31 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
uint len;
uint ext_key_parts= 0;
plugin_ref se_plugin= 0;
- bool vers_can_native= false;
-
+ bool vers_can_native= false, frm_created= 0;
+ Field_data_type_info_array field_data_type_info_array;
MEM_ROOT *old_root= thd->mem_root;
Virtual_column_info **table_check_constraints;
extra2_fields extra2;
-
DBUG_ENTER("TABLE_SHARE::init_from_binary_frm_image");
keyinfo= &first_keyinfo;
thd->mem_root= &share->mem_root;
- if (write && write_frm_image(frm_image, frm_length))
- goto err;
-
if (frm_length < FRM_HEADER_SIZE + FRM_FORMINFO_SIZE)
goto err;
+ if (write)
+ {
+ frm_created= 1;
+ if (write_frm_image(frm_image, frm_length))
+ goto err;
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ if (par_image)
+ if (write_par_image(par_image, par_length))
+ goto err;
+#endif
+ }
+
share->frm_version= frm_image[2];
/*
Check if .frm file created by MySQL 5.0. In this case we want to
@@ -1734,7 +1871,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
{
const CHARSET_INFO *cs= thd->variables.collation_database;
/* unknown charset in frm_image[38] or pre-3.23 frm */
- if (use_mb(cs))
+ if (cs->use_mb())
{
/* Warn that we may be changing the size of character columns */
sql_print_warning("'%s' had no or invalid character set, "
@@ -1811,7 +1948,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
name.length= str_db_type_length;
plugin_ref tmp_plugin= ha_resolve_by_name(thd, &name, false);
- if (tmp_plugin != NULL && !plugin_equals(tmp_plugin, se_plugin))
+ if (tmp_plugin != NULL && !plugin_equals(tmp_plugin, se_plugin) &&
+ legacy_db_type != DB_TYPE_S3)
{
if (se_plugin)
{
@@ -1967,6 +2105,17 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (keyinfo->algorithm == HA_KEY_ALG_LONG_HASH)
hash_fields++;
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ if (par_image && plugin_data(se_plugin, handlerton*) == partition_hton)
+ {
+ /*
+ Discovery returned a partition plugin. Change to use it. The partition
+ engine will then use discovery to find the rest of the plugin tables,
+ which may be in the original engine used for discovery
+ */
+ share->db_plugin= se_plugin;
+ }
+#endif
if (share->db_plugin && !plugin_equals(share->db_plugin, se_plugin))
goto err; // wrong engine (someone changed the frm under our feet?)
@@ -2106,10 +2255,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
if (use_hash)
- use_hash= !my_hash_init(&share->name_hash,
- system_charset_info,
- share->fields,0,0,
- (my_hash_get_key) get_field_name,0,0);
+ use_hash= !my_hash_init(PSI_INSTRUMENT_ME, &share->name_hash,
+ system_charset_info, share->fields, 0, 0,
+ (my_hash_get_key) get_field_name, 0, 0);
if (share->mysql_version >= 50700 && share->mysql_version < 100000 &&
vcol_screen_length)
@@ -2136,7 +2284,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
else
{
- DBUG_PRINT("info", ("Setting system versioning informations"));
+ DBUG_PRINT("info", ("Setting system versioning information"));
if (init_period_from_extra2(&vers, extra2.system_period.str,
extra2.system_period.str + extra2.system_period.length))
goto err;
@@ -2162,9 +2310,37 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (init_period_from_extra2(&period, pos, end))
goto err;
+ if (extra2_str_size(period.name.length)
+ + extra2_str_size(period.constr_name.length)
+ + 2 * frm_fieldno_size
+ != extra2.application_period.length)
+ goto err;
status_var_increment(thd->status_var.feature_application_time_periods);
}
+ if (extra2.without_overlaps.str)
+ {
+ if (extra2.application_period.str == NULL)
+ goto err;
+ const uchar *key_pos= extra2.without_overlaps.str;
+ period.unique_keys= read_frm_keyno(key_pos);
+ for (uint k= 0; k < period.unique_keys; k++)
+ {
+ key_pos+= frm_keyno_size;
+ uint key_nr= read_frm_keyno(key_pos);
+ key_info[key_nr].without_overlaps= true;
+ }
+
+ if ((period.unique_keys + 1) * frm_keyno_size
+ != extra2.without_overlaps.length)
+ goto err;
+ }
+
+ if (extra2.field_data_type_info.length &&
+ field_data_type_info_array.parse(old_root, share->fields,
+ extra2.field_data_type_info))
+ goto err;
+
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
{
uint interval_nr= 0, recpos;
@@ -2193,7 +2369,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
comment_pos+= comment_length;
}
- if ((uchar) strpos[13] == (uchar) MYSQL_TYPE_VIRTUAL)
+ if ((uchar) strpos[13] == (uchar) MYSQL_TYPE_VIRTUAL
+ && likely(share->mysql_version >= 100000))
{
/*
MariaDB version 10.0 version.
@@ -2243,11 +2420,53 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
interval_nr= (uint) strpos[12];
enum_field_types field_type= (enum_field_types) strpos[13];
if (!(handler= Type_handler::get_handler_by_real_type(field_type)))
- goto err; // Not supported field type
+ {
+ if (field_type == 245 &&
+ share->mysql_version >= 50700) // a.k.a MySQL 5.7 JSON
+ {
+ share->incompatible_version|= HA_CREATE_USED_ENGINE;
+ const LEX_CSTRING mysql_json{STRING_WITH_LEN("MYSQL_JSON")};
+ handler= Type_handler::handler_by_name_or_error(thd, mysql_json);
+ }
+
+ if (!handler)
+ goto err; // Not supported field type
+ }
+ handler= handler->type_handler_frm_unpack(strpos);
if (handler->Column_definition_attributes_frm_unpack(&attr, share,
strpos,
&extra2.gis))
goto err;
+
+ if (field_data_type_info_array.count())
+ {
+ const LEX_CSTRING &info= field_data_type_info_array.
+ element(i).type_info();
+ DBUG_EXECUTE_IF("frm_data_type_info",
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_UNKNOWN_ERROR, "DBUG: [%u] name='%s' type_info='%.*s'",
+ i, share->fieldnames.type_names[i],
+ (uint) info.length, info.str););
+
+ if (info.length)
+ {
+ const Type_handler *h= Type_handler::handler_by_name_or_error(thd,
+ info);
+ /*
+ This code will eventually be extended here:
+ - If the handler was not found by name, we could
+ still open the table using the fallback type handler "handler",
+ at least for a limited set of commands.
+ - If the handler was found by name, we could check
+ that "h" and "handler" have the same type code
+ (and maybe some other properties) to make sure
+ that the FRM data is consistent.
+ */
+ if (!h)
+ goto err;
+ handler= h;
+ }
+ }
}
if (((uint) strpos[10]) & MYSQL57_GENERATED_FIELD)
@@ -2279,6 +2498,11 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
attr.length= (uint) strpos[3];
recpos= uint2korr(strpos+4),
attr.pack_flag= uint2korr(strpos+6);
+ if (f_is_num(attr.pack_flag))
+ {
+ attr.decimals= f_decimals(attr.pack_flag);
+ attr.pack_flag&= ~FIELDFLAG_DEC_MASK;
+ }
attr.pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files
attr.unireg_check= (Field::utype) MTYP_TYPENR((uint) strpos[8]);
interval_nr= (uint) strpos[10];
@@ -2607,7 +2831,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
KEY_PART_INFO *new_key_part= (keyinfo-1)->key_part +
(keyinfo-1)->ext_key_parts;
uint add_keyparts_for_this_key= add_first_key_parts;
- uint length_bytes= 0, len_null_byte= 0, ext_key_length= 0;
+ uint len_null_byte= 0, ext_key_length= 0;
Field *field;
if ((keyinfo-1)->algorithm == HA_KEY_ALG_LONG_HASH)
@@ -2619,19 +2843,15 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
*/
for (i= 0; i < keyinfo->user_defined_key_parts; i++)
{
+ uint length_bytes= 0;
uint fieldnr= keyinfo->key_part[i].fieldnr;
field= share->field[fieldnr-1];
if (field->null_ptr)
len_null_byte= HA_KEY_NULL_LENGTH;
- if ((field->type() == MYSQL_TYPE_BLOB ||
- field->real_type() == MYSQL_TYPE_VARCHAR ||
- field->type() == MYSQL_TYPE_GEOMETRY) &&
- keyinfo->algorithm != HA_KEY_ALG_LONG_HASH )
- {
- length_bytes= HA_KEY_BLOB_LENGTH;
- }
+ if (keyinfo->algorithm != HA_KEY_ALG_LONG_HASH)
+ length_bytes= field->key_part_length_bytes();
ext_key_length+= keyinfo->key_part[i].length + len_null_byte
+ length_bytes;
@@ -2720,21 +2940,12 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
keyinfo->flags|=HA_NULL_PART_KEY;
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
}
- if (field->type() == MYSQL_TYPE_BLOB ||
- field->real_type() == MYSQL_TYPE_VARCHAR ||
- field->type() == MYSQL_TYPE_GEOMETRY)
- {
- if (field->type() == MYSQL_TYPE_BLOB ||
- field->type() == MYSQL_TYPE_GEOMETRY)
- key_part->key_part_flag|= HA_BLOB_PART;
- else
- key_part->key_part_flag|= HA_VAR_LENGTH_PART;
- key_part->store_length+=HA_KEY_BLOB_LENGTH;
- if (i < keyinfo->user_defined_key_parts)
- keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
- }
- if (field->type() == MYSQL_TYPE_BIT)
- key_part->key_part_flag|= HA_BIT_PART;
+
+ key_part->key_part_flag|= field->key_part_flag();
+ uint16 key_part_length_bytes= field->key_part_length_bytes();
+ key_part->store_length+= key_part_length_bytes;
+ if (i < keyinfo->user_defined_key_parts)
+ keyinfo->key_length+= key_part_length_bytes;
if (i == 0 && key != primary_key)
field->flags |= (((keyinfo->flags & HA_NOSAME ||
@@ -3055,6 +3266,19 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
DBUG_RETURN(0);
err:
+ if (frm_created)
+ {
+ char path[FN_REFLEN+1];
+ strxnmov(path, FN_REFLEN, normalized_path.str, reg_ext, NullS);
+ my_delete(path, MYF(0));
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ if (par_image)
+ {
+ strxnmov(path, FN_REFLEN, normalized_path.str, PAR_EXT, NullS);
+ my_delete(path, MYF(0));
+ }
+#endif
+ }
share->db_plugin= NULL;
share->error= OPEN_FRM_CORRUPTED;
share->open_errno= my_errno;
@@ -3128,7 +3352,6 @@ static bool sql_unusable_for_discovery(THD *thd, handlerton *engine,
int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write,
const char *sql, size_t sql_length)
{
- sql_mode_t saved_mode= thd->variables.sql_mode;
CHARSET_INFO *old_cs= thd->variables.character_set_client;
Parser_state parser_state;
bool error;
@@ -3156,7 +3379,7 @@ int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write,
if (parser_state.init(thd, sql_copy, sql_length))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
- thd->variables.sql_mode= MODE_NO_ENGINE_SUBSTITUTION | MODE_NO_DIR_IN_CREATE;
+ Sql_mode_instant_set sms(thd, MODE_NO_ENGINE_SUBSTITUTION | MODE_NO_DIR_IN_CREATE);
thd->variables.character_set_client= system_charset_info;
tmp_disable_binlog(thd);
old_lex= thd->lex;
@@ -3205,7 +3428,6 @@ ret:
if (arena)
thd->restore_active_arena(arena, &backup);
reenable_binlog(thd);
- thd->variables.sql_mode= saved_mode;
thd->variables.character_set_client= old_cs;
if (unlikely(thd->is_error() || error))
{
@@ -3221,7 +3443,19 @@ ret:
bool TABLE_SHARE::write_frm_image(const uchar *frm, size_t len)
{
- return writefrm(normalized_path.str, db.str, table_name.str, false, frm, len);
+ char file_name[FN_REFLEN+1];
+ strxnmov(file_name, sizeof(file_name)-1, normalized_path.str, reg_ext,
+ NullS);
+ return writefile(file_name, db.str, table_name.str, false,
+ frm, len);
+}
+
+bool TABLE_SHARE::write_par_image(const uchar *par, size_t len)
+{
+ char file_name[FN_REFLEN+1];
+ strxnmov(file_name, sizeof(file_name)-1, normalized_path.str, PAR_EXT,
+ NullS);
+ return writefile(file_name, db.str, table_name.str, false, par, len);
}
@@ -3365,7 +3599,6 @@ static bool fix_and_check_vcol_expr(THD *thd, TABLE *table,
to be part of the virtual column
*/
Item::vcol_func_processor_result res;
- res.errors= 0;
int error= func_expr->walk(&Item::check_vcol_func_processor, 0, &res);
if (unlikely(error || (res.errors & VCOL_IMPOSSIBLE)))
@@ -3581,6 +3814,55 @@ static void print_long_unique_table(TABLE *table)
}
#endif
+bool copy_keys_from_share(TABLE *outparam, MEM_ROOT *root)
+{
+ TABLE_SHARE *share= outparam->s;
+ if (share->key_parts)
+ {
+ KEY *key_info, *key_info_end;
+ KEY_PART_INFO *key_part;
+
+ if (!multi_alloc_root(root, &key_info, share->keys*sizeof(KEY),
+ &key_part, share->ext_key_parts*sizeof(KEY_PART_INFO),
+ NullS))
+ return 1;
+
+ outparam->key_info= key_info;
+
+ memcpy(key_info, share->key_info, sizeof(*key_info)*share->keys);
+ memcpy(key_part, key_info->key_part, sizeof(*key_part)*share->ext_key_parts);
+
+ my_ptrdiff_t adjust_ptrs= PTR_BYTE_DIFF(key_part, key_info->key_part);
+ for (key_info_end= key_info + share->keys ;
+ key_info < key_info_end ;
+ key_info++)
+ {
+ key_info->table= outparam;
+ key_info->key_part= reinterpret_cast<KEY_PART_INFO*>
+ (reinterpret_cast<char*>(key_info->key_part) + adjust_ptrs);
+ if (key_info->algorithm == HA_KEY_ALG_LONG_HASH)
+ key_info->flags&= ~HA_NOSAME;
+ }
+ for (KEY_PART_INFO *key_part_end= key_part+share->ext_key_parts;
+ key_part < key_part_end;
+ key_part++)
+ {
+ Field *field= key_part->field= outparam->field[key_part->fieldnr - 1];
+ if (field->key_length() != key_part->length &&
+ !(field->flags & BLOB_FLAG))
+ {
+ /*
+ We are using only a prefix of the column as a key:
+ Create a new field for the key part that matches the index
+ */
+ field= key_part->field=field->make_new_field(root, outparam, 0);
+ field->field_length= key_part->length;
+ }
+ }
+ }
+ return 0;
+}
+
/*
Open a table based on a TABLE_SHARE
@@ -3634,14 +3916,15 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
outparam->write_row_record= NULL;
if (share->incompatible_version &&
- !(ha_open_flags & (HA_OPEN_FOR_ALTER | HA_OPEN_FOR_REPAIR)))
+ !(ha_open_flags & (HA_OPEN_FOR_ALTER | HA_OPEN_FOR_REPAIR |
+ HA_OPEN_FOR_FLUSH)))
{
/* one needs to run mysql_upgrade on the table */
error= OPEN_FRM_NEEDS_REBUILD;
goto err;
}
- init_sql_alloc(&outparam->mem_root, "table", TABLE_ALLOC_BLOCK_SIZE, 0,
- MYF(0));
+ init_sql_alloc(key_memory_TABLE, &outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE,
+ 0, MYF(0));
/*
We have to store the original alias in mem_root as constraints and virtual
@@ -3719,6 +4002,15 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
sizeof(Field*)))))
goto err; /* purecov: inspected */
+ /* Allocate storage for range optimizer */
+ if (!multi_alloc_root(&outparam->mem_root,
+ &outparam->opt_range,
+ share->keys * sizeof(TABLE::OPT_RANGE),
+ &outparam->const_key_parts,
+ share->keys * sizeof(key_part_map),
+ NullS))
+ goto err;
+
outparam->field= field_ptr;
record= (uchar*) outparam->record[0]-1; /* Fieldstart = 1 */
@@ -3744,57 +4036,8 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
outparam->found_next_number_field=
outparam->field[(uint) (share->found_next_number_field - share->field)];
- /* Fix key->name and key_part->field */
- if (share->key_parts)
- {
- KEY *key_info, *key_info_end;
- KEY_PART_INFO *key_part;
- uint n_length;
- n_length= share->keys*sizeof(KEY) + share->ext_key_parts*sizeof(KEY_PART_INFO);
- if (!(key_info= (KEY*) alloc_root(&outparam->mem_root, n_length)))
- goto err;
- outparam->key_info= key_info;
- key_part= (reinterpret_cast<KEY_PART_INFO*>(key_info+share->keys));
-
- memcpy(key_info, share->key_info, sizeof(*key_info)*share->keys);
- memcpy(key_part, share->key_info[0].key_part, (sizeof(*key_part) *
- share->ext_key_parts));
-
- for (key_info_end= key_info + share->keys ;
- key_info < key_info_end ;
- key_info++)
- {
- KEY_PART_INFO *key_part_end;
-
- key_info->table= outparam;
- key_info->key_part= key_part;
-
- key_part_end= key_part + (share->use_ext_keys ? key_info->ext_key_parts :
- key_info->user_defined_key_parts) ;
- if (key_info->algorithm == HA_KEY_ALG_LONG_HASH)
- {
- key_part_end++;
- key_info->flags&= ~HA_NOSAME;
- }
- for ( ; key_part < key_part_end; key_part++)
- {
- Field *field= key_part->field= outparam->field[key_part->fieldnr - 1];
- if (field->key_length() != key_part->length &&
- !(field->flags & BLOB_FLAG))
- {
- /*
- We are using only a prefix of the column as a key:
- Create a new field for the key part that matches the index
- */
- field= key_part->field=field->make_new_field(&outparam->mem_root,
- outparam, 0);
- const_cast<uint32_t&>(field->field_length)= key_part->length;
- }
- }
- if (!share->use_ext_keys)
- key_part+= key_info->ext_key_parts - key_info->user_defined_key_parts;
- }
- }
+ if (copy_keys_from_share(outparam, &outparam->mem_root))
+ goto err;
/*
Process virtual and default columns, if any.
@@ -3825,7 +4068,6 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
outparam->check_constraints= check_constraint_ptr;
vcol_init_mode mode= VCOL_INIT_DEPENDENCY_FAILURE_IS_WARNING;
-#if MYSQL_VERSION_ID > 100500
switch (thd->lex->sql_command)
{
case SQLCOM_CREATE_TABLE:
@@ -3840,7 +4082,6 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
default:
break;
}
-#endif
if (parse_vcol_defs(thd, &outparam->mem_root, outparam,
&error_reported, mode))
@@ -3999,7 +4240,7 @@ partititon_err:
the fact that table doesn't in fact exist and remove
the stray .frm file.
*/
- if (share->db_type()->discover_table &&
+ if (outparam->file->partition_ht()->discover_table &&
(ha_err == ENOENT || ha_err == HA_ERR_NO_SUCH_TABLE))
error= OPEN_FRM_DISCOVER;
@@ -4519,21 +4760,17 @@ bool get_field(MEM_ROOT *mem, Field *field, String *res)
StringBuffer<MAX_FIELD_WIDTH> str;
bool rc;
THD *thd= field->get_thd();
- sql_mode_t sql_mode_backup= thd->variables.sql_mode;
- thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH;
+ Sql_mode_instant_remove sms(thd, MODE_PAD_CHAR_TO_FULL_LENGTH);
field->val_str(&str);
if ((rc= !str.length() ||
!(to= strmake_root(mem, str.ptr(), str.length()))))
{
res->length(0);
- goto ex;
+ return rc;
}
res->set(to, str.length(), field->charset());
-
-ex:
- thd->variables.sql_mode= sql_mode_backup;
- return rc;
+ return false;
}
@@ -4677,7 +4914,7 @@ bool check_table_name(const char *name, size_t length, bool check_for_path_chars
{
#if defined(USE_MB) && defined(USE_MB_IDENT)
last_char_is_space= my_isspace(system_charset_info, *name);
- if (use_mb(system_charset_info))
+ if (system_charset_info->use_mb())
{
int len=my_ismbchar(system_charset_info, name, end);
if (len)
@@ -4712,7 +4949,7 @@ bool check_column_name(const char *name)
{
#if defined(USE_MB) && defined(USE_MB_IDENT)
last_char_is_space= my_isspace(system_charset_info, *name);
- if (use_mb(system_charset_info))
+ if (system_charset_info->use_mb())
{
int len=my_ismbchar(system_charset_info, name,
name+system_charset_info->mbmaxlen);
@@ -5180,17 +5417,14 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
range_rowid_filter_cost_info_elems= 0;
range_rowid_filter_cost_info_ptr= NULL;
range_rowid_filter_cost_info= NULL;
- update_handler= NULL;
- check_unique_buf= NULL;
vers_write= s->versioned;
- quick_condition_rows=0;
+ opt_range_condition_rows=0;
no_cache= false;
- initialize_quick_structures();
+ initialize_opt_range_structures();
#ifdef HAVE_REPLICATION
/* used in RBR Triggers */
master_had_triggers= 0;
#endif
-
/* Catch wrong handling of the auto_increment_field_not_null. */
DBUG_ASSERT(!auto_increment_field_not_null);
auto_increment_field_not_null= FALSE;
@@ -5204,6 +5438,7 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
(*f_ptr)->cond_selectivity= 1.0;
}
+ notnull_cond= 0;
DBUG_ASSERT(!file->keyread_enabled());
restore_record(this, s->default_values);
@@ -6087,7 +6322,7 @@ TABLE_LIST *TABLE_LIST::last_leaf_for_name_resolution()
want_access Acess which we require
*/
-void TABLE_LIST::register_want_access(ulong want_access)
+void TABLE_LIST::register_want_access(privilege_t want_access)
{
/* Remove SHOW_VIEW_ACL, because it will be checked during making view */
want_access&= ~SHOW_VIEW_ACL;
@@ -6142,7 +6377,7 @@ bool TABLE_LIST::prepare_view_security_context(THD *thd)
}
else
{
- if (thd->security_ctx->master_access & SUPER_ACL)
+ if (thd->security_ctx->master_access & PRIV_REVEAL_MISSING_DEFINER)
{
my_error(ER_NO_SUCH_USER, MYF(0), definer.user.str, definer.host.str);
@@ -6256,7 +6491,7 @@ bool TABLE_LIST::prepare_security(THD *thd)
thd->security_ctx= save_security_ctx;
#else
while ((tbl= tb++))
- tbl->grant.privilege= ~NO_ACCESS;
+ tbl->grant.privilege= ALL_KNOWN_ACL;
#endif
DBUG_RETURN(FALSE);
}
@@ -6522,8 +6757,8 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
&view->view->first_select_lex()->context:
&thd->lex->first_select_lex()->context);
Item *item= (new (thd->mem_root)
- Item_direct_view_ref(thd, context, field_ref, view->alias.str,
- name, view));
+ Item_direct_view_ref(thd, context, field_ref, view->alias,
+ *name, view));
if (!item)
return NULL;
/*
@@ -6910,11 +7145,11 @@ void TABLE::mark_index_columns(uint index, MY_BITMAP *bitmap)
Restore to use normal column maps after key read
NOTES
- This reverse the change done by mark_columns_used_by_index
+ This reverse the change done by mark_index_columns
WARNING
For this to work, one must have the normal table maps in place
- when calling mark_columns_used_by_index
+ when calling mark_index_columns
*/
void TABLE::restore_column_maps_after_keyread(MY_BITMAP *backup)
@@ -7231,8 +7466,7 @@ void TABLE::mark_columns_per_binlog_row_image()
If in RBR we may need to mark some extra columns,
depending on the binlog-row-image command line argument.
*/
- if ((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) &&
- thd->is_current_stmt_binlog_format_row() &&
+ if (file->row_logging &&
!ha_check_storage_engine_flag(s->db_type(), HTON_NO_BINLOG_ROW_OPT))
{
/* if there is no PK, then mark all columns for the BI. */
@@ -7587,12 +7821,28 @@ void TABLE::restore_blob_values(String *blob_storage)
bool TABLE::alloc_keys(uint key_count)
{
- key_info= (KEY*) alloc_root(&mem_root, sizeof(KEY)*(s->keys+key_count));
+ KEY *new_key_info;
+ key_part_map *new_const_key_parts;
+ DBUG_ASSERT(s->tmp_table == INTERNAL_TMP_TABLE);
+
+ if (!multi_alloc_root(&mem_root,
+ &new_key_info, sizeof(*key_info)*(s->keys+key_count),
+ &new_const_key_parts,
+ sizeof(*new_const_key_parts)*(s->keys+key_count),
+ NullS))
+ return TRUE;
if (s->keys)
- memmove(key_info, s->key_info, sizeof(KEY)*s->keys);
- s->key_info= key_info;
+ {
+ memmove(new_key_info, s->key_info, sizeof(*key_info) * s->keys);
+ memmove(new_const_key_parts, const_key_parts,
+ s->keys * sizeof(const_key_parts));
+ }
+ s->key_info= key_info= new_key_info;
+ const_key_parts= new_const_key_parts;
+ bzero((char*) (const_key_parts + s->keys),
+ sizeof(*const_key_parts) * key_count);
max_keys= s->keys+key_count;
- return !(key_info);
+ return FALSE;
}
@@ -7651,14 +7901,9 @@ void TABLE::create_key_part_by_field(KEY_PART_INFO *key_part_info,
{
key_part_info->store_length+= HA_KEY_NULL_LENGTH;
}
- if (field->type() == MYSQL_TYPE_BLOB ||
- field->type() == MYSQL_TYPE_GEOMETRY ||
- field->real_type() == MYSQL_TYPE_VARCHAR)
- {
- key_part_info->store_length+= HA_KEY_BLOB_LENGTH;
- key_part_info->key_part_flag|=
- field->type() == MYSQL_TYPE_BLOB ? HA_BLOB_PART: HA_VAR_LENGTH_PART;
- }
+
+ key_part_info->key_part_flag|= field->key_part_flag();
+ key_part_info->store_length+= field->key_part_length_bytes();
key_part_info->type= (uint8) field->key_type();
key_part_info->key_type =
@@ -8073,7 +8318,7 @@ bool TABLE_LIST::process_index_hints(TABLE *tbl)
(pos= find_type(&tbl->s->keynames, hint->key_name.str,
hint->key_name.length, 1)) <= 0)
{
- my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), hint->key_name.str, alias.str);
+ my_error(ER_KEY_DOES_NOT_EXISTS, MYF(0), hint->key_name.str, alias.str);
return 1;
}
@@ -8178,11 +8423,10 @@ size_t max_row_length(TABLE *table, MY_BITMAP const *cols, const uchar *data)
void init_mdl_requests(TABLE_LIST *table_list)
{
for ( ; table_list ; table_list= table_list->next_global)
- table_list->mdl_request.init(MDL_key::TABLE,
- table_list->db.str, table_list->table_name.str,
- table_list->lock_type >= TL_WRITE_ALLOW_WRITE ?
- MDL_SHARED_WRITE : MDL_SHARED_READ,
- MDL_TRANSACTION);
+ MDL_REQUEST_INIT(&table_list->mdl_request, MDL_key::TABLE,
+ table_list->db.str, table_list->table_name.str,
+ table_list->lock_type >= TL_WRITE_ALLOW_WRITE
+ ? MDL_SHARED_WRITE : MDL_SHARED_READ, MDL_TRANSACTION);
}
@@ -8577,6 +8821,40 @@ void TABLE::evaluate_update_default_function()
DBUG_VOID_RETURN;
}
+/**
+ Compare two records by a specific key (that has WITHOUT OVERLAPS clause)
+
+ @return true, key values are equal and periods overlap
+ false, either key values differ or periods don't overlap
+ */
+bool TABLE::check_period_overlaps(const KEY &key,
+ const uchar *lhs, const uchar *rhs)
+{
+ DBUG_ASSERT(key.without_overlaps);
+ uint base_part_nr= key.user_defined_key_parts - 2;
+ for (uint part_nr= 0; part_nr < base_part_nr; part_nr++)
+ {
+ Field *f= key.key_part[part_nr].field;
+ if (key.key_part[part_nr].null_bit)
+ if (f->is_null_in_record(lhs) || f->is_null_in_record(rhs))
+ return false;
+ uint kp_len= key.key_part[part_nr].length;
+ if (f->cmp_prefix(f->ptr_in_record(lhs), f->ptr_in_record(rhs),
+ kp_len) != 0)
+ return false;
+ }
+
+ uint period_start= key.user_defined_key_parts - 1;
+ uint period_end= key.user_defined_key_parts - 2;
+ const Field *fs= key.key_part[period_start].field;
+ const Field *fe= key.key_part[period_end].field;
+
+ if (fs->cmp(fe->ptr_in_record(lhs), fs->ptr_in_record(rhs)) <= 0)
+ return false;
+ if (fs->cmp(fs->ptr_in_record(lhs), fe->ptr_in_record(rhs)) >= 0)
+ return false;
+ return true;
+}
void TABLE::vers_update_fields()
{
@@ -9142,8 +9420,8 @@ void TABLE_LIST::set_lock_type(THD *thd, enum thr_lock_type lock)
/* we call it only when table is opened and it is "leaf" table*/
DBUG_ASSERT(table);
lock_type= lock;
- /* table->file->get_table() can be 0 for derived tables */
- if (table->file && table->file->get_table())
+ /* If not derived tables */
+ if (table->file && table->file->is_open())
table->file->set_lock_type(lock);
if (is_merged_derived())
{
@@ -9215,35 +9493,6 @@ void re_setup_keyinfo_hash(KEY *key_info)
key_info->ext_key_parts= 1;
key_info->flags&= ~HA_NOSAME;
}
-/**
- @brief clone of current handler.
- Creates a clone of handler used in update for
- unique hash key.
-*/
-void TABLE::clone_handler_for_update()
-{
- if (this->update_handler)
- return;
- handler *update_handler= NULL;
- if (!s->long_unique_table)
- return;
- update_handler= file->clone(s->normalized_path.str,
- in_use->mem_root);
- update_handler->ha_external_lock(in_use, F_RDLCK);
- this->update_handler= update_handler;
- return;
-}
-
-/**
- @brief Deletes update handler object
-*/
-void TABLE::delete_update_handler()
-{
- update_handler->ha_external_lock(in_use, F_UNLCK);
- update_handler->ha_close();
- delete update_handler;
- this->update_handler= NULL;
-}
LEX_CSTRING *fk_option_name(enum_fk_option opt)
{
@@ -9576,7 +9825,7 @@ bool TR_table::check(bool error)
}
Field_enum *iso_level= static_cast<Field_enum *>(table->field[FLD_ISO_LEVEL]);
- st_typelib *typelib= iso_level->typelib;
+ const st_typelib *typelib= iso_level->typelib;
if (typelib->count != 4)
goto wrong_enum;
@@ -9602,12 +9851,12 @@ bool TR_table::check(bool error)
return false;
}
-bool vers_select_conds_t::resolve_units(THD *thd)
+bool vers_select_conds_t::check_units(THD *thd)
{
DBUG_ASSERT(type != SYSTEM_TIME_UNSPECIFIED);
DBUG_ASSERT(start.item);
- return start.resolve_unit(thd) ||
- end.resolve_unit(thd);
+ return start.check_unit(thd) ||
+ end.check_unit(thd);
}
bool vers_select_conds_t::eq(const vers_select_conds_t &conds) const
@@ -9633,22 +9882,21 @@ bool vers_select_conds_t::eq(const vers_select_conds_t &conds) const
}
-bool Vers_history_point::resolve_unit(THD *thd)
+bool Vers_history_point::check_unit(THD *thd)
{
if (!item)
return false;
if (item->fix_fields_if_needed(thd, &item))
return true;
- return item->this_item()->real_type_handler()->
- type_handler_for_system_time()->
- Vers_history_point_resolve_unit(thd, this);
-}
-
-
-void Vers_history_point::bad_expression_data_type_error(const char *type) const
-{
- my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
- type, "FOR SYSTEM_TIME");
+ const Type_handler *t= item->this_item()->real_type_handler();
+ DBUG_ASSERT(t);
+ if (!t->vers())
+ {
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
+ t->name().ptr(), "FOR SYSTEM_TIME");
+ return true;
+ }
+ return false;
}
@@ -9722,22 +9970,20 @@ bool TABLE::export_structure(THD *thd, Row_definition_list *defs)
return false;
}
-/*
+/**
@brief
- Initialize all the quick structures that are used to stored the
+ Initialize all the opt_range structures that are used to stored the
estimates when the range optimizer is run.
- @details
- This is specifically needed when we read the TABLE structure from the
- table cache. There can be some garbage data from previous queries
- that need to be reset here.
+ As these are initialized by the range optimizer for all index
+ marked in opt_range_keys, we only mark the memory as undefined
+ to be able to find wrong usage of data with valgrind or MSAN.
*/
-void TABLE::initialize_quick_structures()
+inline void TABLE::initialize_opt_range_structures()
{
- TRASH_ALLOC(quick_rows, sizeof(quick_rows));
- TRASH_ALLOC(quick_key_parts, sizeof(quick_key_parts));
- TRASH_ALLOC(quick_costs, sizeof(quick_costs));
- TRASH_ALLOC(quick_n_ranges, sizeof(quick_n_ranges));
+ TRASH_ALLOC((void*)&opt_range_keys, sizeof(opt_range_keys));
+ TRASH_ALLOC(opt_range, s->keys * sizeof(*opt_range));
+ TRASH_ALLOC(const_key_parts, s->keys * sizeof(*const_key_parts));
}
/*