mirror of
https://github.com/MariaDB/server.git
synced 2025-09-02 09:41:40 +03:00
Apply InnoDB snapshot innodb-5.1-ss1726.
Bug #16979: AUTO_INC lock in InnoDB works a table level lock - this is a major change in InnoDB auto-inc handling. Bug #27950: Duplicate entry error in auto-inc after mysqld restart - Init AUTOINC from delete_row(). Bug #28781: InnoDB increments auto-increment value incorrectly with ON DUPLICATE KEY UPDATE - Use value specified by MySQL, in update_row().
This commit is contained in:
@@ -501,7 +501,7 @@ ERROR 23000: Duplicate entry 'test2' for key 'ggid'
|
||||
select * from t1;
|
||||
id ggid email passwd
|
||||
1 this will work
|
||||
3 test2 this will work
|
||||
4 test2 this will work
|
||||
select * from t1 where id=1;
|
||||
id ggid email passwd
|
||||
1 this will work
|
||||
|
@@ -410,14 +410,27 @@ dict_table_get_col_name(
|
||||
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||
|
||||
s = table->col_names;
|
||||
|
||||
for (i = 0; i < col_nr; i++) {
|
||||
s += strlen(s) + 1;
|
||||
if (s) {
|
||||
for (i = 0; i < col_nr; i++) {
|
||||
s += strlen(s) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
Acquire the autoinc lock.*/
|
||||
|
||||
void
|
||||
dict_table_autoinc_lock(
|
||||
/*====================*/
|
||||
dict_table_t* table)
|
||||
{
|
||||
mutex_enter(&table->autoinc_mutex);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Initializes the autoinc counter. It is not an error to initialize an already
|
||||
initialized counter. */
|
||||
@@ -428,54 +441,8 @@ dict_table_autoinc_initialize(
|
||||
dict_table_t* table, /* in: table */
|
||||
ib_longlong value) /* in: next value to assign to a row */
|
||||
{
|
||||
mutex_enter(&(table->autoinc_mutex));
|
||||
|
||||
table->autoinc_inited = TRUE;
|
||||
table->autoinc = value;
|
||||
|
||||
mutex_exit(&(table->autoinc_mutex));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Gets the next autoinc value (== autoinc counter value), 0 if not yet
|
||||
initialized. If initialized, increments the counter by 1. */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_get(
|
||||
/*===================*/
|
||||
/* out: value for a new row, or 0 */
|
||||
dict_table_t* table) /* in: table */
|
||||
{
|
||||
ib_longlong value;
|
||||
|
||||
mutex_enter(&(table->autoinc_mutex));
|
||||
|
||||
if (!table->autoinc_inited) {
|
||||
|
||||
value = 0;
|
||||
} else {
|
||||
value = table->autoinc;
|
||||
table->autoinc = table->autoinc + 1;
|
||||
}
|
||||
|
||||
mutex_exit(&(table->autoinc_mutex));
|
||||
|
||||
return(value);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Decrements the autoinc counter value by 1. */
|
||||
|
||||
void
|
||||
dict_table_autoinc_decrement(
|
||||
/*=========================*/
|
||||
dict_table_t* table) /* in: table */
|
||||
{
|
||||
mutex_enter(&(table->autoinc_mutex));
|
||||
|
||||
table->autoinc = table->autoinc - 1;
|
||||
|
||||
mutex_exit(&(table->autoinc_mutex));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@@ -490,32 +457,6 @@ dict_table_autoinc_read(
|
||||
{
|
||||
ib_longlong value;
|
||||
|
||||
mutex_enter(&(table->autoinc_mutex));
|
||||
|
||||
if (!table->autoinc_inited) {
|
||||
|
||||
value = 0;
|
||||
} else {
|
||||
value = table->autoinc;
|
||||
}
|
||||
|
||||
mutex_exit(&(table->autoinc_mutex));
|
||||
|
||||
return(value);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Peeks the autoinc counter value, 0 if not yet initialized. Does not
|
||||
increment the counter. The read not protected by any mutex! */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_peek(
|
||||
/*====================*/
|
||||
/* out: value of the counter */
|
||||
dict_table_t* table) /* in: table */
|
||||
{
|
||||
ib_longlong value;
|
||||
|
||||
if (!table->autoinc_inited) {
|
||||
|
||||
value = 0;
|
||||
@@ -527,7 +468,7 @@ dict_table_autoinc_peek(
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Updates the autoinc counter if the value supplied is equal or bigger than the
|
||||
Updates the autoinc counter if the value supplied is greater than the
|
||||
current value. If not inited, does nothing. */
|
||||
|
||||
void
|
||||
@@ -537,15 +478,21 @@ dict_table_autoinc_update(
|
||||
dict_table_t* table, /* in: table */
|
||||
ib_longlong value) /* in: value which was assigned to a row */
|
||||
{
|
||||
mutex_enter(&(table->autoinc_mutex));
|
||||
if (table->autoinc_inited && value > table->autoinc) {
|
||||
|
||||
if (table->autoinc_inited) {
|
||||
if (value >= table->autoinc) {
|
||||
table->autoinc = value + 1;
|
||||
}
|
||||
table->autoinc = value;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_exit(&(table->autoinc_mutex));
|
||||
/************************************************************************
|
||||
Release the autoinc lock.*/
|
||||
|
||||
void
|
||||
dict_table_autoinc_unlock(
|
||||
/*======================*/
|
||||
dict_table_t* table) /* in: release autoinc lock for this table */
|
||||
{
|
||||
mutex_exit(&table->autoinc_mutex);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@@ -842,28 +789,18 @@ dict_table_get(
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Adds a table object to the dictionary cache. */
|
||||
Adds system columns to a table object. */
|
||||
|
||||
void
|
||||
dict_table_add_to_cache(
|
||||
/*====================*/
|
||||
dict_table_t* table) /* in: table */
|
||||
dict_table_add_system_columns(
|
||||
/*==========================*/
|
||||
dict_table_t* table, /* in/out: table */
|
||||
mem_heap_t* heap) /* in: temporary heap */
|
||||
{
|
||||
ulint fold;
|
||||
ulint id_fold;
|
||||
ulint i;
|
||||
ulint row_len;
|
||||
|
||||
ut_ad(table);
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
ut_ad(table->n_def == table->n_cols - DATA_N_SYS_COLS);
|
||||
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||
ut_ad(table->cached == FALSE);
|
||||
|
||||
fold = ut_fold_string(table->name);
|
||||
id_fold = ut_fold_dulint(table->id);
|
||||
|
||||
table->cached = TRUE;
|
||||
ut_ad(!table->cached);
|
||||
|
||||
/* NOTE: the system columns MUST be added in the following order
|
||||
(so that they can be indexed by the numerical value of DATA_ROW_ID,
|
||||
@@ -871,19 +808,19 @@ dict_table_add_to_cache(
|
||||
The clustered index will not always physically contain all
|
||||
system columns. */
|
||||
|
||||
dict_mem_table_add_col(table, "DB_ROW_ID", DATA_SYS,
|
||||
dict_mem_table_add_col(table, heap, "DB_ROW_ID", DATA_SYS,
|
||||
DATA_ROW_ID | DATA_NOT_NULL,
|
||||
DATA_ROW_ID_LEN);
|
||||
#if DATA_ROW_ID != 0
|
||||
#error "DATA_ROW_ID != 0"
|
||||
#endif
|
||||
dict_mem_table_add_col(table, "DB_TRX_ID", DATA_SYS,
|
||||
dict_mem_table_add_col(table, heap, "DB_TRX_ID", DATA_SYS,
|
||||
DATA_TRX_ID | DATA_NOT_NULL,
|
||||
DATA_TRX_ID_LEN);
|
||||
#if DATA_TRX_ID != 1
|
||||
#error "DATA_TRX_ID != 1"
|
||||
#endif
|
||||
dict_mem_table_add_col(table, "DB_ROLL_PTR", DATA_SYS,
|
||||
dict_mem_table_add_col(table, heap, "DB_ROLL_PTR", DATA_SYS,
|
||||
DATA_ROLL_PTR | DATA_NOT_NULL,
|
||||
DATA_ROLL_PTR_LEN);
|
||||
#if DATA_ROLL_PTR != 2
|
||||
@@ -895,10 +832,34 @@ dict_table_add_to_cache(
|
||||
#if DATA_N_SYS_COLS != 3
|
||||
#error "DATA_N_SYS_COLS != 3"
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Adds a table object to the dictionary cache. */
|
||||
|
||||
void
|
||||
dict_table_add_to_cache(
|
||||
/*====================*/
|
||||
dict_table_t* table, /* in: table */
|
||||
mem_heap_t* heap) /* in: temporary heap */
|
||||
{
|
||||
ulint fold;
|
||||
ulint id_fold;
|
||||
ulint i;
|
||||
ulint row_len;
|
||||
|
||||
/* The lower limit for what we consider a "big" row */
|
||||
#define BIG_ROW_SIZE 1024
|
||||
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
|
||||
dict_table_add_system_columns(table, heap);
|
||||
|
||||
table->cached = TRUE;
|
||||
|
||||
fold = ut_fold_string(table->name);
|
||||
id_fold = ut_fold_dulint(table->id);
|
||||
|
||||
row_len = 0;
|
||||
for (i = 0; i < table->n_def; i++) {
|
||||
ulint col_len = dict_col_get_max_size(
|
||||
|
@@ -90,6 +90,11 @@ dict_mem_table_create(
|
||||
mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
|
||||
|
||||
table->autoinc_inited = FALSE;
|
||||
|
||||
/* The actual increment value will be set by MySQL, we simply
|
||||
default to 1 here.*/
|
||||
table->autoinc_increment = 1;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
table->magic_n = DICT_TABLE_MAGIC_N;
|
||||
#endif /* UNIV_DEBUG */
|
||||
@@ -108,18 +113,11 @@ dict_mem_table_free(
|
||||
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||
|
||||
mutex_free(&(table->autoinc_mutex));
|
||||
|
||||
if (table->col_names && (table->n_def < table->n_cols)) {
|
||||
ut_free((void*)table->col_names);
|
||||
}
|
||||
|
||||
mem_heap_free(table->heap);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Add 'name' to end of the col_names array (see dict_table_t::col_names). Call
|
||||
ut_free on col_names (if not NULL), allocate new array (if heap, from it,
|
||||
otherwise with ut_malloc), and copy col_names + name to it. */
|
||||
Append 'name' to 'col_names' (@see dict_table_t::col_names). */
|
||||
static
|
||||
const char*
|
||||
dict_add_col_name(
|
||||
@@ -129,21 +127,19 @@ dict_add_col_name(
|
||||
NULL */
|
||||
ulint cols, /* in: number of existing columns */
|
||||
const char* name, /* in: new column name */
|
||||
mem_heap_t* heap) /* in: heap, or NULL */
|
||||
mem_heap_t* heap) /* in: heap */
|
||||
{
|
||||
ulint i;
|
||||
ulint old_len;
|
||||
ulint new_len;
|
||||
ulint total_len;
|
||||
const char* s;
|
||||
char* res;
|
||||
ulint old_len;
|
||||
ulint new_len;
|
||||
ulint total_len;
|
||||
char* res;
|
||||
|
||||
ut_a(((cols == 0) && !col_names) || ((cols > 0) && col_names));
|
||||
ut_a(*name);
|
||||
ut_ad(!cols == !col_names);
|
||||
|
||||
/* Find out length of existing array. */
|
||||
if (col_names) {
|
||||
s = col_names;
|
||||
const char* s = col_names;
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < cols; i++) {
|
||||
s += strlen(s) + 1;
|
||||
@@ -157,11 +153,7 @@ dict_add_col_name(
|
||||
new_len = strlen(name) + 1;
|
||||
total_len = old_len + new_len;
|
||||
|
||||
if (heap) {
|
||||
res = mem_heap_alloc(heap, total_len);
|
||||
} else {
|
||||
res = ut_malloc(total_len);
|
||||
}
|
||||
res = mem_heap_alloc(heap, total_len);
|
||||
|
||||
if (old_len > 0) {
|
||||
memcpy(res, col_names, old_len);
|
||||
@@ -169,10 +161,6 @@ dict_add_col_name(
|
||||
|
||||
memcpy(res + old_len, name, new_len);
|
||||
|
||||
if (col_names) {
|
||||
ut_free((char*)col_names);
|
||||
}
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
@@ -183,7 +171,8 @@ void
|
||||
dict_mem_table_add_col(
|
||||
/*===================*/
|
||||
dict_table_t* table, /* in: table */
|
||||
const char* name, /* in: column name */
|
||||
mem_heap_t* heap, /* in: temporary memory heap, or NULL */
|
||||
const char* name, /* in: column name, or NULL */
|
||||
ulint mtype, /* in: main datatype */
|
||||
ulint prtype, /* in: precise type */
|
||||
ulint len) /* in: precision */
|
||||
@@ -191,21 +180,32 @@ dict_mem_table_add_col(
|
||||
dict_col_t* col;
|
||||
ulint mbminlen;
|
||||
ulint mbmaxlen;
|
||||
mem_heap_t* heap;
|
||||
ulint i;
|
||||
|
||||
ut_ad(table && name);
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||
ut_ad(!heap == !name);
|
||||
|
||||
table->n_def++;
|
||||
i = table->n_def++;
|
||||
|
||||
heap = table->n_def < table->n_cols ? NULL : table->heap;
|
||||
table->col_names = dict_add_col_name(table->col_names,
|
||||
table->n_def - 1,
|
||||
name, heap);
|
||||
if (name) {
|
||||
if (UNIV_UNLIKELY(table->n_def == table->n_cols)) {
|
||||
heap = table->heap;
|
||||
}
|
||||
if (UNIV_LIKELY(i) && UNIV_UNLIKELY(!table->col_names)) {
|
||||
/* All preceding column names are empty. */
|
||||
char* s = mem_heap_alloc(heap, table->n_def);
|
||||
memset(s, 0, table->n_def);
|
||||
table->col_names = s;
|
||||
}
|
||||
|
||||
col = (dict_col_t*) dict_table_get_nth_col(table, table->n_def - 1);
|
||||
table->col_names = dict_add_col_name(table->col_names,
|
||||
i, name, heap);
|
||||
}
|
||||
|
||||
col->ind = table->n_def - 1;
|
||||
col = (dict_col_t*) dict_table_get_nth_col(table, i);
|
||||
|
||||
col->ind = i;
|
||||
col->ord_part = 0;
|
||||
|
||||
col->mtype = (unsigned int) mtype;
|
||||
@@ -318,7 +318,7 @@ dict_mem_index_add_field(
|
||||
{
|
||||
dict_field_t* field;
|
||||
|
||||
ut_ad(index && name);
|
||||
ut_ad(index);
|
||||
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
|
||||
|
||||
index->n_def++;
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,10 @@ typedef struct st_innobase_share {
|
||||
} INNOBASE_SHARE;
|
||||
|
||||
|
||||
struct dict_index_struct;
|
||||
struct row_prebuilt_struct;
|
||||
|
||||
typedef struct dict_index_struct dict_index_t;
|
||||
typedef struct row_prebuilt_struct row_prebuilt_t;
|
||||
|
||||
/* The class defining a handle to an Innodb table */
|
||||
@@ -70,6 +73,11 @@ class ha_innobase: public handler
|
||||
int change_active_index(uint keynr);
|
||||
int general_fetch(uchar* buf, uint direction, uint match_mode);
|
||||
int innobase_read_and_init_auto_inc(longlong* ret);
|
||||
ulong innobase_autoinc_lock();
|
||||
ulong innobase_set_max_autoinc(ulonglong auto_inc);
|
||||
ulong innobase_reset_autoinc(ulonglong auto_inc);
|
||||
ulong innobase_get_auto_increment(ulonglong* value);
|
||||
dict_index_t* innobase_get_index(uint keynr);
|
||||
|
||||
/* Init values for the class: */
|
||||
public:
|
||||
|
@@ -462,7 +462,8 @@ ibuf_data_init_for_space(
|
||||
page_t* root;
|
||||
page_t* header_page;
|
||||
mtr_t mtr;
|
||||
char buf[50];
|
||||
char* buf;
|
||||
mem_heap_t* heap;
|
||||
dict_table_t* table;
|
||||
dict_index_t* index;
|
||||
ulint n_used;
|
||||
@@ -516,16 +517,20 @@ ibuf_data_init_for_space(
|
||||
|
||||
ibuf_exit();
|
||||
|
||||
heap = mem_heap_create(450);
|
||||
buf = mem_heap_alloc(heap, 50);
|
||||
|
||||
sprintf(buf, "SYS_IBUF_TABLE_%lu", (ulong) space);
|
||||
/* use old-style record format for the insert buffer */
|
||||
table = dict_mem_table_create(buf, space, 2, 0);
|
||||
|
||||
dict_mem_table_add_col(table, "PAGE_NO", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, "TYPES", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "PAGE_NO", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "TYPES", DATA_BINARY, 0, 0);
|
||||
|
||||
table->id = ut_dulint_add(DICT_IBUF_ID_MIN, space);
|
||||
|
||||
dict_table_add_to_cache(table);
|
||||
dict_table_add_to_cache(table, heap);
|
||||
mem_heap_free(heap);
|
||||
|
||||
index = dict_mem_index_create(
|
||||
buf, "CLUST_IND", space,
|
||||
@@ -1139,7 +1144,7 @@ ibuf_dummy_index_add_col(
|
||||
ulint len) /* in: length of the column */
|
||||
{
|
||||
ulint i = index->table->n_def;
|
||||
dict_mem_table_add_col(index->table, "DUMMY",
|
||||
dict_mem_table_add_col(index->table, NULL, NULL,
|
||||
dtype_get_mtype(type),
|
||||
dtype_get_prtype(type),
|
||||
dtype_get_len(type));
|
||||
@@ -1161,11 +1166,6 @@ ibuf_dummy_index_free(
|
||||
dict_mem_table_free(table);
|
||||
}
|
||||
|
||||
void
|
||||
dict_index_print_low(
|
||||
/*=================*/
|
||||
dict_index_t* index); /* in: index */
|
||||
|
||||
/*************************************************************************
|
||||
Builds the entry to insert into a non-clustered index when we have the
|
||||
corresponding record in an ibuf index. */
|
||||
|
@@ -171,6 +171,13 @@ dict_col_name_is_reserved(
|
||||
/* out: TRUE if name is reserved */
|
||||
const char* name); /* in: column name */
|
||||
/************************************************************************
|
||||
Acquire the autoinc lock.*/
|
||||
|
||||
void
|
||||
dict_table_autoinc_lock(
|
||||
/*====================*/
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Initializes the autoinc counter. It is not an error to initialize an already
|
||||
initialized counter. */
|
||||
|
||||
@@ -180,22 +187,6 @@ dict_table_autoinc_initialize(
|
||||
dict_table_t* table, /* in: table */
|
||||
ib_longlong value); /* in: next value to assign to a row */
|
||||
/************************************************************************
|
||||
Gets the next autoinc value (== autoinc counter value), 0 if not yet
|
||||
initialized. If initialized, increments the counter by 1. */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_get(
|
||||
/*===================*/
|
||||
/* out: value for a new row, or 0 */
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Decrements the autoinc counter value by 1. */
|
||||
|
||||
void
|
||||
dict_table_autoinc_decrement(
|
||||
/*=========================*/
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Reads the next autoinc value (== autoinc counter value), 0 if not yet
|
||||
initialized. */
|
||||
|
||||
@@ -205,15 +196,6 @@ dict_table_autoinc_read(
|
||||
/* out: value for a new row, or 0 */
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Peeks the autoinc counter value, 0 if not yet initialized. Does not
|
||||
increment the counter. The read not protected by any mutex! */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_peek(
|
||||
/*====================*/
|
||||
/* out: value of the counter */
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Updates the autoinc counter if the value supplied is equal or bigger than the
|
||||
current value. If not inited, does nothing. */
|
||||
|
||||
@@ -223,13 +205,29 @@ dict_table_autoinc_update(
|
||||
|
||||
dict_table_t* table, /* in: table */
|
||||
ib_longlong value); /* in: value which was assigned to a row */
|
||||
/************************************************************************
|
||||
Release the autoinc lock.*/
|
||||
|
||||
void
|
||||
dict_table_autoinc_unlock(
|
||||
/*======================*/
|
||||
dict_table_t* table); /* in: table */
|
||||
/**************************************************************************
|
||||
Adds system columns to a table object. */
|
||||
|
||||
void
|
||||
dict_table_add_system_columns(
|
||||
/*==========================*/
|
||||
dict_table_t* table, /* in/out: table */
|
||||
mem_heap_t* heap); /* in: temporary heap */
|
||||
/**************************************************************************
|
||||
Adds a table object to the dictionary cache. */
|
||||
|
||||
void
|
||||
dict_table_add_to_cache(
|
||||
/*====================*/
|
||||
dict_table_t* table); /* in: table */
|
||||
dict_table_t* table, /* in: table */
|
||||
mem_heap_t* heap); /* in: temporary heap */
|
||||
/**************************************************************************
|
||||
Removes a table object from the dictionary cache. */
|
||||
|
||||
|
@@ -72,7 +72,8 @@ void
|
||||
dict_mem_table_add_col(
|
||||
/*===================*/
|
||||
dict_table_t* table, /* in: table */
|
||||
const char* name, /* in: column name */
|
||||
mem_heap_t* heap, /* in: temporary memory heap, or NULL */
|
||||
const char* name, /* in: column name, or NULL */
|
||||
ulint mtype, /* in: main datatype */
|
||||
ulint prtype, /* in: precise type */
|
||||
ulint len); /* in: precision */
|
||||
@@ -410,6 +411,11 @@ struct dict_table_struct{
|
||||
SELECT MAX(auto inc column) */
|
||||
ib_longlong autoinc;/* autoinc counter value to give to the
|
||||
next inserted row */
|
||||
|
||||
ib_longlong autoinc_increment;
|
||||
/* The increment step of the auto increment
|
||||
column. Value must be greater than or equal
|
||||
to 1 */
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint magic_n;/* magic number */
|
||||
# define DICT_TABLE_MAGIC_N 76333786
|
||||
|
@@ -609,7 +609,7 @@ lock_validate(void);
|
||||
/* out: TRUE if ok */
|
||||
/*************************************************************************
|
||||
Return approximate number or record locks (bits set in the bitmap) for
|
||||
this transaction. Since delete-marked records maybe removed, the
|
||||
this transaction. Since delete-marked records may be removed, the
|
||||
record count will not be precise. */
|
||||
|
||||
ulint
|
||||
|
@@ -670,6 +670,7 @@ struct row_prebuilt_struct {
|
||||
to this heap */
|
||||
mem_heap_t* old_vers_heap; /* memory heap where a previous
|
||||
version is built in consistent read */
|
||||
ulonglong last_value; /* last value of AUTO-INC interval */
|
||||
ulint magic_n2; /* this should be the same as
|
||||
magic_n */
|
||||
};
|
||||
|
@@ -171,7 +171,17 @@ row_search_check_if_query_cache_permitted(
|
||||
trx_t* trx, /* in: transaction object */
|
||||
const char* norm_name); /* in: concatenation of database name,
|
||||
'/' char, table name */
|
||||
/***********************************************************************
|
||||
Read the max AUTOINC value from an index. */
|
||||
|
||||
ulint
|
||||
row_search_max_autoinc(
|
||||
/*===================*/
|
||||
/* out: DB_SUCCESS if all OK else
|
||||
error code */
|
||||
dict_index_t* index, /* in: index to search */
|
||||
const char* col_name, /* in: autoinc column name */
|
||||
ib_longlong* value); /* out: AUTOINC value read */
|
||||
|
||||
/* A structure for caching column values for prefetched rows */
|
||||
struct sel_buf_struct{
|
||||
|
@@ -681,6 +681,9 @@ struct trx_struct{
|
||||
trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
|
||||
records which are currently processed
|
||||
by a rollback operation */
|
||||
ulint n_autoinc_rows; /* no. of AUTO-INC rows required for
|
||||
an SQL statement. This is useful for
|
||||
multi-row INSERTs */
|
||||
/*------------------------------*/
|
||||
char detailed_error[256]; /* detailed error message for last
|
||||
error, or empty. */
|
||||
|
@@ -63,7 +63,7 @@ ut_test_malloc(
|
||||
/* out: TRUE if succeeded */
|
||||
ulint n); /* in: try to allocate this many bytes */
|
||||
/**************************************************************************
|
||||
Frees a memory bloock allocated with ut_malloc. */
|
||||
Frees a memory block allocated with ut_malloc. */
|
||||
|
||||
void
|
||||
ut_free(
|
||||
|
@@ -2481,7 +2481,6 @@ recv_init_crash_recovery(void)
|
||||
"InnoDB: buffer...\n");
|
||||
trx_sys_doublewrite_init_or_restore_pages(TRUE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
|
@@ -655,6 +655,8 @@ row_create_prebuilt(
|
||||
|
||||
prebuilt->old_vers_heap = NULL;
|
||||
|
||||
prebuilt->last_value = 0;
|
||||
|
||||
return(prebuilt);
|
||||
}
|
||||
|
||||
@@ -2894,6 +2896,8 @@ next_rec:
|
||||
dict_table_change_id_in_cache(table, new_id);
|
||||
}
|
||||
|
||||
/* MySQL calls ha_innobase::reset_auto_increment() which does
|
||||
the same thing. */
|
||||
dict_table_autoinc_initialize(table, 0);
|
||||
dict_update_statistics(table);
|
||||
|
||||
|
@@ -4519,3 +4519,169 @@ row_search_check_if_query_cache_permitted(
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Read the AUTOINC column from the current row. */
|
||||
static
|
||||
ib_longlong
|
||||
row_search_autoinc_read_column(
|
||||
/*===========================*/
|
||||
/* out: value read from the column */
|
||||
dict_index_t* index, /* in: index to read from */
|
||||
const rec_t* rec, /* in: current rec */
|
||||
ulint col_no, /* in: column number */
|
||||
ibool unsigned_type) /* in: signed or unsigned flag */
|
||||
{
|
||||
ulint len;
|
||||
byte* ptr;
|
||||
const byte* data;
|
||||
ib_longlong value;
|
||||
mem_heap_t* heap = NULL;
|
||||
byte dest[sizeof(value)];
|
||||
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||
ulint* offsets = offsets_;
|
||||
|
||||
*offsets_ = sizeof offsets_ / sizeof *offsets_;
|
||||
|
||||
/* TODO: We have to cast away the const of rec for now. This needs
|
||||
to be fixed later.*/
|
||||
offsets = rec_get_offsets(
|
||||
(rec_t*) rec, index, offsets, ULINT_UNDEFINED, &heap);
|
||||
|
||||
/* TODO: We have to cast away the const of rec for now. This needs
|
||||
to be fixed later.*/
|
||||
data = rec_get_nth_field((rec_t*)rec, offsets, col_no, &len);
|
||||
|
||||
ut_a(len != UNIV_SQL_NULL);
|
||||
ut_a(len <= sizeof value);
|
||||
|
||||
/* Convert integer data from Innobase to a little-endian format,
|
||||
sign bit restored to normal */
|
||||
|
||||
for (ptr = dest + len; ptr != dest; ++data) {
|
||||
--ptr;
|
||||
*ptr = *data;
|
||||
}
|
||||
|
||||
if (!unsigned_type) {
|
||||
dest[len - 1] ^= 128;
|
||||
}
|
||||
|
||||
/* The assumption here is that the AUTOINC value can't be negative.*/
|
||||
switch (len) {
|
||||
case 8:
|
||||
value = *(ib_longlong*) ptr;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
value = *(ib_uint32_t*) ptr;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
value = *(uint16 *) ptr;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
value = *ptr;
|
||||
break;
|
||||
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
ut_a(value >= 0);
|
||||
|
||||
return(value);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Get the last row. */
|
||||
static
|
||||
const rec_t*
|
||||
row_search_autoinc_get_rec(
|
||||
/*=======================*/
|
||||
/* out: current rec or NULL */
|
||||
btr_pcur_t* pcur, /* in: the current cursor */
|
||||
mtr_t* mtr) /* in: mini transaction */
|
||||
{
|
||||
do {
|
||||
const rec_t* rec = btr_pcur_get_rec(pcur);
|
||||
|
||||
if (page_rec_is_user_rec(rec)) {
|
||||
return(rec);
|
||||
}
|
||||
} while (btr_pcur_move_to_prev(pcur, mtr));
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Read the max AUTOINC value from an index. */
|
||||
|
||||
ulint
|
||||
row_search_max_autoinc(
|
||||
/*===================*/
|
||||
/* out: DB_SUCCESS if all OK else
|
||||
error code, DB_RECORD_NOT_FOUND if
|
||||
column name can't be found in index */
|
||||
dict_index_t* index, /* in: index to search */
|
||||
const char* col_name, /* in: name of autoinc column */
|
||||
ib_longlong* value) /* out: AUTOINC value read */
|
||||
{
|
||||
ulint i;
|
||||
ulint n_cols;
|
||||
dict_field_t* dfield = NULL;
|
||||
ulint error = DB_SUCCESS;
|
||||
|
||||
n_cols = dict_index_get_n_ordering_defined_by_user(index);
|
||||
|
||||
/* Search the index for the AUTOINC column name */
|
||||
for (i = 0; i < n_cols; ++i) {
|
||||
dfield = dict_index_get_nth_field(index, i);
|
||||
|
||||
if (strcmp(col_name, dfield->name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*value = 0;
|
||||
|
||||
/* Must find the AUTOINC column name */
|
||||
if (i < n_cols && dfield) {
|
||||
mtr_t mtr;
|
||||
btr_pcur_t pcur;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
/* Open at the high/right end (FALSE), and INIT
|
||||
cursor (TRUE) */
|
||||
btr_pcur_open_at_index_side(
|
||||
FALSE, index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
|
||||
|
||||
if (page_get_n_recs(btr_pcur_get_page(&pcur)) > 0) {
|
||||
const rec_t* rec;
|
||||
|
||||
rec = row_search_autoinc_get_rec(&pcur, &mtr);
|
||||
|
||||
if (rec != NULL) {
|
||||
ibool unsigned_type = (
|
||||
dfield->col->prtype & DATA_UNSIGNED);
|
||||
|
||||
*value = row_search_autoinc_read_column(
|
||||
index, rec, i, unsigned_type);
|
||||
}
|
||||
}
|
||||
|
||||
btr_pcur_close(&pcur);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
} else {
|
||||
error = DB_RECORD_NOT_FOUND;
|
||||
}
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
@@ -195,6 +195,8 @@ trx_create(
|
||||
memset(&trx->xid, 0, sizeof(trx->xid));
|
||||
trx->xid.formatID = -1;
|
||||
|
||||
trx->n_autoinc_rows = 0;
|
||||
|
||||
trx_reset_new_rec_lock_info(trx);
|
||||
|
||||
return(trx);
|
||||
|
Reference in New Issue
Block a user