summaryrefslogtreecommitdiff
path: root/sql/handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/handler.cc')
-rw-r--r--sql/handler.cc238
1 files changed, 169 insertions, 69 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index edd6e40b8ec..c5d6fa29f8f 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -11,8 +11,8 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
/** @file handler.cc
@@ -4898,10 +4898,7 @@ void handler::get_dynamic_partition_info(PARTITION_STATS *stat_info,
stat_info->create_time= stats.create_time;
stat_info->update_time= stats.update_time;
stat_info->check_time= stats.check_time;
- stat_info->check_sum= 0;
- if (table_flags() & (HA_HAS_OLD_CHECKSUM | HA_HAS_NEW_CHECKSUM))
- stat_info->check_sum= checksum();
- return;
+ stat_info->check_sum= stats.checksum;
}
@@ -5023,6 +5020,98 @@ end:
}
+static void flush_checksum(ha_checksum *row_crc, uchar **checksum_start,
+ size_t *checksum_length)
+{
+ if (*checksum_start)
+ {
+ *row_crc= my_checksum(*row_crc, *checksum_start, *checksum_length);
+ *checksum_start= NULL;
+ *checksum_length= 0;
+ }
+}
+
+
+/* calculating table's checksum */
+int handler::calculate_checksum()
+{
+ int error;
+ THD *thd=ha_thd();
+ DBUG_ASSERT(table->s->last_null_bit_pos < 8);
+ uchar null_mask= table->s->last_null_bit_pos
+ ? 256 - (1 << table->s->last_null_bit_pos) : 0;
+
+ table->use_all_stored_columns();
+ stats.checksum= 0;
+
+ if ((error= ha_rnd_init(1)))
+ return error;
+
+ for (;;)
+ {
+ if (thd->killed)
+ return HA_ERR_ABORTED_BY_USER;
+
+ ha_checksum row_crc= 0;
+ error= table->file->ha_rnd_next(table->record[0]);
+ if (error)
+ break;
+
+ if (table->s->null_bytes)
+ {
+ /* fix undefined null bits */
+ table->record[0][table->s->null_bytes-1] |= null_mask;
+ if (!(table->s->db_create_options & HA_OPTION_PACK_RECORD))
+ table->record[0][0] |= 1;
+
+ row_crc= my_checksum(row_crc, table->record[0], table->s->null_bytes);
+ }
+
+ uchar *checksum_start= NULL;
+ size_t checksum_length= 0;
+ for (uint i= 0; i < table->s->fields; i++ )
+ {
+ Field *f= table->field[i];
+
+ if (! thd->variables.old_mode && f->is_real_null(0))
+ {
+ flush_checksum(&row_crc, &checksum_start, &checksum_length);
+ continue;
+ }
+ /*
+ BLOB and VARCHAR have pointers in their field, we must convert
+ to string; GEOMETRY is implemented on top of BLOB.
+ BIT may store its data among NULL bits, convert as well.
+ */
+ switch (f->type()) {
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_GEOMETRY:
+ case MYSQL_TYPE_BIT:
+ {
+ flush_checksum(&row_crc, &checksum_start, &checksum_length);
+ String tmp;
+ f->val_str(&tmp);
+ row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), tmp.length());
+ break;
+ }
+ default:
+ if (!checksum_start)
+ checksum_start= f->ptr;
+ DBUG_ASSERT(checksum_start + checksum_length == f->ptr);
+ checksum_length+= f->pack_length();
+ break;
+ }
+ }
+ flush_checksum(&row_crc, &checksum_start, &checksum_length);
+
+ stats.checksum+= row_crc;
+ }
+ table->file->ha_rnd_end();
+ return error == HA_ERR_END_OF_FILE ? 0 : error;
+}
+
+
/****************************************************************************
** Some general functions that isn't in the handler class
****************************************************************************/
@@ -6350,8 +6439,8 @@ int handler::ha_reset()
table->default_column_bitmaps();
pushed_cond= NULL;
tracker= NULL;
- mark_trx_read_write_done= check_table_binlog_row_based_done=
- check_table_binlog_row_based_result= 0;
+ mark_trx_read_write_done= 0;
+ clear_cached_table_binlog_row_based_flag();
/* Reset information about pushed engine conditions */
cancel_pushed_idx_cond();
/* Reset information about pushed index conditions */
@@ -7339,8 +7428,9 @@ bool Table_scope_and_contents_source_st::vers_check_system_fields(
{
if (!(options & HA_VERSIONED_TABLE))
return false;
- return vers_info.check_sys_fields(create_table.table_name, create_table.db,
- alter_info);
+ return vers_info.check_sys_fields(
+ create_table.table_name, create_table.db, alter_info,
+ ha_check_storage_engine_flag(db_type, HTON_NATIVE_SYS_VERSIONING));
}
@@ -7449,7 +7539,11 @@ bool Vers_parse_info::fix_alter_info(THD *thd, Alter_info *alter_info,
if (alter_info->flags & ALTER_ADD_SYSTEM_VERSIONING)
{
- if (check_sys_fields(table_name, share->db, alter_info))
+ const bool can_native=
+ ha_check_storage_engine_flag(create_info->db_type,
+ HTON_NATIVE_SYS_VERSIONING) ||
+ create_info->db_type->db_type == DB_TYPE_PARTITION_DB;
+ if (check_sys_fields(table_name, share->db, alter_info, can_native))
return true;
}
@@ -7554,80 +7648,86 @@ bool Vers_parse_info::check_conditions(const Lex_table_name &table_name,
return false;
}
+static bool is_versioning_timestamp(const Create_field *f)
+{
+ return (f->type_handler() == &type_handler_datetime2 ||
+ f->type_handler() == &type_handler_timestamp2) &&
+ f->length == MAX_DATETIME_FULL_WIDTH;
+}
+
+static bool is_some_bigint(const Create_field *f)
+{
+ return f->type_handler() == &type_handler_longlong ||
+ f->type_handler() == &type_handler_vers_trx_id;
+}
+
+static bool is_versioning_bigint(const Create_field *f)
+{
+ return is_some_bigint(f) && f->flags & UNSIGNED_FLAG &&
+ f->length == MY_INT64_NUM_DECIMAL_DIGITS - 1;
+}
+
+static bool require_timestamp(const Create_field *f, Lex_table_name table_name)
+{
+ my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str, "TIMESTAMP(6)",
+ table_name.str);
+ return true;
+}
+static bool require_bigint(const Create_field *f, Lex_table_name table_name)
+{
+ my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str,
+ "BIGINT(20) UNSIGNED", table_name.str);
+ return true;
+}
+
bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name,
const Lex_table_name &db,
- Alter_info *alter_info)
+ Alter_info *alter_info,
+ bool can_native) const
{
if (check_conditions(table_name, db))
return true;
+ const Create_field *row_start= NULL;
+ const Create_field *row_end= NULL;
+
List_iterator<Create_field> it(alter_info->create_list);
- uint found_flag= 0;
while (Create_field *f= it++)
{
- vers_sys_type_t f_check_unit= VERS_UNDEFINED;
- uint sys_flag= f->flags & VERS_SYSTEM_FIELD;
+ if (!row_start && f->flags & VERS_SYS_START_FLAG)
+ row_start= f;
+ else if (!row_end && f->flags & VERS_SYS_END_FLAG)
+ row_end= f;
+ }
- if (!sys_flag)
- continue;
+ const bool expect_timestamp=
+ !can_native || !is_some_bigint(row_start) || !is_some_bigint(row_end);
- if (sys_flag & found_flag)
- {
- my_error(ER_VERS_DUPLICATE_ROW_START_END, MYF(0),
- found_flag & VERS_SYS_START_FLAG ? "START" : "END",
- f->field_name.str);
- return true;
- }
+ if (expect_timestamp)
+ {
+ if (!is_versioning_timestamp(row_start))
+ return require_timestamp(row_start, table_name);
- sys_flag|= found_flag;
+ if (!is_versioning_timestamp(row_end))
+ return require_timestamp(row_end, table_name);
+ }
+ else
+ {
+ if (!is_versioning_bigint(row_start))
+ return require_bigint(row_start, table_name);
- if ((f->type_handler() == &type_handler_datetime2 ||
- f->type_handler() == &type_handler_timestamp2) &&
- f->length == MAX_DATETIME_FULL_WIDTH)
- {
- f_check_unit= VERS_TIMESTAMP;
- }
- else if (f->type_handler() == &type_handler_longlong
- && (f->flags & UNSIGNED_FLAG)
- && f->length == (MY_INT64_NUM_DECIMAL_DIGITS - 1))
- {
- f_check_unit= VERS_TRX_ID;
- }
- else
- {
- if (!check_unit)
- check_unit= VERS_TIMESTAMP;
- goto error;
- }
+ if (!is_versioning_bigint(row_end))
+ return require_bigint(row_end, table_name);
+ }
- if (f_check_unit)
- {
- if (check_unit)
- {
- if (check_unit == f_check_unit)
- {
- if (check_unit == VERS_TRX_ID && !TR_table::use_transaction_registry)
- {
- my_error(ER_VERS_TRT_IS_DISABLED, MYF(0));
- return true;
- }
- return false;
- }
- error:
- my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str,
- check_unit == VERS_TIMESTAMP ?
- "TIMESTAMP(6)" :
- "BIGINT(20) UNSIGNED",
- table_name.str);
- return true;
- }
- check_unit= f_check_unit;
- }
+ if (is_versioning_bigint(row_start) && is_versioning_bigint(row_end) &&
+ !TR_table::use_transaction_registry)
+ {
+ my_error(ER_VERS_TRT_IS_DISABLED, MYF(0));
+ return true;
}
- my_error(ER_MISSING, MYF(0), table_name.str, found_flag & VERS_SYS_START_FLAG ?
- "ROW END" : found_flag ? "ROW START" : "ROW START/END");
- return true;
+ return false;
}
bool Table_period_info::check_field(const Create_field* f,