diff options
author | unknown <konstantin@oak.local> | 2003-12-20 02:16:10 +0300 |
---|---|---|
committer | unknown <konstantin@oak.local> | 2003-12-20 02:16:10 +0300 |
commit | 32c6b0d72a120dcafb1ae084bbc1c57c5fc5701f (patch) | |
tree | c9441e15b696703bb24911352787db69a6784020 /sql/sql_class.h | |
parent | 8d987f9e532689545becf521aa6a6aa6b23bf330 (diff) | |
download | mariadb-git-32c6b0d72a120dcafb1ae084bbc1c57c5fc5701f.tar.gz |
Prepared_statement deployed instead of PREP_STMT.
libmysqld/lib_sql.cc:
Prepared_statement now resides entirely in sql_prepare.cc
Embedded versions of setup_params_data moved to sql_prepare.cc
sql/mysql_priv.h:
removed declarations for non-existing functions
sql/slave.cc:
no thd->init_for_queries() any more
sql/sql_class.cc:
added Statement and Statement_map classes.
PREP_STMT replaced with Statement (Prepared_statement) and moved to
sql_prepare.cc
sql/sql_class.h:
added Statement and Statement_map classes.
PREP_STMT replaced with Statement (Prepared_statement) and moved to
sql_prepare.cc
sql/sql_parse.cc:
thd->init_for_queries() doesn't exist any more
comment moved to proper place
sql/sql_prepare.cc:
PREP_STMT replaced with Prepared_statement
minor code cleanups
tests/client_test.c:
Later in the test we rely on order of rows, which normally is not defined.
My patch changes the order.
Diffstat (limited to 'sql/sql_class.h')
-rw-r--r-- | sql/sql_class.h | 208 |
1 files changed, 167 insertions, 41 deletions
diff --git a/sql/sql_class.h b/sql/sql_class.h index 2a7523c890b..d663521b296 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -328,30 +328,6 @@ public: }; -/* This is a struct as it's allocated in tree_insert */ - -typedef struct st_prep_stmt -{ - THD *thd; - LEX lex; - Item_param **param; - Item *free_list; - MEM_ROOT mem_root; - String *query; - ulong stmt_id; - uint param_count; - uint last_errno; - char last_error[MYSQL_ERRMSG_SIZE]; - bool error_in_prepare, long_data_used; - bool log_full_query; -#ifndef EMBEDDED_LIBRARY - bool (*setup_params)(st_prep_stmt *stmt, uchar *pos, uchar *read_pos); -#else - bool (*setup_params_data)(st_prep_stmt *stmt); -#endif -} PREP_STMT; - - class delayed_insert; class select_result; @@ -428,12 +404,158 @@ struct system_variables }; void free_tmp_table(THD *thd, TABLE *entry); + +class Prepared_statement; + +/* + State of a single command executed against this connection. + One connection can contain a lot of simultaneously running statements, + some of which could be: + - prepared, that is, contain placeholders, + - opened as cursors. We maintain 1 to 1 relationship between + statement and cursor - if user wants to create another cursor for his + query, we create another statement for it. + To perform some action with statement we reset THD part to the state of + that statement, do the action, and then save back modified state from THD + to the statement. It will be changed in near future, and Statement will + be used explicitly. +*/ + +class Statement +{ + Statement(const Statement &rhs); /* not implemented: */ + Statement &operator=(const Statement &rhs); /* non-copyable */ +public: + /* FIXME: must be private */ + LEX main_lex; +public: + /* + Uniquely identifies each statement object in thread scope; change during + statement lifetime. FIXME: must be const + */ + ulong id; + + /* + Id of current query. Statement can be reused to execute several queries + query_id is global in context of the whole MySQL server. + ID is automatically generated from mutex-protected counter. + It's used in handler code for various purposes: to check which columns + from table are necessary for this select, to check if it's necessary to + update auto-updatable fields (like auto_increment and timestamp). + */ + ulong query_id; + /* + - if set_query_id=1, we set field->query_id for all fields. In that case + field list can not contain duplicates. + */ + bool set_query_id; + /* + This variable is used in post-parse stage to declare that sum-functions, + or functions which have sense only if GROUP BY is present, are allowed. + For example in queries + SELECT MIN(i) FROM foo + SELECT GROUP_CONCAT(a, b, MIN(i)) FROM ... GROUP BY ... + MIN(i) have no sense. + Though it's grammar-related issue, it's hard to catch it out during the + parse stage because GROUP BY clause goes in the end of query. This + variable is mainly used in setup_fields/fix_fields. + See item_sum.cc for details. + */ + bool allow_sum_func; + /* + Type of current query: COM_PREPARE, COM_QUERY, etc. Set from + first byte of the packet in do_command() + */ + enum enum_server_command command; + + LEX *lex; // parse tree descriptor + /* + Points to the query associated with this statement. It's const, but + we need to declare it char * because all table handlers are written + in C and need to point to it. + */ + char *query; + uint32 query_length; // current query length + /* + List of items created in the parser for this query. Every item puts + itself to the list on creation (see Item::Item() for details)) + */ + Item *free_list; + MEM_ROOT mem_root; + +public: + /* We build without RTTI, so dynamic_cast can't be used. */ + enum Type + { + STATEMENT, + PREPARED_STATEMENT + }; + + /* + This constructor is called when statement is a subobject of THD: + some variables are initialized in THD::init due to locking problems + */ + Statement(); + + Statement(THD *thd); + virtual ~Statement(); + + /* Assign execution context (note: not all members) of given stmt to self */ + void set_statement(Statement *stmt); + /* return class type */ + virtual Type type() const; +}; + + +/* + Used to seek all existing statements in the connection + Deletes all statements in destructor. +*/ + +class Statement_map +{ +public: + Statement_map(); + + int insert(Statement *statement) + { + int rc= my_hash_insert(&st_hash, (byte *) statement); + if (rc == 0) + last_found_statement= statement; + return rc; + } + + Statement *find(ulong id) + { + if (last_found_statement == 0 || id != last_found_statement->id) + last_found_statement= (Statement *) hash_search(&st_hash, (byte *) &id, + sizeof(id)); + return last_found_statement; + } + void erase(Statement *statement) + { + if (statement == last_found_statement) + last_found_statement= 0; + hash_delete(&st_hash, (byte *) statement); + } + + ~Statement_map() + { + hash_free(&st_hash); + } +private: + HASH st_hash; + Statement *last_found_statement; +}; + + /* For each client connection we create a separate thread with THD serving as a thread/connection descriptor */ -class THD :public ilink +class THD :public ilink, + public Statement { public: #ifdef EMBEDDED_LIBRARY @@ -446,23 +568,25 @@ public: ulong extra_length; #endif NET net; // client connection descriptor - LEX main_lex; - LEX *lex; // parse tree descriptor - MEM_ROOT mem_root; // 1 command-life memory pool - MEM_ROOT con_root; // connection-life memory MEM_ROOT warn_root; // For warnings and errors Protocol *protocol; // Current protocol Protocol_simple protocol_simple; // Normal protocol Protocol_prep protocol_prep; // Binary protocol HASH user_vars; // hash for user variables - TREE prepared_statements; String packet; // dynamic buffer for network I/O struct sockaddr_in remote; // client socket address struct rand_struct rand; // used for authentication struct system_variables variables; // Changeable local variables pthread_mutex_t LOCK_delete; // Locked before thd is deleted - char *query; // Points to the current query, + /* all prepared statements and cursors of this connection */ + Statement_map stmt_map; + /* + keeps THD state while it is used for active statement + Note, that double free_root() is safe, so we don't need to do any + special cleanup for it in THD destructor. + */ + Statement stmt_backup; /* A pointer to the stack frame of handle_one_connection(), which is called first in the thread for handling a client @@ -502,7 +626,6 @@ public: and are still in use by this thread */ TABLE *open_tables,*temporary_tables, *handler_tables, *derived_tables; - // TODO: document the variables below MYSQL_LOCK *lock; /* Current locks */ MYSQL_LOCK *locked_tables; /* Tables locked with LOCK */ /* @@ -511,12 +634,10 @@ public: chapter 'Miscellaneous functions', for functions GET_LOCK, RELEASE_LOCK. */ ULL *ull; - PREP_STMT *last_prepared_stmt; #ifndef DBUG_OFF uint dbug_sentry; // watch out for memory corruption #endif struct st_my_thread_var *mysys_var; - enum enum_server_command command; uint32 server_id; uint32 file_id; // for LOAD DATA INFILE /* @@ -549,7 +670,6 @@ public: free_root(&mem_root,MYF(MY_KEEP_PREALLOC)); } } transaction; - Item *free_list, *handler_items; Field *dupp_field; #ifndef __WIN__ sigset_t signals,block_signals; @@ -580,18 +700,25 @@ public: USER_CONN *user_connect; CHARSET_INFO *db_charset; List<TABLE> temporary_tables_should_be_free; // list of temporary tables + /* + FIXME: this, and some other variables like 'count_cuted_fields' + maybe should be statement/cursor local, that is, moved to Statement + class. With current implementation warnings produced in each prepared + statement/cursor settle here. + */ List <MYSQL_ERROR> warn_list; uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END]; uint total_warn_count; - ulong query_id, warn_id, version, options, thread_id, col_access; - ulong current_stmt_id; + ulong warn_id, version, options, thread_id, col_access; + + /* Statement id is thread-wide. This counter is used to generate ids */ + ulong statement_id_counter; ulong rand_saved_seed1, rand_saved_seed2; ulong row_count; // Row counter, mainly for errors and warnings long dbug_thread_id; pthread_t real_id; uint current_tablenr,tmp_table; uint server_status,open_options,system_thread; - uint32 query_length; uint32 db_length; uint select_number; //number of select (used for EXPLAIN) /* variables.transaction_isolation is reset to this after each commit */ @@ -604,9 +731,9 @@ public: char scramble[SCRAMBLE_LENGTH+1]; bool slave_thread; - bool set_query_id,locked,some_tables_deleted; + bool locked, some_tables_deleted; bool last_cuted_field; - bool no_errors, allow_sum_func, password, is_fatal_error; + bool no_errors, password, is_fatal_error; bool query_start_used,last_insert_id_used,insert_id_used,rand_used; bool in_lock_tables,global_read_lock; bool query_error, bootstrap, cleanup_done; @@ -634,7 +761,6 @@ public: void init(void); void change_user(void); - void init_for_queries(); void cleanup(void); bool store_globals(); #ifdef SIGNAL_WITH_VIO_CLOSE |