diff options
Diffstat (limited to 'sql/sql_prepare.cc')
-rw-r--r-- | sql/sql_prepare.cc | 743 |
1 files changed, 0 insertions, 743 deletions
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 64e4cd30561..32a3ab87006 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -204,7 +204,6 @@ public: bool execute_bulk_loop(String *expanded_query, bool open_cursor, uchar *packet_arg, uchar *packet_end_arg); - bool execute_server_runnable(Server_runnable *server_runnable); my_bool set_bulk_parameters(bool reset); bool bulk_iterations() { return iterations; }; /* Destroy this statement */ @@ -228,78 +227,6 @@ private: void swap_prepared_statement(Prepared_statement *copy); }; -/** - Execute one SQL statement in an isolated context. -*/ - -class Execute_sql_statement: public Server_runnable -{ -public: - Execute_sql_statement(LEX_STRING sql_text); - virtual bool execute_server_code(THD *thd); -private: - LEX_STRING m_sql_text; -}; - - -class Ed_connection; - -/** - Protocol_local: a helper class to intercept the result - of the data written to the network. -*/ - -class Protocol_local :public Protocol -{ -public: - Protocol_local(THD *thd, Ed_connection *ed_connection); - ~Protocol_local() { free_root(&m_rset_root, MYF(0)); } -protected: - virtual void prepare_for_resend(); - virtual bool write(); - virtual bool store_null(); - virtual bool store_tiny(longlong from); - virtual bool store_short(longlong from); - virtual bool store_long(longlong from); - virtual bool store_longlong(longlong from, bool unsigned_flag); - virtual bool store_decimal(const my_decimal *); - virtual bool store(const char *from, size_t length, CHARSET_INFO *cs); - virtual bool store(const char *from, size_t length, - CHARSET_INFO *fromcs, CHARSET_INFO *tocs); - virtual bool store(MYSQL_TIME *time, int decimals); - virtual bool store_date(MYSQL_TIME *time); - virtual bool store_time(MYSQL_TIME *time, int decimals); - virtual bool store(float value, uint32 decimals, String *buffer); - virtual bool store(double value, uint32 decimals, String *buffer); - virtual bool store(Field *field); - - virtual bool send_result_set_metadata(List<Item> *list, uint flags); - virtual bool send_out_parameters(List<Item_param> *sp_params); -#ifdef EMBEDDED_LIBRARY - void remove_last_row(); -#endif - virtual enum enum_protocol_type type() { return PROTOCOL_LOCAL; }; - - virtual bool send_ok(uint server_status, uint statement_warn_count, - ulonglong affected_rows, ulonglong last_insert_id, - const char *message, bool skip_flush); - - virtual bool send_eof(uint server_status, uint statement_warn_count); - virtual bool send_error(uint sql_errno, const char *err_msg, const char* sqlstate); -private: - bool store_string(const char *str, size_t length, - CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs); - - bool store_column(const void *data, size_t length); - void opt_add_row_to_rset(); -private: - Ed_connection *m_connection; - MEM_ROOT m_rset_root; - List<Ed_row> *m_rset; - size_t m_column_count; - Ed_column *m_current_row; - Ed_column *m_current_column; -}; /****************************************************************************** Implementation @@ -3917,71 +3844,6 @@ Reprepare_observer::report_error(THD *thd) } -/******************************************************************* -* Server_runnable -*******************************************************************/ - -Server_runnable::~Server_runnable() -{ -} - -/////////////////////////////////////////////////////////////////////////// - -Execute_sql_statement:: -Execute_sql_statement(LEX_STRING sql_text) - :m_sql_text(sql_text) -{} - - -/** - Parse and execute a statement. Does not prepare the query. - - Allows to execute a statement from within another statement. - The main property of the implementation is that it does not - affect the environment -- i.e. you can run many - executions without having to cleanup/reset THD in between. -*/ - -bool -Execute_sql_statement::execute_server_code(THD *thd) -{ - PSI_statement_locker *parent_locker; - bool error; - - if (alloc_query(thd, m_sql_text.str, m_sql_text.length)) - return TRUE; - - Parser_state parser_state; - if (parser_state.init(thd, thd->query(), thd->query_length())) - return TRUE; - - parser_state.m_lip.multi_statements= FALSE; - lex_start(thd); - - error= parse_sql(thd, &parser_state, NULL) || thd->is_error(); - - if (error) - goto end; - - thd->lex->set_trg_event_type_for_tables(); - - parent_locker= thd->m_statement_psi; - thd->m_statement_psi= NULL; - error= mysql_execute_command(thd); - thd->m_statement_psi= parent_locker; - - /* report error issued during command execution */ - if (error == 0 && thd->spcont == NULL) - general_log_write(thd, COM_STMT_EXECUTE, - thd->query(), thd->query_length()); - -end: - thd->lex->restore_set_statement_var(); - lex_end(thd->lex); - - return error; -} - /*************************************************************************** Prepared_statement ****************************************************************************/ @@ -4727,40 +4589,6 @@ reexecute: } -bool -Prepared_statement::execute_server_runnable(Server_runnable *server_runnable) -{ - Statement stmt_backup; - bool error; - Query_arena *save_stmt_arena= thd->stmt_arena; - Item_change_list save_change_list; - thd->Item_change_list::move_elements_to(&save_change_list); - - state= STMT_CONVENTIONAL_EXECUTION; - - if (!(lex= new (mem_root) st_lex_local)) - return TRUE; - - thd->set_n_backup_statement(this, &stmt_backup); - thd->set_n_backup_active_arena(this, &stmt_backup); - thd->stmt_arena= this; - - error= server_runnable->execute_server_code(thd); - - thd->cleanup_after_query(); - - thd->restore_active_arena(this, &stmt_backup); - thd->restore_backup_statement(this, &stmt_backup); - thd->stmt_arena= save_stmt_arena; - - save_change_list.move_elements_to(thd); - - /* Items and memory will freed in destructor */ - - return error; -} - - /** Reprepare this prepared statement. @@ -5205,574 +5033,3 @@ void Prepared_statement::deallocate() /* Statement map calls delete stmt on erase */ thd->stmt_map.erase(this); } - - -/*************************************************************************** -* Ed_result_set -***************************************************************************/ -/** - Use operator delete to free memory of Ed_result_set. - Accessing members of a class after the class has been destroyed - is a violation of the C++ standard but is commonly used in the - server code. -*/ - -void Ed_result_set::operator delete(void *ptr, size_t size) throw () -{ - if (ptr) - { - /* - Make a stack copy, otherwise free_root() will attempt to - write to freed memory. - */ - MEM_ROOT own_root= ((Ed_result_set*) ptr)->m_mem_root; - free_root(&own_root, MYF(0)); - } -} - - -/** - Initialize an instance of Ed_result_set. - - Instances of the class, as well as all result set rows, are - always allocated in the memory root passed over as the second - argument. In the constructor, we take over ownership of the - memory root. It will be freed when the class is destroyed. - - sic: Ed_result_est is not designed to be allocated on stack. -*/ - -Ed_result_set::Ed_result_set(List<Ed_row> *rows_arg, - size_t column_count_arg, - MEM_ROOT *mem_root_arg) - :m_mem_root(*mem_root_arg), - m_column_count(column_count_arg), - m_rows(rows_arg), - m_next_rset(NULL) -{ - /* Take over responsibility for the memory */ - clear_alloc_root(mem_root_arg); -} - -/*************************************************************************** -* Ed_result_set -***************************************************************************/ - -/** - Create a new "execute direct" connection. -*/ - -Ed_connection::Ed_connection(THD *thd) - :m_diagnostics_area(thd->query_id, false, true), - m_thd(thd), - m_rsets(0), - m_current_rset(0) -{ -} - - -/** - Free all result sets of the previous statement, if any, - and reset warnings and errors. - - Called before execution of the next query. -*/ - -void -Ed_connection::free_old_result() -{ - while (m_rsets) - { - Ed_result_set *rset= m_rsets->m_next_rset; - delete m_rsets; - m_rsets= rset; - } - m_current_rset= m_rsets; - m_diagnostics_area.reset_diagnostics_area(); - m_diagnostics_area.clear_warning_info(m_thd->query_id); -} - - -/** - A simple wrapper that uses a helper class to execute SQL statements. -*/ - -bool -Ed_connection::execute_direct(LEX_STRING sql_text) -{ - Execute_sql_statement execute_sql_statement(sql_text); - DBUG_PRINT("ed_query", ("%s", sql_text.str)); - - return execute_direct(&execute_sql_statement); -} - - -/** - Execute a fragment of server functionality without an effect on - thd, and store results in memory. - - Conventions: - - the code fragment must finish with OK, EOF or ERROR. - - the code fragment doesn't have to close thread tables, - free memory, commit statement transaction or do any other - cleanup that is normally done in the end of dispatch_command(). - - @param server_runnable A code fragment to execute. -*/ - -bool Ed_connection::execute_direct(Server_runnable *server_runnable) -{ - bool rc= FALSE; - Protocol_local protocol_local(m_thd, this); - Prepared_statement stmt(m_thd); - Protocol *save_protocol= m_thd->protocol; - Diagnostics_area *save_diagnostics_area= m_thd->get_stmt_da(); - - DBUG_ENTER("Ed_connection::execute_direct"); - - free_old_result(); /* Delete all data from previous execution, if any */ - - m_thd->protocol= &protocol_local; - m_thd->set_stmt_da(&m_diagnostics_area); - - rc= stmt.execute_server_runnable(server_runnable); - m_thd->protocol->end_statement(); - - m_thd->protocol= save_protocol; - m_thd->set_stmt_da(save_diagnostics_area); - /* - Protocol_local makes use of m_current_rset to keep - track of the last result set, while adding result sets to the end. - Reset it to point to the first result set instead. - */ - m_current_rset= m_rsets; - - DBUG_RETURN(rc); -} - - -/** - A helper method that is called only during execution. - - Although Ed_connection doesn't support multi-statements, - a statement may generate many result sets. All subsequent - result sets are appended to the end. - - @pre This is called only by Protocol_local. -*/ - -void -Ed_connection::add_result_set(Ed_result_set *ed_result_set) -{ - if (m_rsets) - { - m_current_rset->m_next_rset= ed_result_set; - /* While appending, use m_current_rset as a pointer to the tail. */ - m_current_rset= ed_result_set; - } - else - m_current_rset= m_rsets= ed_result_set; -} - - -/** - Release ownership of the current result set to the client. - - Since we use a simple linked list for result sets, - this method uses a linear search of the previous result - set to exclude the released instance from the list. - - @todo Use double-linked list, when this is really used. - - XXX: This has never been tested with more than one result set! - - @pre There must be a result set. -*/ - -Ed_result_set * -Ed_connection::store_result_set() -{ - Ed_result_set *ed_result_set; - - DBUG_ASSERT(m_current_rset); - - if (m_current_rset == m_rsets) - { - /* Assign the return value */ - ed_result_set= m_current_rset; - /* Exclude the return value from the list. */ - m_current_rset= m_rsets= m_rsets->m_next_rset; - } - else - { - Ed_result_set *prev_rset= m_rsets; - /* Assign the return value. */ - ed_result_set= m_current_rset; - - /* Exclude the return value from the list */ - while (prev_rset->m_next_rset != m_current_rset) - prev_rset= ed_result_set->m_next_rset; - m_current_rset= prev_rset->m_next_rset= m_current_rset->m_next_rset; - } - ed_result_set->m_next_rset= NULL; /* safety */ - - return ed_result_set; -} - -/************************************************************************* -* Protocol_local -**************************************************************************/ - -Protocol_local::Protocol_local(THD *thd, Ed_connection *ed_connection) - :Protocol(thd), - m_connection(ed_connection), - m_rset(NULL), - m_column_count(0), - m_current_row(NULL), - m_current_column(NULL) -{ - clear_alloc_root(&m_rset_root); -} - -/** - Called between two result set rows. - - Prepare structures to fill result set rows. - Unfortunately, we can't return an error here. If memory allocation - fails, we'll have to return an error later. And so is done - in methods such as @sa store_column(). -*/ - -void Protocol_local::prepare_for_resend() -{ - DBUG_ASSERT(alloc_root_inited(&m_rset_root)); - - opt_add_row_to_rset(); - /* Start a new row. */ - m_current_row= (Ed_column *) alloc_root(&m_rset_root, - sizeof(Ed_column) * m_column_count); - m_current_column= m_current_row; -} - - -/** - In "real" protocols this is called to finish a result set row. - Unused in the local implementation. -*/ - -bool Protocol_local::write() -{ - return FALSE; -} - -/** - A helper function to add the current row to the current result - set. Called in @sa prepare_for_resend(), when a new row is started, - and in send_eof(), when the result set is finished. -*/ - -void Protocol_local::opt_add_row_to_rset() -{ - if (m_current_row) - { - /* Add the old row to the result set */ - Ed_row *ed_row= new (&m_rset_root) Ed_row(m_current_row, m_column_count); - if (ed_row) - m_rset->push_back(ed_row, &m_rset_root); - } -} - - -/** - Add a NULL column to the current row. -*/ - -bool Protocol_local::store_null() -{ - if (m_current_column == NULL) - return TRUE; /* prepare_for_resend() failed to allocate memory. */ - - bzero(m_current_column, sizeof(*m_current_column)); - ++m_current_column; - return FALSE; -} - - -/** - A helper method to add any column to the current row - in its binary form. - - Allocates memory for the data in the result set memory root. -*/ - -bool Protocol_local::store_column(const void *data, size_t length) -{ - if (m_current_column == NULL) - return TRUE; /* prepare_for_resend() failed to allocate memory. */ - /* - alloc_root() automatically aligns memory, so we don't need to - do any extra alignment if we're pointing to, say, an integer. - */ - m_current_column->str= (char*) memdup_root(&m_rset_root, - data, - length + 1 /* Safety */); - if (! m_current_column->str) - return TRUE; - m_current_column->str[length]= '\0'; /* Safety */ - m_current_column->length= length; - ++m_current_column; - return FALSE; -} - - -/** - Store a string value in a result set column, optionally - having converted it to character_set_results. -*/ - -bool -Protocol_local::store_string(const char *str, size_t length, - CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs) -{ - /* Store with conversion */ - uint error_unused; - - if (dst_cs && !my_charset_same(src_cs, dst_cs) && - src_cs != &my_charset_bin && - dst_cs != &my_charset_bin) - { - if (convert->copy(str, length, src_cs, dst_cs, &error_unused)) - return TRUE; - str= convert->ptr(); - length= convert->length(); - } - return store_column(str, length); -} - - -/** Store a tiny int as is (1 byte) in a result set column. */ - -bool Protocol_local::store_tiny(longlong value) -{ - char v= (char) value; - return store_column(&v, 1); -} - - -/** Store a short as is (2 bytes, host order) in a result set column. */ - -bool Protocol_local::store_short(longlong value) -{ - int16 v= (int16) value; - return store_column(&v, 2); -} - - -/** Store a "long" as is (4 bytes, host order) in a result set column. */ - -bool Protocol_local::store_long(longlong value) -{ - int32 v= (int32) value; - return store_column(&v, 4); -} - - -/** Store a "longlong" as is (8 bytes, host order) in a result set column. */ - -bool Protocol_local::store_longlong(longlong value, bool unsigned_flag) -{ - int64 v= (int64) value; - return store_column(&v, 8); -} - - -/** Store a decimal in string format in a result set column */ - -bool Protocol_local::store_decimal(const my_decimal *value) -{ - char buf[DECIMAL_MAX_STR_LENGTH]; - String str(buf, sizeof (buf), &my_charset_bin); - int rc; - - rc= my_decimal2string(E_DEC_FATAL_ERROR, value, 0, 0, 0, &str); - - if (rc) - return TRUE; - - return store_column(str.ptr(), str.length()); -} - - -/** Convert to cs_results and store a string. */ - -bool Protocol_local::store(const char *str, size_t length, - CHARSET_INFO *src_cs) -{ - CHARSET_INFO *dst_cs; - - dst_cs= m_connection->m_thd->variables.character_set_results; - return store_string(str, length, src_cs, dst_cs); -} - - -/** Store a string. */ - -bool Protocol_local::store(const char *str, size_t length, - CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs) -{ - return store_string(str, length, src_cs, dst_cs); -} - - -/* Store MYSQL_TIME (in binary format) */ - -bool Protocol_local::store(MYSQL_TIME *time, int decimals) -{ - if (decimals != AUTO_SEC_PART_DIGITS) - my_time_trunc(time, decimals); - return store_column(time, sizeof(MYSQL_TIME)); -} - - -/** Store MYSQL_TIME (in binary format) */ - -bool Protocol_local::store_date(MYSQL_TIME *time) -{ - return store_column(time, sizeof(MYSQL_TIME)); -} - - -/** Store MYSQL_TIME (in binary format) */ - -bool Protocol_local::store_time(MYSQL_TIME *time, int decimals) -{ - if (decimals != AUTO_SEC_PART_DIGITS) - my_time_trunc(time, decimals); - return store_column(time, sizeof(MYSQL_TIME)); -} - - -/* Store a floating point number, as is. */ - -bool Protocol_local::store(float value, uint32 decimals, String *buffer) -{ - return store_column(&value, sizeof(float)); -} - - -/* Store a double precision number, as is. */ - -bool Protocol_local::store(double value, uint32 decimals, String *buffer) -{ - return store_column(&value, sizeof (double)); -} - - -/* Store a Field. */ - -bool Protocol_local::store(Field *field) -{ - if (field->is_null()) - return store_null(); - return field->send_binary(this); -} - - -/** Called to start a new result set. */ - -bool Protocol_local::send_result_set_metadata(List<Item> *columns, uint) -{ - DBUG_ASSERT(m_rset == 0 && !alloc_root_inited(&m_rset_root)); - - init_sql_alloc(&m_rset_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); - - if (! (m_rset= new (&m_rset_root) List<Ed_row>)) - return TRUE; - - m_column_count= columns->elements; - - return FALSE; -} - - -/** - Normally this is a separate result set with OUT parameters - of stored procedures. Currently unsupported for the local - version. -*/ - -bool Protocol_local::send_out_parameters(List<Item_param> *sp_params) -{ - return FALSE; -} - - -/** Called for statements that don't have a result set, at statement end. */ - -bool -Protocol_local::send_ok(uint server_status, uint statement_warn_count, - ulonglong affected_rows, ulonglong last_insert_id, - const char *message, bool skip_flush) -{ - /* - Just make sure nothing is sent to the client, we have grabbed - the status information in the connection diagnostics area. - */ - return FALSE; -} - - -/** - Called at the end of a result set. Append a complete - result set to the list in Ed_connection. - - Don't send anything to the client, but instead finish - building of the result set at hand. -*/ - -bool Protocol_local::send_eof(uint server_status, uint statement_warn_count) -{ - Ed_result_set *ed_result_set; - - DBUG_ASSERT(m_rset); - - opt_add_row_to_rset(); - m_current_row= 0; - - ed_result_set= new (&m_rset_root) Ed_result_set(m_rset, m_column_count, - &m_rset_root); - - m_rset= NULL; - - if (! ed_result_set) - return TRUE; - - /* In case of successful allocation memory ownership was transferred. */ - DBUG_ASSERT(!alloc_root_inited(&m_rset_root)); - - /* - Link the created Ed_result_set instance into the list of connection - result sets. Never fails. - */ - m_connection->add_result_set(ed_result_set); - return FALSE; -} - - -/** Called to send an error to the client at the end of a statement. */ - -bool -Protocol_local::send_error(uint sql_errno, const char *err_msg, const char*) -{ - /* - Just make sure that nothing is sent to the client (default - implementation). - */ - return FALSE; -} - - -#ifdef EMBEDDED_LIBRARY -void Protocol_local::remove_last_row() -{ } -#endif |