diff options
author | Marko Mäkelä <marko.makela@oracle.com> | 2010-05-14 16:02:28 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@oracle.com> | 2010-05-14 16:02:28 +0300 |
commit | c3c2279cbd8427f29c3e884336b154ddf0a803c7 (patch) | |
tree | f222db304a15efa12714a2ba4e44ec27195aa5f8 /storage | |
parent | 162ab29157201ca075fccd405bb23f2626a11a9c (diff) | |
download | mariadb-git-c3c2279cbd8427f29c3e884336b154ddf0a803c7.tar.gz |
Make the InnoDB FOREIGN KEY parser understand multi-statements. (Bug #48024)
Also make InnoDB thinks that /*/ only starts a comment. (Bug #53644).
struct trx_struct: Add mysql_query_len.
ha_innodb.cc: Use trx_query_string() instead of trx_query() and
initialize trx->mysql_query_len.
INNOBASE_COPY_STMT(thd, trx): New macro, to initialize
trx->mysql_query_str and trx->mysql_query_len.
dict_strip_comments(): Add and observe the parameter sql_length. Treat
/*/ as the start of a comment.
dict_create_foreign_constraints(), row_table_add_foreign_constraints():
Add the parameter sql_length.
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/dict/dict0dict.c | 48 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 25 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.h | 2 | ||||
-rw-r--r-- | storage/innobase/include/dict0dict.h | 1 | ||||
-rw-r--r-- | storage/innobase/include/row0mysql.h | 1 | ||||
-rw-r--r-- | storage/innobase/include/trx0trx.h | 2 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.c | 5 | ||||
-rw-r--r-- | storage/innobase/trx/trx0trx.c | 3 |
8 files changed, 58 insertions, 29 deletions
diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index b8251a99105..d3b277d2d7a 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -2586,25 +2586,28 @@ dict_strip_comments( /* out, own: SQL string stripped from comments; the caller must free this with mem_free()! */ - const char* sql_string) /* in: SQL string */ + const char* sql_string, /* in: SQL string */ + size_t sql_length) /* in: length of sql_string */ { char* str; const char* sptr; + const char* eptr = sql_string + sql_length; char* ptr; /* unclosed quote character (0 if none) */ char quote = 0; - str = mem_alloc(strlen(sql_string) + 1); + str = mem_alloc(sql_length + 1); sptr = sql_string; ptr = str; for (;;) { scan_more: - if (*sptr == '\0') { + if (sptr >= eptr || *sptr == '\0') { +end_of_string: *ptr = '\0'; - ut_a(ptr <= str + strlen(sql_string)); + ut_a(ptr <= str + sql_length); return(str); } @@ -2623,30 +2626,35 @@ scan_more: || (sptr[0] == '-' && sptr[1] == '-' && sptr[2] == ' ')) { for (;;) { + if (++sptr >= eptr) { + goto end_of_string; + } + /* In Unix a newline is 0x0A while in Windows it is 0x0D followed by 0x0A */ - if (*sptr == (char)0x0A - || *sptr == (char)0x0D - || *sptr == '\0') { - + switch (*sptr) { + case (char) 0X0A: + case (char) 0x0D: + case '\0': goto scan_more; } - - sptr++; } } else if (!quote && *sptr == '/' && *(sptr + 1) == '*') { + sptr += 2; for (;;) { - if (*sptr == '*' && *(sptr + 1) == '/') { - - sptr += 2; - - goto scan_more; + if (sptr >= eptr) { + goto end_of_string; } - if (*sptr == '\0') { - + switch (*sptr) { + case '\0': goto scan_more; + case '*': + if (sptr[1] == '/') { + sptr += 2; + goto scan_more; + } } sptr++; @@ -3348,6 +3356,7 @@ dict_create_foreign_constraints( name before it: test.table2; the default database id the database of parameter name */ + size_t sql_length, /* in: length of sql_string */ const char* name, /* in: table full name in the normalized form database_name/table_name */ @@ -3362,7 +3371,7 @@ dict_create_foreign_constraints( ut_a(trx); ut_a(trx->mysql_thd); - str = dict_strip_comments(sql_string); + str = dict_strip_comments(sql_string, sql_length); heap = mem_heap_create(10000); err = dict_create_foreign_constraints_low( @@ -3411,7 +3420,8 @@ dict_foreign_parse_drop_constraints( *constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*)); - str = dict_strip_comments(*(trx->mysql_query_str)); + str = dict_strip_comments(*trx->mysql_query_str, + *trx->mysql_query_len); ptr = str; ut_ad(mutex_own(&(dict_sys->mutex))); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ebf01fbc296..f2a6c52ce7b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1140,6 +1140,15 @@ innobase_next_autoinc( return(next_value); } +/** Copy the current SQL statement. +* @param[in] thd MySQL client connection +* @param[in/out] trx InnoDB transaction */ +#define INNOBASE_COPY_STMT(thd, trx) do { \ + LEX_STRING* stmt = thd_query_string(thd); \ + (trx)->mysql_query_str = &stmt->str; \ + (trx)->mysql_query_len = &stmt->length; \ +} while (0) + /************************************************************************* Gets the InnoDB transaction handle for a MySQL handler object, creates an InnoDB transaction struct if the corresponding MySQL thread struct still @@ -1160,7 +1169,7 @@ check_trx_exists( trx = trx_allocate_for_mysql(); trx->mysql_thd = thd; - trx->mysql_query_str = thd_query(thd); + INNOBASE_COPY_STMT(thd, trx); /* Update the info whether we should skip XA steps that eat CPU time */ @@ -5578,7 +5587,7 @@ ha_innobase::create( trx = trx_allocate_for_mysql(); trx->mysql_thd = thd; - trx->mysql_query_str = thd_query(thd); + INNOBASE_COPY_STMT(thd, trx); if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) { trx->check_foreigns = FALSE; @@ -5674,8 +5683,10 @@ ha_innobase::create( } if (*trx->mysql_query_str) { - error = row_table_add_foreign_constraints(trx, - *trx->mysql_query_str, norm_name, + error = row_table_add_foreign_constraints( + trx, + *trx->mysql_query_str, *trx->mysql_query_len, + norm_name, create_info->options & HA_LEX_CREATE_TMP_TABLE); error = convert_error_code_to_mysql(error, NULL); @@ -5866,7 +5877,7 @@ ha_innobase::delete_table( trx = trx_allocate_for_mysql(); trx->mysql_thd = thd; - trx->mysql_query_str = thd_query(thd); + INNOBASE_COPY_STMT(thd, trx); if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) { trx->check_foreigns = FALSE; @@ -5955,7 +5966,7 @@ innobase_drop_database( #endif trx = trx_allocate_for_mysql(); trx->mysql_thd = thd; - trx->mysql_query_str = thd_query(thd); + INNOBASE_COPY_STMT(thd, trx); if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) { trx->check_foreigns = FALSE; @@ -6025,7 +6036,7 @@ ha_innobase::rename_table( trx = trx_allocate_for_mysql(); trx->mysql_thd = thd; - trx->mysql_query_str = thd_query(thd); + INNOBASE_COPY_STMT(thd, trx); if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) { trx->check_foreigns = FALSE; diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 5b3df16875a..eb9199b8955 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -210,7 +210,7 @@ the definitions are bracketed with #ifdef INNODB_COMPATIBILITY_HOOKS */ extern "C" { struct charset_info_st *thd_charset(MYSQL_THD thd); -char **thd_query(MYSQL_THD thd); +LEX_STRING *thd_query_string(MYSQL_THD thd); /** Get the file name of the MySQL binlog. * @return the name of the binlog file diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 7d5ff09c7a6..e76f23d0767 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -309,6 +309,7 @@ dict_create_foreign_constraints( name before it: test.table2; the default database id the database of parameter name */ + size_t sql_length, /* in: length of sql_string */ const char* name, /* in: table full name in the normalized form database_name/table_name */ diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 5430190fa51..40fcdbb9548 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -366,6 +366,7 @@ row_table_add_foreign_constraints( FOREIGN KEY (a, b) REFERENCES table2(c, d), table2 can be written also with the database name before it: test.table2 */ + size_t sql_length, /* in: length of sql_string */ const char* name, /* in: table full name in the normalized form database_name/table_name */ diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index cdbf1970715..97a47d9f46e 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -444,6 +444,8 @@ struct trx_struct{ char** mysql_query_str;/* pointer to the field in mysqld_thd which contains the pointer to the current SQL query string */ + size_t* mysql_query_len;/* pointer to the length of the + current SQL query string */ const char* mysql_log_file_name; /* if MySQL binlog is used, this field contains a pointer to the latest file diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index a0e0ee99775..20fb69499a1 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -2103,6 +2103,7 @@ row_table_add_foreign_constraints( FOREIGN KEY (a, b) REFERENCES table2(c, d), table2 can be written also with the database name before it: test.table2 */ + size_t sql_length, /* in: length of sql_string */ const char* name, /* in: table full name in the normalized form database_name/table_name */ @@ -2124,8 +2125,8 @@ row_table_add_foreign_constraints( trx->dict_operation = TRUE; - err = dict_create_foreign_constraints(trx, sql_string, name, - reject_fks); + err = dict_create_foreign_constraints(trx, sql_string, sql_length, + name, reject_fks); if (err == DB_SUCCESS) { /* Check that also referencing constraints are ok */ diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c index fae479feddc..545226a5994 100644 --- a/storage/innobase/trx/trx0trx.c +++ b/storage/innobase/trx/trx0trx.c @@ -131,6 +131,8 @@ trx_create( trx->mysql_thd = NULL; trx->mysql_query_str = NULL; + trx->mysql_query_len = NULL; + trx->active_trans = 0; trx->duplicates = 0; @@ -936,6 +938,7 @@ trx_commit_off_kernel( trx->undo_no = ut_dulint_zero; trx->last_sql_stat_start.least_undo_no = ut_dulint_zero; trx->mysql_query_str = NULL; + trx->mysql_query_len = NULL; ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0); ut_ad(UT_LIST_GET_LEN(trx->trx_locks) == 0); |