summaryrefslogtreecommitdiff
path: root/sql/sql_class.h
diff options
context:
space:
mode:
authorunknown <konstantin@oak.local>2003-12-20 02:16:10 +0300
committerunknown <konstantin@oak.local>2003-12-20 02:16:10 +0300
commit32c6b0d72a120dcafb1ae084bbc1c57c5fc5701f (patch)
treec9441e15b696703bb24911352787db69a6784020 /sql/sql_class.h
parent8d987f9e532689545becf521aa6a6aa6b23bf330 (diff)
downloadmariadb-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.h208
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