diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2019-05-19 20:55:37 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2019-05-19 20:55:37 +0200 |
commit | c07325f932abef2032b2e56532f6cb615e2a1161 (patch) | |
tree | 754ca158e45ebc014e5cbeaf4c3e7581f9575d76 /sql/handler.cc | |
parent | 7f8187bc432f79afe4c0549d68845a68e6c159ab (diff) | |
parent | 2ae83affef5a4d89f38272db31a400f968279a7a (diff) | |
download | mariadb-git-c07325f932abef2032b2e56532f6cb615e2a1161.tar.gz |
Merge branch '10.3' into 10.4
Diffstat (limited to 'sql/handler.cc')
-rw-r--r-- | sql/handler.cc | 238 |
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, |