diff options
author | Alexey Botchkov <holyfoot@askmonty.org> | 2016-01-26 16:00:59 +0400 |
---|---|---|
committer | Alexey Botchkov <holyfoot@askmonty.org> | 2016-01-26 23:18:13 +0400 |
commit | df2695495188b0c3459eabb40c8e390f56cddb27 (patch) | |
tree | b0262db29ac4475b5f9065e6a6294a702a894e27 /sql | |
parent | a095c99301a0acac9b2db9b294f24a8753ebed48 (diff) | |
download | mariadb-git-df2695495188b0c3459eabb40c8e390f56cddb27.tar.gz |
MDEV-5273 Prepared statement doesn't return metadata after prepare.
The metadata creation part of the mysqld_shww_create separated
to be used on the mysqld_stmt_prepare stage.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_prepare.cc | 46 | ||||
-rw-r--r-- | sql/sql_show.cc | 90 | ||||
-rw-r--r-- | sql/sql_show.h | 2 |
3 files changed, 109 insertions, 29 deletions
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 55f05c3762c..e9ffac39352 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -103,6 +103,7 @@ When one supplies long data for a placeholder: #include "sql_derived.h" // mysql_derived_prepare, // mysql_handle_derived #include "sql_cursor.h" +#include "sql_show.h" #include "sp_head.h" #include "sp.h" #include "sp_cache.h" @@ -1812,6 +1813,42 @@ static bool mysql_test_create_table(Prepared_statement *stmt) /** + Validate and prepare for execution CREATE TABLE statement. + + @param stmt prepared statement + @param tables list of tables used in this query + + @retval + FALSE success + @retval + TRUE error, error message is set in THD +*/ + +static int mysql_test_show_create_table(Prepared_statement *stmt, + TABLE_LIST *tables) +{ + DBUG_ENTER("mysql_test_show_create_table"); + THD *thd= stmt->thd; + List<Item> fields; + char buff[2048]; + String buffer(buff, sizeof(buff), system_charset_info); + + if (mysqld_show_create_get_fields(thd, tables, &fields, &buffer)) + goto err_exit; + + if (send_prep_stmt(stmt, fields.elements) || + thd->protocol->send_result_set_metadata(&fields, Protocol::SEND_EOF) || + thd->protocol->flush()) + goto err_exit; + + DBUG_RETURN(2); + +err_exit: + DBUG_RETURN(1); +} + + +/** @brief Validate and prepare for execution CREATE VIEW statement @param stmt prepared statement @@ -2144,7 +2181,14 @@ static bool check_prepared_statement(Prepared_statement *stmt) case SQLCOM_CREATE_TABLE: res= mysql_test_create_table(stmt); break; - + case SQLCOM_SHOW_CREATE: + res= mysql_test_show_create_table(stmt, tables); + if (res == 2) + { + /* Statement and field info has already been sent */ + DBUG_RETURN(FALSE); + } + break; case SQLCOM_CREATE_VIEW: if (lex->create_view_mode == VIEW_ALTER) { diff --git a/sql/sql_show.cc b/sql/sql_show.cc index dd7a71f15fa..b2bf5a9ffb0 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1092,39 +1092,29 @@ public: /* - Return CREATE command for table or view + Return metadata for CREATE command for table or view @param thd Thread handler @param table_list Table / view + @param field_list resulting list of fields + @param buffer resulting CREATE statement @return @retval 0 OK @retval 1 Error - @notes - table_list->db and table_list->table_name are kept unchanged to - not cause problems with SP. */ bool -mysqld_show_create(THD *thd, TABLE_LIST *table_list) +mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list, + List<Item> *field_list, String *buffer) { - Protocol *protocol= thd->protocol; - char buff[2048]; - String buffer(buff, sizeof(buff), system_charset_info); - List<Item> field_list; bool error= TRUE; MEM_ROOT *mem_root= thd->mem_root; - DBUG_ENTER("mysqld_show_create"); + DBUG_ENTER("mysqld_show_create_get_fields"); DBUG_PRINT("enter",("db: %s table: %s",table_list->db, table_list->table_name)); - /* - Metadata locks taken during SHOW CREATE should be released when - the statmement completes as it is an information statement. - */ - MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint(); - /* We want to preserve the tree for views. */ thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW; @@ -1155,45 +1145,89 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) goto exit; } - buffer.length(0); + buffer->length(0); if (table_list->view) - buffer.set_charset(table_list->view_creation_ctx->get_client_cs()); + buffer->set_charset(table_list->view_creation_ctx->get_client_cs()); if ((table_list->view ? - show_create_view(thd, table_list, &buffer) : - show_create_table(thd, table_list, &buffer, NULL, WITHOUT_DB_NAME))) + show_create_view(thd, table_list, buffer) : + show_create_table(thd, table_list, buffer, NULL, WITHOUT_DB_NAME))) goto exit; if (table_list->view) { - field_list.push_back(new (mem_root) + field_list->push_back(new (mem_root) Item_empty_string(thd, "View", NAME_CHAR_LEN), mem_root); - field_list.push_back(new (mem_root) + field_list->push_back(new (mem_root) Item_empty_string(thd, "Create View", - MY_MAX(buffer.length(),1024)), + MY_MAX(buffer->length(),1024)), mem_root); - field_list.push_back(new (mem_root) + field_list->push_back(new (mem_root) Item_empty_string(thd, "character_set_client", MY_CS_NAME_SIZE), mem_root); - field_list.push_back(new (mem_root) + field_list->push_back(new (mem_root) Item_empty_string(thd, "collation_connection", MY_CS_NAME_SIZE), mem_root); } else { - field_list.push_back(new (mem_root) + field_list->push_back(new (mem_root) Item_empty_string(thd, "Table", NAME_CHAR_LEN), mem_root); // 1024 is for not to confuse old clients - field_list.push_back(new (mem_root) + field_list->push_back(new (mem_root) Item_empty_string(thd, "Create Table", - MY_MAX(buffer.length(),1024)), + MY_MAX(buffer->length(),1024)), mem_root); } + error= FALSE; + +exit: + DBUG_RETURN(error); +} + + +/* + Return CREATE command for table or view + + @param thd Thread handler + @param table_list Table / view + + @return + @retval 0 OK + @retval 1 Error + + @notes + table_list->db and table_list->table_name are kept unchanged to + not cause problems with SP. +*/ + +bool +mysqld_show_create(THD *thd, TABLE_LIST *table_list) +{ + Protocol *protocol= thd->protocol; + char buff[2048]; + String buffer(buff, sizeof(buff), system_charset_info); + List<Item> field_list; + bool error= TRUE; + MEM_ROOT *mem_root= thd->mem_root; + DBUG_ENTER("mysqld_show_create"); + DBUG_PRINT("enter",("db: %s table: %s",table_list->db, + table_list->table_name)); + + /* + Metadata locks taken during SHOW CREATE should be released when + the statmement completes as it is an information statement. + */ + MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint(); + + + if (mysqld_show_create_get_fields(thd, table_list, &field_list, &buffer)) + goto exit; if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | diff --git a/sql/sql_show.h b/sql/sql_show.h index 029249f4129..06ff909733a 100644 --- a/sql/sql_show.h +++ b/sql/sql_show.h @@ -85,6 +85,8 @@ bool append_identifier(THD *thd, String *packet, const char *name, uint length); void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild); int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd); +bool mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list, + List<Item> *field_list, String *buffer); bool mysqld_show_create(THD *thd, TABLE_LIST *table_list); bool mysqld_show_create_db(THD *thd, LEX_STRING *db_name, LEX_STRING *orig_db_name, |