mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-18366 Crash on SELECT on a table with indexed virtual columns
The problem was in improper error handling behavior in `row_upd_build_difference_binary`: `innobase_free_row_for_vcol` wasn't called. To eliminate this problem in all potential places, a refactoring has been made: * class ib_vcol_row is added. It owns VCOL_STORAGE and heap and maintains it in RAII manner * all innobase_allocate_row_for_vcol/innobase_free_row_for_vcol pairs are substituted with ib_vcol_row usage * row_merge_buf_add is only left untouched because it doesn't own vheap passed as an argument * innobase_allocate_row_for_vcol does not allocate VCOL_STORAGE anymore and accepts it as an argument -- this reduces a number of memory allocations * move rec_printer out of `#ifndef DBUG_OFF` and mark it cold
This commit is contained in:
@@ -259,6 +259,9 @@ ERROR 22007: Incorrect date value: '20190132' for column `test`.`t1`.`vb` at row
|
|||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
a b vb
|
a b vb
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b vb
|
||||||
|
1 20190132 0000-00-00
|
||||||
CHECK TABLE t1;
|
CHECK TABLE t1;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 check status OK
|
test.t1 check status OK
|
||||||
|
@@ -278,7 +278,6 @@ DELETE FROM t1;
|
|||||||
INSERT INTO t1 (a,b) VALUES(1,20190123);
|
INSERT INTO t1 (a,b) VALUES(1,20190123);
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
# MDEV-18366 FIXME: fix the crash and enable this
|
SELECT * FROM t1;
|
||||||
# SELECT * FROM t1;
|
|
||||||
CHECK TABLE t1;
|
CHECK TABLE t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
@@ -21827,57 +21827,46 @@ innobase_get_field_from_update_vector(
|
|||||||
@param[out] record Pointer to allocated MariaDB record
|
@param[out] record Pointer to allocated MariaDB record
|
||||||
@param[out] storage Internal storage for blobs etc
|
@param[out] storage Internal storage for blobs etc
|
||||||
|
|
||||||
@retval false on success
|
@retval true on success
|
||||||
@retval true on malloc failure or failed to open the maria table
|
@retval false on malloc failure or failed to open the maria table
|
||||||
for purge thread.
|
for purge thread.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool innobase_allocate_row_for_vcol(
|
bool innobase_allocate_row_for_vcol(THD *thd, dict_index_t *index,
|
||||||
THD * thd,
|
mem_heap_t **heap, TABLE **table,
|
||||||
dict_index_t* index,
|
VCOL_STORAGE *storage)
|
||||||
mem_heap_t** heap,
|
|
||||||
TABLE** table,
|
|
||||||
byte** record,
|
|
||||||
VCOL_STORAGE** storage)
|
|
||||||
{
|
{
|
||||||
TABLE *maria_table;
|
TABLE *maria_table;
|
||||||
String *blob_value_storage;
|
String *blob_value_storage;
|
||||||
if (!*table)
|
if (!*table)
|
||||||
*table= innodb_find_table_for_vc(thd, index->table);
|
*table = innodb_find_table_for_vc(thd, index->table);
|
||||||
|
|
||||||
/* For purge thread, there is a possiblity that table could have
|
/* For purge thread, there is a possiblity that table could have
|
||||||
dropped, corrupted or unaccessible. */
|
dropped, corrupted or unaccessible. */
|
||||||
if (!*table)
|
if (!*table)
|
||||||
return true;
|
return false;
|
||||||
maria_table= *table;
|
maria_table = *table;
|
||||||
if (!*heap && !(*heap= mem_heap_create(srv_page_size)))
|
if (!*heap && !(*heap = mem_heap_create(srv_page_size)))
|
||||||
{
|
return false;
|
||||||
*storage= 0;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
*record= static_cast<byte*>(mem_heap_alloc(*heap,
|
|
||||||
maria_table->s->reclength));
|
|
||||||
*storage= static_cast<VCOL_STORAGE*>
|
|
||||||
(mem_heap_alloc(*heap, sizeof(**storage)));
|
|
||||||
blob_value_storage= static_cast<String*>
|
|
||||||
(mem_heap_alloc(*heap,
|
|
||||||
maria_table->s->virtual_not_stored_blob_fields *
|
|
||||||
sizeof(String)));
|
|
||||||
if (!*record || !*storage || !blob_value_storage)
|
|
||||||
{
|
|
||||||
*storage= 0;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
(*storage)->maria_table= maria_table;
|
|
||||||
(*storage)->innobase_record= *record;
|
|
||||||
(*storage)->maria_record= maria_table->field[0]->record_ptr();
|
|
||||||
(*storage)->blob_value_storage= blob_value_storage;
|
|
||||||
|
|
||||||
maria_table->move_fields(maria_table->field, *record,
|
uchar *record = static_cast<byte *>(mem_heap_alloc(*heap,
|
||||||
(*storage)->maria_record);
|
maria_table->s->reclength));
|
||||||
|
|
||||||
|
size_t len = maria_table->s->virtual_not_stored_blob_fields * sizeof(String);
|
||||||
|
blob_value_storage = static_cast<String *>(mem_heap_alloc(*heap, len));
|
||||||
|
|
||||||
|
if (!record || !blob_value_storage)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
storage->maria_table = maria_table;
|
||||||
|
storage->innobase_record = record;
|
||||||
|
storage->maria_record = maria_table->field[0]->record_ptr();
|
||||||
|
storage->blob_value_storage = blob_value_storage;
|
||||||
|
|
||||||
|
maria_table->move_fields(maria_table->field, record, storage->maria_record);
|
||||||
maria_table->remember_blob_values(blob_value_storage);
|
maria_table->remember_blob_values(blob_value_storage);
|
||||||
|
|
||||||
return FALSE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1076,16 +1076,17 @@ struct rec_offsets_print
|
|||||||
@param[in,out] o output stream
|
@param[in,out] o output stream
|
||||||
@param[in] r record to display
|
@param[in] r record to display
|
||||||
@return the output stream */
|
@return the output stream */
|
||||||
|
ATTRIBUTE_COLD
|
||||||
std::ostream&
|
std::ostream&
|
||||||
operator<<(std::ostream& o, const rec_offsets_print& r);
|
operator<<(std::ostream& o, const rec_offsets_print& r);
|
||||||
|
|
||||||
# ifndef DBUG_OFF
|
|
||||||
/** Pretty-printer of records and tuples */
|
/** Pretty-printer of records and tuples */
|
||||||
class rec_printer : public std::ostringstream {
|
class rec_printer : public std::ostringstream {
|
||||||
public:
|
public:
|
||||||
/** Construct a pretty-printed record.
|
/** Construct a pretty-printed record.
|
||||||
@param rec record with header
|
@param rec record with header
|
||||||
@param offsets rec_get_offsets(rec, ...) */
|
@param offsets rec_get_offsets(rec, ...) */
|
||||||
|
ATTRIBUTE_COLD
|
||||||
rec_printer(const rec_t* rec, const rec_offs* offsets)
|
rec_printer(const rec_t* rec, const rec_offs* offsets)
|
||||||
:
|
:
|
||||||
std::ostringstream ()
|
std::ostringstream ()
|
||||||
@@ -1099,6 +1100,7 @@ public:
|
|||||||
@param rec record, possibly lacking header
|
@param rec record, possibly lacking header
|
||||||
@param info rec_get_info_bits(rec)
|
@param info rec_get_info_bits(rec)
|
||||||
@param offsets rec_get_offsets(rec, ...) */
|
@param offsets rec_get_offsets(rec, ...) */
|
||||||
|
ATTRIBUTE_COLD
|
||||||
rec_printer(const rec_t* rec, ulint info, const rec_offs* offsets)
|
rec_printer(const rec_t* rec, ulint info, const rec_offs* offsets)
|
||||||
:
|
:
|
||||||
std::ostringstream ()
|
std::ostringstream ()
|
||||||
@@ -1108,6 +1110,7 @@ public:
|
|||||||
|
|
||||||
/** Construct a pretty-printed tuple.
|
/** Construct a pretty-printed tuple.
|
||||||
@param tuple data tuple */
|
@param tuple data tuple */
|
||||||
|
ATTRIBUTE_COLD
|
||||||
rec_printer(const dtuple_t* tuple)
|
rec_printer(const dtuple_t* tuple)
|
||||||
:
|
:
|
||||||
std::ostringstream ()
|
std::ostringstream ()
|
||||||
@@ -1118,6 +1121,7 @@ public:
|
|||||||
/** Construct a pretty-printed tuple.
|
/** Construct a pretty-printed tuple.
|
||||||
@param field array of data tuple fields
|
@param field array of data tuple fields
|
||||||
@param n number of fields */
|
@param n number of fields */
|
||||||
|
ATTRIBUTE_COLD
|
||||||
rec_printer(const dfield_t* field, ulint n)
|
rec_printer(const dfield_t* field, ulint n)
|
||||||
:
|
:
|
||||||
std::ostringstream ()
|
std::ostringstream ()
|
||||||
@@ -1134,7 +1138,7 @@ private:
|
|||||||
/** Assignment operator */
|
/** Assignment operator */
|
||||||
rec_printer& operator=(const rec_printer& other);
|
rec_printer& operator=(const rec_printer& other);
|
||||||
};
|
};
|
||||||
# endif /* !DBUG_OFF */
|
|
||||||
|
|
||||||
# ifdef UNIV_DEBUG
|
# ifdef UNIV_DEBUG
|
||||||
/** Read the DB_TRX_ID of a clustered index record.
|
/** Read the DB_TRX_ID of a clustered index record.
|
||||||
|
@@ -814,6 +814,8 @@ struct VCOL_STORAGE
|
|||||||
byte *innobase_record;
|
byte *innobase_record;
|
||||||
byte *maria_record;
|
byte *maria_record;
|
||||||
String *blob_value_storage;
|
String *blob_value_storage;
|
||||||
|
VCOL_STORAGE(): maria_table(NULL), innobase_record(NULL),
|
||||||
|
maria_record(NULL), blob_value_storage(NULL) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -836,12 +838,42 @@ bool innobase_allocate_row_for_vcol(
|
|||||||
dict_index_t* index,
|
dict_index_t* index,
|
||||||
mem_heap_t** heap,
|
mem_heap_t** heap,
|
||||||
TABLE** table,
|
TABLE** table,
|
||||||
byte** record,
|
VCOL_STORAGE* storage);
|
||||||
VCOL_STORAGE** storage);
|
|
||||||
|
|
||||||
/** Free memory allocated by innobase_allocate_row_for_vcol() */
|
/** Free memory allocated by innobase_allocate_row_for_vcol() */
|
||||||
void innobase_free_row_for_vcol(VCOL_STORAGE *storage);
|
void innobase_free_row_for_vcol(VCOL_STORAGE *storage);
|
||||||
|
|
||||||
|
class ib_vcol_row
|
||||||
|
{
|
||||||
|
VCOL_STORAGE storage;
|
||||||
|
public:
|
||||||
|
mem_heap_t *heap;
|
||||||
|
|
||||||
|
ib_vcol_row(mem_heap_t *heap) : heap(heap) {}
|
||||||
|
|
||||||
|
byte *record(THD *thd, dict_index_t *index, TABLE **table)
|
||||||
|
{
|
||||||
|
if (!storage.innobase_record)
|
||||||
|
{
|
||||||
|
bool ok = innobase_allocate_row_for_vcol(thd, index, &heap, table,
|
||||||
|
&storage);
|
||||||
|
if (!ok)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return storage.innobase_record;
|
||||||
|
};
|
||||||
|
|
||||||
|
~ib_vcol_row()
|
||||||
|
{
|
||||||
|
if (heap)
|
||||||
|
{
|
||||||
|
if (storage.innobase_record)
|
||||||
|
innobase_free_row_for_vcol(&storage);
|
||||||
|
mem_heap_free(heap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** Get the computed value by supplying the base column values.
|
/** Get the computed value by supplying the base column values.
|
||||||
@param[in,out] row the data row
|
@param[in,out] row the data row
|
||||||
@param[in] col virtual column
|
@param[in] col virtual column
|
||||||
|
@@ -916,16 +916,15 @@ row_ins_invalidate_query_cache(
|
|||||||
@param[in] index clustered index of child table
|
@param[in] index clustered index of child table
|
||||||
@param[in] node parent update node
|
@param[in] node parent update node
|
||||||
@param[in] foreign foreign key information
|
@param[in] foreign foreign key information
|
||||||
@param[out] err error code. */
|
@return error code. */
|
||||||
static
|
static
|
||||||
void
|
dberr_t
|
||||||
row_ins_foreign_fill_virtual(
|
row_ins_foreign_fill_virtual(
|
||||||
upd_node_t* cascade,
|
upd_node_t* cascade,
|
||||||
const rec_t* rec,
|
const rec_t* rec,
|
||||||
dict_index_t* index,
|
dict_index_t* index,
|
||||||
upd_node_t* node,
|
upd_node_t* node,
|
||||||
dict_foreign_t* foreign,
|
dict_foreign_t* foreign)
|
||||||
dberr_t* err)
|
|
||||||
{
|
{
|
||||||
THD* thd = current_thd;
|
THD* thd = current_thd;
|
||||||
row_ext_t* ext;
|
row_ext_t* ext;
|
||||||
@@ -934,10 +933,7 @@ row_ins_foreign_fill_virtual(
|
|||||||
const rec_offs* offsets =
|
const rec_offs* offsets =
|
||||||
rec_get_offsets(rec, index, offsets_, true,
|
rec_get_offsets(rec, index, offsets_, true,
|
||||||
ULINT_UNDEFINED, &cascade->heap);
|
ULINT_UNDEFINED, &cascade->heap);
|
||||||
mem_heap_t* v_heap = NULL;
|
|
||||||
TABLE* mysql_table= NULL;
|
TABLE* mysql_table= NULL;
|
||||||
VCOL_STORAGE* vcol_storage= NULL;
|
|
||||||
byte* record;
|
|
||||||
upd_t* update = cascade->update;
|
upd_t* update = cascade->update;
|
||||||
ulint n_v_fld = index->table->n_v_def;
|
ulint n_v_fld = index->table->n_v_def;
|
||||||
ulint n_diff;
|
ulint n_diff;
|
||||||
@@ -957,12 +953,10 @@ row_ins_foreign_fill_virtual(
|
|||||||
innobase_init_vc_templ(index->table);
|
innobase_init_vc_templ(index->table);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (innobase_allocate_row_for_vcol(thd, index, &v_heap,
|
ib_vcol_row vc(NULL);
|
||||||
&mysql_table,
|
uchar *record = vc.record(thd, index, &mysql_table);
|
||||||
&record, &vcol_storage)) {
|
if (!record) {
|
||||||
if (v_heap) mem_heap_free(v_heap);
|
return DB_OUT_OF_MEMORY;
|
||||||
*err = DB_OUT_OF_MEMORY;
|
|
||||||
goto func_exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ulint i = 0; i < n_v_fld; i++) {
|
for (ulint i = 0; i < n_v_fld; i++) {
|
||||||
@@ -978,12 +972,11 @@ row_ins_foreign_fill_virtual(
|
|||||||
|
|
||||||
dfield_t* vfield = innobase_get_computed_value(
|
dfield_t* vfield = innobase_get_computed_value(
|
||||||
update->old_vrow, col, index,
|
update->old_vrow, col, index,
|
||||||
&v_heap, update->heap, NULL, thd, mysql_table,
|
&vc.heap, update->heap, NULL, thd, mysql_table,
|
||||||
record, NULL, NULL, NULL);
|
record, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (vfield == NULL) {
|
if (vfield == NULL) {
|
||||||
*err = DB_COMPUTE_VALUE_FAILED;
|
return DB_COMPUTE_VALUE_FAILED;
|
||||||
goto func_exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
upd_field = upd_get_nth_field(update, n_diff);
|
upd_field = upd_get_nth_field(update, n_diff);
|
||||||
@@ -1008,13 +1001,12 @@ row_ins_foreign_fill_virtual(
|
|||||||
|
|
||||||
dfield_t* new_vfield = innobase_get_computed_value(
|
dfield_t* new_vfield = innobase_get_computed_value(
|
||||||
update->old_vrow, col, index,
|
update->old_vrow, col, index,
|
||||||
&v_heap, update->heap, NULL, thd,
|
&vc.heap, update->heap, NULL, thd,
|
||||||
mysql_table, record, NULL,
|
mysql_table, record, NULL,
|
||||||
node->update, foreign);
|
node->update, foreign);
|
||||||
|
|
||||||
if (new_vfield == NULL) {
|
if (new_vfield == NULL) {
|
||||||
*err = DB_COMPUTE_VALUE_FAILED;
|
return DB_COMPUTE_VALUE_FAILED;
|
||||||
goto func_exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dfield_copy(&(upd_field->new_val), new_vfield);
|
dfield_copy(&(upd_field->new_val), new_vfield);
|
||||||
@@ -1024,14 +1016,7 @@ row_ins_foreign_fill_virtual(
|
|||||||
}
|
}
|
||||||
|
|
||||||
update->n_fields = n_diff;
|
update->n_fields = n_diff;
|
||||||
*err = DB_SUCCESS;
|
return DB_SUCCESS;
|
||||||
|
|
||||||
func_exit:
|
|
||||||
if (v_heap) {
|
|
||||||
if (vcol_storage)
|
|
||||||
innobase_free_row_for_vcol(vcol_storage);
|
|
||||||
mem_heap_free(v_heap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
@@ -1312,9 +1297,9 @@ row_ins_foreign_check_on_constraint(
|
|||||||
|
|
||||||
if (foreign->v_cols != NULL
|
if (foreign->v_cols != NULL
|
||||||
&& foreign->v_cols->size() > 0) {
|
&& foreign->v_cols->size() > 0) {
|
||||||
row_ins_foreign_fill_virtual(
|
err = row_ins_foreign_fill_virtual(
|
||||||
cascade, clust_rec, clust_index,
|
cascade, clust_rec, clust_index,
|
||||||
node, foreign, &err);
|
node, foreign);
|
||||||
|
|
||||||
if (err != DB_SUCCESS) {
|
if (err != DB_SUCCESS) {
|
||||||
goto nonstandard_exit_func;
|
goto nonstandard_exit_func;
|
||||||
@@ -1351,9 +1336,9 @@ row_ins_foreign_check_on_constraint(
|
|||||||
node, foreign, tmp_heap, trx);
|
node, foreign, tmp_heap, trx);
|
||||||
|
|
||||||
if (foreign->v_cols && !foreign->v_cols->empty()) {
|
if (foreign->v_cols && !foreign->v_cols->empty()) {
|
||||||
row_ins_foreign_fill_virtual(
|
err = row_ins_foreign_fill_virtual(
|
||||||
cascade, clust_rec, clust_index,
|
cascade, clust_rec, clust_index,
|
||||||
node, foreign, &err);
|
node, foreign);
|
||||||
|
|
||||||
if (err != DB_SUCCESS) {
|
if (err != DB_SUCCESS) {
|
||||||
goto nonstandard_exit_func;
|
goto nonstandard_exit_func;
|
||||||
|
@@ -520,8 +520,7 @@ row_merge_buf_add(
|
|||||||
ulint bucket = 0;
|
ulint bucket = 0;
|
||||||
doc_id_t write_doc_id;
|
doc_id_t write_doc_id;
|
||||||
ulint n_row_added = 0;
|
ulint n_row_added = 0;
|
||||||
VCOL_STORAGE* vcol_storage= 0;
|
VCOL_STORAGE vcol_storage;
|
||||||
byte* record;
|
|
||||||
DBUG_ENTER("row_merge_buf_add");
|
DBUG_ENTER("row_merge_buf_add");
|
||||||
|
|
||||||
if (buf->n_tuples >= buf->max_tuples) {
|
if (buf->n_tuples >= buf->max_tuples) {
|
||||||
@@ -594,8 +593,11 @@ row_merge_buf_add(
|
|||||||
dict_index_t* clust_index
|
dict_index_t* clust_index
|
||||||
= dict_table_get_first_index(new_table);
|
= dict_table_get_first_index(new_table);
|
||||||
|
|
||||||
if (!vcol_storage &&
|
if (!vcol_storage.innobase_record &&
|
||||||
innobase_allocate_row_for_vcol(trx->mysql_thd, clust_index, v_heap, &my_table, &record, &vcol_storage)) {
|
!innobase_allocate_row_for_vcol(
|
||||||
|
trx->mysql_thd, clust_index,
|
||||||
|
v_heap, &my_table,
|
||||||
|
&vcol_storage)) {
|
||||||
*err = DB_OUT_OF_MEMORY;
|
*err = DB_OUT_OF_MEMORY;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -603,8 +605,8 @@ row_merge_buf_add(
|
|||||||
row_field = innobase_get_computed_value(
|
row_field = innobase_get_computed_value(
|
||||||
row, v_col, clust_index,
|
row, v_col, clust_index,
|
||||||
v_heap, NULL, ifield, trx->mysql_thd,
|
v_heap, NULL, ifield, trx->mysql_thd,
|
||||||
my_table, record, old_table, NULL,
|
my_table, vcol_storage.innobase_record,
|
||||||
NULL);
|
old_table, NULL, NULL);
|
||||||
|
|
||||||
if (row_field == NULL) {
|
if (row_field == NULL) {
|
||||||
*err = DB_COMPUTE_VALUE_FAILED;
|
*err = DB_COMPUTE_VALUE_FAILED;
|
||||||
@@ -846,13 +848,13 @@ row_merge_buf_add(
|
|||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (vcol_storage)
|
if (vcol_storage.innobase_record)
|
||||||
innobase_free_row_for_vcol(vcol_storage);
|
innobase_free_row_for_vcol(&vcol_storage);
|
||||||
DBUG_RETURN(n_row_added);
|
DBUG_RETURN(n_row_added);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (vcol_storage)
|
if (vcol_storage.innobase_record)
|
||||||
innobase_free_row_for_vcol(vcol_storage);
|
innobase_free_row_for_vcol(&vcol_storage);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -176,9 +176,6 @@ row_sel_sec_rec_is_for_clust_rec(
|
|||||||
rec_offs sec_offsets_[REC_OFFS_SMALL_SIZE];
|
rec_offs sec_offsets_[REC_OFFS_SMALL_SIZE];
|
||||||
rec_offs* clust_offs = clust_offsets_;
|
rec_offs* clust_offs = clust_offsets_;
|
||||||
rec_offs* sec_offs = sec_offsets_;
|
rec_offs* sec_offs = sec_offsets_;
|
||||||
ibool is_equal = TRUE;
|
|
||||||
VCOL_STORAGE* vcol_storage= 0;
|
|
||||||
byte* record;
|
|
||||||
|
|
||||||
rec_offs_init(clust_offsets_);
|
rec_offs_init(clust_offsets_);
|
||||||
rec_offs_init(sec_offsets_);
|
rec_offs_init(sec_offsets_);
|
||||||
@@ -197,6 +194,7 @@ row_sel_sec_rec_is_for_clust_rec(
|
|||||||
}
|
}
|
||||||
|
|
||||||
heap = mem_heap_create(256);
|
heap = mem_heap_create(256);
|
||||||
|
ib_vcol_row vc(heap);
|
||||||
|
|
||||||
clust_offs = rec_get_offsets(clust_rec, clust_index, clust_offs,
|
clust_offs = rec_get_offsets(clust_rec, clust_index, clust_offs,
|
||||||
true, ULINT_UNDEFINED, &heap);
|
true, ULINT_UNDEFINED, &heap);
|
||||||
@@ -225,16 +223,9 @@ row_sel_sec_rec_is_for_clust_rec(
|
|||||||
dfield_t* vfield;
|
dfield_t* vfield;
|
||||||
row_ext_t* ext;
|
row_ext_t* ext;
|
||||||
|
|
||||||
if (!vcol_storage)
|
byte *record = vc.record(thr_get_trx(thr)->mysql_thd,
|
||||||
{
|
|
||||||
TABLE *mysql_table= thr->prebuilt->m_mysql_table;
|
|
||||||
innobase_allocate_row_for_vcol(thr_get_trx(thr)->mysql_thd,
|
|
||||||
clust_index,
|
clust_index,
|
||||||
&heap,
|
&thr->prebuilt->m_mysql_table);
|
||||||
&mysql_table,
|
|
||||||
&record,
|
|
||||||
&vcol_storage);
|
|
||||||
}
|
|
||||||
|
|
||||||
v_col = reinterpret_cast<const dict_v_col_t*>(col);
|
v_col = reinterpret_cast<const dict_v_col_t*>(col);
|
||||||
|
|
||||||
@@ -284,7 +275,7 @@ row_sel_sec_rec_is_for_clust_rec(
|
|||||||
sec_field, sec_len,
|
sec_field, sec_len,
|
||||||
ifield->prefix_len,
|
ifield->prefix_len,
|
||||||
clust_index->table)) {
|
clust_index->table)) {
|
||||||
goto inequal;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -320,28 +311,19 @@ row_sel_sec_rec_is_for_clust_rec(
|
|||||||
rtr_read_mbr(sec_field, &sec_mbr);
|
rtr_read_mbr(sec_field, &sec_mbr);
|
||||||
|
|
||||||
if (!MBR_EQUAL_CMP(&sec_mbr, &tmp_mbr)) {
|
if (!MBR_EQUAL_CMP(&sec_mbr, &tmp_mbr)) {
|
||||||
is_equal = FALSE;
|
return FALSE;
|
||||||
goto func_exit;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (0 != cmp_data_data(col->mtype, col->prtype,
|
if (0 != cmp_data_data(col->mtype, col->prtype,
|
||||||
clust_field, len,
|
clust_field, len,
|
||||||
sec_field, sec_len)) {
|
sec_field, sec_len)) {
|
||||||
inequal:
|
return FALSE;
|
||||||
is_equal = FALSE;
|
|
||||||
goto func_exit;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func_exit:
|
return TRUE;
|
||||||
if (UNIV_LIKELY_NULL(heap)) {
|
|
||||||
if (UNIV_LIKELY_NULL(vcol_storage))
|
|
||||||
innobase_free_row_for_vcol(vcol_storage);
|
|
||||||
mem_heap_free(heap);
|
|
||||||
}
|
|
||||||
return(is_equal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
|
@@ -1116,10 +1116,6 @@ row_upd_build_difference_binary(
|
|||||||
for purge/mvcc purpose) */
|
for purge/mvcc purpose) */
|
||||||
if (n_v_fld > 0) {
|
if (n_v_fld > 0) {
|
||||||
row_ext_t* ext;
|
row_ext_t* ext;
|
||||||
mem_heap_t* v_heap = NULL;
|
|
||||||
byte* record;
|
|
||||||
VCOL_STORAGE* vcol_storage;
|
|
||||||
|
|
||||||
THD* thd;
|
THD* thd;
|
||||||
|
|
||||||
if (trx == NULL) {
|
if (trx == NULL) {
|
||||||
@@ -1130,9 +1126,8 @@ row_upd_build_difference_binary(
|
|||||||
|
|
||||||
ut_ad(!update->old_vrow);
|
ut_ad(!update->old_vrow);
|
||||||
|
|
||||||
innobase_allocate_row_for_vcol(thd, index, &v_heap,
|
ib_vcol_row vc(NULL);
|
||||||
&mysql_table,
|
uchar *record = vc.record(thd, index, &mysql_table);
|
||||||
&record, &vcol_storage);
|
|
||||||
|
|
||||||
for (i = 0; i < n_v_fld; i++) {
|
for (i = 0; i < n_v_fld; i++) {
|
||||||
const dict_v_col_t* col
|
const dict_v_col_t* col
|
||||||
@@ -1150,10 +1145,9 @@ row_upd_build_difference_binary(
|
|||||||
|
|
||||||
dfield_t* vfield = innobase_get_computed_value(
|
dfield_t* vfield = innobase_get_computed_value(
|
||||||
update->old_vrow, col, index,
|
update->old_vrow, col, index,
|
||||||
&v_heap, heap, NULL, thd, mysql_table, record,
|
&vc.heap, heap, NULL, thd, mysql_table, record,
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
if (vfield == NULL) {
|
if (vfield == NULL) {
|
||||||
if (v_heap) mem_heap_free(v_heap);
|
|
||||||
*error = DB_COMPUTE_VALUE_FAILED;
|
*error = DB_COMPUTE_VALUE_FAILED;
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
@@ -1182,12 +1176,6 @@ row_upd_build_difference_binary(
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v_heap) {
|
|
||||||
if (vcol_storage)
|
|
||||||
innobase_free_row_for_vcol(vcol_storage);
|
|
||||||
mem_heap_free(v_heap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update->n_fields = n_diff;
|
update->n_fields = n_diff;
|
||||||
@@ -2122,14 +2110,8 @@ row_upd_store_v_row(
|
|||||||
THD* thd,
|
THD* thd,
|
||||||
TABLE* mysql_table)
|
TABLE* mysql_table)
|
||||||
{
|
{
|
||||||
mem_heap_t* heap = NULL;
|
|
||||||
dict_index_t* index = dict_table_get_first_index(node->table);
|
dict_index_t* index = dict_table_get_first_index(node->table);
|
||||||
byte* record= 0;
|
ib_vcol_row vc(NULL);
|
||||||
VCOL_STORAGE *vcol_storage= 0;
|
|
||||||
|
|
||||||
if (!update)
|
|
||||||
innobase_allocate_row_for_vcol(thd, index, &heap, &mysql_table,
|
|
||||||
&record, &vcol_storage);
|
|
||||||
|
|
||||||
for (ulint col_no = 0; col_no < dict_table_get_n_v_cols(node->table);
|
for (ulint col_no = 0; col_no < dict_table_get_n_v_cols(node->table);
|
||||||
col_no++) {
|
col_no++) {
|
||||||
@@ -2179,24 +2161,19 @@ row_upd_store_v_row(
|
|||||||
dfield_dup(dfield, node->heap);
|
dfield_dup(dfield, node->heap);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
uchar *record = vc.record(thd, index,
|
||||||
|
&mysql_table);
|
||||||
/* Need to compute, this happens when
|
/* Need to compute, this happens when
|
||||||
deleting row */
|
deleting row */
|
||||||
innobase_get_computed_value(
|
innobase_get_computed_value(
|
||||||
node->row, col, index,
|
node->row, col, index,
|
||||||
&heap, node->heap, NULL,
|
&vc.heap, node->heap,
|
||||||
thd, mysql_table, record, NULL,
|
NULL, thd, mysql_table,
|
||||||
NULL, NULL);
|
record, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (heap) {
|
|
||||||
if (vcol_storage)
|
|
||||||
innobase_free_row_for_vcol(vcol_storage);
|
|
||||||
mem_heap_free(heap);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Stores to the heap the row on which the node->pcur is positioned.
|
/** Stores to the heap the row on which the node->pcur is positioned.
|
||||||
|
@@ -455,11 +455,8 @@ row_vers_build_clust_v_col(
|
|||||||
mem_heap_t* heap,
|
mem_heap_t* heap,
|
||||||
purge_vcol_info_t* vcol_info)
|
purge_vcol_info_t* vcol_info)
|
||||||
{
|
{
|
||||||
mem_heap_t* local_heap = NULL;
|
|
||||||
VCOL_STORAGE *vcol_storage= NULL;
|
|
||||||
THD* thd= current_thd;
|
THD* thd= current_thd;
|
||||||
TABLE* maria_table= 0;
|
TABLE* maria_table= 0;
|
||||||
byte* record= 0;
|
|
||||||
|
|
||||||
ut_ad(dict_index_has_virtual(index));
|
ut_ad(dict_index_has_virtual(index));
|
||||||
ut_ad(index->table == clust_index->table);
|
ut_ad(index->table == clust_index->table);
|
||||||
@@ -469,15 +466,12 @@ row_vers_build_clust_v_col(
|
|||||||
maria_table = vcol_info->table();
|
maria_table = vcol_info->table();
|
||||||
}
|
}
|
||||||
|
|
||||||
innobase_allocate_row_for_vcol(thd, index,
|
ib_vcol_row vc(NULL);
|
||||||
&local_heap,
|
byte *record = vc.record(thd, index, &maria_table);
|
||||||
&maria_table,
|
|
||||||
&record,
|
|
||||||
&vcol_storage);
|
|
||||||
|
|
||||||
if (vcol_info && !vcol_info->table()) {
|
if (vcol_info && !vcol_info->table()) {
|
||||||
vcol_info->set_table(maria_table);
|
vcol_info->set_table(maria_table);
|
||||||
goto func_exit;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ulint i = 0; i < dict_index_get_n_fields(index); i++) {
|
for (ulint i = 0; i < dict_index_get_n_fields(index); i++) {
|
||||||
@@ -491,18 +485,11 @@ row_vers_build_clust_v_col(
|
|||||||
ind_field->col);
|
ind_field->col);
|
||||||
|
|
||||||
innobase_get_computed_value(
|
innobase_get_computed_value(
|
||||||
row, col, clust_index, &local_heap,
|
row, col, clust_index, &vc.heap,
|
||||||
heap, NULL, thd, maria_table, record, NULL,
|
heap, NULL, thd, maria_table, record, NULL,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func_exit:
|
|
||||||
if (local_heap) {
|
|
||||||
if (vcol_storage)
|
|
||||||
innobase_free_row_for_vcol(vcol_storage);
|
|
||||||
mem_heap_free(local_heap);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Build latest virtual column data from undo log
|
/** Build latest virtual column data from undo log
|
||||||
|
Reference in New Issue
Block a user