2006-12-31 01:02:27 +01:00
|
|
|
/* Copyright (C) 2002-2006 MySQL AB
|
2002-12-11 08:17:51 +01:00
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
2006-12-23 20:17:15 +01:00
|
|
|
the Free Software Foundation; version 2 of the License.
|
2002-12-11 08:17:51 +01:00
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
|
2005-05-04 15:05:56 +02:00
|
|
|
#ifdef USE_PRAGMA_INTERFACE
|
2002-12-11 08:17:51 +01:00
|
|
|
#pragma interface /* gcc class implementation */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
class i_string;
|
|
|
|
class THD;
|
2003-01-20 15:47:25 +01:00
|
|
|
typedef struct st_mysql_field MYSQL_FIELD;
|
2003-04-23 16:37:33 +02:00
|
|
|
typedef struct st_mysql_rows MYSQL_ROWS;
|
|
|
|
|
2002-12-11 08:17:51 +01:00
|
|
|
class Protocol
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
THD *thd;
|
|
|
|
String *packet;
|
2004-05-25 00:03:49 +02:00
|
|
|
String *convert;
|
2002-12-11 08:17:51 +01:00
|
|
|
uint field_pos;
|
2005-11-22 23:50:37 +01:00
|
|
|
#ifndef DBUG_OFF
|
2002-12-11 08:17:51 +01:00
|
|
|
enum enum_field_types *field_types;
|
|
|
|
#endif
|
2003-01-15 09:11:44 +01:00
|
|
|
uint field_count;
|
2004-06-09 19:36:48 +02:00
|
|
|
#ifndef EMBEDDED_LIBRARY
|
2003-01-15 09:11:44 +01:00
|
|
|
bool net_store_data(const char *from, uint length);
|
2004-06-09 19:36:48 +02:00
|
|
|
#else
|
|
|
|
virtual bool net_store_data(const char *from, uint length);
|
2003-01-15 09:11:44 +01:00
|
|
|
char **next_field;
|
2003-01-20 15:47:25 +01:00
|
|
|
MYSQL_FIELD *next_mysql_field;
|
2003-01-15 09:11:44 +01:00
|
|
|
MEM_ROOT *alloc;
|
2002-12-17 16:33:25 +01:00
|
|
|
#endif
|
2004-05-25 00:03:49 +02:00
|
|
|
bool store_string_aux(const char *from, uint length,
|
|
|
|
CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
|
2002-12-11 08:17:51 +01:00
|
|
|
public:
|
|
|
|
Protocol() {}
|
2003-11-28 11:18:13 +01:00
|
|
|
Protocol(THD *thd_arg) { init(thd_arg); }
|
2003-03-21 12:18:52 +01:00
|
|
|
virtual ~Protocol() {}
|
2003-11-28 11:18:13 +01:00
|
|
|
void init(THD* thd_arg);
|
Port of cursors to be pushed into 5.0 tree:
- client side part is simple and may be considered stable
- server side part now just joggles with THD state to save execution
state and has no additional locking wisdom.
Lot's of it are to be rewritten.
include/mysql.h:
Cursor patch to push into the main tree, client library part (considered
stable):
- new statement attribute STMT_ATTR_CURSOR_TYPE
- MYSQL_STMT::flags to store statement cursor type
- MYSQL_STMT::server_status to store server status (i. e. if the server
was able to open a cursor for this query).
include/mysql_com.h:
Cursor patch to push into the main tree, client library part (considered
stable):
- new COMmand, COM_FETCH, to fetch K rows from read-only cursor.
By design should support scrollable cursors as well.
- a few new server statuses:
SERVER_STATUS_CURSOR_EXISTS is sent by server in reply to COM_EXECUTE,
when cursor was successfully opened for this query
SERVER_STATUS_LAST_ROW_SENT is sent along with the last row to prevent one
more round trip just for finding out that all rows were fetched from
this cursor (this is server mem savier also).
- and finally, all possible values of STMT_ATTR_CURSOR_TYPE,
while now we support only CURSORT_TYPE_NO_CURSOR and
CURSOR_TYPE_READ_ONLY
libmysql/libmysql.c:
Cursor patch to push into the main tree, client library part (considered
stable):
- simple additions to mysql_stmt_fetch implementation to read data
from an opened cursor: we can read up to iteration count rows per
one request; read rows are buffered in the same way as rows of
mysql_stmt_store_result.
- now send stmt->flags to server to let him now if we wish to have
a cursor for this statement.
- support for setting/getting statement cursor type.
libmysqld/examples/Makefile.am:
Testing cursors was originally implemented in C++. Now when these tests
go into client_test, it's time to convert it to C++ as well.
libmysqld/lib_sql.cc:
- cleanup: send_fields flags are now named.
sql/ha_innodb.cc:
- cleanup: send_fields flags are now named.
sql/mysql_priv.h:
- cursors support: declaration for server-side handler of COM_FETCH
sql/protocol.cc:
- cleanup: send_fields flags are now named.
- we can't anymore assert that field_types[field_pos] is sensible:
if we have COM_EXCUTE(stmt1), COM_EXECUTE(stmt2), COM_FETCH(stmt1)
field_types[field_pos] will point to fields of stmt2.
sql/protocol.h:
- cleanup: send_fields flag_s_ are now named.
sql/protocol_cursor.cc:
- cleanup: send_fields flags are now named.
sql/repl_failsafe.cc:
- cleanup: send_fields flags are now named.
sql/slave.cc:
- cleanup: send_fields flags are now named.
sql/sp.cc:
- cleanup: send_fields flags are now named.
sql/sp_head.cc:
- cleanup: send_fields flags are now named.
sql/sql_acl.cc:
- cleanup: send_fields flags are now named.
sql/sql_class.cc:
- cleanup: send_fields flags are now named.
sql/sql_class.h:
- cleanup: send_fields flags are now named.
sql/sql_error.cc:
- cleanup: send_fields flags are now named.
sql/sql_handler.cc:
- cleanup: send_fields flags are now named.
sql/sql_help.cc:
- cleanup: send_fields flags are now named.
sql/sql_parse.cc:
Server side support for cursors:
- handle COM_FETCH
- enforce assumption that whenever we free thd->free_list,
we reset it to zero. This way it's much easier to handle free_list
in prepared statements implementation.
sql/sql_prepare.cc:
Server side support for cursors:
- implementation of mysql_stmt_fetch (fetch some rows from open cursor).
- management of cursors memory is quite tricky now.
- execute_stmt can't be reused anymore in mysql_stmt_execute and
mysql_sql_stmt_execute
sql/sql_repl.cc:
- cleanup: send_fields flags are now named.
sql/sql_select.cc:
Server side support for cursors:
- implementation of Cursor::open, Cursor::fetch (buggy when it comes to
non-equi joins), cursor cleanups.
- -4 -3 -0 constants indicating return value of sub_select and end_send are
to be renamed to something more readable:
it turned out to be not so simple, so it should come with the other patch.
sql/sql_select.h:
Server side support for cursors:
- declaration of Cursor class.
- JOIN::fetch_limit contains runtime value of rows fetched via cursor.
sql/sql_show.cc:
- cleanup: send_fields flags are now named.
sql/sql_table.cc:
- cleanup: send_fields flags are now named.
sql/sql_union.cc:
- if there was a cursor, don't cleanup unit: we'll need it to fetch
the rest of the rows.
tests/Makefile.am:
Now client_test is in C++.
tests/client_test.cc:
A few elementary tests for cursors.
BitKeeper/etc/ignore:
Added libmysqld/examples/client_test.cc to the ignore list
2004-08-03 12:32:21 +02:00
|
|
|
|
2004-08-28 08:32:27 +02:00
|
|
|
enum { SEND_NUM_ROWS= 1, SEND_DEFAULTS= 2, SEND_EOF= 4 };
|
2004-11-03 11:39:38 +01:00
|
|
|
virtual bool send_fields(List<Item> *list, uint flags);
|
Port of cursors to be pushed into 5.0 tree:
- client side part is simple and may be considered stable
- server side part now just joggles with THD state to save execution
state and has no additional locking wisdom.
Lot's of it are to be rewritten.
include/mysql.h:
Cursor patch to push into the main tree, client library part (considered
stable):
- new statement attribute STMT_ATTR_CURSOR_TYPE
- MYSQL_STMT::flags to store statement cursor type
- MYSQL_STMT::server_status to store server status (i. e. if the server
was able to open a cursor for this query).
include/mysql_com.h:
Cursor patch to push into the main tree, client library part (considered
stable):
- new COMmand, COM_FETCH, to fetch K rows from read-only cursor.
By design should support scrollable cursors as well.
- a few new server statuses:
SERVER_STATUS_CURSOR_EXISTS is sent by server in reply to COM_EXECUTE,
when cursor was successfully opened for this query
SERVER_STATUS_LAST_ROW_SENT is sent along with the last row to prevent one
more round trip just for finding out that all rows were fetched from
this cursor (this is server mem savier also).
- and finally, all possible values of STMT_ATTR_CURSOR_TYPE,
while now we support only CURSORT_TYPE_NO_CURSOR and
CURSOR_TYPE_READ_ONLY
libmysql/libmysql.c:
Cursor patch to push into the main tree, client library part (considered
stable):
- simple additions to mysql_stmt_fetch implementation to read data
from an opened cursor: we can read up to iteration count rows per
one request; read rows are buffered in the same way as rows of
mysql_stmt_store_result.
- now send stmt->flags to server to let him now if we wish to have
a cursor for this statement.
- support for setting/getting statement cursor type.
libmysqld/examples/Makefile.am:
Testing cursors was originally implemented in C++. Now when these tests
go into client_test, it's time to convert it to C++ as well.
libmysqld/lib_sql.cc:
- cleanup: send_fields flags are now named.
sql/ha_innodb.cc:
- cleanup: send_fields flags are now named.
sql/mysql_priv.h:
- cursors support: declaration for server-side handler of COM_FETCH
sql/protocol.cc:
- cleanup: send_fields flags are now named.
- we can't anymore assert that field_types[field_pos] is sensible:
if we have COM_EXCUTE(stmt1), COM_EXECUTE(stmt2), COM_FETCH(stmt1)
field_types[field_pos] will point to fields of stmt2.
sql/protocol.h:
- cleanup: send_fields flag_s_ are now named.
sql/protocol_cursor.cc:
- cleanup: send_fields flags are now named.
sql/repl_failsafe.cc:
- cleanup: send_fields flags are now named.
sql/slave.cc:
- cleanup: send_fields flags are now named.
sql/sp.cc:
- cleanup: send_fields flags are now named.
sql/sp_head.cc:
- cleanup: send_fields flags are now named.
sql/sql_acl.cc:
- cleanup: send_fields flags are now named.
sql/sql_class.cc:
- cleanup: send_fields flags are now named.
sql/sql_class.h:
- cleanup: send_fields flags are now named.
sql/sql_error.cc:
- cleanup: send_fields flags are now named.
sql/sql_handler.cc:
- cleanup: send_fields flags are now named.
sql/sql_help.cc:
- cleanup: send_fields flags are now named.
sql/sql_parse.cc:
Server side support for cursors:
- handle COM_FETCH
- enforce assumption that whenever we free thd->free_list,
we reset it to zero. This way it's much easier to handle free_list
in prepared statements implementation.
sql/sql_prepare.cc:
Server side support for cursors:
- implementation of mysql_stmt_fetch (fetch some rows from open cursor).
- management of cursors memory is quite tricky now.
- execute_stmt can't be reused anymore in mysql_stmt_execute and
mysql_sql_stmt_execute
sql/sql_repl.cc:
- cleanup: send_fields flags are now named.
sql/sql_select.cc:
Server side support for cursors:
- implementation of Cursor::open, Cursor::fetch (buggy when it comes to
non-equi joins), cursor cleanups.
- -4 -3 -0 constants indicating return value of sub_select and end_send are
to be renamed to something more readable:
it turned out to be not so simple, so it should come with the other patch.
sql/sql_select.h:
Server side support for cursors:
- declaration of Cursor class.
- JOIN::fetch_limit contains runtime value of rows fetched via cursor.
sql/sql_show.cc:
- cleanup: send_fields flags are now named.
sql/sql_table.cc:
- cleanup: send_fields flags are now named.
sql/sql_union.cc:
- if there was a cursor, don't cleanup unit: we'll need it to fetch
the rest of the rows.
tests/Makefile.am:
Now client_test is in C++.
tests/client_test.cc:
A few elementary tests for cursors.
BitKeeper/etc/ignore:
Added libmysqld/examples/client_test.cc to the ignore list
2004-08-03 12:32:21 +02:00
|
|
|
|
2002-12-11 08:17:51 +01:00
|
|
|
bool store(I_List<i_string> *str_list);
|
2003-03-17 10:14:04 +01:00
|
|
|
bool store(const char *from, CHARSET_INFO *cs);
|
2002-12-11 08:17:51 +01:00
|
|
|
String *storage_packet() { return packet; }
|
|
|
|
inline void free() { packet->free(); }
|
2003-09-17 17:48:53 +02:00
|
|
|
virtual bool write();
|
2006-12-22 02:59:27 +01:00
|
|
|
inline bool store(int from)
|
|
|
|
{ return store_long((longlong) from); }
|
2002-12-11 08:17:51 +01:00
|
|
|
inline bool store(uint32 from)
|
|
|
|
{ return store_long((longlong) from); }
|
|
|
|
inline bool store(longlong from)
|
|
|
|
{ return store_longlong((longlong) from, 0); }
|
|
|
|
inline bool store(ulonglong from)
|
|
|
|
{ return store_longlong((longlong) from, 1); }
|
2003-05-29 23:47:31 +02:00
|
|
|
inline bool store(String *str)
|
2003-08-19 15:00:12 +02:00
|
|
|
{ return store((char*) str->ptr(), str->length(), str->charset()); }
|
2002-12-17 16:33:25 +01:00
|
|
|
|
2003-01-15 09:11:44 +01:00
|
|
|
virtual bool prepare_for_send(List<Item> *item_list)
|
|
|
|
{
|
|
|
|
field_count=item_list->elements;
|
|
|
|
return 0;
|
|
|
|
}
|
2004-11-02 19:13:27 +01:00
|
|
|
virtual bool flush();
|
2002-12-11 08:17:51 +01:00
|
|
|
virtual void prepare_for_resend()=0;
|
|
|
|
|
|
|
|
virtual bool store_null()=0;
|
|
|
|
virtual bool store_tiny(longlong from)=0;
|
|
|
|
virtual bool store_short(longlong from)=0;
|
|
|
|
virtual bool store_long(longlong from)=0;
|
|
|
|
virtual bool store_longlong(longlong from, bool unsigned_flag)=0;
|
2005-02-08 23:50:45 +01:00
|
|
|
virtual bool store_decimal(const my_decimal *)=0;
|
2003-03-17 10:14:04 +01:00
|
|
|
virtual bool store(const char *from, uint length, CHARSET_INFO *cs)=0;
|
2003-04-07 10:52:48 +02:00
|
|
|
virtual bool store(const char *from, uint length,
|
|
|
|
CHARSET_INFO *fromcs, CHARSET_INFO *tocs)=0;
|
2002-12-11 08:17:51 +01:00
|
|
|
virtual bool store(float from, uint32 decimals, String *buffer)=0;
|
|
|
|
virtual bool store(double from, uint32 decimals, String *buffer)=0;
|
|
|
|
virtual bool store(TIME *time)=0;
|
|
|
|
virtual bool store_date(TIME *time)=0;
|
|
|
|
virtual bool store_time(TIME *time)=0;
|
|
|
|
virtual bool store(Field *field)=0;
|
2006-02-24 17:34:15 +01:00
|
|
|
#ifdef EMBEDDED_LIBRARY
|
|
|
|
int begin_dataset();
|
|
|
|
virtual void remove_last_row() {}
|
|
|
|
#else
|
|
|
|
void remove_last_row() {}
|
|
|
|
#endif
|
Fix for BUG#735 "Prepared Statements: there is no support for Query
Cache".
WL#1569 "Prepared Statements: implement support of Query Cache".
Prepared SELECTs did not look up in the query cache, and their results
were not stored in the query cache. This made them slower than
non-prepared SELECTs in some cases.
The fix is to re-use the expanded query (the prepared query where
"?" placeholders are replaced by their values, at execution time)
for searching/storing in the query cache.
It works fine for statements prepared via mysql_stmt_prepare(), which
are the most commonly used and were the scope of this bugfix and WL.
It works less fine for statements prepared via the SQL command
PREPARE...FROM, which are still not using the query cache if they
have at least one parameter (because then the expanded query contains
names of user variables, and user variables don't work with the
query cache, even in non-prepared queries).
Note that results from prepared SELECTs, which are in the binary
protocol, and results from normal SELECTs, which are in the text
protocol, ignore each other in the query cache, because a result in the
binary protocol should never be served to a SELECT expecting the text
protocol and vice-versa.
Note, after this patch, bug 25843 starts applying to query cache
("changing default database between PREPARE and EXECUTE of statement
breaks binlog"), we need to fix it.
mysql-test/include/have_query_cache.inc:
Now prepared statements work with the query cache, so don't disable
prep stmts by default when doing a query cache test. All tests which
include this file will now be really tested against prepared
statements (in particular, query_cache.test).
mysql-test/r/query_cache.result:
result update
mysql-test/t/grant_cache.test:
Cannot enable this test in ps-protocol, because in normal protocol,
a SELECT failing due to insufficient privileges increments
Qcache_not_cached, while in ps-protocol, no.
In detail: in normal protocol,
the "access denied" errors on SELECT are issued at (stack trace):
mysql_parse/mysql_execute_command/execute_sqlcom_select/handle_select/
mysql_select/JOIN::prepare/setup_wild/insert_fields/
check_grant_all_columns/my_error/my_message_sql, which then calls
push_warning/query_cache_abort: at this moment,
query_cache_store_query() has been called, so query exists in cache,
so thd->net.query_cache_query!=NULL, so query_cache_abort() removes
the query from cache, which causes a query_cache.refused++ (thus,
a Qcache_not_cached++).
While in ps-protocol, the error is issued at prepare time;
for this mysql_test_select() is called, not execute_sqlcom_select()
(and that also leads to JOIN::prepare/etc). Thus, as
query_cache_store_query() has not been called,
thd->net.query_cache_query==NULL, so query_cache_abort() does nothing:
Qcache_not_cached is not incremented.
As this test prints Qcache_not_cached after SELECT failures,
we cannot enable this test in ps-protocol.
mysql-test/t/ndb_cache_multi2.test:
The principle of this test is: two mysqlds connected to one cluster,
both using their query cache. Queries are cached in server1
("select a!=3 from t1", "select * from t1"),
table t1 is modified in server2, we want to see that this invalidates
the query cache of server1. Invalidation with NDB works like this:
when a query is found in the query cache, NDB is asked if the tables
have changed. In this test, ha_ndbcluster calls NDB every millisecond
to collect change information about tables.
Due to this millisecond delay, there is need for a loop ("while...")
in this test, which waits until a query1 ("select a!=3 from t1") is
invalidated (which is equivalent to it returning
up-to-date results), and then expects query2 ("select * from t1")
to have been invalidated (see up-to-date results).
But when enabling --ps-protocol in this test, the logic breaks,
because query1 is still done via mysql_real_query() (see mysqltest.c:
eval_expr() always uses mysql_real_query()). So, query1 returning
up-to-date results is not a sign of it being invalidated in the cache,
because it was NOT in the cache ("select a!=3 from t1" on line 39
was done with prep stmts, while `select a!=3 from t1` is not,
thus the second does not see the first in the cache). Thus, we may run
query2 when cache still has not been invalidated.
The solution is to make the initial "select a!=3 from t1" run
as a normal query, this repairs the broken logic.
But note, "select * from t1" is still using prepared statements
which was the goal of this test with --ps-protocol.
mysql-test/t/query_cache.test:
now that prepared statements work with the query cache, we check
that results in binary protocol (prepared statements) and in text
protocol (normal queries) don't mix in the query cache even though
the text of the statement/query are identical.
sql/mysql_priv.h:
In class Query_cache_flags, we add a bit to say if the result
is in binary or text format (because, a result in binary format
should never be served to a query expecting text format, and vice-
versa).
A macro to emphasize that we read the size of the query cache
without mutex ("maybe" word).
A macro which gives a first indication of if a query is cache-able
(first indication - it does not consider the query cache's state).
sql/protocol.cc:
indentation.
sql/protocol.h:
Children classes of Protocol report their type (currently,
text or binary). Query cache needs to know that.
sql/sql_cache.cc:
When we store a result in the query cache, we need to remember if it's
in binary or text format. And when we search for a result in the query
cache, we need to select only those results which are in the format
which the current statement expects (binary or text).
sql/sql_prepare.cc:
Enabling use of the query cache by prepared statements.
1) Prep stmts are of two types:
a) prepared via the mysql_stmt_prepare() API call
b) prepared via the SQL PREPARE...FROM statement.
2) We already, when executing a prepared statement, sometimes built an
"expanded" statement. For a), "?" placeholders were replaced by their
values. For b), by names of the user variables containing the values.
We did that only when we needed to write the query to logs.
We now use this expanded query also for storing/searching
in the query cache.
Assume a query "SELECT * FROM T WHERE c=?", and the parameter is 10.
For a), the expanded query is "SELECT * FROM T WHERE c=10", we look
for "SELECT * FROM T WHERE c=10" in the query cache, and store that
query's result in the query cache.
For b), the expanded query is "SELECT * FROM T WHERE c=@somevar", and
user variables don't work with the query cache (even inside non-
prepared queries), so we don't enable query caching for SQL PREPARE'd
statements if they have at least one parameter (see
"if (stmt->param_count > 0)" in the patch).
3) If query cache is enabled and this is a SELECT, we build the
expanded query (as an optimisation, we don't want to build this
expanded query if the query cache is disabled or this is not a SELECT).
As the decision of building the expanded query or not is taken
at prepare time (setup_set_params()), if query cache is disabled
at prepare time, we won't build the expanded query at all next
executions, thus shouldn't use this query for query cacheing.
To ensure that we don't, we set safe_to_cache_query to FALSE.
Note that we read the size of the query cache without mutex, which is
ok: if we see it 0 but that cache has just been enlarged, no big deal,
just our statement will not use the query cache; if we see it >0 but
that cache has just been made destroyed, we'll build the expanded
query at all executions, but query_cache_store_query() and
query_cache_send_result_to_client() will read the size with a mutex
and so properly decide to cache or not cache.
4) Some functions in this file were named "withlog", others "with_log",
now using "with_log" for all.
tests/mysql_client_test.c:
Testing of how prepared statements enter and hit the query cache.
test_ps_query_cache() is inspired from test_ps_conj_select().
It creates data, a prepared SELECT statement, executes it once,
then a second time with the same parameter value, to see that cache
is hit, then a 3rd time with another parameter value to see that cache
is not hit. Then, same from another connection, expecting hits.
Then, tests border cases (enables query cache at prepare and disables
at execute and vice-versa).
It checks all results of SELECTs, cache hits and misses.
mysql-test/r/query_cache_sql_prepare.result:
result of new test: we see hits when there is no parameter,
no hit when there is a parameter.
mysql-test/t/query_cache_sql_prepare.test:
new test to see if SQL PREPARE'd statements enter/hit the query cache:
- if having at least one parameter, they should not
- if having zero parameters, they should.
2007-03-09 18:09:57 +01:00
|
|
|
enum enum_protocol_type
|
|
|
|
{
|
|
|
|
PROTOCOL_TEXT= 0, PROTOCOL_BINARY= 1
|
|
|
|
/*
|
|
|
|
before adding here or change the values, consider that it is cast to a
|
|
|
|
bit in sql_cache.cc.
|
|
|
|
*/
|
|
|
|
};
|
|
|
|
virtual enum enum_protocol_type type()= 0;
|
2002-12-11 08:17:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* Class used for the old (MySQL 4.0 protocol) */
|
|
|
|
|
2007-01-30 22:48:05 +01:00
|
|
|
class Protocol_text :public Protocol
|
2002-12-11 08:17:51 +01:00
|
|
|
{
|
|
|
|
public:
|
2007-01-30 22:48:05 +01:00
|
|
|
Protocol_text() {}
|
|
|
|
Protocol_text(THD *thd_arg) :Protocol(thd_arg) {}
|
2002-12-11 08:17:51 +01:00
|
|
|
virtual void prepare_for_resend();
|
|
|
|
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);
|
2005-02-08 23:50:45 +01:00
|
|
|
virtual bool store_decimal(const my_decimal *);
|
2003-03-17 10:14:04 +01:00
|
|
|
virtual bool store(const char *from, uint length, CHARSET_INFO *cs);
|
2003-04-07 10:52:48 +02:00
|
|
|
virtual bool store(const char *from, uint length,
|
|
|
|
CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
|
2002-12-11 08:17:51 +01:00
|
|
|
virtual bool store(TIME *time);
|
|
|
|
virtual bool store_date(TIME *time);
|
|
|
|
virtual bool store_time(TIME *time);
|
|
|
|
virtual bool store(float nr, uint32 decimals, String *buffer);
|
|
|
|
virtual bool store(double from, uint32 decimals, String *buffer);
|
|
|
|
virtual bool store(Field *field);
|
2006-02-24 17:34:15 +01:00
|
|
|
#ifdef EMBEDDED_LIBRARY
|
|
|
|
void remove_last_row();
|
|
|
|
#endif
|
Fix for BUG#735 "Prepared Statements: there is no support for Query
Cache".
WL#1569 "Prepared Statements: implement support of Query Cache".
Prepared SELECTs did not look up in the query cache, and their results
were not stored in the query cache. This made them slower than
non-prepared SELECTs in some cases.
The fix is to re-use the expanded query (the prepared query where
"?" placeholders are replaced by their values, at execution time)
for searching/storing in the query cache.
It works fine for statements prepared via mysql_stmt_prepare(), which
are the most commonly used and were the scope of this bugfix and WL.
It works less fine for statements prepared via the SQL command
PREPARE...FROM, which are still not using the query cache if they
have at least one parameter (because then the expanded query contains
names of user variables, and user variables don't work with the
query cache, even in non-prepared queries).
Note that results from prepared SELECTs, which are in the binary
protocol, and results from normal SELECTs, which are in the text
protocol, ignore each other in the query cache, because a result in the
binary protocol should never be served to a SELECT expecting the text
protocol and vice-versa.
Note, after this patch, bug 25843 starts applying to query cache
("changing default database between PREPARE and EXECUTE of statement
breaks binlog"), we need to fix it.
mysql-test/include/have_query_cache.inc:
Now prepared statements work with the query cache, so don't disable
prep stmts by default when doing a query cache test. All tests which
include this file will now be really tested against prepared
statements (in particular, query_cache.test).
mysql-test/r/query_cache.result:
result update
mysql-test/t/grant_cache.test:
Cannot enable this test in ps-protocol, because in normal protocol,
a SELECT failing due to insufficient privileges increments
Qcache_not_cached, while in ps-protocol, no.
In detail: in normal protocol,
the "access denied" errors on SELECT are issued at (stack trace):
mysql_parse/mysql_execute_command/execute_sqlcom_select/handle_select/
mysql_select/JOIN::prepare/setup_wild/insert_fields/
check_grant_all_columns/my_error/my_message_sql, which then calls
push_warning/query_cache_abort: at this moment,
query_cache_store_query() has been called, so query exists in cache,
so thd->net.query_cache_query!=NULL, so query_cache_abort() removes
the query from cache, which causes a query_cache.refused++ (thus,
a Qcache_not_cached++).
While in ps-protocol, the error is issued at prepare time;
for this mysql_test_select() is called, not execute_sqlcom_select()
(and that also leads to JOIN::prepare/etc). Thus, as
query_cache_store_query() has not been called,
thd->net.query_cache_query==NULL, so query_cache_abort() does nothing:
Qcache_not_cached is not incremented.
As this test prints Qcache_not_cached after SELECT failures,
we cannot enable this test in ps-protocol.
mysql-test/t/ndb_cache_multi2.test:
The principle of this test is: two mysqlds connected to one cluster,
both using their query cache. Queries are cached in server1
("select a!=3 from t1", "select * from t1"),
table t1 is modified in server2, we want to see that this invalidates
the query cache of server1. Invalidation with NDB works like this:
when a query is found in the query cache, NDB is asked if the tables
have changed. In this test, ha_ndbcluster calls NDB every millisecond
to collect change information about tables.
Due to this millisecond delay, there is need for a loop ("while...")
in this test, which waits until a query1 ("select a!=3 from t1") is
invalidated (which is equivalent to it returning
up-to-date results), and then expects query2 ("select * from t1")
to have been invalidated (see up-to-date results).
But when enabling --ps-protocol in this test, the logic breaks,
because query1 is still done via mysql_real_query() (see mysqltest.c:
eval_expr() always uses mysql_real_query()). So, query1 returning
up-to-date results is not a sign of it being invalidated in the cache,
because it was NOT in the cache ("select a!=3 from t1" on line 39
was done with prep stmts, while `select a!=3 from t1` is not,
thus the second does not see the first in the cache). Thus, we may run
query2 when cache still has not been invalidated.
The solution is to make the initial "select a!=3 from t1" run
as a normal query, this repairs the broken logic.
But note, "select * from t1" is still using prepared statements
which was the goal of this test with --ps-protocol.
mysql-test/t/query_cache.test:
now that prepared statements work with the query cache, we check
that results in binary protocol (prepared statements) and in text
protocol (normal queries) don't mix in the query cache even though
the text of the statement/query are identical.
sql/mysql_priv.h:
In class Query_cache_flags, we add a bit to say if the result
is in binary or text format (because, a result in binary format
should never be served to a query expecting text format, and vice-
versa).
A macro to emphasize that we read the size of the query cache
without mutex ("maybe" word).
A macro which gives a first indication of if a query is cache-able
(first indication - it does not consider the query cache's state).
sql/protocol.cc:
indentation.
sql/protocol.h:
Children classes of Protocol report their type (currently,
text or binary). Query cache needs to know that.
sql/sql_cache.cc:
When we store a result in the query cache, we need to remember if it's
in binary or text format. And when we search for a result in the query
cache, we need to select only those results which are in the format
which the current statement expects (binary or text).
sql/sql_prepare.cc:
Enabling use of the query cache by prepared statements.
1) Prep stmts are of two types:
a) prepared via the mysql_stmt_prepare() API call
b) prepared via the SQL PREPARE...FROM statement.
2) We already, when executing a prepared statement, sometimes built an
"expanded" statement. For a), "?" placeholders were replaced by their
values. For b), by names of the user variables containing the values.
We did that only when we needed to write the query to logs.
We now use this expanded query also for storing/searching
in the query cache.
Assume a query "SELECT * FROM T WHERE c=?", and the parameter is 10.
For a), the expanded query is "SELECT * FROM T WHERE c=10", we look
for "SELECT * FROM T WHERE c=10" in the query cache, and store that
query's result in the query cache.
For b), the expanded query is "SELECT * FROM T WHERE c=@somevar", and
user variables don't work with the query cache (even inside non-
prepared queries), so we don't enable query caching for SQL PREPARE'd
statements if they have at least one parameter (see
"if (stmt->param_count > 0)" in the patch).
3) If query cache is enabled and this is a SELECT, we build the
expanded query (as an optimisation, we don't want to build this
expanded query if the query cache is disabled or this is not a SELECT).
As the decision of building the expanded query or not is taken
at prepare time (setup_set_params()), if query cache is disabled
at prepare time, we won't build the expanded query at all next
executions, thus shouldn't use this query for query cacheing.
To ensure that we don't, we set safe_to_cache_query to FALSE.
Note that we read the size of the query cache without mutex, which is
ok: if we see it 0 but that cache has just been enlarged, no big deal,
just our statement will not use the query cache; if we see it >0 but
that cache has just been made destroyed, we'll build the expanded
query at all executions, but query_cache_store_query() and
query_cache_send_result_to_client() will read the size with a mutex
and so properly decide to cache or not cache.
4) Some functions in this file were named "withlog", others "with_log",
now using "with_log" for all.
tests/mysql_client_test.c:
Testing of how prepared statements enter and hit the query cache.
test_ps_query_cache() is inspired from test_ps_conj_select().
It creates data, a prepared SELECT statement, executes it once,
then a second time with the same parameter value, to see that cache
is hit, then a 3rd time with another parameter value to see that cache
is not hit. Then, same from another connection, expecting hits.
Then, tests border cases (enables query cache at prepare and disables
at execute and vice-versa).
It checks all results of SELECTs, cache hits and misses.
mysql-test/r/query_cache_sql_prepare.result:
result of new test: we see hits when there is no parameter,
no hit when there is a parameter.
mysql-test/t/query_cache_sql_prepare.test:
new test to see if SQL PREPARE'd statements enter/hit the query cache:
- if having at least one parameter, they should not
- if having zero parameters, they should.
2007-03-09 18:09:57 +01:00
|
|
|
virtual enum enum_protocol_type type() { return PROTOCOL_TEXT; };
|
2002-12-11 08:17:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2007-01-30 22:48:05 +01:00
|
|
|
class Protocol_binary :public Protocol
|
2002-12-11 08:17:51 +01:00
|
|
|
{
|
|
|
|
private:
|
2003-01-15 09:11:44 +01:00
|
|
|
uint bit_fields;
|
2002-12-11 08:17:51 +01:00
|
|
|
public:
|
2007-01-30 22:48:05 +01:00
|
|
|
Protocol_binary() {}
|
|
|
|
Protocol_binary(THD *thd_arg) :Protocol(thd_arg) {}
|
2002-12-11 08:17:51 +01:00
|
|
|
virtual bool prepare_for_send(List<Item> *item_list);
|
|
|
|
virtual void prepare_for_resend();
|
2003-09-17 17:48:53 +02:00
|
|
|
#ifdef EMBEDDED_LIBRARY
|
|
|
|
virtual bool write();
|
2003-09-18 09:25:00 +02:00
|
|
|
bool net_store_data(const char *from, uint length);
|
2003-09-17 17:48:53 +02:00
|
|
|
#endif
|
2002-12-11 08:17:51 +01:00
|
|
|
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);
|
2005-02-08 23:50:45 +01:00
|
|
|
virtual bool store_decimal(const my_decimal *);
|
2003-03-17 10:14:04 +01:00
|
|
|
virtual bool store(const char *from,uint length, CHARSET_INFO *cs);
|
2003-04-07 10:52:48 +02:00
|
|
|
virtual bool store(const char *from, uint length,
|
|
|
|
CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
|
2002-12-11 08:17:51 +01:00
|
|
|
virtual bool store(TIME *time);
|
|
|
|
virtual bool store_date(TIME *time);
|
|
|
|
virtual bool store_time(TIME *time);
|
|
|
|
virtual bool store(float nr, uint32 decimals, String *buffer);
|
|
|
|
virtual bool store(double from, uint32 decimals, String *buffer);
|
|
|
|
virtual bool store(Field *field);
|
Fix for BUG#735 "Prepared Statements: there is no support for Query
Cache".
WL#1569 "Prepared Statements: implement support of Query Cache".
Prepared SELECTs did not look up in the query cache, and their results
were not stored in the query cache. This made them slower than
non-prepared SELECTs in some cases.
The fix is to re-use the expanded query (the prepared query where
"?" placeholders are replaced by their values, at execution time)
for searching/storing in the query cache.
It works fine for statements prepared via mysql_stmt_prepare(), which
are the most commonly used and were the scope of this bugfix and WL.
It works less fine for statements prepared via the SQL command
PREPARE...FROM, which are still not using the query cache if they
have at least one parameter (because then the expanded query contains
names of user variables, and user variables don't work with the
query cache, even in non-prepared queries).
Note that results from prepared SELECTs, which are in the binary
protocol, and results from normal SELECTs, which are in the text
protocol, ignore each other in the query cache, because a result in the
binary protocol should never be served to a SELECT expecting the text
protocol and vice-versa.
Note, after this patch, bug 25843 starts applying to query cache
("changing default database between PREPARE and EXECUTE of statement
breaks binlog"), we need to fix it.
mysql-test/include/have_query_cache.inc:
Now prepared statements work with the query cache, so don't disable
prep stmts by default when doing a query cache test. All tests which
include this file will now be really tested against prepared
statements (in particular, query_cache.test).
mysql-test/r/query_cache.result:
result update
mysql-test/t/grant_cache.test:
Cannot enable this test in ps-protocol, because in normal protocol,
a SELECT failing due to insufficient privileges increments
Qcache_not_cached, while in ps-protocol, no.
In detail: in normal protocol,
the "access denied" errors on SELECT are issued at (stack trace):
mysql_parse/mysql_execute_command/execute_sqlcom_select/handle_select/
mysql_select/JOIN::prepare/setup_wild/insert_fields/
check_grant_all_columns/my_error/my_message_sql, which then calls
push_warning/query_cache_abort: at this moment,
query_cache_store_query() has been called, so query exists in cache,
so thd->net.query_cache_query!=NULL, so query_cache_abort() removes
the query from cache, which causes a query_cache.refused++ (thus,
a Qcache_not_cached++).
While in ps-protocol, the error is issued at prepare time;
for this mysql_test_select() is called, not execute_sqlcom_select()
(and that also leads to JOIN::prepare/etc). Thus, as
query_cache_store_query() has not been called,
thd->net.query_cache_query==NULL, so query_cache_abort() does nothing:
Qcache_not_cached is not incremented.
As this test prints Qcache_not_cached after SELECT failures,
we cannot enable this test in ps-protocol.
mysql-test/t/ndb_cache_multi2.test:
The principle of this test is: two mysqlds connected to one cluster,
both using their query cache. Queries are cached in server1
("select a!=3 from t1", "select * from t1"),
table t1 is modified in server2, we want to see that this invalidates
the query cache of server1. Invalidation with NDB works like this:
when a query is found in the query cache, NDB is asked if the tables
have changed. In this test, ha_ndbcluster calls NDB every millisecond
to collect change information about tables.
Due to this millisecond delay, there is need for a loop ("while...")
in this test, which waits until a query1 ("select a!=3 from t1") is
invalidated (which is equivalent to it returning
up-to-date results), and then expects query2 ("select * from t1")
to have been invalidated (see up-to-date results).
But when enabling --ps-protocol in this test, the logic breaks,
because query1 is still done via mysql_real_query() (see mysqltest.c:
eval_expr() always uses mysql_real_query()). So, query1 returning
up-to-date results is not a sign of it being invalidated in the cache,
because it was NOT in the cache ("select a!=3 from t1" on line 39
was done with prep stmts, while `select a!=3 from t1` is not,
thus the second does not see the first in the cache). Thus, we may run
query2 when cache still has not been invalidated.
The solution is to make the initial "select a!=3 from t1" run
as a normal query, this repairs the broken logic.
But note, "select * from t1" is still using prepared statements
which was the goal of this test with --ps-protocol.
mysql-test/t/query_cache.test:
now that prepared statements work with the query cache, we check
that results in binary protocol (prepared statements) and in text
protocol (normal queries) don't mix in the query cache even though
the text of the statement/query are identical.
sql/mysql_priv.h:
In class Query_cache_flags, we add a bit to say if the result
is in binary or text format (because, a result in binary format
should never be served to a query expecting text format, and vice-
versa).
A macro to emphasize that we read the size of the query cache
without mutex ("maybe" word).
A macro which gives a first indication of if a query is cache-able
(first indication - it does not consider the query cache's state).
sql/protocol.cc:
indentation.
sql/protocol.h:
Children classes of Protocol report their type (currently,
text or binary). Query cache needs to know that.
sql/sql_cache.cc:
When we store a result in the query cache, we need to remember if it's
in binary or text format. And when we search for a result in the query
cache, we need to select only those results which are in the format
which the current statement expects (binary or text).
sql/sql_prepare.cc:
Enabling use of the query cache by prepared statements.
1) Prep stmts are of two types:
a) prepared via the mysql_stmt_prepare() API call
b) prepared via the SQL PREPARE...FROM statement.
2) We already, when executing a prepared statement, sometimes built an
"expanded" statement. For a), "?" placeholders were replaced by their
values. For b), by names of the user variables containing the values.
We did that only when we needed to write the query to logs.
We now use this expanded query also for storing/searching
in the query cache.
Assume a query "SELECT * FROM T WHERE c=?", and the parameter is 10.
For a), the expanded query is "SELECT * FROM T WHERE c=10", we look
for "SELECT * FROM T WHERE c=10" in the query cache, and store that
query's result in the query cache.
For b), the expanded query is "SELECT * FROM T WHERE c=@somevar", and
user variables don't work with the query cache (even inside non-
prepared queries), so we don't enable query caching for SQL PREPARE'd
statements if they have at least one parameter (see
"if (stmt->param_count > 0)" in the patch).
3) If query cache is enabled and this is a SELECT, we build the
expanded query (as an optimisation, we don't want to build this
expanded query if the query cache is disabled or this is not a SELECT).
As the decision of building the expanded query or not is taken
at prepare time (setup_set_params()), if query cache is disabled
at prepare time, we won't build the expanded query at all next
executions, thus shouldn't use this query for query cacheing.
To ensure that we don't, we set safe_to_cache_query to FALSE.
Note that we read the size of the query cache without mutex, which is
ok: if we see it 0 but that cache has just been enlarged, no big deal,
just our statement will not use the query cache; if we see it >0 but
that cache has just been made destroyed, we'll build the expanded
query at all executions, but query_cache_store_query() and
query_cache_send_result_to_client() will read the size with a mutex
and so properly decide to cache or not cache.
4) Some functions in this file were named "withlog", others "with_log",
now using "with_log" for all.
tests/mysql_client_test.c:
Testing of how prepared statements enter and hit the query cache.
test_ps_query_cache() is inspired from test_ps_conj_select().
It creates data, a prepared SELECT statement, executes it once,
then a second time with the same parameter value, to see that cache
is hit, then a 3rd time with another parameter value to see that cache
is not hit. Then, same from another connection, expecting hits.
Then, tests border cases (enables query cache at prepare and disables
at execute and vice-versa).
It checks all results of SELECTs, cache hits and misses.
mysql-test/r/query_cache_sql_prepare.result:
result of new test: we see hits when there is no parameter,
no hit when there is a parameter.
mysql-test/t/query_cache_sql_prepare.test:
new test to see if SQL PREPARE'd statements enter/hit the query cache:
- if having at least one parameter, they should not
- if having zero parameters, they should.
2007-03-09 18:09:57 +01:00
|
|
|
virtual enum enum_protocol_type type() { return PROTOCOL_BINARY; };
|
2002-12-11 08:17:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
void send_warning(THD *thd, uint sql_errno, const char *err=0);
|
2004-10-20 15:06:54 +02:00
|
|
|
void net_printf_error(THD *thd, uint sql_errno, ...);
|
|
|
|
void net_send_error(THD *thd, uint sql_errno=0, const char *err=0);
|
2002-12-11 08:17:51 +01:00
|
|
|
void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
|
|
|
|
const char *info=0);
|
2005-06-30 14:17:10 +02:00
|
|
|
void send_eof(THD *thd);
|
2003-07-18 16:25:54 +02:00
|
|
|
bool send_old_password_request(THD *thd);
|
2002-12-11 08:17:51 +01:00
|
|
|
char *net_store_data(char *to,const char *from, uint length);
|
|
|
|
char *net_store_data(char *to,int32 from);
|
|
|
|
char *net_store_data(char *to,longlong from);
|
2003-09-17 17:48:53 +02:00
|
|
|
|