diff options
author | konstantin@oak.local <> | 2003-11-27 20:51:53 +0300 |
---|---|---|
committer | konstantin@oak.local <> | 2003-11-27 20:51:53 +0300 |
commit | c75bb0a654db5ce8ecb7b3a952890b100fef31e1 (patch) | |
tree | a1161b4b2f69bc0ec5235db502853d986c76a4a7 /sql | |
parent | 56ec2351a0a3ddf7aee6b2580c7c56fa21a2e033 (diff) | |
download | mariadb-git-c75bb0a654db5ce8ecb7b3a952890b100fef31e1.tar.gz |
Second attempt: trying to add Statement context to sources.
Added classes Statement, Statement_map
Merge commit
Diffstat (limited to 'sql')
-rw-r--r-- | sql/slave.cc | 1 | ||||
-rw-r--r-- | sql/sql_class.cc | 108 | ||||
-rw-r--r-- | sql/sql_class.h | 134 | ||||
-rw-r--r-- | sql/sql_parse.cc | 8 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 2 |
5 files changed, 206 insertions, 47 deletions
diff --git a/sql/slave.cc b/sql/slave.cc index c531d3cc4f7..a10d0488eed 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3106,7 +3106,6 @@ slave_begin: sql_print_error("Failed during slave thread initialization"); goto err; } - thd->init_for_queries(); rli->sql_thd= thd; thd->temporary_tables = rli->save_temporary_tables; // restore temp tables pthread_mutex_lock(&LOCK_thread_count); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index e2d1069975b..539c864d5ee 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -86,28 +86,28 @@ extern "C" void free_user_var(user_var_entry *entry) ** Thread specific functions ****************************************************************************/ -THD::THD():user_time(0), is_fatal_error(0), +THD::THD():user_time(0), + is_fatal_error(0), last_insert_id_used(0), insert_id_used(0), rand_used(0), in_lock_tables(0), global_read_lock(0), bootstrap(0), spcont(NULL) { - lex= &main_lex; - host=user=priv_user=db=query=ip=0; + host= user= priv_user= db= ip= 0; host_or_ip= "connecting host"; - locked=some_tables_deleted=no_errors=password= - query_start_used=prepare_command=0; + locked=some_tables_deleted=no_errors=password= 0; + query_start_used= 0; count_cuted_fields= CHECK_FIELD_IGNORE; killed= NOT_KILLED; - db_length=query_length=col_access=0; + db_length= col_access=0; query_error= tmp_table_used= 0; next_insert_id=last_insert_id=0; open_tables= temporary_tables= handler_tables= derived_tables= 0; tmp_table=0; lock=locked_tables=0; used_tables=0; - cuted_fields= sent_row_count= current_stmt_id= 0L; + cuted_fields= sent_row_count= 0L; + statement_id_counter= 0UL; // Must be reset to handle error with THD's created for init of mysqld - lex->current_select= 0; start_time=(time_t) 0; current_linfo = 0; slave_thread = 0; @@ -141,7 +141,6 @@ THD::THD():user_time(0), is_fatal_error(0), server_id = ::server_id; slave_net = 0; command=COM_CONNECT; - set_query_id=1; #ifndef NO_EMBEDDED_ACCESS_CHECKS db_access=NO_ACCESS; #endif @@ -149,6 +148,9 @@ THD::THD():user_time(0), is_fatal_error(0), *scramble= '\0'; init(); + init_sql_alloc(&mem_root, // must be after init() + variables.query_alloc_block_size, + variables.query_prealloc_size); /* Initialize sub structures */ bzero((char*) &mem_root,sizeof(mem_root)); init_alloc_root(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE); @@ -192,7 +194,9 @@ THD::THD():user_time(0), is_fatal_error(0), transaction.trans_log.end_of_file= max_binlog_cache_size; } #endif - + init_sql_alloc(&transaction.mem_root, + variables.trans_alloc_block_size, + variables.trans_prealloc_size); /* We need good random number initialization for new thread Just coping global one will not work @@ -236,22 +240,6 @@ void THD::init(void) /* - Init THD for query processing - - This has to be called once before we call mysql_parse() -*/ - -void THD::init_for_queries() -{ - init_sql_alloc(&mem_root, variables.query_alloc_block_size, - variables.query_prealloc_size); - init_sql_alloc(&transaction.mem_root, - variables.trans_alloc_block_size, - variables.trans_prealloc_size); -} - - -/* Do what's needed when one invokes change user SYNOPSIS @@ -351,7 +339,6 @@ THD::~THD() safeFree(user); safeFree(db); safeFree(ip); - free_root(&mem_root,MYF(0)); free_root(&warn_root,MYF(0)); free_root(&transaction.mem_root,MYF(0)); mysys_var=0; // Safety (shouldn't be needed) @@ -1269,3 +1256,70 @@ bool select_dumpvar::send_eof() ::send_ok(thd,row_count); return 0; } + + +/* + Statement functions +*/ + +Statement::Statement(THD *thd) + :id(++thd->statement_id_counter), + query_id(0), /* initialized later */ + set_query_id(1), + allow_sum_func(0), /* initialized later */ + command(COM_SLEEP), /* reset in THD counstructor and mysql_parse */ + lex(&main_lex), + query(0), + query_length(0), + free_list(0) /* reset in THD constructor */ +{ + init_sql_alloc(&mem_root, + thd->variables.query_alloc_block_size, + thd->variables.query_prealloc_size); +} + +/* + This constructor is called when statement is a subobject of THD: + Some variables are initialized in THD::init due to locking problems + This statement object will be used to +*/ + +Statement::Statement() + :id(0), + query_id(0), + set_query_id(1), + allow_sum_func(0), + command(COM_SLEEP), + lex(&main_lex), + query(0), + query_length(0), + free_list(0) +{ + bzero((char *) &mem_root, sizeof(mem_root)); +} + + +Statement::~Statement() +{ + free_root(&mem_root, MYF(0)); +} + +C_MODE_START + +static byte * +get_statement_id_as_hash_key(const byte *record, uint *key_length, + my_bool not_used __attribute__((unused))) +{ + const Statement *statement= (const Statement *) record; + *key_length= sizeof(statement->id); + return (byte *) &((const Statement *) statement)->id; +} + +C_MODE_END + +Statement_map::Statement_map() +{ + enum { START_HASH_SIZE = 16 }; + hash_init(&st_hash, default_charset_info, START_HASH_SIZE, 0, 0, + get_statement_id_as_hash_key, (hash_free_key) 0, MYF(0)); +} diff --git a/sql/sql_class.h b/sql/sql_class.h index f9d74f8b4da..211232e85ea 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -431,12 +431,126 @@ struct system_variables }; void free_tmp_table(THD *thd, TABLE *entry); + + +/* + 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 +{ +public: + /* FIXME: must be private */ + LEX main_lex; +public: + /* + Uniquely identifies each statement object in scope of thread. + Can't be const at the moment because of substitute() method + */ + /* 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; + +protected: + Statement(); +public: + Statement(THD *thd); + virtual ~Statement(); +}; + + +/* + Used to seek all existing statements in the connection + Not responsible for statements memory. +*/ + +class Statement_map +{ +public: + Statement_map(); + + int insert(Statement *statement) + { + return my_hash_insert(&st_hash, (byte *) statement); + } + Statement *seek(ulonglong id) + { + return (Statement *) hash_search(&st_hash, (byte *) &id, sizeof(id)); + } + void erase(Statement *statement) + { + hash_delete(&st_hash, (byte *) statement); + } + + ~Statement_map() { hash_free(&st_hash); } +private: + HASH st_hash; +}; + + /* 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 @@ -449,9 +563,6 @@ 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 warn_root; // For warnings and errors Protocol *protocol; // Current protocol Protocol_simple protocol_simple; // Normal protocol @@ -464,7 +575,6 @@ public: struct system_variables variables; // Changeable local variables pthread_mutex_t LOCK_delete; // Locked before thd is deleted - char *query; // Points to the current query, /* A pointer to the stack frame of handle_one_connection(), which is called first in the thread for handling a client @@ -513,7 +623,6 @@ public: 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 /* @@ -546,7 +655,6 @@ public: free_root(&mem_root,MYF(MY_KEEP_PREALLOC)); } } transaction; - Item *free_list; Field *dupp_field; #ifndef __WIN__ sigset_t signals,block_signals; @@ -580,15 +688,16 @@ public: 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; - 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 */ @@ -601,9 +710,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 system_thread,in_lock_tables,global_read_lock; bool query_error, bootstrap, cleanup_done; @@ -647,7 +756,6 @@ public: void init(void); void change_user(void); - void init_for_queries(); void cleanup(void); bool store_globals(); #ifdef SIGNAL_WITH_VIO_CLOSE diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7afc268b270..ea34fdd6ac5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -949,7 +949,6 @@ pthread_handler_decl(handle_one_connection,arg) thd->command=COM_SLEEP; thd->version=refresh_version; thd->set_time(); - thd->init_for_queries(); while (!net->error && net->vio != 0 && !(thd->killed == THD::KILL_CONNECTION)) { if (do_command(thd)) @@ -1029,7 +1028,6 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) thd->priv_user=thd->user=(char*) my_strdup("boot", MYF(MY_WME)); buff= (char*) thd->net.buff; - thd->init_for_queries(); while (fgets(buff, thd->net.max_packet, file)) { uint length=(uint) strlen(buff); @@ -1202,13 +1200,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, { NET *net= &thd->net; bool error= 0; + DBUG_ENTER("dispatch_command"); + + thd->command=command; /* Commands which will always take a long time should be marked with this so that they will not get logged to the slow query log */ - DBUG_ENTER("dispatch_command"); - - thd->command=command; thd->slow_command=FALSE; thd->set_time(); VOID(pthread_mutex_lock(&LOCK_thread_count)); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 9721b77e38a..4791dd94bd6 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -904,7 +904,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) bzero((char*) &stmt, sizeof(stmt)); - stmt.stmt_id= ++thd->current_stmt_id; + stmt.stmt_id= ++thd->statement_id_counter; init_sql_alloc(&stmt.mem_root, thd->variables.query_alloc_block_size, thd->variables.query_prealloc_size); |