mirror of
https://github.com/MariaDB/server.git
synced 2025-09-03 20:43:11 +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;
|
select * from t1;
|
||||||
id ggid email passwd
|
id ggid email passwd
|
||||||
1 this will work
|
1 this will work
|
||||||
3 test2 this will work
|
4 test2 this will work
|
||||||
select * from t1 where id=1;
|
select * from t1 where id=1;
|
||||||
id ggid email passwd
|
id ggid email passwd
|
||||||
1 this will work
|
1 this will work
|
||||||
|
@@ -410,14 +410,27 @@ dict_table_get_col_name(
|
|||||||
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||||
|
|
||||||
s = table->col_names;
|
s = table->col_names;
|
||||||
|
if (s) {
|
||||||
for (i = 0; i < col_nr; i++) {
|
for (i = 0; i < col_nr; i++) {
|
||||||
s += strlen(s) + 1;
|
s += strlen(s) + 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return(s);
|
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
|
Initializes the autoinc counter. It is not an error to initialize an already
|
||||||
initialized counter. */
|
initialized counter. */
|
||||||
@@ -428,54 +441,8 @@ dict_table_autoinc_initialize(
|
|||||||
dict_table_t* table, /* in: table */
|
dict_table_t* table, /* in: table */
|
||||||
ib_longlong value) /* in: next value to assign to a row */
|
ib_longlong value) /* in: next value to assign to a row */
|
||||||
{
|
{
|
||||||
mutex_enter(&(table->autoinc_mutex));
|
|
||||||
|
|
||||||
table->autoinc_inited = TRUE;
|
table->autoinc_inited = TRUE;
|
||||||
table->autoinc = value;
|
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;
|
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) {
|
if (!table->autoinc_inited) {
|
||||||
|
|
||||||
value = 0;
|
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. */
|
current value. If not inited, does nothing. */
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -537,15 +478,21 @@ dict_table_autoinc_update(
|
|||||||
dict_table_t* table, /* in: table */
|
dict_table_t* table, /* in: table */
|
||||||
ib_longlong value) /* in: value which was assigned to a row */
|
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) {
|
table->autoinc = value;
|
||||||
if (value >= table->autoinc) {
|
|
||||||
table->autoinc = value + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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
|
void
|
||||||
dict_table_add_to_cache(
|
dict_table_add_system_columns(
|
||||||
/*====================*/
|
/*==========================*/
|
||||||
dict_table_t* table) /* in: table */
|
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(table);
|
||||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
|
||||||
ut_ad(table->n_def == table->n_cols - DATA_N_SYS_COLS);
|
ut_ad(table->n_def == table->n_cols - DATA_N_SYS_COLS);
|
||||||
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||||
ut_ad(table->cached == FALSE);
|
ut_ad(!table->cached);
|
||||||
|
|
||||||
fold = ut_fold_string(table->name);
|
|
||||||
id_fold = ut_fold_dulint(table->id);
|
|
||||||
|
|
||||||
table->cached = TRUE;
|
|
||||||
|
|
||||||
/* NOTE: the system columns MUST be added in the following order
|
/* 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,
|
(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
|
The clustered index will not always physically contain all
|
||||||
system columns. */
|
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 | DATA_NOT_NULL,
|
||||||
DATA_ROW_ID_LEN);
|
DATA_ROW_ID_LEN);
|
||||||
#if DATA_ROW_ID != 0
|
#if DATA_ROW_ID != 0
|
||||||
#error "DATA_ROW_ID != 0"
|
#error "DATA_ROW_ID != 0"
|
||||||
#endif
|
#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 | DATA_NOT_NULL,
|
||||||
DATA_TRX_ID_LEN);
|
DATA_TRX_ID_LEN);
|
||||||
#if DATA_TRX_ID != 1
|
#if DATA_TRX_ID != 1
|
||||||
#error "DATA_TRX_ID != 1"
|
#error "DATA_TRX_ID != 1"
|
||||||
#endif
|
#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 | DATA_NOT_NULL,
|
||||||
DATA_ROLL_PTR_LEN);
|
DATA_ROLL_PTR_LEN);
|
||||||
#if DATA_ROLL_PTR != 2
|
#if DATA_ROLL_PTR != 2
|
||||||
@@ -895,10 +832,34 @@ dict_table_add_to_cache(
|
|||||||
#if DATA_N_SYS_COLS != 3
|
#if DATA_N_SYS_COLS != 3
|
||||||
#error "DATA_N_SYS_COLS != 3"
|
#error "DATA_N_SYS_COLS != 3"
|
||||||
#endif
|
#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 */
|
/* The lower limit for what we consider a "big" row */
|
||||||
#define BIG_ROW_SIZE 1024
|
#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;
|
row_len = 0;
|
||||||
for (i = 0; i < table->n_def; i++) {
|
for (i = 0; i < table->n_def; i++) {
|
||||||
ulint col_len = dict_col_get_max_size(
|
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);
|
mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
|
||||||
|
|
||||||
table->autoinc_inited = FALSE;
|
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
|
#ifdef UNIV_DEBUG
|
||||||
table->magic_n = DICT_TABLE_MAGIC_N;
|
table->magic_n = DICT_TABLE_MAGIC_N;
|
||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
@@ -108,18 +113,11 @@ dict_mem_table_free(
|
|||||||
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||||
|
|
||||||
mutex_free(&(table->autoinc_mutex));
|
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);
|
mem_heap_free(table->heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
Add 'name' to end of the col_names array (see dict_table_t::col_names). Call
|
Append 'name' to 'col_names' (@see dict_table_t::col_names). */
|
||||||
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. */
|
|
||||||
static
|
static
|
||||||
const char*
|
const char*
|
||||||
dict_add_col_name(
|
dict_add_col_name(
|
||||||
@@ -129,21 +127,19 @@ dict_add_col_name(
|
|||||||
NULL */
|
NULL */
|
||||||
ulint cols, /* in: number of existing columns */
|
ulint cols, /* in: number of existing columns */
|
||||||
const char* name, /* in: new column name */
|
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 old_len;
|
||||||
ulint new_len;
|
ulint new_len;
|
||||||
ulint total_len;
|
ulint total_len;
|
||||||
const char* s;
|
|
||||||
char* res;
|
char* res;
|
||||||
|
|
||||||
ut_a(((cols == 0) && !col_names) || ((cols > 0) && col_names));
|
ut_ad(!cols == !col_names);
|
||||||
ut_a(*name);
|
|
||||||
|
|
||||||
/* Find out length of existing array. */
|
/* Find out length of existing array. */
|
||||||
if (col_names) {
|
if (col_names) {
|
||||||
s = col_names;
|
const char* s = col_names;
|
||||||
|
ulint i;
|
||||||
|
|
||||||
for (i = 0; i < cols; i++) {
|
for (i = 0; i < cols; i++) {
|
||||||
s += strlen(s) + 1;
|
s += strlen(s) + 1;
|
||||||
@@ -157,11 +153,7 @@ dict_add_col_name(
|
|||||||
new_len = strlen(name) + 1;
|
new_len = strlen(name) + 1;
|
||||||
total_len = old_len + new_len;
|
total_len = old_len + new_len;
|
||||||
|
|
||||||
if (heap) {
|
|
||||||
res = mem_heap_alloc(heap, total_len);
|
res = mem_heap_alloc(heap, total_len);
|
||||||
} else {
|
|
||||||
res = ut_malloc(total_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (old_len > 0) {
|
if (old_len > 0) {
|
||||||
memcpy(res, col_names, old_len);
|
memcpy(res, col_names, old_len);
|
||||||
@@ -169,10 +161,6 @@ dict_add_col_name(
|
|||||||
|
|
||||||
memcpy(res + old_len, name, new_len);
|
memcpy(res + old_len, name, new_len);
|
||||||
|
|
||||||
if (col_names) {
|
|
||||||
ut_free((char*)col_names);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(res);
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +171,8 @@ void
|
|||||||
dict_mem_table_add_col(
|
dict_mem_table_add_col(
|
||||||
/*===================*/
|
/*===================*/
|
||||||
dict_table_t* table, /* in: table */
|
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 mtype, /* in: main datatype */
|
||||||
ulint prtype, /* in: precise type */
|
ulint prtype, /* in: precise type */
|
||||||
ulint len) /* in: precision */
|
ulint len) /* in: precision */
|
||||||
@@ -191,21 +180,32 @@ dict_mem_table_add_col(
|
|||||||
dict_col_t* col;
|
dict_col_t* col;
|
||||||
ulint mbminlen;
|
ulint mbminlen;
|
||||||
ulint mbmaxlen;
|
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(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||||
|
ut_ad(!heap == !name);
|
||||||
|
|
||||||
table->n_def++;
|
i = table->n_def++;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
heap = table->n_def < table->n_cols ? NULL : table->heap;
|
|
||||||
table->col_names = dict_add_col_name(table->col_names,
|
table->col_names = dict_add_col_name(table->col_names,
|
||||||
table->n_def - 1,
|
i, name, heap);
|
||||||
name, heap);
|
}
|
||||||
|
|
||||||
col = (dict_col_t*) dict_table_get_nth_col(table, table->n_def - 1);
|
col = (dict_col_t*) dict_table_get_nth_col(table, i);
|
||||||
|
|
||||||
col->ind = table->n_def - 1;
|
col->ind = i;
|
||||||
col->ord_part = 0;
|
col->ord_part = 0;
|
||||||
|
|
||||||
col->mtype = (unsigned int) mtype;
|
col->mtype = (unsigned int) mtype;
|
||||||
@@ -318,7 +318,7 @@ dict_mem_index_add_field(
|
|||||||
{
|
{
|
||||||
dict_field_t* field;
|
dict_field_t* field;
|
||||||
|
|
||||||
ut_ad(index && name);
|
ut_ad(index);
|
||||||
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
|
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
|
||||||
|
|
||||||
index->n_def++;
|
index->n_def++;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,10 @@ typedef struct st_innobase_share {
|
|||||||
} INNOBASE_SHARE;
|
} INNOBASE_SHARE;
|
||||||
|
|
||||||
|
|
||||||
|
struct dict_index_struct;
|
||||||
struct row_prebuilt_struct;
|
struct row_prebuilt_struct;
|
||||||
|
|
||||||
|
typedef struct dict_index_struct dict_index_t;
|
||||||
typedef struct row_prebuilt_struct row_prebuilt_t;
|
typedef struct row_prebuilt_struct row_prebuilt_t;
|
||||||
|
|
||||||
/* The class defining a handle to an Innodb table */
|
/* 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 change_active_index(uint keynr);
|
||||||
int general_fetch(uchar* buf, uint direction, uint match_mode);
|
int general_fetch(uchar* buf, uint direction, uint match_mode);
|
||||||
int innobase_read_and_init_auto_inc(longlong* ret);
|
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: */
|
/* Init values for the class: */
|
||||||
public:
|
public:
|
||||||
|
@@ -462,7 +462,8 @@ ibuf_data_init_for_space(
|
|||||||
page_t* root;
|
page_t* root;
|
||||||
page_t* header_page;
|
page_t* header_page;
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
char buf[50];
|
char* buf;
|
||||||
|
mem_heap_t* heap;
|
||||||
dict_table_t* table;
|
dict_table_t* table;
|
||||||
dict_index_t* index;
|
dict_index_t* index;
|
||||||
ulint n_used;
|
ulint n_used;
|
||||||
@@ -516,16 +517,20 @@ ibuf_data_init_for_space(
|
|||||||
|
|
||||||
ibuf_exit();
|
ibuf_exit();
|
||||||
|
|
||||||
|
heap = mem_heap_create(450);
|
||||||
|
buf = mem_heap_alloc(heap, 50);
|
||||||
|
|
||||||
sprintf(buf, "SYS_IBUF_TABLE_%lu", (ulong) space);
|
sprintf(buf, "SYS_IBUF_TABLE_%lu", (ulong) space);
|
||||||
/* use old-style record format for the insert buffer */
|
/* use old-style record format for the insert buffer */
|
||||||
table = dict_mem_table_create(buf, space, 2, 0);
|
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, heap, "PAGE_NO", DATA_BINARY, 0, 0);
|
||||||
dict_mem_table_add_col(table, "TYPES", 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);
|
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(
|
index = dict_mem_index_create(
|
||||||
buf, "CLUST_IND", space,
|
buf, "CLUST_IND", space,
|
||||||
@@ -1139,7 +1144,7 @@ ibuf_dummy_index_add_col(
|
|||||||
ulint len) /* in: length of the column */
|
ulint len) /* in: length of the column */
|
||||||
{
|
{
|
||||||
ulint i = index->table->n_def;
|
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_mtype(type),
|
||||||
dtype_get_prtype(type),
|
dtype_get_prtype(type),
|
||||||
dtype_get_len(type));
|
dtype_get_len(type));
|
||||||
@@ -1161,11 +1166,6 @@ ibuf_dummy_index_free(
|
|||||||
dict_mem_table_free(table);
|
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
|
Builds the entry to insert into a non-clustered index when we have the
|
||||||
corresponding record in an ibuf index. */
|
corresponding record in an ibuf index. */
|
||||||
|
@@ -171,6 +171,13 @@ dict_col_name_is_reserved(
|
|||||||
/* out: TRUE if name is reserved */
|
/* out: TRUE if name is reserved */
|
||||||
const char* name); /* in: column name */
|
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
|
Initializes the autoinc counter. It is not an error to initialize an already
|
||||||
initialized counter. */
|
initialized counter. */
|
||||||
|
|
||||||
@@ -180,22 +187,6 @@ dict_table_autoinc_initialize(
|
|||||||
dict_table_t* table, /* in: table */
|
dict_table_t* table, /* in: table */
|
||||||
ib_longlong value); /* in: next value to assign to a row */
|
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
|
Reads the next autoinc value (== autoinc counter value), 0 if not yet
|
||||||
initialized. */
|
initialized. */
|
||||||
|
|
||||||
@@ -205,15 +196,6 @@ dict_table_autoinc_read(
|
|||||||
/* out: value for a new row, or 0 */
|
/* out: value for a new row, or 0 */
|
||||||
dict_table_t* table); /* in: table */
|
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
|
Updates the autoinc counter if the value supplied is equal or bigger than the
|
||||||
current value. If not inited, does nothing. */
|
current value. If not inited, does nothing. */
|
||||||
|
|
||||||
@@ -223,13 +205,29 @@ dict_table_autoinc_update(
|
|||||||
|
|
||||||
dict_table_t* table, /* in: table */
|
dict_table_t* table, /* in: table */
|
||||||
ib_longlong value); /* in: value which was assigned to a row */
|
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. */
|
Adds a table object to the dictionary cache. */
|
||||||
|
|
||||||
void
|
void
|
||||||
dict_table_add_to_cache(
|
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. */
|
Removes a table object from the dictionary cache. */
|
||||||
|
|
||||||
|
@@ -72,7 +72,8 @@ void
|
|||||||
dict_mem_table_add_col(
|
dict_mem_table_add_col(
|
||||||
/*===================*/
|
/*===================*/
|
||||||
dict_table_t* table, /* in: table */
|
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 mtype, /* in: main datatype */
|
||||||
ulint prtype, /* in: precise type */
|
ulint prtype, /* in: precise type */
|
||||||
ulint len); /* in: precision */
|
ulint len); /* in: precision */
|
||||||
@@ -410,6 +411,11 @@ struct dict_table_struct{
|
|||||||
SELECT MAX(auto inc column) */
|
SELECT MAX(auto inc column) */
|
||||||
ib_longlong autoinc;/* autoinc counter value to give to the
|
ib_longlong autoinc;/* autoinc counter value to give to the
|
||||||
next inserted row */
|
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
|
#ifdef UNIV_DEBUG
|
||||||
ulint magic_n;/* magic number */
|
ulint magic_n;/* magic number */
|
||||||
# define DICT_TABLE_MAGIC_N 76333786
|
# define DICT_TABLE_MAGIC_N 76333786
|
||||||
|
@@ -609,7 +609,7 @@ lock_validate(void);
|
|||||||
/* out: TRUE if ok */
|
/* out: TRUE if ok */
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Return approximate number or record locks (bits set in the bitmap) for
|
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. */
|
record count will not be precise. */
|
||||||
|
|
||||||
ulint
|
ulint
|
||||||
|
@@ -670,6 +670,7 @@ struct row_prebuilt_struct {
|
|||||||
to this heap */
|
to this heap */
|
||||||
mem_heap_t* old_vers_heap; /* memory heap where a previous
|
mem_heap_t* old_vers_heap; /* memory heap where a previous
|
||||||
version is built in consistent read */
|
version is built in consistent read */
|
||||||
|
ulonglong last_value; /* last value of AUTO-INC interval */
|
||||||
ulint magic_n2; /* this should be the same as
|
ulint magic_n2; /* this should be the same as
|
||||||
magic_n */
|
magic_n */
|
||||||
};
|
};
|
||||||
|
@@ -171,7 +171,17 @@ row_search_check_if_query_cache_permitted(
|
|||||||
trx_t* trx, /* in: transaction object */
|
trx_t* trx, /* in: transaction object */
|
||||||
const char* norm_name); /* in: concatenation of database name,
|
const char* norm_name); /* in: concatenation of database name,
|
||||||
'/' char, table 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 */
|
/* A structure for caching column values for prefetched rows */
|
||||||
struct sel_buf_struct{
|
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
|
trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
|
||||||
records which are currently processed
|
records which are currently processed
|
||||||
by a rollback operation */
|
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
|
char detailed_error[256]; /* detailed error message for last
|
||||||
error, or empty. */
|
error, or empty. */
|
||||||
|
@@ -63,7 +63,7 @@ ut_test_malloc(
|
|||||||
/* out: TRUE if succeeded */
|
/* out: TRUE if succeeded */
|
||||||
ulint n); /* in: try to allocate this many bytes */
|
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
|
void
|
||||||
ut_free(
|
ut_free(
|
||||||
|
@@ -2481,7 +2481,6 @@ recv_init_crash_recovery(void)
|
|||||||
"InnoDB: buffer...\n");
|
"InnoDB: buffer...\n");
|
||||||
trx_sys_doublewrite_init_or_restore_pages(TRUE);
|
trx_sys_doublewrite_init_or_restore_pages(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
|
@@ -655,6 +655,8 @@ row_create_prebuilt(
|
|||||||
|
|
||||||
prebuilt->old_vers_heap = NULL;
|
prebuilt->old_vers_heap = NULL;
|
||||||
|
|
||||||
|
prebuilt->last_value = 0;
|
||||||
|
|
||||||
return(prebuilt);
|
return(prebuilt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2894,6 +2896,8 @@ next_rec:
|
|||||||
dict_table_change_id_in_cache(table, new_id);
|
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_table_autoinc_initialize(table, 0);
|
||||||
dict_update_statistics(table);
|
dict_update_statistics(table);
|
||||||
|
|
||||||
|
@@ -4519,3 +4519,169 @@ row_search_check_if_query_cache_permitted(
|
|||||||
|
|
||||||
return(ret);
|
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));
|
memset(&trx->xid, 0, sizeof(trx->xid));
|
||||||
trx->xid.formatID = -1;
|
trx->xid.formatID = -1;
|
||||||
|
|
||||||
|
trx->n_autoinc_rows = 0;
|
||||||
|
|
||||||
trx_reset_new_rec_lock_info(trx);
|
trx_reset_new_rec_lock_info(trx);
|
||||||
|
|
||||||
return(trx);
|
return(trx);
|
||||||
|
Reference in New Issue
Block a user