diff options
author | unknown <karen.langford@oracle.com> | 2011-02-08 12:52:33 +0100 |
---|---|---|
committer | Karen Langford <karen.langford@oracle.com> | 2011-02-08 12:52:33 +0100 |
commit | 17fe23e46c32be51014da82e01bfd43a783d2c48 (patch) | |
tree | 07f8c2be8340694279693caa7339c671b43cb30e /storage/innodb_plugin | |
parent | 994132add6118b8d91893d495a8cb628c1017da4 (diff) | |
parent | de3c4428b8c759e85631d8d70b5845c872de5400 (diff) | |
download | mariadb-git-17fe23e46c32be51014da82e01bfd43a783d2c48.tar.gz |
Merge from mysql-5.1.55-release
Diffstat (limited to 'storage/innodb_plugin')
-rw-r--r-- | storage/innodb_plugin/ChangeLog | 10 | ||||
-rw-r--r-- | storage/innodb_plugin/dict/dict0dict.c | 10 | ||||
-rw-r--r-- | storage/innodb_plugin/handler/ha_innodb.cc | 10 | ||||
-rw-r--r-- | storage/innodb_plugin/handler/i_s.cc | 11 | ||||
-rw-r--r-- | storage/innodb_plugin/include/univ.i | 12 | ||||
-rw-r--r-- | storage/innodb_plugin/include/ut0vec.h | 19 | ||||
-rw-r--r-- | storage/innodb_plugin/include/ut0vec.ic | 29 | ||||
-rw-r--r-- | storage/innodb_plugin/lock/lock0lock.c | 78 | ||||
-rw-r--r-- | storage/innodb_plugin/row/row0merge.c | 4 |
9 files changed, 163 insertions, 20 deletions
diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 18ab48f32a5..3d8057fd3e1 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -50,6 +50,16 @@ bad "rows examined" estimates 2011-01-06 The InnoDB Team + * row/row0merge.c: + Fix Bug#59312 Examine MAX_FULL_NAME_LEN in InnoDB to address + possible insufficient name buffer + +2011-01-06 The InnoDB Team + * dict/dict0dict.c, handler/ha_innodb.cc, handler/i_s.cc, + include/univ.i: + Fix Bug#58643 InnoDB: too long table name + +2011-01-06 The InnoDB Team * handler/i_s.cc, include/trx0i_s.h, trx/trx0i_s.c: Fix Bug#55397 cannot select from innodb_trx when trx_query contains blobs that aren't strings diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c index ff56e9cb76a..a8787bbda61 100644 --- a/storage/innodb_plugin/dict/dict0dict.c +++ b/storage/innodb_plugin/dict/dict0dict.c @@ -932,7 +932,7 @@ dict_table_rename_in_cache( dict_foreign_t* foreign; dict_index_t* index; ulint fold; - char old_name[MAX_TABLE_NAME_LEN + 1]; + char old_name[MAX_FULL_NAME_LEN + 1]; ut_ad(table); ut_ad(mutex_own(&(dict_sys->mutex))); @@ -944,7 +944,7 @@ dict_table_rename_in_cache( ut_print_timestamp(stderr); fprintf(stderr, "InnoDB: too long table name: '%s', " "max length is %d\n", table->name, - MAX_TABLE_NAME_LEN); + MAX_FULL_NAME_LEN); ut_error; } @@ -994,11 +994,11 @@ dict_table_rename_in_cache( ut_fold_string(old_name), table); if (strlen(new_name) > strlen(table->name)) { - /* We allocate MAX_TABLE_NAME_LEN+1 bytes here to avoid + /* We allocate MAX_FULL_NAME_LEN + 1 bytes here to avoid memory fragmentation, we assume a repeated calls of ut_realloc() with the same size do not cause fragmentation */ - ut_a(strlen(new_name) <= MAX_TABLE_NAME_LEN); - table->name = ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1); + ut_a(strlen(new_name) <= MAX_FULL_NAME_LEN); + table->name = ut_realloc(table->name, MAX_FULL_NAME_LEN + 1); } memcpy(table->name, new_name, strlen(new_name) + 1); diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 2d60c7397b0..dda2fbaa4d2 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -6028,6 +6028,16 @@ create_table_def( DBUG_RETURN(HA_ERR_GENERIC); } + /* MySQL does the name length check. But we do additional check + on the name length here */ + if (strlen(table_name) > MAX_FULL_NAME_LEN) { + push_warning_printf( + (THD*) trx->mysql_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TABLE_NAME, + "InnoDB: Table Name or Database Name is too long"); + DBUG_RETURN(ER_TABLE_NAME); + } + n_cols = form->s->fields; /* We pass 0 as the space id, and determine at a lower level the space diff --git a/storage/innodb_plugin/handler/i_s.cc b/storage/innodb_plugin/handler/i_s.cc index 24996496b0c..b0149967e9b 100644 --- a/storage/innodb_plugin/handler/i_s.cc +++ b/storage/innodb_plugin/handler/i_s.cc @@ -587,16 +587,7 @@ fill_innodb_locks_from_cache( for (i = 0; i < rows_num; i++) { i_s_locks_row_t* row; - - /* note that the decoded database or table name is - never expected to be longer than NAME_LEN; - NAME_LEN for database name - 2 for surrounding quotes around database name - NAME_LEN for table name - 2 for surrounding quotes around table name - 1 for the separating dot (.) - 9 for the #mysql50# prefix */ - char buf[2 * NAME_LEN + 14]; + char buf[MAX_FULL_NAME_LEN + 1]; const char* bufend; char lock_trx_id[TRX_ID_MAX_LEN + 1]; diff --git a/storage/innodb_plugin/include/univ.i b/storage/innodb_plugin/include/univ.i index 4425950748b..ffb927214bb 100644 --- a/storage/innodb_plugin/include/univ.i +++ b/storage/innodb_plugin/include/univ.i @@ -296,6 +296,18 @@ number does not include a terminating '\0'. InnoDB probably can handle longer names internally */ #define MAX_TABLE_NAME_LEN 192 +/* The maximum length of a database name. Like MAX_TABLE_NAME_LEN this is +the MySQL's NAME_LEN, see check_and_convert_db_name(). */ +#define MAX_DATABASE_NAME_LEN MAX_TABLE_NAME_LEN + +/* MAX_FULL_NAME_LEN defines the full name path including the +database name and table name. In addition, 14 bytes is added for: + 2 for surrounding quotes around table name + 1 for the separating dot (.) + 9 for the #mysql50# prefix */ +#define MAX_FULL_NAME_LEN \ + (MAX_TABLE_NAME_LEN + MAX_DATABASE_NAME_LEN + 14) + /* UNIVERSAL TYPE DEFINITIONS ========================== diff --git a/storage/innodb_plugin/include/ut0vec.h b/storage/innodb_plugin/include/ut0vec.h index a770f671cfc..0f8b955b098 100644 --- a/storage/innodb_plugin/include/ut0vec.h +++ b/storage/innodb_plugin/include/ut0vec.h @@ -94,6 +94,25 @@ ib_vector_get( ulint n); /*!< in: element index to get */ /****************************************************************//** +Get last element. The vector must not be empty. +@return last element */ +UNIV_INLINE +void* +ib_vector_get_last( +/*===============*/ + ib_vector_t* vec); /*!< in: vector */ + +/****************************************************************//** +Set the n'th element. */ +UNIV_INLINE +void +ib_vector_set( +/*==========*/ + ib_vector_t* vec, /*!< in/out: vector */ + ulint n, /*!< in: element index to set */ + void* elem); /*!< in: data element */ + +/****************************************************************//** Remove the last element from the vector. */ UNIV_INLINE void* diff --git a/storage/innodb_plugin/include/ut0vec.ic b/storage/innodb_plugin/include/ut0vec.ic index 02e881f9bca..34c858868ce 100644 --- a/storage/innodb_plugin/include/ut0vec.ic +++ b/storage/innodb_plugin/include/ut0vec.ic @@ -51,6 +51,35 @@ ib_vector_get( } /****************************************************************//** +Get last element. The vector must not be empty. +@return last element */ +UNIV_INLINE +void* +ib_vector_get_last( +/*===============*/ + ib_vector_t* vec) /*!< in: vector */ +{ + ut_a(vec->used > 0); + + return(vec->data[vec->used - 1]); +} + +/****************************************************************//** +Set the n'th element. */ +UNIV_INLINE +void +ib_vector_set( +/*==========*/ + ib_vector_t* vec, /*!< in/out: vector */ + ulint n, /*!< in: element index to set */ + void* elem) /*!< in: data element */ +{ + ut_a(n < vec->used); + + vec->data[n] = elem; +} + +/****************************************************************//** Remove the last element from the vector. @return last vector element */ UNIV_INLINE diff --git a/storage/innodb_plugin/lock/lock0lock.c b/storage/innodb_plugin/lock/lock0lock.c index 77d69d11a2d..c8bbc5c02bd 100644 --- a/storage/innodb_plugin/lock/lock0lock.c +++ b/storage/innodb_plugin/lock/lock0lock.c @@ -3625,6 +3625,80 @@ lock_table_create( } /*************************************************************//** +Pops autoinc lock requests from the transaction's autoinc_locks. We +handle the case where there are gaps in the array and they need to +be popped off the stack. */ +UNIV_INLINE +void +lock_table_pop_autoinc_locks( +/*=========================*/ + trx_t* trx) /*!< in/out: transaction that owns the AUTOINC locks */ +{ + ut_ad(mutex_own(&kernel_mutex)); + ut_ad(!ib_vector_is_empty(trx->autoinc_locks)); + + /* Skip any gaps, gaps are NULL lock entries in the + trx->autoinc_locks vector. */ + + do { + ib_vector_pop(trx->autoinc_locks); + + if (ib_vector_is_empty(trx->autoinc_locks)) { + return; + } + + } while (ib_vector_get_last(trx->autoinc_locks) == NULL); +} + +/*************************************************************//** +Removes an autoinc lock request from the transaction's autoinc_locks. */ +UNIV_INLINE +void +lock_table_remove_autoinc_lock( +/*===========================*/ + lock_t* lock, /*!< in: table lock */ + trx_t* trx) /*!< in/out: transaction that owns the lock */ +{ + lock_t* autoinc_lock; + lint i = ib_vector_size(trx->autoinc_locks) - 1; + + ut_ad(mutex_own(&kernel_mutex)); + ut_ad(lock_get_mode(lock) == LOCK_AUTO_INC); + ut_ad(lock_get_type_low(lock) & LOCK_TABLE); + ut_ad(!ib_vector_is_empty(trx->autoinc_locks)); + + /* With stored functions and procedures the user may drop + a table within the same "statement". This special case has + to be handled by deleting only those AUTOINC locks that were + held by the table being dropped. */ + + autoinc_lock = ib_vector_get(trx->autoinc_locks, i); + + /* This is the default fast case. */ + + if (autoinc_lock == lock) { + lock_table_pop_autoinc_locks(trx); + } else { + /* The last element should never be NULL */ + ut_a(autoinc_lock != NULL); + + /* Handle freeing the locks from within the stack. */ + + while (--i >= 0) { + autoinc_lock = ib_vector_get(trx->autoinc_locks, i); + + if (UNIV_LIKELY(autoinc_lock == lock)) { + ib_vector_set(trx->autoinc_locks, i, NULL); + return; + } + } + + /* Must find the autoinc lock. */ + ut_error; + } +} + +/*************************************************************//** Removes a table lock request from the queue and the trx list of locks; this is a low-level function which does NOT check if waiting requests can now be granted. */ @@ -3663,10 +3737,8 @@ lock_table_remove_low( if (!lock_get_wait(lock) && !ib_vector_is_empty(trx->autoinc_locks)) { - lock_t* autoinc_lock; - autoinc_lock = ib_vector_pop(trx->autoinc_locks); - ut_a(autoinc_lock == lock); + lock_table_remove_autoinc_lock(lock, trx); } ut_a(table->n_waiting_or_granted_auto_inc_locks > 0); diff --git a/storage/innodb_plugin/row/row0merge.c b/storage/innodb_plugin/row/row0merge.c index 160edd32fbf..647d0031635 100644 --- a/storage/innodb_plugin/row/row0merge.c +++ b/storage/innodb_plugin/row/row0merge.c @@ -2341,7 +2341,7 @@ row_merge_rename_tables( { ulint err = DB_ERROR; pars_info_t* info; - char old_name[MAX_TABLE_NAME_LEN + 1]; + char old_name[MAX_FULL_NAME_LEN + 1]; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_ad(old_table != new_table); @@ -2356,7 +2356,7 @@ row_merge_rename_tables( ut_print_timestamp(stderr); fprintf(stderr, "InnoDB: too long table name: '%s', " "max length is %d\n", old_table->name, - MAX_TABLE_NAME_LEN); + MAX_FULL_NAME_LEN); ut_error; } |