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().
parent 7f429ecc
...@@ -501,7 +501,7 @@ ERROR 23000: Duplicate entry 'test2' for key 'ggid' ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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; char* res;
const char* s;
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( ...@@ -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( ...@@ -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 ...@@ -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( ...@@ -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++;
heap = table->n_def < table->n_cols ? NULL : table->heap; if (name) {
table->col_names = dict_add_col_name(table->col_names, if (UNIV_UNLIKELY(table->n_def == table->n_cols)) {
table->n_def - 1, heap = table->heap;
name, 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;
}
table->col_names = dict_add_col_name(table->col_names,
i, 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( ...@@ -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++;
......
This diff is collapsed.
...@@ -32,7 +32,10 @@ typedef struct st_innobase_share { ...@@ -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 ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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 ...@@ -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{ ...@@ -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); ...@@ -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 { ...@@ -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( ...@@ -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{ ...@@ -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( ...@@ -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(
......
...@@ -115,7 +115,7 @@ dulint recv_max_page_lsn; ...@@ -115,7 +115,7 @@ dulint recv_max_page_lsn;
Initialize crash recovery environment. Can be called iff Initialize crash recovery environment. Can be called iff
recv_needed_recovery == FALSE. */ recv_needed_recovery == FALSE. */
static static
void void
recv_init_crash_recovery(void); recv_init_crash_recovery(void);
/*===========================*/ /*===========================*/
...@@ -2450,7 +2450,7 @@ void ...@@ -2450,7 +2450,7 @@ void
recv_init_crash_recovery(void) recv_init_crash_recovery(void)
/*==========================*/ /*==========================*/
{ {
ut_a(!recv_needed_recovery); ut_a(!recv_needed_recovery);
recv_needed_recovery = TRUE; recv_needed_recovery = TRUE;
...@@ -2481,7 +2481,6 @@ recv_init_crash_recovery(void) ...@@ -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);
} }
} }
/************************************************************ /************************************************************
...@@ -2805,7 +2804,7 @@ recv_recovery_from_checkpoint_start( ...@@ -2805,7 +2804,7 @@ recv_recovery_from_checkpoint_start(
recv_synchronize_groups(up_to_date_group); recv_synchronize_groups(up_to_date_group);
if (!recv_needed_recovery) { if (!recv_needed_recovery) {
ut_a(ut_dulint_cmp(checkpoint_lsn, ut_a(ut_dulint_cmp(checkpoint_lsn,
recv_sys->recovered_lsn) == 0); recv_sys->recovered_lsn) == 0);
} else { } else {
......
...@@ -655,6 +655,8 @@ row_create_prebuilt( ...@@ -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 @@ row_truncate_table_for_mysql( ...@@ -2894,6 +2896,8 @@ row_truncate_table_for_mysql(
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( ...@@ -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( ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment