summaryrefslogtreecommitdiff
path: root/storage/innodb_plugin
diff options
context:
space:
mode:
authorunknown <karen.langford@oracle.com>2011-02-08 12:52:33 +0100
committerKaren Langford <karen.langford@oracle.com>2011-02-08 12:52:33 +0100
commit17fe23e46c32be51014da82e01bfd43a783d2c48 (patch)
tree07f8c2be8340694279693caa7339c671b43cb30e /storage/innodb_plugin
parent994132add6118b8d91893d495a8cb628c1017da4 (diff)
parentde3c4428b8c759e85631d8d70b5845c872de5400 (diff)
downloadmariadb-git-17fe23e46c32be51014da82e01bfd43a783d2c48.tar.gz
Merge from mysql-5.1.55-release
Diffstat (limited to 'storage/innodb_plugin')
-rw-r--r--storage/innodb_plugin/ChangeLog10
-rw-r--r--storage/innodb_plugin/dict/dict0dict.c10
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.cc10
-rw-r--r--storage/innodb_plugin/handler/i_s.cc11
-rw-r--r--storage/innodb_plugin/include/univ.i12
-rw-r--r--storage/innodb_plugin/include/ut0vec.h19
-rw-r--r--storage/innodb_plugin/include/ut0vec.ic29
-rw-r--r--storage/innodb_plugin/lock/lock0lock.c78
-rw-r--r--storage/innodb_plugin/row/row0merge.c4
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;
}