summaryrefslogtreecommitdiff
path: root/sql/table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/table.cc')
-rw-r--r--sql/table.cc193
1 files changed, 131 insertions, 62 deletions
diff --git a/sql/table.cc b/sql/table.cc
index 93684cb5221..c38fe249741 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2008, 2016, MariaDB
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
+ Copyright (c) 2008, 2018, 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
@@ -677,7 +677,7 @@ err:
mysql_file_close(file, MYF(MY_WME));
err_not_open:
- if (share->error && !error_given)
+ if (unlikely(share->error && !error_given))
{
share->open_errno= my_errno;
open_table_error(share, share->error, share->open_errno);
@@ -1856,6 +1856,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
vers_can_native= plugin_hton(se_plugin)->flags & HTON_NATIVE_SYS_VERSIONING;
row_start_field= row_start;
row_end_field= row_end;
+ status_var_increment(thd->status_var.feature_system_versioning);
} // if (system_period == NULL)
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
@@ -2804,8 +2805,8 @@ int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write,
thd->reset_db(&db);
lex_start(thd);
- if ((error= parse_sql(thd, & parser_state, NULL) ||
- sql_unusable_for_discovery(thd, hton, sql_copy)))
+ if (unlikely((error= parse_sql(thd, & parser_state, NULL) ||
+ sql_unusable_for_discovery(thd, hton, sql_copy))))
goto ret;
thd->lex->create_info.db_type= hton;
@@ -2837,7 +2838,7 @@ ret:
reenable_binlog(thd);
thd->variables.sql_mode= saved_mode;
thd->variables.character_set_client= old_cs;
- if (thd->is_error() || error)
+ if (unlikely(thd->is_error() || error))
{
thd->clear_error();
my_error(ER_SQL_DISCOVER_ERROR, MYF(0),
@@ -2997,14 +2998,14 @@ static bool fix_and_check_vcol_expr(THD *thd, TABLE *table,
res.errors= 0;
int error= func_expr->walk(&Item::check_vcol_func_processor, 0, &res);
- if (error || (res.errors & VCOL_IMPOSSIBLE))
+ if (unlikely(error || (res.errors & VCOL_IMPOSSIBLE)))
{
// this can only happen if the frm was corrupted
my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), res.name,
vcol->get_vcol_type_name(), vcol->name.str);
DBUG_RETURN(1);
}
- else if (res.errors & VCOL_AUTO_INC)
+ else if (unlikely(res.errors & VCOL_AUTO_INC))
{
/*
An auto_increment field may not be used in an expression for
@@ -3085,7 +3086,7 @@ unpack_vcol_info_from_frm(THD *thd, MEM_ROOT *mem_root, TABLE *table,
lex.last_field= &vcol_storage;
error= parse_sql(thd, &parser_state, NULL);
- if (error)
+ if (unlikely(error))
goto end;
if (lex.current_select->table_list.first[0].next_global)
@@ -3354,7 +3355,8 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
if (share->table_check_constraints || share->field_check_constraints)
outparam->check_constraints= check_constraint_ptr;
- if (parse_vcol_defs(thd, &outparam->mem_root, outparam, &error_reported))
+ if (unlikely(parse_vcol_defs(thd, &outparam->mem_root, outparam,
+ &error_reported)))
{
error= OPEN_FRM_CORRUPTED;
goto err;
@@ -3506,7 +3508,8 @@ partititon_err:
/* Set a flag if the table is crashed and it can be auto. repaired */
share->crashed= (outparam->file->auto_repair(ha_err) &&
!(ha_open_flags & HA_OPEN_FOR_REPAIR));
- outparam->file->print_error(ha_err, MYF(0));
+ if (!thd->is_error())
+ outparam->file->print_error(ha_err, MYF(0));
error_reported= TRUE;
if (ha_err == HA_ERR_TABLE_DEF_CHANGED)
@@ -3579,7 +3582,7 @@ partititon_err:
table TABLE object to free
*/
-int closefrm(register TABLE *table)
+int closefrm(TABLE *table)
{
int error=0;
DBUG_ENTER("closefrm");
@@ -3616,7 +3619,7 @@ int closefrm(register TABLE *table)
/* Deallocate temporary blob storage */
-void free_blobs(register TABLE *table)
+void free_blobs(TABLE *table)
{
uint *ptr, *end;
for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
@@ -3810,17 +3813,6 @@ void append_unescaped(String *res, const char *pos, size_t length)
for (; pos != end ; pos++)
{
-#if defined(USE_MB) && MYSQL_VERSION_ID < 40100
- uint mblen;
- if (use_mb(default_charset_info) &&
- (mblen= my_ismbchar(default_charset_info, pos, end)))
- {
- res->append(pos, mblen);
- pos+= mblen;
- continue;
- }
-#endif
-
switch (*pos) {
case 0: /* Must be escaped for 'mysql' */
res->append('\\');
@@ -4235,7 +4227,7 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def)
/* Whether the table definition has already been validated. */
if (table->s->table_field_def_cache == table_def)
- DBUG_RETURN(FALSE);
+ goto end;
if (table->s->fields != table_def->count)
{
@@ -4268,6 +4260,8 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def)
is backward compatible.
*/
}
+ else
+ {
StringBuffer<1024> sql_type(system_charset_info);
sql_type.extra_allocation(256); // Allocate min 256 characters at once
for (i=0 ; i < table_def->count; i++, field_def++)
@@ -4353,6 +4347,7 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def)
error= TRUE;
}
}
+ }
if (table_def->primary_key_parts)
{
@@ -4394,9 +4389,19 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def)
}
}
- if (! error)
+ if (likely(! error))
table->s->table_field_def_cache= table_def;
+end:
+
+ if (has_keys && !error && !table->key_info)
+ {
+ report_error(0, "Incorrect definition of table %s.%s: "
+ "indexes are missing",
+ table->s->db.str, table->alias.c_ptr());
+ error= TRUE;
+ }
+
DBUG_RETURN(error);
}
@@ -5258,14 +5263,25 @@ int TABLE_LIST::view_check_option(THD *thd, bool ignore_failure)
int TABLE::verify_constraints(bool ignore_failure)
{
+ /*
+ We have to check is_error() first as we are checking it for each
+ constraint to catch fatal warnings.
+ */
+ if (in_use->is_error())
+ return (VIEW_CHECK_ERROR);
+
/* go trough check option clauses for fields and table */
if (check_constraints &&
!(in_use->variables.option_bits & OPTION_NO_CHECK_CONSTRAINT_CHECKS))
{
for (Virtual_column_info **chk= check_constraints ; *chk ; chk++)
{
- /* yes! NULL is ok, see 4.23.3.4 Table check constraints, part 2, SQL:2016 */
- if ((*chk)->expr->val_int() == 0 && !(*chk)->expr->null_value)
+ /*
+ yes! NULL is ok.
+ see 4.23.3.4 Table check constraints, part 2, SQL:2016
+ */
+ if (((*chk)->expr->val_int() == 0 && !(*chk)->expr->null_value) ||
+ in_use->is_error())
{
my_error(ER_CONSTRAINT_FAILED,
MYF(ignore_failure ? ME_JUST_WARNING : 0), (*chk)->name.str,
@@ -5274,7 +5290,11 @@ int TABLE::verify_constraints(bool ignore_failure)
}
}
}
- return(VIEW_CHECK_OK);
+ /*
+ We have to check in_use() as checking constraints may have generated
+ warnings that should be treated as errors
+ */
+ return(!in_use->is_error() ? VIEW_CHECK_OK : VIEW_CHECK_ERROR);
}
/*
@@ -6780,7 +6800,7 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl)
if (bitmap_is_set(write_set, tmp_vfield->field_index))
bitmap_updated= mark_virtual_col(tmp_vfield);
else if (tmp_vfield->vcol_info->stored_in_db ||
- (tmp_vfield->flags & PART_KEY_FLAG))
+ (tmp_vfield->flags & (PART_KEY_FLAG | FIELD_IN_PART_FUNC_FLAG)))
{
if (insert_fl)
{
@@ -7789,8 +7809,8 @@ void TABLE::vers_update_fields()
{
if (!vers_write)
return;
- if (vers_start_field()->store_timestamp(in_use->systime(),
- in_use->systime_sec_part()))
+ if (vers_start_field()->store_timestamp(in_use->query_start(),
+ in_use->query_start_sec_part()))
DBUG_ASSERT(0);
}
else
@@ -7805,8 +7825,8 @@ void TABLE::vers_update_fields()
void TABLE::vers_update_end()
{
- if (vers_end_field()->store_timestamp(in_use->systime(),
- in_use->systime_sec_part()))
+ if (vers_end_field()->store_timestamp(in_use->query_start(),
+ in_use->query_start_sec_part()))
DBUG_ASSERT(0);
}
@@ -7957,7 +7977,7 @@ bool TABLE::insert_all_rows_into_tmp_table(THD *thd,
tmp_table->file->ha_disable_indexes(HA_KEY_SWITCH_ALL);
file->ha_index_or_rnd_end();
- if (file->ha_rnd_init_with_error(1))
+ if (unlikely(file->ha_rnd_init_with_error(1)))
DBUG_RETURN(1);
if (tmp_table->no_rows)
@@ -7969,10 +7989,10 @@ bool TABLE::insert_all_rows_into_tmp_table(THD *thd,
tmp_table->file->ha_start_bulk_insert(file->stats.records);
}
- while (!file->ha_rnd_next(tmp_table->record[0]))
+ while (likely(!file->ha_rnd_next(tmp_table->record[0])))
{
write_err= tmp_table->file->ha_write_tmp_row(tmp_table->record[0]);
- if (write_err)
+ if (unlikely(write_err))
{
bool is_duplicate;
if (tmp_table->file->is_fatal_error(write_err, HA_CHECK_DUP) &&
@@ -7983,7 +8003,7 @@ bool TABLE::insert_all_rows_into_tmp_table(THD *thd,
DBUG_RETURN(1);
}
- if (thd->check_killed())
+ if (unlikely(thd->check_killed()))
{
thd->send_kill_message();
goto err_killed;
@@ -8154,7 +8174,21 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view)
(first_table && first_table->is_multitable()))
set_multitable();
- unit->derived= this;
+ if (!unit->derived)
+ unit->derived= this;
+ else if (!is_with_table_recursive_reference() && unit->derived != this)
+ {
+ if (unit->derived->is_with_table_recursive_reference())
+ unit->derived= this;
+ else if (vers_conditions.eq(unit->derived->vers_conditions))
+ vers_conditions.empty();
+ else
+ {
+ my_error(ER_CONFLICTING_FOR_SYSTEM_TIME, MYF(0));
+ return TRUE;
+ }
+ }
+
if (init_view && !view)
{
/* This is all what we can do for a derived table for now. */
@@ -8440,17 +8474,15 @@ bool TR_table::update(ulonglong start_id, ulonglong end_id)
if (!table && open())
return true;
- timeval start_time= {thd->systime(), long(thd->systime_sec_part())};
- thd->set_start_time();
- timeval end_time= {thd->systime(), long(thd->systime_sec_part())};
+ store(FLD_BEGIN_TS, thd->transaction_time());
+ timeval end_time= {thd->query_start(), long(thd->query_start_sec_part())};
store(FLD_TRX_ID, start_id);
store(FLD_COMMIT_ID, end_id);
- store(FLD_BEGIN_TS, start_time);
store(FLD_COMMIT_TS, end_time);
store_iso_level(thd->tx_isolation);
int error= table->file->ha_write_row(table->record[0]);
- if (error)
+ if (unlikely(error))
table->file->print_error(error, MYF(0));
return error;
}
@@ -8469,10 +8501,10 @@ bool TR_table::query(ulonglong trx_id)
Item *field= newx Item_field(thd, &slex.context, (*this)[FLD_TRX_ID]);
Item *value= newx Item_int(thd, trx_id);
COND *conds= newx Item_func_eq(thd, field, value);
- if ((error= setup_conds(thd, this, dummy, &conds)))
+ if (unlikely((error= setup_conds(thd, this, dummy, &conds))))
return false;
select= make_select(table, 0, 0, conds, NULL, 0, &error);
- if (error || !select)
+ if (unlikely(error || !select))
return false;
// FIXME: (performance) force index 'transaction_id'
error= init_read_record(&info, thd, table, select, NULL,
@@ -8503,11 +8535,11 @@ bool TR_table::query(MYSQL_TIME &commit_time, bool backwards)
conds= newx Item_func_ge(thd, field, value);
else
conds= newx Item_func_le(thd, field, value);
- if ((error= setup_conds(thd, this, dummy, &conds)))
+ if (unlikely((error= setup_conds(thd, this, dummy, &conds))))
return false;
// FIXME: (performance) force index 'commit_timestamp'
select= make_select(table, 0, 0, conds, NULL, 0, &error);
- if (error || !select)
+ if (unlikely(error || !select))
return false;
error= init_read_record(&info, thd, table, select, NULL,
1 /* use_record_cache */, true /* print_error */,
@@ -8567,6 +8599,12 @@ bool TR_table::query_sees(bool &result, ulonglong trx_id1, ulonglong trx_id0,
return false;
}
+ if (trx_id0 == ULONGLONG_MAX || trx_id1 == 0)
+ {
+ result= false;
+ return false;
+ }
+
if (!commit_id1)
{
if (!query(trx_id1))
@@ -8702,28 +8740,53 @@ bool TR_table::check(bool error)
return false;
}
-void vers_select_conds_t::resolve_units(bool timestamps_only)
+bool vers_select_conds_t::resolve_units(THD *thd)
{
DBUG_ASSERT(type != SYSTEM_TIME_UNSPECIFIED);
DBUG_ASSERT(start.item);
- start.resolve_unit(timestamps_only);
- end.resolve_unit(timestamps_only);
+ return start.resolve_unit(thd) ||
+ end.resolve_unit(thd);
}
-void Vers_history_point::resolve_unit(bool timestamps_only)
+bool vers_select_conds_t::eq(const vers_select_conds_t &conds) const
{
- if (item && unit == VERS_UNDEFINED)
- {
- if (item->type() == Item::FIELD_ITEM || timestamps_only)
- unit= VERS_TIMESTAMP;
- else if (item->result_type() == INT_RESULT ||
- item->result_type() == REAL_RESULT)
- unit= VERS_TRX_ID;
- else
- unit= VERS_TIMESTAMP;
+ if (type != conds.type)
+ return false;
+ switch (type) {
+ case SYSTEM_TIME_UNSPECIFIED:
+ case SYSTEM_TIME_ALL:
+ return true;
+ case SYSTEM_TIME_BEFORE:
+ DBUG_ASSERT(0);
+ case SYSTEM_TIME_AS_OF:
+ return start.eq(conds.start);
+ case SYSTEM_TIME_FROM_TO:
+ case SYSTEM_TIME_BETWEEN:
+ return start.eq(conds.start) && end.eq(conds.end);
}
+ DBUG_ASSERT(0);
+ return false;
}
+
+bool Vers_history_point::resolve_unit(THD *thd)
+{
+ if (!item)
+ return false;
+ if (!item->fixed && item->fix_fields(thd, &item))
+ return true;
+ return item->this_item()->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");
+}
+
+
void Vers_history_point::fix_item()
{
if (item && item->decimals == 0 && item->type() == Item::FUNC_ITEM &&
@@ -8731,8 +8794,14 @@ void Vers_history_point::fix_item()
item->decimals= 6;
}
+
+bool Vers_history_point::eq(const vers_history_point_t &point) const
+{
+ return unit == point.unit && item->eq(point.item, false);
+}
+
void Vers_history_point::print(String *str, enum_query_type query_type,
- const char *prefix, size_t plen)
+ const char *prefix, size_t plen) const
{
const static LEX_CSTRING unit_type[]=
{