diff options
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r-- | sql/sql_parse.cc | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4d9930535a7..afc4e31f3cd 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1960,7 +1960,91 @@ mysql_execute_command(THD *thd) } break; } - + case SQLCOM_PREPARE: + { + char *stmt_name= lex->prepared_stmt_name.str; + uint name_len= lex->prepared_stmt_name.length; + Prepared_statement *stmt; + SQL_PREP_STMT_ENTRY *entry; + DBUG_PRINT("info", ("PREPARE: %.*s FROM '%.*s' \n", name_len, stmt_name, + lex->prepared_stmt_code.length, + lex->prepared_stmt_code.str)); + if ((entry=(SQL_PREP_STMT_ENTRY*)hash_search(&thd->sql_prepared_stmts, + (byte*)stmt_name, name_len))) + { + /* Free the statement with the same name and reuse hash entry */ + thd->stmt_map.erase((Statement*)entry->stmt); + } + else + { + uint size=ALIGN_SIZE(sizeof(SQL_PREP_STMT_ENTRY))+name_len+1; + if (!hash_inited(&thd->sql_prepared_stmts) || + !(entry= (SQL_PREP_STMT_ENTRY*)my_malloc(size,MYF(MY_WME)))) + { + send_error(thd, ER_OUT_OF_RESOURCES); + break; + } + entry->name.str= (char*)entry + ALIGN_SIZE(sizeof(SQL_PREP_STMT_ENTRY)); + entry->name.length= name_len; + memcpy(entry->name.str, stmt_name, name_len+1); + if (my_hash_insert(&thd->sql_prepared_stmts, (byte*)entry)) + { + my_free((char*)entry,MYF(0)); + send_error(thd, ER_OUT_OF_RESOURCES); + break; + } + } + /* Pretend this is a COM_PREPARE query so parser allows placeholders etc*/ + thd->command= COM_PREPARE; + /* 'length+1' is for alloc_query that strips the last character */ + stmt= mysql_stmt_prepare(thd, lex->prepared_stmt_code.str, + lex->prepared_stmt_code.length + 1, true); + if (stmt) + { + entry->stmt= stmt; + send_ok(thd, 0L, 0L, "Statement prepared"); + } + else + hash_delete(&thd->sql_prepared_stmts, (byte*)entry); + break; + } + case SQLCOM_EXECUTE: + { + char *stmt_name= lex->prepared_stmt_name.str; + uint name_len= lex->prepared_stmt_name.length; + SQL_PREP_STMT_ENTRY *entry; + DBUG_PRINT("info", ("EXECUTE: %.*s\n", name_len, stmt_name)); + + if (!(entry= (SQL_PREP_STMT_ENTRY*)hash_search(&thd->sql_prepared_stmts, + (byte*)stmt_name, + name_len))) + { + send_error(thd, ER_UNKNOWN_STMT_HANDLER, "Undefined prepared statement"); + lex->prepared_stmt_params.empty(); + break; + } + mysql_sql_stmt_execute(thd, entry->stmt); + lex->prepared_stmt_params.empty(); + break; + } + case SQLCOM_DEALLOCATE_PREPARE: + { + char *stmt_name= lex->prepared_stmt_name.str; + uint name_len= lex->prepared_stmt_name.length; + SQL_PREP_STMT_ENTRY *entry; + DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n", name_len, stmt_name)); + if (!(entry= (SQL_PREP_STMT_ENTRY*)hash_search(&thd->sql_prepared_stmts, + (byte*)stmt_name, + name_len))) + { + send_error(thd, ER_UNKNOWN_STMT_HANDLER, "Undefined prepared statement"); + break; + } + thd->stmt_map.erase((Statement*)entry->stmt); + hash_delete(&thd->sql_prepared_stmts, (byte*)entry); + send_ok(thd); + break; + } case SQLCOM_DO: if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) || (res= open_and_lock_tables(thd,tables)))) |