1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

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.
This commit is contained in:
unknown
2003-12-20 02:16:10 +03:00
parent 8d987f9e53
commit 32c6b0d72a
8 changed files with 613 additions and 430 deletions

View File

@ -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