1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

SQL, IB: various refactoring [#337]

This commit is contained in:
Eugene Kosov
2017-11-24 15:34:57 +03:00
committed by Aleksey Midenkov
parent 4dd8736c15
commit 0cdc1164dc
23 changed files with 267 additions and 183 deletions

View File

@@ -198,7 +198,7 @@ enum enum_indicator_type
#define VERS_SYS_END_FLAG (1 << 28) /* autogenerated column declared with
`generated always as row end`
(see II.a SQL Standard).*/
#define VERS_OPTIMIZED_UPDATE_FLAG (1 << 29) /* column that doesn't support
#define VERS_UPDATE_UNVERSIONED_FLAG (1 << 29) /* column that doesn't support
system versioning when table
itself supports it*/
#define HIDDEN_FLAG (1 << 31) /* hide from SELECT * */

View File

@@ -1455,6 +1455,11 @@ public:
return flags & (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG);
}
bool vers_update_unversioned() const
{
return flags & VERS_UPDATE_UNVERSIONED_FLAG;
}
virtual bool vers_trx_id() const
{
return false;

View File

@@ -6859,7 +6859,7 @@ bool Vers_parse_info::check_and_fix_implicit(
!with_system_versioning) ||
f->versioning == Column_definition::WITHOUT_VERSIONING)
{
f->flags|= VERS_OPTIMIZED_UPDATE_FLAG;
f->flags|= VERS_UPDATE_UNVERSIONED_FLAG;
}
}
@@ -6999,7 +6999,7 @@ bool Vers_parse_info::check_and_fix_alter(THD *thd, Alter_info *alter_info,
while (Create_field *f= it++)
{
if (f->versioning == Column_definition::WITHOUT_VERSIONING)
f->flags|= VERS_OPTIMIZED_UPDATE_FLAG;
f->flags|= VERS_UPDATE_UNVERSIONED_FLAG;
if (f->change.str && (start == f->change || end == f->change))
{

View File

@@ -10384,7 +10384,7 @@ Item *Item_field::vers_optimized_fields_transformer(THD *thd, uchar *)
if (!field)
return this;
if (field->flags & VERS_OPTIMIZED_UPDATE_FLAG && context &&
if (field->vers_update_unversioned() && context &&
field->table->pos_in_table_list &&
field->table->pos_in_table_list->vers_conditions)
{

View File

@@ -710,12 +710,6 @@ extern "C" void thd_kill_timeout(THD* thd)
mysql_mutex_unlock(&thd->LOCK_thd_data);
}
Time_zone * thd_get_timezone(THD * thd)
{
DBUG_ASSERT(thd && thd->variables.time_zone);
return thd->variables.time_zone;
}
void thd_vers_update_trt(THD * thd, bool value)
{
thd->vers_update_trt= value;

View File

@@ -155,6 +155,7 @@ extern bool volatile shutdown_in_progress;
extern "C" LEX_STRING * thd_query_string (MYSQL_THD thd);
extern "C" size_t thd_query_safe(MYSQL_THD thd, char *buf, size_t buflen);
void thd_vers_update_trt(THD *thd, bool value);
/**
@class CSET_STRING
@@ -4564,6 +4565,8 @@ public:
/* Handling of timeouts for commands */
thr_timer_t query_timer;
// Storage engine may set this to true is we want to write a row to
// transaction_registry table on transaction commit.
bool vers_update_trt;
public:

View File

@@ -16743,7 +16743,7 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field,
HIDDEN_FLAG |
VERS_SYS_START_FLAG |
VERS_SYS_END_FLAG |
VERS_OPTIMIZED_UPDATE_FLAG));
VERS_UPDATE_UNVERSIONED_FLAG));
if (org_field->maybe_null() || (item && item->maybe_null))
new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join
if (org_field->type() == MYSQL_TYPE_VAR_STRING ||

View File

@@ -2188,7 +2188,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(def_value.ptr(), def_value.length(), system_charset_info);
}
if (field->flags & VERS_OPTIMIZED_UPDATE_FLAG)
if (field->vers_update_unversioned())
{
packet->append(STRING_WITH_LEN(" WITHOUT SYSTEM VERSIONING"));
}

View File

@@ -161,7 +161,7 @@ static bool check_has_vers_fields(List<Item> &items)
while (Item *item= it++)
{
if (Item_field *item_field= item->field_for_view_update())
if (!(item_field->field->flags & VERS_OPTIMIZED_UPDATE_FLAG))
if (!item_field->field->vers_update_unversioned())
return true;
}
return false;

View File

@@ -2051,7 +2051,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
{
uchar flags= *extra2_field_flags++;
if (flags & VERS_OPTIMIZED_UPDATE)
reg_field->flags|= VERS_OPTIMIZED_UPDATE_FLAG;
reg_field->flags|= VERS_UPDATE_UNVERSIONED_FLAG;
if (flags & HIDDEN)
reg_field->flags|= HIDDEN_FLAG;
}
@@ -8527,7 +8527,8 @@ void TR_table::store(uint field_id, timeval ts)
void TR_table::store_data(ulonglong trx_id, ulonglong commit_id, timeval commit_ts)
{
timeval start_time= {thd->start_time, thd->start_time_sec_part};
timeval start_time= {static_cast<int>(thd->start_time),
static_cast<int>(thd->start_time_sec_part)};
store(FLD_TRX_ID, trx_id);
store(FLD_COMMIT_ID, commit_id);
store(FLD_BEGIN_TS, start_time);

View File

@@ -2930,14 +2930,14 @@ inline void mark_as_null_row(TABLE *table)
bool is_simple_order(ORDER *order);
class Open_tables_backup;
/** Transaction Registry Table (TRT)
This table holds transaction IDs, their corresponding times and other
transaction-related data which is used for transaction order resolution.
When versioned table marks its records lifetime with transaction IDs,
TRT is used to get their actual timestamps. */
class Open_tables_backup;
class TR_table: public TABLE_LIST
{
THD *thd;
@@ -2952,33 +2952,111 @@ public:
FLD_ISO_LEVEL,
FIELD_COUNT
};
/**
@param[in,out] Thread handle
@param[in] Current transaction is read-write.
*/
TR_table(THD *_thd, bool rw= false);
/**
Opens a transaction_registry table.
@retval true on error, false otherwise.
*/
bool open();
~TR_table();
/**
@retval current thd
*/
THD *get_thd() const { return thd; }
/**
Stores value to internal transaction_registry TABLE object.
@param[in] field number in a TABLE
@param[in] value to store
*/
void store(uint field_id, ulonglong val);
/**
Stores value to internal transaction_registry TABLE object.
@param[in] field number in a TABLE
@param[in] value to store
*/
void store(uint field_id, timeval ts);
/**
Stores value to internal transaction_registry TABLE object.
@param[in] current (InnoDB) transaction id
@param[in] InnoDB transaction counter at the time of transaction commit
@param[in] transaction commit timestamp
*/
void store_data(ulonglong trx_id, ulonglong commit_id, timeval commit_ts);
/**
Writes a row from internal TABLE object to transaction_registry table.
@retval true on error, false otherwise.
*/
bool update();
// return true if found; false if not found or error
/**
Checks whether a row with specified transaction_id exists in a
transaction_registry table.
@param[in] transacton_id value
@retval true if exists, false it not exists or an error occured
*/
bool query(ulonglong trx_id);
/**
Gets a row from transaction_registry with the closest commit_timestamp to
first argument. We can search for a value which a lesser or greater than
first argument. Also loads a row into an internal TABLE object.
@param[in] timestamp
@param[in] true if we search for a lesser timestamp, false if greater
@retval true if exists, false it not exists or an error occured
*/
bool query(MYSQL_TIME &commit_time, bool backwards);
// return true if error
/**
Checks whether transaction1 sees transaction0.
@param[out] true if transaction1 sees transaction0, undefined on error and
when transaction1=transaction0 and false otherwise
@param[in] transaction_id of transaction1
@param[in] transaction_id of transaction0
@param[in] commit time of transaction1 or 0 if we want it to be queried
@param[in] isolation level (from handler.h) of transaction1
@param[in] commit time of transaction0 or 0 if we want it to be queried
@retval true on error, false otherwise
*/
bool query_sees(bool &result, ulonglong trx_id1, ulonglong trx_id0,
ulonglong commit_id1= 0, enum_tx_isolation iso_level1= ISO_READ_UNCOMMITTED,
ulonglong commit_id1= 0,
enum_tx_isolation iso_level1= ISO_READ_UNCOMMITTED,
ulonglong commit_id0= 0);
/**
@retval transaction isolation level of a row from internal TABLE object.
*/
enum_tx_isolation iso_level() const;
/**
Stores transactioin isolation level to internal TABLE object.
*/
void store_iso_level(enum_tx_isolation iso_level)
{
DBUG_ASSERT(iso_level <= ISO_SERIALIZABLE);
store(FLD_ISO_LEVEL, iso_level + 1);
}
/**
Writes a message to MariaDB log about incorrect transaction_registry schema.
@param[in] a message explained what's incorrect in schema
*/
void warn_schema_incorrect(const char *reason);
/**
Checks whether transaction_registry table has a correct schema.
@retval true if schema is incorrect and false otherwise
*/
bool check();
public:
TABLE * operator-> () const
{
return table;
@@ -2992,13 +3070,13 @@ public:
{
return table;
}
bool operator== (TABLE_LIST &subj) const
bool operator== (const TABLE_LIST &subj) const
{
if (0 != strcmp(db, subj.db))
return false;
return (0 == strcmp(table_name, subj.table_name));
}
bool operator!= (TABLE_LIST &subj) const
bool operator!= (const TABLE_LIST &subj) const
{
return !(*this == subj);
}

View File

@@ -89,7 +89,5 @@ extern my_time_t sec_since_epoch_TIME(MYSQL_TIME *t);
static const int MY_TZ_TABLES_COUNT= 4;
extern Time_zone* thd_get_timezone(THD* thd);
#endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */
#endif /* TZTIME_INCLUDED */

View File

@@ -121,7 +121,7 @@ bool has_extra2_field_flags(List<Create_field> &create_fields)
List_iterator<Create_field> it(create_fields);
while (Create_field *f= it++)
{
if (f->flags & (VERS_OPTIMIZED_UPDATE_FLAG | HIDDEN_FLAG))
if (f->flags & (VERS_UPDATE_UNVERSIONED_FLAG | HIDDEN_FLAG))
return true;
}
return false;
@@ -356,7 +356,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
while (Create_field *field= it++)
{
uchar flags= 0;
if (field->flags & VERS_OPTIMIZED_UPDATE_FLAG)
if (field->flags & VERS_UPDATE_UNVERSIONED_FLAG)
flags|= VERS_OPTIMIZED_UPDATE;
if (field->flags & HIDDEN_FLAG)
flags|= HIDDEN;

View File

@@ -861,3 +861,17 @@ dfield_t::clone(mem_heap_t* heap) const
return(obj);
}
/** Assuming field is sys_trx_end checks whether its value is not SYS_TRX_MAX.
@param dfield field to check
@return true for historical rows and false otherwise*/
bool
dfield_is_historical_sys_trx_end(const dfield_t* dfield)
{
static const trx_id_t MAX = TRX_ID_MAX;
ut_ad(dfield);
ut_ad(dfield->type.prtype & DATA_VERS_END);
const byte* data = static_cast<const byte*>(dfield_get_data(dfield));
ut_ad(dfield_get_len(dfield) == 8);
return(memcmp(data, &MAX, 8));
}

View File

@@ -3623,10 +3623,9 @@ static const char* ha_innobase_exts[] = {
NullS
};
void innodb_get_trt_data(TR_table &trt)
{
THD *thd = trt.get_thd();
trx_t *trx = thd_to_trx(thd);
void innodb_get_trt_data(TR_table& trt) {
THD* thd = trt.get_thd();
trx_t* trx = thd_to_trx(thd);
ut_a(trx);
ut_a(trx->vers_update_trt);
mutex_enter(&trx_sys->mutex);
@@ -3637,8 +3636,7 @@ void innodb_get_trt_data(TR_table &trt)
mutex_exit(&trx_sys->mutex);
// silent downgrade cast warning on win64
timeval commit_ts = {static_cast<int>(sec),
static_cast<int>(usec)};
timeval commit_ts = {static_cast<int>(sec), static_cast<int>(usec)};
trt.store_data(trx->id, commit_id, commit_ts);
trx->vers_update_trt = false;
}
@@ -6521,6 +6519,10 @@ no_such_table:
}
}
if (table && m_prebuilt->table) {
ut_ad(table->versioned() == m_prebuilt->table->versioned());
}
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
DBUG_RETURN(0);
}
@@ -8365,17 +8367,18 @@ no_commit:
innobase_srv_conc_enter_innodb(m_prebuilt);
vers_set_fields = (table->versioned_write() &&
(sql_command != SQLCOM_CREATE_TABLE || table->s->vtmd))
?
ROW_INS_VERSIONED :
ROW_INS_NORMAL;
vers_set_fields =
(table->versioned_write()
&& (sql_command != SQLCOM_CREATE_TABLE || table->s->vtmd))
? ROW_INS_VERSIONED
: ROW_INS_NORMAL;
/* Step-5: Execute insert graph that will result in actual insert. */
error = row_insert_for_mysql((byte*) record, m_prebuilt, vers_set_fields);
if (m_prebuilt->trx->vers_update_trt)
if (m_prebuilt->trx->vers_update_trt) {
thd_vers_update_trt(m_user_thd, true);
}
DEBUG_SYNC(m_user_thd, "ib_after_row_insert");
@@ -8626,6 +8629,7 @@ calc_row_difference(
doc_id_t doc_id = FTS_NULL_DOC_ID;
ulint num_v = 0;
uint n_fields = mysql_fields(table);
bool table_versioned = prebuilt->table->versioned();
ut_ad(!srv_read_only_mode);
@@ -8876,9 +8880,8 @@ calc_row_difference(
}
n_changed++;
if (!prebuilt->upd_node->versioned &&
prebuilt->table->versioned() &&
!(field->flags & VERS_OPTIMIZED_UPDATE_FLAG)) {
if (table_versioned
&& !field->vers_update_unversioned()) {
prebuilt->upd_node->versioned = true;
}
@@ -8987,9 +8990,7 @@ calc_row_difference(
++n_changed;
if (!prebuilt->upd_node->versioned &&
prebuilt->table->versioned() &&
!(field->flags & VERS_OPTIMIZED_UPDATE_FLAG)) {
if (table_versioned && !field->vers_update_unversioned()) {
prebuilt->upd_node->versioned = true;
}
} else {
@@ -9175,13 +9176,14 @@ ha_innobase::update_row(
innobase_srv_conc_enter_innodb(m_prebuilt);
if (!table->versioned_write())
if (!table->versioned_write()) {
m_prebuilt->upd_node->versioned = false;
}
if (m_prebuilt->upd_node->versioned) {
vers_set_fields = true;
if (thd_sql_command(m_user_thd) == SQLCOM_ALTER_TABLE && !table->s->vtmd)
{
if (thd_sql_command(m_user_thd) == SQLCOM_ALTER_TABLE
&& !table->s->vtmd) {
m_prebuilt->upd_node->vers_delete = true;
} else {
m_prebuilt->upd_node->vers_delete = false;
@@ -9192,12 +9194,14 @@ ha_innobase::update_row(
error = row_update_for_mysql(m_prebuilt, vers_set_fields);
if (error == DB_SUCCESS && vers_ins_row) {
if (trx->id != static_cast<trx_id_t>(table->vers_start_field()->val_int()))
if (trx->id != static_cast<trx_id_t>(table->vers_start_field()->val_int())) {
error = row_insert_for_mysql((byte*) old_row, m_prebuilt, ROW_INS_HISTORICAL);
}
}
if (m_prebuilt->trx->vers_update_trt)
if (m_prebuilt->trx->vers_update_trt) {
thd_vers_update_trt(m_user_thd, true);
}
if (error == DB_SUCCESS && autoinc) {
/* A value for an AUTO_INCREMENT column
@@ -9313,13 +9317,13 @@ ha_innobase::delete_row(
innobase_srv_conc_enter_innodb(m_prebuilt);
bool vers_set_fields =
table->versioned_write() &&
table->vers_end_field()->is_max();
table->versioned_write() && table->vers_end_field()->is_max();
error = row_update_for_mysql(m_prebuilt, vers_set_fields);
if (m_prebuilt->trx->vers_update_trt)
if (m_prebuilt->trx->vers_update_trt) {
thd_vers_update_trt(m_user_thd, true);
}
innobase_srv_conc_exit_innodb(m_prebuilt);
@@ -11407,6 +11411,7 @@ create_table_info_t::create_table_def()
for (i = 0; i < n_cols; i++) {
ulint is_virtual;
bool is_stored = false;
Field* field = m_form->field[i];
ulint vers_row_start = 0;
ulint vers_row_end = 0;

View File

@@ -586,8 +586,6 @@ bool thd_is_strict_mode(const MYSQL_THD thd);
*/
extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file);
extern void thd_vers_update_trt(THD * thd, bool value);
/** Get the partition_info working copy.
@param thd Thread object.
@return NULL or pointer to partition_info working copy. */

View File

@@ -631,9 +631,10 @@ instant_alter_column_possible(
const Alter_inplace_info* ha_alter_info,
const TABLE* table)
{
if (ha_alter_info->create_info->vers_info.with_system_versioning)
// Making table system-versioned instantly is not implemented yet.
if (ha_alter_info->create_info->vers_info.with_system_versioning) {
return false;
}
if (~ha_alter_info->handler_flags
& Alter_inplace_info::ADD_STORED_BASE_COLUMN) {
@@ -7086,8 +7087,9 @@ ok_exit:
ctx->m_stage, add_v, eval_table,
ha_alter_info->handler_flags & Alter_inplace_info::ALTER_DROP_HISTORICAL);
if (m_prebuilt->trx->vers_update_trt)
if (m_prebuilt->trx->vers_update_trt) {
thd_vers_update_trt(m_user_thd, true);
}
#ifndef DBUG_OFF
oom:
@@ -9753,7 +9755,6 @@ foreign_fail:
DBUG_RETURN(false);
}
/**
@param thd the session
@param start_value the lower bound

View File

@@ -508,6 +508,12 @@ dtuple_print(
const dtuple_t* tuple) /*!< in: tuple */
MY_ATTRIBUTE((nonnull));
/** Assuming field is sys_trx_end checks whether its value is not SYS_TRX_MAX.
@param dfield field to check
@return true for historical rows and false otherwise*/
bool
dfield_is_historical_sys_trx_end(const dfield_t* dfield);
/** Print the contents of a tuple.
@param[out] o output stream
@param[in] field array of data fields

View File

@@ -229,39 +229,4 @@ struct ins_node_t{
#define INS_NODE_ALLOC_ROW_ID 2 /* row id should be allocated */
#define INS_NODE_INSERT_ENTRIES 3 /* index entries should be built and
inserted */
UNIV_INLINE
void row_ins_set_tuple_col_8(
dtuple_t* tuple,
int col,
ib_uint64_t data,
byte* buf)
{
static const ulint fsize = sizeof(data);
dfield_t* dfield = dtuple_get_nth_field(tuple, col);
ut_ad(dfield->type.len == fsize);
if (dfield->len == UNIV_SQL_NULL) {
dfield_set_data(dfield, buf, fsize);
}
ut_ad(dfield->len == dfield->type.len && dfield->data);
mach_write_to_8(dfield->data, data);
}
UNIV_INLINE
void row_ins_set_tuple_col_8(
dtuple_t* tuple,
int col,
timeval& data,
byte* buf)
{
dfield_t* dfield = dtuple_get_nth_field(tuple, col);
ut_ad(dfield->type.len == 8);
if (dfield->len == UNIV_SQL_NULL) {
dfield_set_data(dfield, buf, 8);
}
ut_ad(dfield->len == dfield->type.len && dfield->data);
mach_write_to_4(reinterpret_cast<byte*>(dfield->data), (ulint) data.tv_sec);
mach_write_to_4(reinterpret_cast<byte*>(dfield->data) + 4, (ulint) data.tv_usec);
}
#endif

View File

@@ -237,9 +237,12 @@ row_lock_table_for_mysql(
/** System Versioning: row_insert_for_mysql() modes */
enum ins_mode_t {
ROW_INS_NORMAL = 0, ///< plain row (without versioning)
ROW_INS_VERSIONED, ///< sys_trx_start = TRX_ID, sys_trx_end = MAX
ROW_INS_HISTORICAL ///< sys_trx_end = TRX_ID
/* plain row (without versioning) */
ROW_INS_NORMAL = 0,
/* sys_trx_start = TRX_ID, sys_trx_end = MAX */
ROW_INS_VERSIONED,
/* sys_trx_end = TRX_ID */
ROW_INS_HISTORICAL
};
/** Does an insert for MySQL.

View File

@@ -429,7 +429,7 @@ row_ins_cascade_ancestor_updates_table(
upd_node = static_cast<upd_node_t*>(parent);
if (upd_node->table == table && upd_node->is_delete == FALSE
if (upd_node->table == table && !upd_node->is_delete
&& !upd_node->vers_delete) {
return(TRUE);
@@ -1573,18 +1573,19 @@ private:
ulint& counter;
};
/*********************************************************************//**
Reads sys_trx_end field from clustered index row.
/** Reads sys_trx_end field from clustered index row.
@param[in] rec clustered row
@param[in] offsets offsets
@param[in] index clustered index
@return trx_id_t */
static
trx_id_t
row_ins_get_sys_trx_end(
/*===================================*/
const rec_t *rec, /*!< in: clustered row */
ulint *offsets, /*!< in: offsets */
dict_index_t *index) /*!< in: clustered index */
const rec_t* rec,
const ulint* offsets,
const dict_index_t* index)
{
ut_a(dict_index_is_clust(index));
ut_a(index->is_clust());
ulint len;
ulint nfield = dict_col_get_clust_pos(
@@ -1594,51 +1595,46 @@ row_ins_get_sys_trx_end(
return(mach_read_from_8(field));
}
/**
Performs search at clustered index and returns sys_trx_end if row was found.
/** Performs search at clustered index and returns sys_trx_end if row was found.
@param[in] index secondary index of record
@param[in] rec record in a secondary index
@param[out] end_trx_id value from clustered index
@return DB_SUCCESS, DB_NO_REFERENCED_ROW */
@return sys_trx_end on success or 0 at failure */
static
dberr_t
trx_id_t
row_ins_search_sys_trx_end(
dict_index_t *index,
const rec_t *rec,
trx_id_t *end_trx_id)
dict_index_t* index,
const rec_t* rec)
{
ut_ad(!index->is_clust());
bool found = false;
mem_heap_t *heap = mem_heap_create(256);
dict_index_t *clust_index = NULL;
trx_id_t result = 0;
mem_heap_t* heap = NULL;
dict_index_t* clust_index = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint *offsets = offsets_;
ulint* offsets = offsets_;
rec_offs_init(offsets_);
mtr_t mtr;
mtr_start(&mtr);
mtr.start();
rec_t *clust_rec =
rec_t* clust_rec =
row_get_clust_rec(BTR_SEARCH_LEAF, rec, index, &clust_index, &mtr);
if (!clust_rec)
goto not_found;
if (clust_rec) {
offsets = rec_get_offsets(clust_rec, clust_index, offsets, true,
ULINT_UNDEFINED, &heap);
*end_trx_id = row_ins_get_sys_trx_end(clust_rec, offsets, clust_index);
found = true;
not_found:
mtr_commit(&mtr);
mem_heap_free(heap);
if (!found) {
result =
row_ins_get_sys_trx_end(clust_rec, offsets, clust_index);
} else {
ib::error() << "foreign constraints: secondary index is out of "
"sync";
ut_ad(false && "secondary index is out of sync");
return(DB_NO_REFERENCED_ROW);
ut_ad(!"secondary index is out of sync");
}
return(DB_SUCCESS);
mtr.commit();
if (heap) {
mem_heap_free(heap);
}
return(result);
}
/***************************************************************//**
@@ -1705,15 +1701,13 @@ row_ins_check_foreign_constraint(
}
/* System Versioning: if sys_trx_end != Inf, we
suppress the foreign key check */
if (table->versioned() &&
dfield_get_type(field)->prtype & DATA_VERS_END) {
byte* data = static_cast<byte*>(dfield_get_data(field));
ut_ad(data);
trx_id_t end_trx_id = mach_read_from_8(data);
if (end_trx_id != TRX_ID_MAX)
if (dfield_get_type(field)->prtype & DATA_VERS_END) {
ut_ad(table->versioned());
if (dfield_is_historical_sys_trx_end(field)) {
goto exit_func;
}
}
}
if (que_node_get_type(thr->run_node) == QUE_NODE_UPDATE) {
upd_node = static_cast<upd_node_t*>(thr->run_node);
@@ -1844,19 +1838,20 @@ row_ins_check_foreign_constraint(
if (check_table->versioned()) {
trx_id_t end_trx_id = 0;
if (dict_index_is_clust(check_index)) {
if (check_index->is_clust()) {
end_trx_id =
row_ins_get_sys_trx_end(
rec, offsets, check_index);
} else if (row_ins_search_sys_trx_end(
check_index, rec, &end_trx_id) !=
DB_SUCCESS) {
} else if (!(end_trx_id =
row_ins_search_sys_trx_end(
check_index, rec))) {
break;
}
if (end_trx_id != TRX_ID_MAX)
if (end_trx_id != TRX_ID_MAX) {
continue;
}
}
if (rec_get_deleted_flag(rec,
rec_offs_comp(offsets))) {

View File

@@ -1743,6 +1743,8 @@ row_merge_read_clustered_index(
ib_uint64_t read_rows = 0;
ib_uint64_t table_total_rows = 0;
ulonglong historic_auto_decrement = 0xffffffffffffffff;
char new_sys_trx_start[8];
char new_sys_trx_end[8];
DBUG_ENTER("row_merge_read_clustered_index");
@@ -1917,6 +1919,9 @@ row_merge_read_clustered_index(
prev_fields = NULL;
}
mach_write_to_8(new_sys_trx_start, trx->id);
mach_write_to_8(new_sys_trx_end, TRX_ID_MAX);
/* Scan the clustered index. */
for (;;) {
const rec_t* rec;
@@ -2242,13 +2247,10 @@ end_of_index:
bool historical_row = false;
if (new_table->versioned()) {
const dfield_t *dfield = dtuple_get_nth_field(
const dfield_t* dfield = dtuple_get_nth_field(
row, new_table->vers_end);
const byte *data = static_cast<const byte *>(
dfield_get_data(dfield));
ut_ad(dfield_get_len(dfield) == 8);
historical_row =
mach_read_from_8(data) != TRX_ID_MAX;
dfield_is_historical_sys_trx_end(dfield);
}
const dfield_t* dfield;
@@ -2272,10 +2274,11 @@ end_of_index:
}
ulonglong value;
if (likely(!historical_row))
if (likely(!historical_row)) {
value = sequence++;
else
} else {
value = historic_auto_decrement--;
}
switch (dtype_get_mtype(dtype)) {
case DATA_INT: {
@@ -2305,30 +2308,27 @@ end_of_index:
if (old_table->versioned()) {
if (!new_table->versioned() || drop_historical) {
const dict_col_t *col =
&old_table->cols
[old_table->vers_end];
const ulint nfield = dict_col_get_clust_pos(
col, clust_index);
const dict_col_t* col =
&old_table->cols[old_table->vers_end];
const ulint nfield =
dict_col_get_clust_pos(col, clust_index);
ulint len = 0;
const rec_t *sys_trx_end = rec_get_nth_field(
const rec_t* sys_trx_end = rec_get_nth_field(
rec, offsets, nfield, &len);
ut_ad(len == 8);
if (mach_read_from_8(sys_trx_end) != TRX_ID_MAX)
if (mach_read_from_8(sys_trx_end)
!= TRX_ID_MAX) {
continue;
}
}
} else if (new_table->versioned()) {
void *sys_trx_start = mem_heap_alloc(row_heap, 8);
void *sys_trx_end = mem_heap_alloc(row_heap, 8);
mach_write_to_8(sys_trx_start, trx->id);
mach_write_to_8(sys_trx_end, TRX_ID_MAX);
dfield_t *start = dtuple_get_nth_field(
row, new_table->vers_start);
dfield_t *end = dtuple_get_nth_field(
row, new_table->vers_end);
dfield_set_data(start, sys_trx_start, 8);
dfield_set_data(end, sys_trx_end, 8);
trx->vers_update_trt= true;
dfield_t* start =
dtuple_get_nth_field(row, new_table->vers_start);
dfield_t* end =
dtuple_get_nth_field(row, new_table->vers_end);
dfield_set_data(start, new_sys_trx_start, 8);
dfield_set_data(end, new_sys_trx_end, 8);
trx->vers_update_trt = true;
}
write_buffers:

View File

@@ -1420,6 +1420,23 @@ row_mysql_get_table_status(
return(err);
}
/** Writes 8 bytes to nth tuple field
@param[in] tuple where to write
@param[in] nth index in tuple
@param[in] data what to write
@param[in] buf field data buffer */
static
void
set_tuple_col_8(dtuple_t* tuple, int col, uint64_t data, byte* buf) {
dfield_t* dfield = dtuple_get_nth_field(tuple, col);
ut_ad(dfield->type.len == 8);
if (dfield->len == UNIV_SQL_NULL) {
dfield_set_data(dfield, buf, 8);
}
ut_ad(dfield->len == dfield->type.len && dfield->data);
mach_write_to_8(dfield->data, data);
}
/** Does an insert for MySQL.
@param[in] mysql_rec row in the MySQL format
@param[in,out] prebuilt prebuilt struct in MySQL handle
@@ -1504,14 +1521,14 @@ row_insert_for_mysql(
ut_ad(t->mysql_col_len == 8);
if (ins_mode == ROW_INS_HISTORICAL) {
row_ins_set_tuple_col_8(node->row, table->vers_end, trx->id, node->vers_end_buf);
set_tuple_col_8(node->row, table->vers_end, trx->id, node->vers_end_buf);
}
else /* ROW_INS_VERSIONED */ {
row_ins_set_tuple_col_8(node->row, table->vers_end, IB_UINT64_MAX, node->vers_end_buf);
int8store(&mysql_rec[t->mysql_col_offset], IB_UINT64_MAX);
set_tuple_col_8(node->row, table->vers_end, TRX_ID_MAX, node->vers_end_buf);
int8store(&mysql_rec[t->mysql_col_offset], TRX_ID_MAX);
t = &prebuilt->mysql_template[table->vers_start];
ut_ad(t->mysql_col_len == 8);
row_ins_set_tuple_col_8(node->row, table->vers_start, trx->id, node->vers_start_buf);
set_tuple_col_8(node->row, table->vers_start, trx->id, node->vers_start_buf);
int8store(&mysql_rec[t->mysql_col_offset], trx->id);
}
}
@@ -2129,8 +2146,8 @@ run_again:
node->cascade_upd_nodes = cascade_upd_nodes;
cascade_upd_nodes->pop_front();
thr->fk_cascade_depth++;
vers_set_fields = node->table->versioned() &&
(node->is_delete || node->versioned);
vers_set_fields = node->table->versioned()
&& (node->is_delete || node->versioned);
goto run_again;
}
@@ -2210,11 +2227,12 @@ run_again:
prebuilt->table->stat_modified_counter++;
}
if (node->table->versioned() &&
(node->versioned || node->vers_delete ||
if (node->table->versioned()
&& (node->versioned
|| node->vers_delete
// TODO: improve this check (check if we touch only
// unversioned fields in foreigh table)
node->foreign)) {
|| node->foreign)) {
trx->vers_update_trt = true;
}