mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
WL#2930 Adding view and cursor 'protocols' to mysqltest
- Part2, actually adding the new functionality client/mysqltest.c: adding the new functionality run with views, cursor and stored procedures mysql-test/mysql-test-run.pl: Adding new switches
This commit is contained in:
@@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
#define MTEST_VERSION "2.5"
|
#define MTEST_VERSION "2.6"
|
||||||
|
|
||||||
#include <my_global.h>
|
#include <my_global.h>
|
||||||
#include <mysql_embed.h>
|
#include <mysql_embed.h>
|
||||||
@@ -108,7 +108,8 @@
|
|||||||
enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD,
|
enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD,
|
||||||
OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC,
|
OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC,
|
||||||
OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH,
|
OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH,
|
||||||
OPT_SSL_CIPHER,OPT_PS_PROTOCOL};
|
OPT_SSL_CIPHER,OPT_PS_PROTOCOL,OPT_SP_PROTOCOL,OPT_CURSOR_PROTOCOL,
|
||||||
|
OPT_VIEW_PROTOCOL};
|
||||||
|
|
||||||
/* ************************************************************************ */
|
/* ************************************************************************ */
|
||||||
/*
|
/*
|
||||||
@@ -158,7 +159,11 @@ static char *db = 0, *pass=0;
|
|||||||
const char *user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./";
|
const char *user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./";
|
||||||
static int port = 0;
|
static int port = 0;
|
||||||
static my_bool opt_big_test= 0, opt_compress= 0, silent= 0, verbose = 0;
|
static my_bool opt_big_test= 0, opt_compress= 0, silent= 0, verbose = 0;
|
||||||
static my_bool tty_password= 0, ps_protocol= 0, ps_protocol_enabled= 0;
|
static my_bool tty_password= 0;
|
||||||
|
static my_bool ps_protocol= 0, ps_protocol_enabled= 0;
|
||||||
|
static my_bool sp_protocol= 0, sp_protocol_enabled= 0;
|
||||||
|
static my_bool view_protocol= 0, view_protocol_enabled= 0;
|
||||||
|
static my_bool cursor_protocol= 0, cursor_protocol_enabled= 0;
|
||||||
static int parsing_disabled= 0;
|
static int parsing_disabled= 0;
|
||||||
static uint start_lineno, *lineno;
|
static uint start_lineno, *lineno;
|
||||||
const char *manager_user="root",*manager_host=0;
|
const char *manager_user="root",*manager_host=0;
|
||||||
@@ -212,11 +217,14 @@ static int got_end_timer= FALSE;
|
|||||||
static void timer_output(void);
|
static void timer_output(void);
|
||||||
static ulonglong timer_now(void);
|
static ulonglong timer_now(void);
|
||||||
|
|
||||||
static my_regex_t ps_re; /* Holds precompiled re for valid PS statements */
|
/* Precompiled re's */
|
||||||
static void ps_init_re(void);
|
static my_regex_t ps_re; /* the query can be run using PS protocol */
|
||||||
static int ps_match_re(char *);
|
static my_regex_t sp_re; /* the query can be run as a SP */
|
||||||
static char *ps_eprint(int);
|
static my_regex_t view_re; /* the query can be run as a view*/
|
||||||
static void ps_free_reg(void);
|
|
||||||
|
static void init_re(void);
|
||||||
|
static int match_re(my_regex_t *, char *);
|
||||||
|
static void free_re(void);
|
||||||
|
|
||||||
static const char *embedded_server_groups[]=
|
static const char *embedded_server_groups[]=
|
||||||
{
|
{
|
||||||
@@ -240,6 +248,7 @@ struct connection
|
|||||||
{
|
{
|
||||||
MYSQL mysql;
|
MYSQL mysql;
|
||||||
char *name;
|
char *name;
|
||||||
|
MYSQL_STMT* stmt;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -433,7 +442,6 @@ static VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
|
|||||||
|
|
||||||
static void var_free(void* v);
|
static void var_free(void* v);
|
||||||
|
|
||||||
int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname);
|
|
||||||
void dump_result_to_reject_file(const char *record_file, char *buf, int size);
|
void dump_result_to_reject_file(const char *record_file, char *buf, int size);
|
||||||
|
|
||||||
int close_connection(struct st_query*);
|
int close_connection(struct st_query*);
|
||||||
@@ -539,6 +547,9 @@ static void close_cons()
|
|||||||
DBUG_ENTER("close_cons");
|
DBUG_ENTER("close_cons");
|
||||||
for (--next_con; next_con >= cons; --next_con)
|
for (--next_con; next_con >= cons; --next_con)
|
||||||
{
|
{
|
||||||
|
if (next_con->stmt)
|
||||||
|
mysql_stmt_close(next_con->stmt);
|
||||||
|
next_con->stmt= 0;
|
||||||
mysql_close(&next_con->mysql);
|
mysql_close(&next_con->mysql);
|
||||||
my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR));
|
my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR));
|
||||||
}
|
}
|
||||||
@@ -593,8 +604,7 @@ static void free_used_memory()
|
|||||||
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
|
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
|
||||||
free_defaults(default_argv);
|
free_defaults(default_argv);
|
||||||
mysql_server_end();
|
mysql_server_end();
|
||||||
if (ps_protocol)
|
free_re();
|
||||||
ps_free_reg();
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -660,7 +670,7 @@ void init_parser()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
|
static int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
|
||||||
{
|
{
|
||||||
MY_STAT stat_info;
|
MY_STAT stat_info;
|
||||||
char *tmp, *res_ptr;
|
char *tmp, *res_ptr;
|
||||||
@@ -2715,6 +2725,15 @@ static struct my_option my_long_options[] =
|
|||||||
{"ps-protocol", OPT_PS_PROTOCOL, "Use prepared statements protocol for communication",
|
{"ps-protocol", OPT_PS_PROTOCOL, "Use prepared statements protocol for communication",
|
||||||
(gptr*) &ps_protocol, (gptr*) &ps_protocol, 0,
|
(gptr*) &ps_protocol, (gptr*) &ps_protocol, 0,
|
||||||
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
|
{"sp-protocol", OPT_SP_PROTOCOL, "Use stored procedures for select",
|
||||||
|
(gptr*) &sp_protocol, (gptr*) &sp_protocol, 0,
|
||||||
|
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
|
{"cursor-protocol", OPT_CURSOR_PROTOCOL, "Use cursors for prepared statment",
|
||||||
|
(gptr*) &cursor_protocol, (gptr*) &cursor_protocol, 0,
|
||||||
|
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
|
{"view-protocol", OPT_VIEW_PROTOCOL, "Use views for select",
|
||||||
|
(gptr*) &view_protocol, (gptr*) &view_protocol, 0,
|
||||||
|
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
{"quiet", 's', "Suppress all normal output.", (gptr*) &silent,
|
{"quiet", 's', "Suppress all normal output.", (gptr*) &silent,
|
||||||
(gptr*) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
(gptr*) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
{"record", 'r', "Record output of test_file into result file.",
|
{"record", 'r', "Record output of test_file into result file.",
|
||||||
@@ -2776,8 +2795,6 @@ void usage()
|
|||||||
|
|
||||||
#include <help_end.h>
|
#include <help_end.h>
|
||||||
|
|
||||||
#include <help_end.h>
|
|
||||||
|
|
||||||
|
|
||||||
static my_bool
|
static my_bool
|
||||||
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
||||||
@@ -3222,6 +3239,7 @@ static void append_table_headings(DYNAMIC_STRING* ds,
|
|||||||
static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
|
static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
|
||||||
{
|
{
|
||||||
uint count;
|
uint count;
|
||||||
|
MYSQL_RES *warn_res;
|
||||||
DBUG_ENTER("append_warnings");
|
DBUG_ENTER("append_warnings");
|
||||||
|
|
||||||
if (!(count= mysql_warning_count(mysql)))
|
if (!(count= mysql_warning_count(mysql)))
|
||||||
@@ -3237,12 +3255,10 @@ static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
|
|||||||
if (mysql_real_query(mysql, "SHOW WARNINGS", 13))
|
if (mysql_real_query(mysql, "SHOW WARNINGS", 13))
|
||||||
die("Error running query \"SHOW WARNINGS\": %s", mysql_error(mysql));
|
die("Error running query \"SHOW WARNINGS\": %s", mysql_error(mysql));
|
||||||
|
|
||||||
MYSQL_RES *warn_res= mysql_store_result(mysql);
|
if (!(warn_res= mysql_store_result(mysql)))
|
||||||
if (!warn_res)
|
|
||||||
die("Warning count is %u but didn't get any warnings",
|
die("Warning count is %u but didn't get any warnings",
|
||||||
count);
|
count);
|
||||||
|
|
||||||
|
|
||||||
dynstr_append_mem(ds, "Warnings:\n", 10);
|
dynstr_append_mem(ds, "Warnings:\n", 10);
|
||||||
append_result(ds, warn_res);
|
append_result(ds, warn_res);
|
||||||
mysql_free_result(warn_res);
|
mysql_free_result(warn_res);
|
||||||
@@ -3258,6 +3274,7 @@ static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
|
|||||||
run_query_normal
|
run_query_normal
|
||||||
mysql - mysql handle
|
mysql - mysql handle
|
||||||
command - currrent command pointer
|
command - currrent command pointer
|
||||||
|
flags -flags indicating wheter to SEND and/or REAP
|
||||||
query - query string to execute
|
query - query string to execute
|
||||||
query_len - length query string to execute
|
query_len - length query string to execute
|
||||||
ds - output buffer wherte to store result form query
|
ds - output buffer wherte to store result form query
|
||||||
@@ -3279,7 +3296,7 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command,
|
|||||||
if (flags & QUERY_SEND)
|
if (flags & QUERY_SEND)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Send the query, using the undocumented function mysql_send_query
|
Send the query
|
||||||
*/
|
*/
|
||||||
if (mysql_send_query(mysql, query, query_len))
|
if (mysql_send_query(mysql, query, query_len))
|
||||||
{
|
{
|
||||||
@@ -3295,7 +3312,7 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command,
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
When on first result set, call mysql_read_query_result to retrrieve
|
When on first result set, call mysql_read_query_result to retrieve
|
||||||
answer to the query sent earlier
|
answer to the query sent earlier
|
||||||
*/
|
*/
|
||||||
if ((counter==0) && mysql_read_query_result(mysql))
|
if ((counter==0) && mysql_read_query_result(mysql))
|
||||||
@@ -3526,17 +3543,19 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
|
|||||||
{
|
{
|
||||||
MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */
|
MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */
|
||||||
MYSQL_STMT *stmt;
|
MYSQL_STMT *stmt;
|
||||||
|
DYNAMIC_STRING ds_prepare_warnings;
|
||||||
DBUG_ENTER("run_query_stmt");
|
DBUG_ENTER("run_query_stmt");
|
||||||
DBUG_PRINT("query", ("'%-.60s'", query));
|
DBUG_PRINT("query", ("'%-.60s'", query));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We must allocate a new stmt for each query in this program because this
|
Init a new stmt if it's not alreday one created for this connectoon
|
||||||
may be a new connection.
|
|
||||||
|
|
||||||
Well, it could be stored togeter with mysql pointer in cur_con struct
|
|
||||||
*/
|
*/
|
||||||
|
if(!(stmt= cur_con->stmt))
|
||||||
|
{
|
||||||
if (!(stmt= mysql_stmt_init(mysql)))
|
if (!(stmt= mysql_stmt_init(mysql)))
|
||||||
die("unable to init stmt structure");
|
die("unable to init stmt structure");
|
||||||
|
cur_con->stmt= stmt;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Prepare the query
|
Prepare the query
|
||||||
@@ -3548,11 +3567,36 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the warnings from mysql_stmt_prepare and keep them in a
|
||||||
|
separate string
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!disable_warnings)
|
||||||
|
{
|
||||||
|
init_dynamic_string(&ds_prepare_warnings, "", 1024, 1024);
|
||||||
|
append_warnings(&ds_prepare_warnings, mysql);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
No need to call mysql_stmt_bind_param() because we have no
|
No need to call mysql_stmt_bind_param() because we have no
|
||||||
parameter markers.
|
parameter markers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef BUG14013_FIXED
|
||||||
|
/*
|
||||||
|
Use cursor when retrieving result
|
||||||
|
*/
|
||||||
|
if (cursor_protocol_enabled)
|
||||||
|
{
|
||||||
|
unsigned long type= CURSOR_TYPE_READ_ONLY;
|
||||||
|
if (mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type))
|
||||||
|
die("mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s",
|
||||||
|
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Execute the query
|
Execute the query
|
||||||
*/
|
*/
|
||||||
@@ -3571,7 +3615,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
|
|||||||
{
|
{
|
||||||
my_bool one= 1;
|
my_bool one= 1;
|
||||||
if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one))
|
if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one))
|
||||||
die("mysql_stmt_attr_set failed': %d %s",
|
die("mysql_stmt_attr_set(STMT_ATTR_UPDATE_MAX_LENGTH) failed': %d %s",
|
||||||
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
|
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3589,14 +3633,14 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
|
|||||||
/* If we got here the statement was both executed and read succeesfully */
|
/* If we got here the statement was both executed and read succeesfully */
|
||||||
handle_no_error(command);
|
handle_no_error(command);
|
||||||
|
|
||||||
|
if (!disable_result_log)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
Not all statements creates a result set. If there is one we can
|
Not all statements creates a result set. If there is one we can
|
||||||
now create another normal result set that contains the meta
|
now create another normal result set that contains the meta
|
||||||
data. This set can be handled almost like any other non prepared
|
data. This set can be handled almost like any other non prepared
|
||||||
statement result set.
|
statement result set.
|
||||||
*/
|
*/
|
||||||
if (!disable_result_log)
|
|
||||||
{
|
|
||||||
if ((res= mysql_stmt_result_metadata(stmt)) != NULL)
|
if ((res= mysql_stmt_result_metadata(stmt)) != NULL)
|
||||||
{
|
{
|
||||||
/* Take the column count from meta info */
|
/* Take the column count from meta info */
|
||||||
@@ -3614,29 +3658,44 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
|
|||||||
mysql_free_result(res); /* Free normal result set with meta data */
|
mysql_free_result(res); /* Free normal result set with meta data */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
This is a query without resultset
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add warnings from prepare to output
|
||||||
|
*/
|
||||||
|
if (!disable_warnings)
|
||||||
|
dynstr_append(ds, ds_prepare_warnings.str);
|
||||||
|
}
|
||||||
|
|
||||||
if (!disable_warnings)
|
if (!disable_warnings)
|
||||||
append_warnings(ds, mysql);
|
append_warnings(ds, mysql);
|
||||||
|
|
||||||
if (!disable_info)
|
if (!disable_info)
|
||||||
append_info(ds, (ulong)mysql_affected_rows(mysql), mysql_info(mysql));
|
append_info(ds, (ulong)mysql_affected_rows(mysql), mysql_info(mysql));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
free_replace();
|
free_replace();
|
||||||
|
|
||||||
|
if (!disable_warnings)
|
||||||
|
dynstr_free(&ds_prepare_warnings);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We save the return code (mysql_stmt_errno(stmt)) from the last call sent
|
We save the return code (mysql_stmt_errno(stmt)) from the last call sent
|
||||||
to the server into the mysqltest builtin variable $mysql_errno. This
|
to the server into the mysqltest builtin variable $mysql_errno. This
|
||||||
variable then can be used from the test case itself.
|
variable then can be used from the test case itself.
|
||||||
*/
|
*/
|
||||||
var_set_errno(mysql_stmt_errno(stmt));
|
var_set_errno(mysql_stmt_errno(stmt));
|
||||||
mysql_stmt_close(stmt);
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Run query
|
Run query
|
||||||
|
|
||||||
flags control the phased/stages of query execution to be performed
|
flags control the phased/stages of query execution to be performed
|
||||||
@@ -3653,10 +3712,12 @@ end:
|
|||||||
static void run_query(MYSQL *mysql, struct st_query *command, int flags)
|
static void run_query(MYSQL *mysql, struct st_query *command, int flags)
|
||||||
{
|
{
|
||||||
DYNAMIC_STRING *ds;
|
DYNAMIC_STRING *ds;
|
||||||
DYNAMIC_STRING ds_tmp;
|
DYNAMIC_STRING ds_result;
|
||||||
DYNAMIC_STRING eval_query;
|
DYNAMIC_STRING eval_query;
|
||||||
char *query;
|
char *query;
|
||||||
int query_len;
|
int query_len;
|
||||||
|
my_bool view_created= 0, sp_created= 0;
|
||||||
|
my_bool complete_query= ((flags & QUERY_SEND) && (flags & QUERY_REAP));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Evaluate query if this is an eval command
|
Evaluate query if this is an eval command
|
||||||
@@ -3682,13 +3743,15 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags)
|
|||||||
*/
|
*/
|
||||||
if (command->record_file[0])
|
if (command->record_file[0])
|
||||||
{
|
{
|
||||||
init_dynamic_string(&ds_tmp, "", 16384, 65536);
|
init_dynamic_string(&ds_result, "", 16384, 65536);
|
||||||
ds= &ds_tmp;
|
ds= &ds_result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ds= &ds_res;
|
ds= &ds_res;
|
||||||
|
|
||||||
/* Store the query into the output buffer */
|
/*
|
||||||
|
Log the query into the output buffer
|
||||||
|
*/
|
||||||
if (!disable_query_log && (flags & QUERY_SEND))
|
if (!disable_query_log && (flags & QUERY_SEND))
|
||||||
{
|
{
|
||||||
replace_dynstr_append_mem(ds, query, query_len);
|
replace_dynstr_append_mem(ds, query, query_len);
|
||||||
@@ -3696,22 +3759,107 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags)
|
|||||||
dynstr_append_mem(ds, "\n", 1);
|
dynstr_append_mem(ds, "\n", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (view_protocol_enabled &&
|
||||||
|
complete_query &&
|
||||||
|
match_re(&view_re, query))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Create the query as a view.
|
||||||
|
Use replace since view can exist from a failed mysqltest run
|
||||||
|
*/
|
||||||
|
DYNAMIC_STRING query_str;
|
||||||
|
init_dynamic_string(&query_str,
|
||||||
|
"CREATE OR REPLACE VIEW mysqltest_tmp_v AS ",
|
||||||
|
query_len+64, 256);
|
||||||
|
dynstr_append_mem(&query_str, query, query_len);
|
||||||
|
if (mysql_query(mysql, query_str.str))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Failed to create the view, this is not fatal
|
||||||
|
just run the query the normal way
|
||||||
|
*/
|
||||||
|
DBUG_PRINT("view_create_error",
|
||||||
|
("Failed to create view '%s': %d: %s", query_str.str,
|
||||||
|
mysql_errno(mysql), mysql_error(mysql)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Yes, it was possible to create this query as a view
|
||||||
|
*/
|
||||||
|
view_created= 1;
|
||||||
|
query= (char*)"SELECT * FROM mysqltest_tmp_v";
|
||||||
|
query_len = strlen(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
dynstr_free(&query_str);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sp_protocol_enabled &&
|
||||||
|
complete_query &&
|
||||||
|
match_re(&sp_re, query))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Create the query as a stored procedure
|
||||||
|
Drop first since sp can exist from a failed mysqltest run
|
||||||
|
*/
|
||||||
|
DYNAMIC_STRING query_str;
|
||||||
|
init_dynamic_string(&query_str,
|
||||||
|
"DROP PROCEDURE IF EXISTS mysqltest_tmp_sp;\n",
|
||||||
|
query_len+64, 256);
|
||||||
|
mysql_query(mysql, query_str.str);
|
||||||
|
dynstr_set(&query_str, "CREATE PROCEDURE mysqltest_tmp_sp()\n");
|
||||||
|
dynstr_append_mem(&query_str, query, query_len);
|
||||||
|
if (mysql_query(mysql, query_str.str))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Failed to create the stored procedure for this query,
|
||||||
|
this is not fatal just run the query the normal way
|
||||||
|
*/
|
||||||
|
DBUG_PRINT("sp_create_error",
|
||||||
|
("Failed to create sp '%s': %d: %s", query_str.str,
|
||||||
|
mysql_errno(mysql), mysql_error(mysql)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sp_created= 1;
|
||||||
|
|
||||||
|
query= (char*)"CALL mysqltest_tmp_sp()";
|
||||||
|
query_len = strlen(query);
|
||||||
|
}
|
||||||
|
dynstr_free(&query_str);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Find out how to run this query
|
Find out how to run this query
|
||||||
|
|
||||||
We don't have a mysql_stmt_send_execute() so it must be a
|
Always run with normal C API if it's not a complete
|
||||||
complete SEND+REAP to use prepared statement
|
SEND + REAP
|
||||||
|
|
||||||
If it is a '?' in the query it may be a SQL level prepared
|
If it is a '?' in the query it may be a SQL level prepared
|
||||||
statement already and we can't do it twice
|
statement already and we can't do it twice
|
||||||
*/
|
*/
|
||||||
if (ps_protocol_enabled &&
|
if (ps_protocol_enabled &&
|
||||||
(flags & QUERY_SEND) && (flags & QUERY_REAP) &&
|
complete_query &&
|
||||||
ps_match_re(query))
|
match_re(&ps_re, query))
|
||||||
run_query_stmt(mysql, command, query, query_len, ds);
|
run_query_stmt(mysql, command, query, query_len, ds);
|
||||||
else
|
else
|
||||||
run_query_normal(mysql, command, flags, query, query_len, ds);
|
run_query_normal(mysql, command, flags, query, query_len, ds);
|
||||||
|
|
||||||
|
if (sp_created)
|
||||||
|
{
|
||||||
|
if (mysql_query(mysql, "DROP PROCEDURE mysqltest_tmp_sp "))
|
||||||
|
die("Failed to drop sp: %d: %s", mysql_errno(mysql), mysql_error(mysql));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (view_created)
|
||||||
|
{
|
||||||
|
if (mysql_query(mysql, "DROP VIEW mysqltest_tmp_v "))
|
||||||
|
die("Failed to drop view: %d: %s",
|
||||||
|
mysql_errno(mysql), mysql_error(mysql));
|
||||||
|
}
|
||||||
|
|
||||||
if (record)
|
if (record)
|
||||||
{
|
{
|
||||||
/* Recording in progress */
|
/* Recording in progress */
|
||||||
@@ -3730,19 +3878,45 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags)
|
|||||||
check_result(ds, command->record_file, command->require_file);
|
check_result(ds, command->record_file, command->require_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ds == &ds_tmp)
|
if (ds == &ds_result)
|
||||||
dynstr_free(&ds_tmp);
|
dynstr_free(&ds_result);
|
||||||
if (command->type == Q_EVAL)
|
if (command->type == Q_EVAL)
|
||||||
dynstr_free(&eval_query);
|
dynstr_free(&eval_query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************\
|
/****************************************************************************\
|
||||||
* Functions to match SQL statements that can be prepared
|
* Functions to detect different SQL statements
|
||||||
\****************************************************************************/
|
\****************************************************************************/
|
||||||
|
|
||||||
static void ps_init_re(void)
|
static char *re_eprint(int err)
|
||||||
{
|
{
|
||||||
|
static char epbuf[100];
|
||||||
|
size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL,
|
||||||
|
epbuf, sizeof(epbuf));
|
||||||
|
assert(len <= sizeof(epbuf));
|
||||||
|
return(epbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_re_comp(my_regex_t *re, const char* str)
|
||||||
|
{
|
||||||
|
int err= my_regcomp(re, str, (REG_EXTENDED | REG_ICASE | REG_NOSUB),
|
||||||
|
&my_charset_latin1);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
char erbuf[100];
|
||||||
|
int len= my_regerror(err, re, erbuf, sizeof(erbuf));
|
||||||
|
die("error %s, %d/%d `%s'\n",
|
||||||
|
re_eprint(err), len, (int)sizeof(erbuf), erbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_re(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Filter for queries that can be run using the
|
||||||
|
MySQL Prepared Statements C API
|
||||||
|
*/
|
||||||
const char *ps_re_str =
|
const char *ps_re_str =
|
||||||
"^("
|
"^("
|
||||||
"[[:space:]]*REPLACE[[:space:]]|"
|
"[[:space:]]*REPLACE[[:space:]]|"
|
||||||
@@ -3757,50 +3931,48 @@ static void ps_init_re(void)
|
|||||||
"[[:space:]]*UPDATE[[:space:]]+MULTI[[:space:]]|"
|
"[[:space:]]*UPDATE[[:space:]]+MULTI[[:space:]]|"
|
||||||
"[[:space:]]*INSERT[[:space:]]+SELECT[[:space:]])";
|
"[[:space:]]*INSERT[[:space:]]+SELECT[[:space:]])";
|
||||||
|
|
||||||
int err= my_regcomp(&ps_re, ps_re_str,
|
/*
|
||||||
(REG_EXTENDED | REG_ICASE | REG_NOSUB),
|
Filter for queries that can be run using the
|
||||||
&my_charset_latin1);
|
Stored procedures
|
||||||
if (err)
|
*/
|
||||||
{
|
const char *sp_re_str =ps_re_str;
|
||||||
char erbuf[100];
|
|
||||||
int len= my_regerror(err, &ps_re, erbuf, sizeof(erbuf));
|
/*
|
||||||
fprintf(stderr, "error %s, %d/%d `%s'\n",
|
Filter for queries that can be run as views
|
||||||
ps_eprint(err), len, (int)sizeof(erbuf), erbuf);
|
*/
|
||||||
exit(1);
|
const char *view_re_str =
|
||||||
}
|
"^("
|
||||||
|
"[[:space:]]*SELECT[[:space:]])";
|
||||||
|
|
||||||
|
init_re_comp(&ps_re, ps_re_str);
|
||||||
|
init_re_comp(&sp_re, sp_re_str);
|
||||||
|
init_re_comp(&view_re, view_re_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int ps_match_re(char *stmt_str)
|
static int match_re(my_regex_t *re, char *str)
|
||||||
{
|
{
|
||||||
int err= my_regexec(&ps_re, stmt_str, (size_t)0, NULL, 0);
|
int err= my_regexec(re, str, (size_t)0, NULL, 0);
|
||||||
|
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
return 1;
|
return 1;
|
||||||
else if (err == REG_NOMATCH)
|
else if (err == REG_NOMATCH)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
|
||||||
{
|
{
|
||||||
char erbuf[100];
|
char erbuf[100];
|
||||||
int len= my_regerror(err, &ps_re, erbuf, sizeof(erbuf));
|
int len= my_regerror(err, re, erbuf, sizeof(erbuf));
|
||||||
fprintf(stderr, "error %s, %d/%d `%s'\n",
|
die("error %s, %d/%d `%s'\n",
|
||||||
ps_eprint(err), len, (int)sizeof(erbuf), erbuf);
|
re_eprint(err), len, (int)sizeof(erbuf), erbuf);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ps_eprint(int err)
|
static void free_re(void)
|
||||||
{
|
|
||||||
static char epbuf[100];
|
|
||||||
size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL, epbuf, sizeof(epbuf));
|
|
||||||
assert(len <= sizeof(epbuf));
|
|
||||||
return(epbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void ps_free_reg(void)
|
|
||||||
{
|
{
|
||||||
my_regfree(&ps_re);
|
my_regfree(&ps_re);
|
||||||
|
my_regfree(&sp_re);
|
||||||
|
my_regfree(&view_re);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
@@ -3930,8 +4102,7 @@ static void init_var_hash(MYSQL *mysql)
|
|||||||
v= var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "62",0);
|
v= var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "62",0);
|
||||||
my_hash_insert(&var_hash, (byte*) v);
|
my_hash_insert(&var_hash, (byte*) v);
|
||||||
v= var_init(0,"SERVER_VERSION", 0, mysql_get_server_info(mysql), 0);
|
v= var_init(0,"SERVER_VERSION", 0, mysql_get_server_info(mysql), 0);
|
||||||
my_hash_insert(&var_hash, (byte*) v);
|
my_hash_insert(&var_hash, (byte*) v); v= var_init(0,"DB", 2, db, 0);
|
||||||
v= var_init(0,"DB", 2, db, 0);
|
|
||||||
my_hash_insert(&var_hash, (byte*) v);
|
my_hash_insert(&var_hash, (byte*) v);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@@ -3988,11 +4159,15 @@ int main(int argc, char **argv)
|
|||||||
if (manager_host)
|
if (manager_host)
|
||||||
init_manager();
|
init_manager();
|
||||||
#endif
|
#endif
|
||||||
if (ps_protocol)
|
init_re();
|
||||||
{
|
ps_protocol_enabled= ps_protocol;
|
||||||
|
sp_protocol_enabled= sp_protocol;
|
||||||
|
view_protocol_enabled= view_protocol;
|
||||||
|
cursor_protocol_enabled= cursor_protocol;
|
||||||
|
/* Cursor protcol implies ps protocol */
|
||||||
|
if (cursor_protocol_enabled)
|
||||||
ps_protocol_enabled= 1;
|
ps_protocol_enabled= 1;
|
||||||
ps_init_re();
|
|
||||||
}
|
|
||||||
if (!( mysql_init(&cur_con->mysql)))
|
if (!( mysql_init(&cur_con->mysql)))
|
||||||
die("Failed in mysql_init()");
|
die("Failed in mysql_init()");
|
||||||
if (opt_compress)
|
if (opt_compress)
|
||||||
@@ -5282,3 +5457,5 @@ FILE *my_popen(const char *cmd, const char *mode __attribute__((unused)))
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __NETWARE__ or __WIN__*/
|
#endif /* __NETWARE__ or __WIN__*/
|
||||||
|
|
||||||
|
|
||||||
|
@@ -191,6 +191,9 @@ our $opt_ssl;
|
|||||||
our $opt_skip_ssl;
|
our $opt_skip_ssl;
|
||||||
our $opt_ssl_supported;
|
our $opt_ssl_supported;
|
||||||
our $opt_ps_protocol;
|
our $opt_ps_protocol;
|
||||||
|
our $opt_sp_protocol;
|
||||||
|
our $opt_cursor_protocol;
|
||||||
|
our $opt_view_protocol;
|
||||||
|
|
||||||
our $opt_current_test;
|
our $opt_current_test;
|
||||||
our $opt_ddd;
|
our $opt_ddd;
|
||||||
@@ -490,6 +493,9 @@ sub command_line_setup () {
|
|||||||
# Control what engine/variation to run
|
# Control what engine/variation to run
|
||||||
'embedded-server' => \$opt_embedded_server,
|
'embedded-server' => \$opt_embedded_server,
|
||||||
'ps-protocol' => \$opt_ps_protocol,
|
'ps-protocol' => \$opt_ps_protocol,
|
||||||
|
'sp-protocol' => \$opt_sp_protocol,
|
||||||
|
'view-protocol' => \$opt_view_protocol,
|
||||||
|
'cursor-protocol' => \$opt_cursor_protocol,
|
||||||
'ssl|with-openssl' => \$opt_ssl,
|
'ssl|with-openssl' => \$opt_ssl,
|
||||||
'skip-ssl' => \$opt_skip_ssl,
|
'skip-ssl' => \$opt_skip_ssl,
|
||||||
'compress' => \$opt_compress,
|
'compress' => \$opt_compress,
|
||||||
@@ -2554,6 +2560,21 @@ sub run_mysqltest ($) {
|
|||||||
mtr_add_arg($args, "--ps-protocol");
|
mtr_add_arg($args, "--ps-protocol");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( $opt_sp_protocol )
|
||||||
|
{
|
||||||
|
mtr_add_arg($args, "--sp-protocol");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $opt_view_protocol )
|
||||||
|
{
|
||||||
|
mtr_add_arg($args, "--view-protocol");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $opt_cursor_protocol )
|
||||||
|
{
|
||||||
|
mtr_add_arg($args, "--cursor-protocol");
|
||||||
|
}
|
||||||
|
|
||||||
if ( $opt_strace_client )
|
if ( $opt_strace_client )
|
||||||
{
|
{
|
||||||
$exe= "strace"; # FIXME there are ktrace, ....
|
$exe= "strace"; # FIXME there are ktrace, ....
|
||||||
@@ -2685,6 +2706,10 @@ Options to control what engine/variation to run
|
|||||||
|
|
||||||
embedded-server Use the embedded server, i.e. no mysqld daemons
|
embedded-server Use the embedded server, i.e. no mysqld daemons
|
||||||
ps-protocol Use the binary protocol between client and server
|
ps-protocol Use the binary protocol between client and server
|
||||||
|
cursor-protocol Use the cursor protocol between client and server
|
||||||
|
(implies --ps-protocol)
|
||||||
|
view-protocol Create a view to execute all non updating queries
|
||||||
|
sp-protocol Create a stored procedure to execute all queries
|
||||||
compress Use the compressed protocol between client and server
|
compress Use the compressed protocol between client and server
|
||||||
ssl Use ssl protocol between client and server
|
ssl Use ssl protocol between client and server
|
||||||
skip-ssl Dont start sterver with support for ssl connections
|
skip-ssl Dont start sterver with support for ssl connections
|
||||||
|
Reference in New Issue
Block a user