summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/Makefile.am4
-rw-r--r--client/mysqltest.c691
-rw-r--r--configure.in2
-rw-r--r--libmysql/libmysql.c39
-rw-r--r--libmysqld/examples/Makefile.am5
-rw-r--r--mysql-test/include/have_query_cache.inc3
-rw-r--r--mysql-test/include/ps_conv.inc2
-rw-r--r--mysql-test/mysql-test-run.sh2
-rw-r--r--mysql-test/r/ctype_utf8.result4
-rw-r--r--mysql-test/r/fulltext_cache.result36
-rw-r--r--mysql-test/r/fulltext_left_join.result12
-rw-r--r--mysql-test/r/fulltext_multi.result30
-rw-r--r--mysql-test/r/innodb-lock.result1
-rw-r--r--mysql-test/t/create.test3
-rw-r--r--mysql-test/t/ctype_utf8.test2
-rw-r--r--mysql-test/t/date_formats.test10
-rw-r--r--mysql-test/t/fulltext_cache.test4
-rw-r--r--mysql-test/t/fulltext_left_join.test2
-rw-r--r--mysql-test/t/fulltext_multi.test6
-rw-r--r--mysql-test/t/func_group.test4
-rw-r--r--mysql-test/t/func_sapdb.test18
-rw-r--r--mysql-test/t/innodb-lock-master.opt1
-rw-r--r--mysql-test/t/innodb-lock.test2
-rw-r--r--mysql-test/t/insert.test3
-rw-r--r--mysql-test/t/insert_select.test3
-rw-r--r--mysql-test/t/insert_update.test4
-rw-r--r--mysql-test/t/metadata.test2
-rw-r--r--mysql-test/t/multi_statement.test3
-rw-r--r--mysql-test/t/ps_1general.test3
-rw-r--r--mysql-test/t/rollback.test2
-rw-r--r--mysql-test/t/rpl_redirect.test2
-rw-r--r--mysql-test/t/rpl_user_variables.test3
-rw-r--r--mysql-test/t/select.test6
-rw-r--r--mysql-test/t/status.test2
-rw-r--r--mysql-test/t/type_blob.test3
-rw-r--r--mysql-test/t/type_float.test3
-rw-r--r--mysql-test/t/union.test4
-rw-r--r--mysql-test/t/warnings.test13
-rw-r--r--mysys/my_alloc.c2
-rw-r--r--sql-common/client.c2
-rw-r--r--sql-common/my_time.c6
-rw-r--r--sql/field.cc4
-rw-r--r--sql/item_cmpfunc.cc8
-rw-r--r--sql/item_subselect.cc4
-rw-r--r--sql/item_sum.cc36
-rw-r--r--sql/item_sum.h1
-rw-r--r--sql/protocol.cc7
-rw-r--r--sql/set_var.cc3
-rw-r--r--sql/sql_base.cc63
-rw-r--r--sql/sql_class.cc3
-rw-r--r--sql/sql_error.cc3
-rw-r--r--sql/sql_insert.cc8
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc21
-rw-r--r--sql/sql_prepare.cc11
-rw-r--r--sql/sql_union.cc9
56 files changed, 935 insertions, 197 deletions
diff --git a/client/Makefile.am b/client/Makefile.am
index 24a4bece825..a9da284a753 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -17,7 +17,8 @@
# This file is public domain and comes with NO WARRANTY of any kind
#AUTOMAKE_OPTIONS = nostdinc
-INCLUDES = -I$(top_srcdir)/include $(openssl_includes)
+INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/regex \
+ $(openssl_includes)
LIBS = @CLIENT_LIBS@
DEPLIB= ../libmysql/libmysqlclient.la
LDADD = @CLIENT_EXTRA_LDFLAGS@ $(DEPLIB)
@@ -36,6 +37,7 @@ mysqldump_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES) $(DEPLIB)
mysqlimport_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES) $(DEPLIB)
mysqltest_SOURCES= mysqltest.c ../mysys/my_getsystime.c
mysqltest_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES) $(DEPLIB)
+mysqltest_LDADD = $(LDADD) $(top_builddir)/regex/libregex.a
mysqlbinlog_SOURCES = mysqlbinlog.cc ../mysys/mf_tempdir.c
mysqlbinlog_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES) $(DEPLIB)
mysqlmanagerc_SOURCES = mysqlmanagerc.c
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 7623b9bde73..4c87561ab84 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -42,7 +42,7 @@
**********************************************************************/
-#define MTEST_VERSION "2.2"
+#define MTEST_VERSION "2.3"
#include <my_global.h>
#include <mysql_embed.h>
@@ -53,12 +53,13 @@
#include <mysqld_error.h>
#include <m_ctype.h>
#include <my_dir.h>
+#include <errmsg.h> /* Error codes */
#include <hash.h>
#include <my_getopt.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <violite.h>
-
+#include <regex.h> /* Our own version of lib */
#define MAX_QUERY 131072
#define MAX_VAR_NAME 256
#define MAX_COLUMNS 256
@@ -93,7 +94,7 @@
enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD,
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_CIPHER};
+ OPT_SSL_CIPHER,OPT_PS_PROTOCOL};
/* ************************************************************************ */
/*
@@ -131,8 +132,8 @@ static int record = 0, opt_sleep=0;
static char *db = 0, *pass=0;
const char* user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./";
static int port = 0;
-static my_bool opt_big_test= 0, opt_compress= 0, silent= 0, verbose = 0,
- tty_password= 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 uint start_lineno, *lineno;
const char* manager_user="root",*manager_host=0;
char *manager_pass=0;
@@ -157,7 +158,7 @@ static int block_stack[BLOCK_STACK_DEPTH];
static int block_ok_stack[BLOCK_STACK_DEPTH];
static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
-static char *charset_name = "latin1"; /* Default character set name */
+static const char *charset_name= "latin1"; /* Default character set name */
static int embedded_server_arg_count=0;
static char *embedded_server_args[MAX_SERVER_ARGS];
@@ -171,6 +172,12 @@ static int got_end_timer= FALSE;
static void timer_output(void);
static ulonglong timer_now(void);
+static regex_t ps_re; /* Holds precompiled re for valid PS statements */
+static void ps_init_re(void);
+static int ps_match_re(char *);
+static char *ps_eprint(int);
+static void ps_free_reg(void);
+
static const char *embedded_server_groups[] = {
"server",
"embedded",
@@ -270,7 +277,7 @@ Q_EXEC, Q_DELIMITER,
Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL,
Q_START_TIMER, Q_END_TIMER,
-Q_CHARACTER_SET,
+Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
@@ -352,6 +359,8 @@ const char *command_names[]=
"start_timer",
"end_timer",
"character_set",
+ "disable_ps_protocol",
+ "enable_ps_protocol",
0
};
@@ -523,6 +532,8 @@ static void free_used_memory()
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
free_defaults(default_argv);
mysql_server_end();
+ if (ps_protocol)
+ ps_free_reg();
my_end(MY_CHECK_ERROR);
DBUG_VOID_RETURN;
}
@@ -2089,6 +2100,9 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection.", (gptr*) &port,
(gptr*) &port, 0, GET_INT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0},
+ {"ps-protocol", OPT_PS_PROTOCOL, "Use prepared statements protocol for communication",
+ (gptr*) &ps_protocol, (gptr*) &ps_protocol, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"quiet", 's', "Suppress all normal output.", (gptr*) &silent,
(gptr*) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"record", 'r', "Record output of test_file into result file.",
@@ -2367,7 +2381,36 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
* the result will be read - for regular query, both bits must be on
*/
-int run_query(MYSQL* mysql, struct st_query* q, int flags)
+static int run_query_normal(MYSQL *mysql, struct st_query *q, int flags);
+static int run_query_stmt (MYSQL *mysql, struct st_query *q, int flags);
+static void run_query_stmt_handle_warnings(MYSQL *mysql, DYNAMIC_STRING *ds);
+static int run_query_stmt_handle_error(char *query, struct st_query *q,
+ MYSQL_STMT *stmt, DYNAMIC_STRING *ds);
+static void run_query_display_metadata(MYSQL_FIELD *field, uint num_fields,
+ DYNAMIC_STRING *ds);
+
+static int run_query(MYSQL *mysql, struct st_query *q, int flags)
+{
+
+ /*
+ Try to find out if we can run this statement using the prepared
+ statement protocol.
+
+ We don't have a mysql_stmt_send_execute() so we only handle
+ complete SEND+REAP.
+
+ If it is a '?' in the query it may be a SQL level prepared
+ statement already and we can't do it twice
+ */
+
+ if (ps_protocol_enabled && disable_info &&
+ (flags & QUERY_SEND) && (flags & QUERY_REAP) && ps_match_re(q->query))
+ return run_query_stmt (mysql, q, flags);
+ return run_query_normal(mysql, q, flags);
+}
+
+
+static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags)
{
MYSQL_RES* res= 0;
uint i;
@@ -2377,7 +2420,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
DYNAMIC_STRING eval_query;
char* query;
int query_len, got_error_on_send= 0;
- DBUG_ENTER("run_query");
+ DBUG_ENTER("run_query_normal");
DBUG_PRINT("enter",("flags: %d", flags));
if (q->type != Q_EVAL)
@@ -2520,56 +2563,14 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
{
if (res)
{
- MYSQL_FIELD *field, *field_end;
+ MYSQL_FIELD *field= mysql_fetch_fields(res);
uint num_fields= mysql_num_fields(res);
if (display_metadata)
- {
- dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\tColumn_alias\tName\tType\tLength\tMax length\tIs_null\tFlags\tDecimals\tCharsetnr\n");
- for (field= mysql_fetch_fields(res), field_end= field+num_fields ;
- field < field_end ;
- field++)
- {
- char buff[22];
- dynstr_append_mem(ds, field->catalog, field->catalog_length);
- dynstr_append_mem(ds, "\t", 1);
- dynstr_append_mem(ds, field->db, field->db_length);
- dynstr_append_mem(ds, "\t", 1);
- dynstr_append_mem(ds, field->org_table, field->org_table_length);
- dynstr_append_mem(ds, "\t", 1);
- dynstr_append_mem(ds, field->table, field->table_length);
- dynstr_append_mem(ds, "\t", 1);
- dynstr_append_mem(ds, field->org_name, field->org_name_length);
- dynstr_append_mem(ds, "\t", 1);
- dynstr_append_mem(ds, field->name, field->name_length);
- dynstr_append_mem(ds, "\t", 1);
- int10_to_str((int) field->type, buff, 10);
- dynstr_append(ds, buff);
- dynstr_append_mem(ds, "\t", 1);
- int10_to_str((int) field->length, buff, 10);
- dynstr_append(ds, buff);
- dynstr_append_mem(ds, "\t", 1);
- int10_to_str((int) field->max_length, buff, 10);
- dynstr_append(ds, buff);
- dynstr_append_mem(ds, "\t", 1);
- dynstr_append_mem(ds, (char*) (IS_NOT_NULL(field->flags) ?
- "N" : "Y"), 1);
- dynstr_append_mem(ds, "\t", 1);
-
- int10_to_str((int) field->flags, buff, 10);
- dynstr_append(ds, buff);
- dynstr_append_mem(ds, "\t", 1);
- int10_to_str((int) field->decimals, buff, 10);
- dynstr_append(ds, buff);
- dynstr_append_mem(ds, "\t", 1);
- int10_to_str((int) field->charsetnr, buff, 10);
- dynstr_append(ds, buff);
- dynstr_append_mem(ds, "\n", 1);
- }
- }
+ run_query_display_metadata(field, num_fields, ds);
+
if (!display_result_vertically)
{
- field= mysql_fetch_fields(res);
for (i = 0; i < num_fields; i++)
{
if (i)
@@ -2645,6 +2646,576 @@ end:
}
+/****************************************************************************\
+ * If --ps-protocol run ordinary statements using prepared statemnt C API
+\****************************************************************************/
+
+/*
+ We don't have a mysql_stmt_send_execute() so we only handle
+ complete SEND+REAP
+*/
+
+static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
+{
+ int error= 0; /* Function return code if "goto end;" */
+ int err; /* Temporary storage of return code from calls */
+ int query_len, got_error_on_execute;
+ uint num_rows;
+ char *query;
+ MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */
+ DYNAMIC_STRING *ds;
+ DYNAMIC_STRING ds_tmp;
+ DYNAMIC_STRING eval_query;
+ MYSQL_STMT *stmt;
+ DBUG_ENTER("run_query_stmt");
+
+ /*
+ We must allocate a new stmt for each query in this program becasue this
+ may be a new connection.
+ */
+ if (!(stmt= mysql_stmt_init(mysql)))
+ die("At line %u: unable init stmt structure");
+
+ if (q->type != Q_EVAL)
+ {
+ query= q->query;
+ query_len= strlen(query);
+ }
+ else
+ {
+ init_dynamic_string(&eval_query, "", 16384, 65536);
+ do_eval(&eval_query, q->query);
+ query= eval_query.str;
+ query_len= eval_query.length;
+ }
+ DBUG_PRINT("query", ("'%-.60s'", query));
+
+ if (q->record_file[0])
+ {
+ init_dynamic_string(&ds_tmp, "", 16384, 65536);
+ ds= &ds_tmp;
+ }
+ else
+ ds= &ds_res;
+
+ /* Store the query into the output buffer if not disabled */
+ if (!disable_query_log)
+ {
+ replace_dynstr_append_mem(ds,query, query_len);
+ dynstr_append_mem(ds, delimiter, delimiter_length);
+ dynstr_append_mem(ds, "\n", 1);
+ }
+
+ /*
+ We use the prepared statement interface but there is actually no
+ '?' in the query. If unpreparable we fall back to use normal
+ C API.
+ */
+ if ((err= mysql_stmt_prepare(stmt, query, query_len)) == CR_NO_PREPARE_STMT)
+ return run_query_normal(mysql, q, flags);
+
+ if (err != 0)
+ {
+ if (q->abort_on_error)
+ {
+ die("At line %u: unable to prepare statement '%s': "
+ "%s (mysql_stmt_errno=%d returned=%d)",
+ start_lineno, query,
+ mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err);
+ }
+ else
+ {
+ /*
+ Preparing is part of normal execution and some errors may be expected
+ */
+ error= run_query_stmt_handle_error(query, q, stmt, ds);
+ goto end;
+ }
+ }
+
+ /* We may have got warnings already, collect them if any */
+ /* FIXME we only want this if the statement succeeds I think */
+ run_query_stmt_handle_warnings(mysql, ds);
+
+ /*
+ No need to call mysql_stmt_bind_param() because we have no
+ parameter markers.
+
+ To optimize performance we use a global 'stmt' that is initiated
+ once. A new prepare will implicitely close the old one. When we
+ terminate we will lose the connection, this also closes the last
+ prepared statement.
+ */
+
+ if ((got_error_on_execute= mysql_stmt_execute(stmt)) != 0) /* 0 == Success */
+ {
+ if (q->abort_on_error)
+ {
+ /* We got an error, unexpected */
+ die("At line %u: unable to execute statement '%s': "
+ "%s (mysql_stmt_errno=%d returned=%d)",
+ start_lineno, query, mysql_stmt_error(stmt),
+ mysql_stmt_errno(stmt), got_error_on_execute);
+ }
+ else
+ {
+ /* We got an error, maybe expected */
+ error= run_query_stmt_handle_error(query, q, stmt, ds);
+ goto end;
+ }
+ }
+
+ /*
+ We instruct that we want to update the "max_length" field in
+ mysql_stmt_store_result(), this is our only way to know how much
+ buffer to allocate for result data
+ */
+ {
+ my_bool one= 1;
+ if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH,
+ (void*) &one) != 0)
+ die("At line %u: unable to set stmt attribute "
+ "'STMT_ATTR_UPDATE_MAX_LENGTH': %s (returned=%d)",
+ start_lineno, query, err);
+ }
+
+ /*
+ If we got here the statement succeeded and was expected to do so,
+ get data. Note that this can still give errors found during execution!
+ */
+ if ((err= mysql_stmt_store_result(stmt)) != 0)
+ {
+ if (q->abort_on_error)
+ {
+ /* We got an error, unexpected */
+ die("At line %u: unable to execute statement '%s': "
+ "%s (mysql_stmt_errno=%d returned=%d)",
+ start_lineno, query, mysql_stmt_error(stmt),
+ mysql_stmt_errno(stmt), got_error_on_execute);
+ }
+ else
+ {
+ /* We got an error, maybe expected */
+ error= run_query_stmt_handle_error(query, q, stmt, ds);
+ goto end;
+ }
+ }
+
+ /* If we got here the statement was both executed and read succeesfully */
+
+ if (q->expected_errno[0].type == ERR_ERRNO &&
+ q->expected_errno[0].code.errnum != 0)
+ {
+ verbose_msg("query '%s' succeeded - should have failed with errno %d...",
+ q->query, q->expected_errno[0].code.errnum);
+ error= 1;
+ goto end;
+ }
+
+ num_rows= mysql_stmt_num_rows(stmt);
+
+ /*
+ Not all statements creates a result set. If there is one we can
+ now create another normal result set that contains the meta
+ data. This set can be handled almost like any other non prepared
+ statement result set.
+ */
+ if (!disable_result_log && ((res= mysql_stmt_result_metadata(stmt)) != NULL))
+ {
+ /* Take the column count from meta info */
+ MYSQL_FIELD *field= mysql_fetch_fields(res);
+ uint num_fields= mysql_num_fields(res);
+
+ /* FIXME check error from the above? */
+
+ if (display_metadata)
+ run_query_display_metadata(field, num_fields, ds);
+
+ if (!display_result_vertically)
+ {
+ /* Display the table heading with the names tab separated */
+ uint col_idx;
+ for (col_idx= 0; col_idx < num_fields; col_idx++)
+ {
+ if (col_idx)
+ dynstr_append_mem(ds, "\t", 1);
+ replace_dynstr_append_mem(ds, field[col_idx].name,
+ strlen(field[col_idx].name));
+ }
+ dynstr_append_mem(ds, "\n", 1);
+ }
+
+ /* Now we are to put the real result into the output buffer */
+ /* FIXME when it works, create function append_stmt_result() */
+ {
+ MYSQL_BIND *bind;
+ my_bool *is_null;
+ unsigned long *length;
+ /* FIXME we don't handle vertical display ..... */
+ uint col_idx, row_idx;
+
+ /* Allocate array with bind structs, lengths and NULL flags */
+ bind= (MYSQL_BIND*) my_malloc(num_fields * sizeof(MYSQL_BIND),
+ MYF(MY_WME | MY_FAE));
+ length= (unsigned long*) my_malloc(num_fields * sizeof(unsigned long),
+ MYF(MY_WME | MY_FAE));
+ is_null= (my_bool*) my_malloc(num_fields * sizeof(my_bool),
+ MYF(MY_WME | MY_FAE));
+
+ for (col_idx= 0; col_idx < num_fields; col_idx++)
+ {
+ /* Allocate data for output */
+ /*
+ FIXME it may be a bug that for non string/blob types
+ 'max_length' is 0, should try out 'length' in that case
+ */
+ uint max_length= max(field[col_idx].max_length + 1, 1024);
+ char *str_data= (char *) my_malloc(max_length, MYF(MY_WME | MY_FAE));
+
+ bind[col_idx].buffer_type= MYSQL_TYPE_STRING;
+ bind[col_idx].buffer= (char *)str_data;
+ bind[col_idx].buffer_length= max_length;
+ bind[col_idx].is_null= &is_null[col_idx];
+ bind[col_idx].length= &length[col_idx];
+ }
+
+ /* Fill in the data into the structures created above */
+ if ((err= mysql_stmt_bind_result(stmt, bind)) != 0)
+ die("At line %u: unable to bind result to statement '%s': "
+ "%s (mysql_stmt_errno=%d returned=%d)",
+ start_lineno, query,
+ mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err);
+
+ /* Read result from each row */
+ for (row_idx= 0; row_idx < num_rows; row_idx++)
+ {
+ if ((err= mysql_stmt_fetch(stmt)) != 0)
+ die("At line %u: unable to fetch all rows from statement '%s': "
+ "%s (mysql_stmt_errno=%d returned=%d)",
+ start_lineno, query,
+ mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err);
+
+ /* Read result from each column */
+ for (col_idx= 0; col_idx < num_fields; col_idx++)
+ {
+ /* FIXME is string terminated? */
+ const char *val= (const char *)bind[col_idx].buffer;
+ ulonglong len= *bind[col_idx].length;
+ if (col_idx < max_replace_column && replace_column[col_idx])
+ {
+ val= replace_column[col_idx];
+ len= strlen(val);
+ }
+ if (*bind[col_idx].is_null)
+ {
+ val= "NULL";
+ len= 4;
+ }
+ if (!display_result_vertically)
+ {
+ if (col_idx) /* No tab before first col */
+ dynstr_append_mem(ds, "\t", 1);
+ replace_dynstr_append_mem(ds, val, len);
+ }
+ else
+ {
+ dynstr_append(ds, field[col_idx].name);
+ dynstr_append_mem(ds, "\t", 1);
+ replace_dynstr_append_mem(ds, val, len);
+ dynstr_append_mem(ds, "\n", 1);
+ }
+ }
+ if (!display_result_vertically)
+ dynstr_append_mem(ds, "\n", 1);
+ }
+
+ if ((err= mysql_stmt_fetch(stmt)) != MYSQL_NO_DATA)
+ die("At line %u: fetch didn't end with MYSQL_NO_DATA from statement "
+ "'%s': %s (mysql_stmt_errno=%d returned=%d)",
+ start_lineno, query,
+ mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err);
+
+ free_replace_column();
+
+ for (col_idx= 0; col_idx < num_fields; col_idx++)
+ {
+ /* Free data for output */
+ my_free((gptr)bind[col_idx].buffer, MYF(MY_WME | MY_FAE));
+ }
+ /* Free array with bind structs, lengths and NULL flags */
+ my_free((gptr)bind , MYF(MY_WME | MY_FAE));
+ my_free((gptr)length , MYF(MY_WME | MY_FAE));
+ my_free((gptr)is_null , MYF(MY_WME | MY_FAE));
+ }
+
+ /* Add all warnings to the result */
+ run_query_stmt_handle_warnings(mysql, ds);
+
+ if (!disable_info)
+ {
+ char buf[40];
+ sprintf(buf,"affected rows: %lu\n",(ulong) mysql_affected_rows(mysql));
+ dynstr_append(ds, buf);
+ if (mysql_info(mysql))
+ {
+ dynstr_append(ds, "info: ");
+ dynstr_append(ds, mysql_info(mysql));
+ dynstr_append_mem(ds, "\n", 1);
+ }
+ }
+ }
+ run_query_stmt_handle_warnings(mysql, ds);
+
+ if (record)
+ {
+ if (!q->record_file[0] && !result_file)
+ die("At line %u: Missing result file", start_lineno);
+ if (!result_file)
+ str_to_file(q->record_file, ds->str, ds->length);
+ }
+ else if (q->record_file[0])
+ {
+ error= check_result(ds, q->record_file, q->require_file);
+ }
+ if (res)
+ mysql_free_result(res); /* Free normal result set with meta data */
+ last_result= 0; /* FIXME have no idea what this is about... */
+
+ if (err >= 1)
+ mysql_error(mysql); /* FIXME strange, has no effect... */
+
+end:
+ free_replace();
+ last_result=0;
+ if (ds == &ds_tmp)
+ dynstr_free(&ds_tmp);
+ if (q->type == Q_EVAL)
+ dynstr_free(&eval_query);
+ mysql_stmt_close(stmt);
+ DBUG_RETURN(error);
+}
+
+
+/****************************************************************************\
+ * Broken out sub functions to run_query_stmt()
+\****************************************************************************/
+
+static void run_query_display_metadata(MYSQL_FIELD *field, uint num_fields,
+ DYNAMIC_STRING *ds)
+{
+ MYSQL_FIELD *field_end;
+ dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
+ "Column_alias\tName\tType\tLength\tMax length\tIs_null\t"
+ "Flags\tDecimals\tCharsetnr\n");
+
+ for (field_end= field+num_fields ;
+ field < field_end ;
+ field++)
+ {
+ char buff[22];
+ dynstr_append_mem(ds, field->catalog,
+ field->catalog_length);
+ dynstr_append_mem(ds, "\t", 1);
+ dynstr_append_mem(ds, field->db, field->db_length);
+ dynstr_append_mem(ds, "\t", 1);
+ dynstr_append_mem(ds, field->org_table,
+ field->org_table_length);
+ dynstr_append_mem(ds, "\t", 1);
+ dynstr_append_mem(ds, field->table,
+ field->table_length);
+ dynstr_append_mem(ds, "\t", 1);
+ dynstr_append_mem(ds, field->org_name,
+ field->org_name_length);
+ dynstr_append_mem(ds, "\t", 1);
+ dynstr_append_mem(ds, field->name, field->name_length);
+ dynstr_append_mem(ds, "\t", 1);
+ int10_to_str((int) field->type, buff, 10);
+ dynstr_append(ds, buff);
+ dynstr_append_mem(ds, "\t", 1);
+ int10_to_str((int) field->length, buff, 10);
+ dynstr_append(ds, buff);
+ dynstr_append_mem(ds, "\t", 1);
+ int10_to_str((int) field->max_length, buff, 10);
+ dynstr_append(ds, buff);
+ dynstr_append_mem(ds, "\t", 1);
+ dynstr_append_mem(ds, (char*) (IS_NOT_NULL(field->flags) ?
+ "N" : "Y"), 1);
+ dynstr_append_mem(ds, "\t", 1);
+
+ int10_to_str((int) field->flags, buff, 10);
+ dynstr_append(ds, buff);
+ dynstr_append_mem(ds, "\t", 1);
+ int10_to_str((int) field->decimals, buff, 10);
+ dynstr_append(ds, buff);
+ dynstr_append_mem(ds, "\t", 1);
+ int10_to_str((int) field->charsetnr, buff, 10);
+ dynstr_append(ds, buff);
+ dynstr_append_mem(ds, "\n", 1);
+ }
+}
+
+
+static void run_query_stmt_handle_warnings(MYSQL *mysql, DYNAMIC_STRING *ds)
+{
+ uint count;
+ DBUG_ENTER("run_query_stmt_handle_warnings");
+
+ if (!disable_warnings && (count= mysql_warning_count(mysql)))
+ {
+ if (mysql_real_query(mysql, "SHOW WARNINGS", 13) == 0)
+ {
+ MYSQL_RES *warn_res= mysql_store_result(mysql);
+ if (!warn_res)
+ verbose_msg("Warning count is %u but didn't get any warnings\n",
+ count);
+ else
+ {
+ dynstr_append_mem(ds, "Warnings:\n", 10);
+ append_result(ds, warn_res);
+ mysql_free_result(warn_res);
+ }
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+static int run_query_stmt_handle_error(char *query, struct st_query *q,
+ MYSQL_STMT *stmt, DYNAMIC_STRING *ds)
+{
+ if (q->require_file) /* FIXME don't understand this one */
+ {
+ abort_not_supported_test();
+ }
+
+ if (q->abort_on_error)
+ die("At line %u: query '%s' failed: %d: %s", start_lineno, query,
+ mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
+ else
+ {
+ int i;
+
+ for (i=0 ; (uint) i < q->expected_errors ; i++)
+ {
+ if (((q->expected_errno[i].type == ERR_ERRNO) &&
+ (q->expected_errno[i].code.errnum == mysql_stmt_errno(stmt))) ||
+ ((q->expected_errno[i].type == ERR_SQLSTATE) &&
+ (strcmp(q->expected_errno[i].code.sqlstate,
+ mysql_stmt_sqlstate(stmt)) == 0)))
+ {
+ if (i == 0 && q->expected_errors == 1)
+ {
+ /* Only log error if there is one possible error */
+ dynstr_append_mem(ds,"ERROR ",6);
+ replace_dynstr_append_mem(ds, mysql_stmt_sqlstate(stmt),
+ strlen(mysql_stmt_sqlstate(stmt)));
+ dynstr_append_mem(ds, ": ", 2);
+ replace_dynstr_append_mem(ds,mysql_stmt_error(stmt),
+ strlen(mysql_stmt_error(stmt)));
+ dynstr_append_mem(ds,"\n",1);
+ }
+ /* Don't log error if we may not get an error */
+ else if (q->expected_errno[0].type == ERR_SQLSTATE ||
+ (q->expected_errno[0].type == ERR_ERRNO &&
+ q->expected_errno[0].code.errnum != 0))
+ dynstr_append(ds,"Got one of the listed errors\n");
+ return 0; /* Ok */
+ }
+ }
+ DBUG_PRINT("info",("i: %d expected_errors: %d", i,
+ q->expected_errors));
+ dynstr_append_mem(ds, "ERROR ",6);
+ replace_dynstr_append_mem(ds, mysql_stmt_sqlstate(stmt),
+ strlen(mysql_stmt_sqlstate(stmt)));
+ dynstr_append_mem(ds,": ",2);
+ replace_dynstr_append_mem(ds, mysql_stmt_error(stmt),
+ strlen(mysql_stmt_error(stmt)));
+ dynstr_append_mem(ds,"\n",1);
+ if (i)
+ {
+ verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
+ q->query, mysql_stmt_errno(stmt), q->expected_errno[0]);
+ return 1; /* Error */
+ }
+ verbose_msg("query '%s' failed: %d: %s", q->query, mysql_stmt_errno(stmt),
+ mysql_stmt_error(stmt));
+ /*
+ if we do not abort on error, failure to run the query does
+ not fail the whole test case
+ */
+ return 0;
+ }
+
+ return 0;
+}
+
+/****************************************************************************\
+ * Functions to match SQL statements that can be prepared
+\****************************************************************************/
+
+static void ps_init_re(void)
+{
+ const char *ps_re_str =
+ "^("
+ "[[:space:]]*REPLACE[[:space:]]|"
+ "[[:space:]]*INSERT[[:space:]]|"
+ "[[:space:]]*UPDATE[[:space:]]|"
+ "[[:space:]]*DELETE[[:space:]]|"
+ "[[:space:]]*SELECT[[:space:]]|"
+ "[[:space:]]*CREATE[[:space:]]+TABLE[[:space:]]|"
+ "[[:space:]]*DO[[:space:]]|"
+ "[[:space:]]*SET[[:space:]]+OPTION[[:space:]]|"
+ "[[:space:]]*DELETE[[:space:]]+MULTI[[:space:]]|"
+ "[[:space:]]*UPDATE[[:space:]]+MULTI[[:space:]]|"
+ "[[:space:]]*INSERT[[:space:]]+SELECT[[:space:]])";
+
+ int err= regcomp(&ps_re, ps_re_str, (REG_EXTENDED | REG_ICASE | REG_NOSUB),
+ &my_charset_latin1);
+ if (err)
+ {
+ char erbuf[100];
+ int len= regerror(err, &ps_re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "error %s, %d/%d `%s'\n",
+ ps_eprint(err), len, (int)sizeof(erbuf), erbuf);
+ exit(1);
+ }
+}
+
+
+static int ps_match_re(char *stmt_str)
+{
+ int err= regexec(&ps_re, stmt_str, (size_t)0, NULL, 0);
+
+ if (err == 0)
+ return 1;
+ else if (err == REG_NOMATCH)
+ return 0;
+ else
+ {
+ char erbuf[100];
+ int len= regerror(err, &ps_re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "error %s, %d/%d `%s'\n",
+ ps_eprint(err), len, (int)sizeof(erbuf), erbuf);
+ exit(1);
+ }
+}
+
+static char *ps_eprint(int err)
+{
+ static char epbuf[100];
+ size_t len= regerror(REG_ITOA|err, (regex_t *)NULL, epbuf, sizeof(epbuf));
+ assert(len <= sizeof(epbuf));
+ return(epbuf);
+}
+
+
+static void ps_free_reg(void)
+{
+ regfree(&ps_re);
+}
+
+/****************************************************************************/
+
void get_query_type(struct st_query* q)
{
char save;
@@ -2798,6 +3369,11 @@ int main(int argc, char **argv)
if (manager_host)
init_manager();
#endif
+ if (ps_protocol)
+ {
+ ps_protocol_enabled= 1;
+ ps_init_re();
+ }
if (!( mysql_init(&cur_con->mysql)))
die("Failed in mysql_init()");
if (opt_compress)
@@ -2991,6 +3567,13 @@ int main(int argc, char **argv)
case Q_CHARACTER_SET:
set_charset(q);
break;
+ case Q_DISABLE_PS_PROTOCOL:
+ ps_protocol_enabled= 0;
+ break;
+ case Q_ENABLE_PS_PROTOCOL:
+ ps_protocol_enabled= ps_protocol;
+ break;
+
default: processed = 0; break;
}
}
diff --git a/configure.in b/configure.in
index 656af354607..f85c3e1421a 100644
--- a/configure.in
+++ b/configure.in
@@ -2811,7 +2811,7 @@ thread_dirs=
dnl This probably should be cleaned up more - for now the threaded
dnl client is just using plain-old libs.
-sql_client_dirs="libmysql client"
+sql_client_dirs="libmysql strings regex client"
linked_client_targets="linked_libmysql_sources"
CLIENT_LIBS=$NON_THREADED_CLIENT_LIBS
if test "$THREAD_SAFE_CLIENT" != "no"
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 6a67697169a..2dfdfbb687b 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1880,6 +1880,7 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
}
stmt->field_count= (uint) field_count;
stmt->param_count= (ulong) param_count;
+ mysql->warning_count= 0;
DBUG_RETURN(0);
}
@@ -3263,7 +3264,6 @@ static void read_binary_time(MYSQL_TIME *tm, uchar **pos)
tm->minute= (uint) to[6];
tm->second= (uint) to[7];
tm->second_part= (length > 8) ? (ulong) sint4korr(to+8) : 0;
-
tm->year= tm->month= 0;
*pos+= length;
@@ -3489,7 +3489,16 @@ static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
char buff[22]; /* Enough for longlong */
char *end= longlong10_to_str(value, buff, field_is_unsigned ? 10: -10);
/* Resort to string conversion which supports all typecodes */
- fetch_string_with_conversion(param, buff, (uint) (end - buff));
+ uint length= (uint) (end-buff);
+
+ if (field->flags & ZEROFILL_FLAG && length < field->length &&
+ field->length < 21)
+ {
+ bmove_upp((char*) buff+field->length,buff+length, length);
+ bfill((char*) buff, field->length - length,'0');
+ length= field->length;
+ }
+ fetch_string_with_conversion(param, buff, length);
break;
}
}
@@ -3556,8 +3565,14 @@ static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
if (field->decimals >= NOT_FIXED_DEC)
#undef NOT_FIXED_DEC
{
- sprintf(buff, "%-*.*g", (int) min(sizeof(buff)-1, param->buffer_length),
- width, value);
+ /*
+ The 14 below is to ensure that the server and client has the same
+ precisions. This will ensure that on the same machine you get the
+ same value as a string independent of the protocol you use.
+ */
+ sprintf(buff, "%-*.*g", (int) min(sizeof(buff)-1,
+ param->buffer_length),
+ min(14,width), value);
end= strcend(buff, ' ');
*end= 0;
}
@@ -3868,12 +3883,12 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
{
MYSQL_BIND *param, *end;
MYSQL_FIELD *field;
- ulong bind_count;
+ ulong bind_count= stmt->field_count;
uint param_count= 0;
DBUG_ENTER("mysql_stmt_bind_result");
- DBUG_ASSERT(stmt != 0);
+ DBUG_PRINT("enter",("field_count: %d", bind_count));
- if (!stmt->field_count)
+ if (!bind_count)
{
if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
{
@@ -3881,7 +3896,6 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
}
DBUG_RETURN(0);
}
- bind_count= stmt->field_count;
/*
We only need to check that stmt->field_count - if it is not null
@@ -3894,6 +3908,8 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
param < end ;
param++, field++)
{
+ DBUG_PRINT("info",("buffer_type: %u field_type: %u",
+ (uint) param->buffer_type, (uint) field->type));
/*
Set param->is_null to point to a dummy variable if it's not set.
This is to make the execute code easier
@@ -4221,6 +4237,8 @@ int cli_read_binary_rows(MYSQL_STMT *stmt)
*prev_ptr= 0;
mysql->warning_count= uint2korr(cp+1);
mysql->server_status= uint2korr(cp+3);
+ DBUG_PRINT("info",("status: %u warning_count: %u",
+ mysql->server_status, mysql->warning_count));
DBUG_RETURN(0);
}
}
@@ -4316,11 +4334,12 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
bind < end ;
bind++, field++)
{
- bind->buffer_type= field->type;
+ bind->buffer_type= MYSQL_TYPE_NULL;
bind->buffer_length=1;
}
- mysql_stmt_bind_result(stmt, stmt->bind);
+ if (mysql_stmt_bind_result(stmt, stmt->bind))
+ DBUG_RETURN(1);
stmt->bind_result_done= 0; /* No normal bind done */
}
diff --git a/libmysqld/examples/Makefile.am b/libmysqld/examples/Makefile.am
index 2712e0dff48..5b0a86e679c 100644
--- a/libmysqld/examples/Makefile.am
+++ b/libmysqld/examples/Makefile.am
@@ -14,13 +14,14 @@ link_sources:
DEFS = -DEMBEDDED_LIBRARY
INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include -I$(srcdir) \
- -I$(top_srcdir) -I$(top_srcdir)/client $(openssl_includes)
+ -I$(top_srcdir) -I$(top_srcdir)/client -I$(top_srcdir)/regex \
+ $(openssl_includes)
LIBS = @LIBS@ @WRAPLIBS@ @CLIENT_LIBS@
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysqld.a @innodb_system_libs@ @LIBDL@ $(CXXLDFLAGS)
mysqltest_LINK = $(CXXLINK)
-
mysqltest_SOURCES = mysqltest.c
+mysqltest_LDADD = $(LDADD) $(top_builddir)/regex/libregex.a
mysql_SOURCES = mysql.cc readline.cc completion_hash.cc \
my_readline.h sql_string.h completion_hash.h
diff --git a/mysql-test/include/have_query_cache.inc b/mysql-test/include/have_query_cache.inc
index e5e6052c9a7..39549157849 100644
--- a/mysql-test/include/have_query_cache.inc
+++ b/mysql-test/include/have_query_cache.inc
@@ -1,4 +1,7 @@
-- require r/have_query_cache.require
+# As PS are not cached we disable them to ensure the we get the right number
+# of query cache hits
+-- disable_ps_protocol
disable_query_log;
show variables like "have_query_cache";
enable_query_log;
diff --git a/mysql-test/include/ps_conv.inc b/mysql-test/include/ps_conv.inc
index 03d93b6190d..0a5bec26fe7 100644
--- a/mysql-test/include/ps_conv.inc
+++ b/mysql-test/include/ps_conv.inc
@@ -73,7 +73,9 @@ create table t5 as select
show create table t5 ;
--vertical_results
--enable_metadata
+--disable_ps_protocol
select * from t5 ;
+--enable_ps_protocol
--disable_metadata
--horizontal_results
drop table t5 ;
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index b12f7afb9f1..6b40fb3e974 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -321,6 +321,8 @@ while test $# -gt 0; do
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT $1"
SLEEP_TIME_AFTER_RESTART=`$ECHO "$1" | $SED -e "s;--sleep=;;"`
;;
+ --ps-protocol)
+ EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT $1" ;;
--user-test=*)
USER_TEST=`$ECHO "$1" | $SED -e "s;--user-test=;;"`
;;
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index e65eb96cb68..482a6502490 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -766,9 +766,7 @@ list_id smallint unsigned NOT NULL,
term text NOT NULL,
PRIMARY KEY(id),
INDEX(list_id, term(19))
-) TYPE=MyISAM CHARSET=utf8;
-Warnings:
-Warning 1287 'TYPE=storage_engine' is deprecated; use 'ENGINE=storage_engine' instead
+) ENGINE=MyISAM CHARSET=utf8;
INSERT INTO t1 set list_id = 1, term = "testétest";
INSERT INTO t1 set list_id = 1, term = "testetest";
INSERT INTO t1 set list_id = 1, term = "testètest";
diff --git a/mysql-test/r/fulltext_cache.result b/mysql-test/r/fulltext_cache.result
index c489bdefeb8..6a94189d8b4 100644
--- a/mysql-test/r/fulltext_cache.result
+++ b/mysql-test/r/fulltext_cache.result
@@ -21,17 +21,17 @@ INSERT INTO t2 VALUES (5,2,'um copo de Vodka');
INSERT INTO t2 VALUES (6,2,'um chocolate Snickers');
INSERT INTO t2 VALUES (7,1,'Bife');
INSERT INTO t2 VALUES (8,1,'Pizza de Salmao');
-SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi')
+SELECT t1.q, t2.item, t2.id, round(MATCH t2.item AGAINST ('sushi'),8)
as x FROM t1, t2 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
q item id x
-aaaaaaaaa dsaass de sushi 1 1.92378664016724
-aaaaaaaaa dsaass de Bolo de Chocolate 2 0
-aaaaaaaaa dsaass de Feijoada 3 0
-aaaaaaaaa dsaass de Mousse de Chocolate 4 0
-ssde df s fsda sad er um copo de Vodka 5 0
-ssde df s fsda sad er um chocolate Snickers 6 0
-aaaaaaaaa dsaass de Bife 7 0
-aaaaaaaaa dsaass de Pizza de Salmao 8 0
+aaaaaaaaa dsaass de sushi 1 1.92378664
+aaaaaaaaa dsaass de Bolo de Chocolate 2 0.00000000
+aaaaaaaaa dsaass de Feijoada 3 0.00000000
+aaaaaaaaa dsaass de Mousse de Chocolate 4 0.00000000
+ssde df s fsda sad er um copo de Vodka 5 0.00000000
+ssde df s fsda sad er um chocolate Snickers 6 0.00000000
+aaaaaaaaa dsaass de Bife 7 0.00000000
+aaaaaaaaa dsaass de Pizza de Salmao 8 0.00000000
SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi' IN BOOLEAN MODE)
as x FROM t1, t2 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
q item id x
@@ -43,17 +43,17 @@ ssde df s fsda sad er um copo de Vodka 5 0
ssde df s fsda sad er um chocolate Snickers 6 0
aaaaaaaaa dsaass de Bife 7 0
aaaaaaaaa dsaass de Pizza de Salmao 8 0
-SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi')
+SELECT t1.q, t2.item, t2.id, round(MATCH t2.item AGAINST ('sushi'),8)
as x FROM t2, t1 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
q item id x
-aaaaaaaaa dsaass de sushi 1 1.92378664016724
-aaaaaaaaa dsaass de Bolo de Chocolate 2 0
-aaaaaaaaa dsaass de Feijoada 3 0
-aaaaaaaaa dsaass de Mousse de Chocolate 4 0
-ssde df s fsda sad er um copo de Vodka 5 0
-ssde df s fsda sad er um chocolate Snickers 6 0
-aaaaaaaaa dsaass de Bife 7 0
-aaaaaaaaa dsaass de Pizza de Salmao 8 0
+aaaaaaaaa dsaass de sushi 1 1.92378664
+aaaaaaaaa dsaass de Bolo de Chocolate 2 0.00000000
+aaaaaaaaa dsaass de Feijoada 3 0.00000000
+aaaaaaaaa dsaass de Mousse de Chocolate 4 0.00000000
+ssde df s fsda sad er um copo de Vodka 5 0.00000000
+ssde df s fsda sad er um chocolate Snickers 6 0.00000000
+aaaaaaaaa dsaass de Bife 7 0.00000000
+aaaaaaaaa dsaass de Pizza de Salmao 8 0.00000000
SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi' IN BOOLEAN MODE)
as x FROM t2, t1 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
q item id x
diff --git a/mysql-test/r/fulltext_left_join.result b/mysql-test/r/fulltext_left_join.result
index bf3fe73690a..f3dad290525 100644
--- a/mysql-test/r/fulltext_left_join.result
+++ b/mysql-test/r/fulltext_left_join.result
@@ -16,13 +16,13 @@ author VARCHAR(255) NOT NULL
INSERT INTO t2 VALUES('123', 'moi');
INSERT INTO t2 VALUES('123', 'lui');
INSERT INTO t2 VALUES('456', 'lui');
-select match(t1.texte,t1.sujet,t1.motsclefs) against('droit')
+select round(match(t1.texte,t1.sujet,t1.motsclefs) against('droit'),5)
from t1 left join t2 on t2.id=t1.id;
-match(t1.texte,t1.sujet,t1.motsclefs) against('droit')
-0
-0
-0.67003107070923
-0
+round(match(t1.texte,t1.sujet,t1.motsclefs) against('droit'),5)
+0.00000
+0.00000
+0.67003
+0.00000
select match(t1.texte,t1.sujet,t1.motsclefs) against('droit' IN BOOLEAN MODE)
from t1 left join t2 on t2.id=t1.id;
match(t1.texte,t1.sujet,t1.motsclefs) against('droit' IN BOOLEAN MODE)
diff --git a/mysql-test/r/fulltext_multi.result b/mysql-test/r/fulltext_multi.result
index 968b00020e2..289ee004395 100644
--- a/mysql-test/r/fulltext_multi.result
+++ b/mysql-test/r/fulltext_multi.result
@@ -11,19 +11,19 @@ FULLTEXT KEY a(b,c)
INSERT INTO t1 VALUES (1,'lala lolo lili','oooo aaaa pppp');
INSERT INTO t1 VALUES (2,'asdf fdsa','lkjh fghj');
INSERT INTO t1 VALUES (3,'qpwoei','zmxnvb');
-SELECT a, MATCH b AGAINST ('lala lkjh') FROM t1;
-a MATCH b AGAINST ('lala lkjh')
-1 0.67003107070923
-2 0
-3 0
-SELECT a, MATCH c AGAINST ('lala lkjh') FROM t1;
-a MATCH c AGAINST ('lala lkjh')
-1 0
-2 0.67756325006485
-3 0
-SELECT a, MATCH b,c AGAINST ('lala lkjh') FROM t1;
-a MATCH b,c AGAINST ('lala lkjh')
-1 0.64840710163116
-2 0.66266459226608
-3 0
+SELECT a, round(MATCH b AGAINST ('lala lkjh'),5) FROM t1;
+a round(MATCH b AGAINST ('lala lkjh'),5)
+1 0.67003
+2 0.00000
+3 0.00000
+SELECT a, round(MATCH c AGAINST ('lala lkjh'),5) FROM t1;
+a round(MATCH c AGAINST ('lala lkjh'),5)
+1 0.00000
+2 0.67756
+3 0.00000
+SELECT a, round(MATCH b,c AGAINST ('lala lkjh'),5) FROM t1;
+a round(MATCH b,c AGAINST ('lala lkjh'),5)
+1 0.64841
+2 0.66266
+3 0.00000
drop table t1;
diff --git a/mysql-test/r/innodb-lock.result b/mysql-test/r/innodb-lock.result
index 407a85ed038..4ace4065c34 100644
--- a/mysql-test/r/innodb-lock.result
+++ b/mysql-test/r/innodb-lock.result
@@ -1,3 +1,4 @@
+set global innodb_table_locks=1;
select @@innodb_table_locks;
@@innodb_table_locks
1
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index 26c527ca7cb..6f222eedec1 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -272,8 +272,11 @@ insert into t2 values(10),(20);
create table t3 like t1;
show create table t3;
select * from t3;
+# Disable PS becasue of @@warning_count
+--disable_ps_protocol
create table if not exists t3 like t1;
select @@warning_count;
+--enable_ps_protocol
create temporary table t3 like t2;
show create table t3;
select * from t3;
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 238cd6daef3..2ee796eeb67 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -621,7 +621,7 @@ CREATE TABLE t1 (
term text NOT NULL,
PRIMARY KEY(id),
INDEX(list_id, term(19))
-) TYPE=MyISAM CHARSET=utf8;
+) ENGINE=MyISAM CHARSET=utf8;
INSERT INTO t1 set list_id = 1, term = "testétest";
INSERT INTO t1 set list_id = 1, term = "testetest";
INSERT INTO t1 set list_id = 1, term = "testètest";
diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test
index f769fe7af04..c369a9c85d5 100644
--- a/mysql-test/t/date_formats.test
+++ b/mysql-test/t/date_formats.test
@@ -118,8 +118,11 @@ SET datetime_format=default;
# Test of str_to_date
#
+# PS doesn't support fraction of a seconds
+--disable_ps_protocol
select str_to_date(concat('15-01-2001',' 2:59:58.999'),
concat('%d-%m-%Y',' ','%H:%i:%s.%f'));
+--enable_ps_protocol
create table t1 (date char(30), format char(30) not null);
insert into t1 values
@@ -153,7 +156,8 @@ insert into t1 values
('15-01-20', '%d-%m-%y'),
('15-2001-1', '%d-%Y-%c');
-# Use through protocol functions
+# PS doesn't support fractional seconds
+--disable_ps_protocol
select date,format,str_to_date(date, format) as str_to_date from t1;
# Use as a string
select date,format,concat('',str_to_date(date, format)) as con from t1;
@@ -198,6 +202,7 @@ select date,format,str_to_date(date, format) as str_to_date from t1;
select date,format,concat(str_to_date(date, format),'') as con from t1;
drop table t1;
+--enable_ps_protocol
#
# Test of get_format
@@ -221,6 +226,8 @@ insert into t1 values ('2004-07-14'),('2005-07-14');
select date_format(d,"%d") from t1 order by 1;
drop table t1;
+# PS doesn't support fractional seconds
+--disable_ps_protocol
select str_to_date("2003-....01ABCD-02 10:11:12.0012", "%Y-%.%m%@-%d %H:%i:%S.%f") as a;
@@ -249,3 +256,4 @@ select str_to_date("2003-01-02 10:11:12.0012ABCD", "%Y-%m-%d %H:%i:%S.%f") as f1
select str_to_date("2003-04-05 g", "%Y-%m-%d") as f1,
str_to_date("2003-04-05 10:11:12.101010234567", "%Y-%m-%d %H:%i:%S.%f") as f2;
+--enable_ps_protocol
diff --git a/mysql-test/t/fulltext_cache.test b/mysql-test/t/fulltext_cache.test
index 15f32fdb5a0..234deab91e6 100644
--- a/mysql-test/t/fulltext_cache.test
+++ b/mysql-test/t/fulltext_cache.test
@@ -29,13 +29,13 @@ INSERT INTO t2 VALUES (6,2,'um chocolate Snickers');
INSERT INTO t2 VALUES (7,1,'Bife');
INSERT INTO t2 VALUES (8,1,'Pizza de Salmao');
-SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi')
+SELECT t1.q, t2.item, t2.id, round(MATCH t2.item AGAINST ('sushi'),8)
as x FROM t1, t2 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi' IN BOOLEAN MODE)
as x FROM t1, t2 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
-SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi')
+SELECT t1.q, t2.item, t2.id, round(MATCH t2.item AGAINST ('sushi'),8)
as x FROM t2, t1 WHERE (t2.id2 = t1.id) ORDER BY x DESC,t2.id;
SELECT t1.q, t2.item, t2.id, MATCH t2.item AGAINST ('sushi' IN BOOLEAN MODE)
diff --git a/mysql-test/t/fulltext_left_join.test b/mysql-test/t/fulltext_left_join.test
index f8dcfb2aad6..96751ef8678 100644
--- a/mysql-test/t/fulltext_left_join.test
+++ b/mysql-test/t/fulltext_left_join.test
@@ -24,7 +24,7 @@ INSERT INTO t2 VALUES('123', 'moi');
INSERT INTO t2 VALUES('123', 'lui');
INSERT INTO t2 VALUES('456', 'lui');
-select match(t1.texte,t1.sujet,t1.motsclefs) against('droit')
+select round(match(t1.texte,t1.sujet,t1.motsclefs) against('droit'),5)
from t1 left join t2 on t2.id=t1.id;
select match(t1.texte,t1.sujet,t1.motsclefs) against('droit' IN BOOLEAN MODE)
from t1 left join t2 on t2.id=t1.id;
diff --git a/mysql-test/t/fulltext_multi.test b/mysql-test/t/fulltext_multi.test
index c312a5938b2..3a622a551bc 100644
--- a/mysql-test/t/fulltext_multi.test
+++ b/mysql-test/t/fulltext_multi.test
@@ -17,7 +17,7 @@ INSERT INTO t1 VALUES (1,'lala lolo lili','oooo aaaa pppp');
INSERT INTO t1 VALUES (2,'asdf fdsa','lkjh fghj');
INSERT INTO t1 VALUES (3,'qpwoei','zmxnvb');
-SELECT a, MATCH b AGAINST ('lala lkjh') FROM t1;
-SELECT a, MATCH c AGAINST ('lala lkjh') FROM t1;
-SELECT a, MATCH b,c AGAINST ('lala lkjh') FROM t1;
+SELECT a, round(MATCH b AGAINST ('lala lkjh'),5) FROM t1;
+SELECT a, round(MATCH c AGAINST ('lala lkjh'),5) FROM t1;
+SELECT a, round(MATCH b,c AGAINST ('lala lkjh'),5) FROM t1;
drop table t1;
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index 3e001961f90..8d8779e9d1b 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -30,7 +30,11 @@ select grp, sum(a)+count(a)+avg(a)+std(a)+variance(a)+bit_or(a)+bit_and(a)+min(a
create table t2 (grp int, a bigint unsigned, c char(10));
insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp;
+
+# REPLACE ... SELECT doesn't yet work with PS
+--disable_ps_protocol
replace into t2 select grp, a, c from t1 limit 2,1;
+--enable_ps_protocol
select * from t2;
drop table t1,t2;
diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test
index 24028437fde..2ae3c438243 100644
--- a/mysql-test/t/func_sapdb.test
+++ b/mysql-test/t/func_sapdb.test
@@ -47,17 +47,23 @@ select subtime("1997-12-31 23:59:59.999999", "1998-01-01 01:01:01.999999");
select subtime("01:00:00.999999", "02:00:00.999998");
select subtime("02:01:01.999999", "01:01:01.999999");
+# PS doesn't support fractional seconds
+--disable_ps_protocol
select timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002");
select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002");
select timediff("1997-12-30 23:59:59.000001","1997-12-31 23:59:59.000002");
select timediff("1997-12-31 23:59:59.000001","23:59:59.000001");
select timediff("2000:01:01 00:00:00", "2000:01:01 00:00:00.000001");
+--enable_ps_protocol
select maketime(10,11,12);
select maketime(25,11,12);
select maketime(-25,11,12);
-#Extraction functions
+# Extraction functions
+
+# PS doesn't support fractional seconds
+--disable_ps_protocol
select timestamp("2001-12-01", "01:01:01.999999");
select timestamp("2001-13-01", "01:01:01.000001");
select timestamp("2001-12-01", "25:01:01");
@@ -69,6 +75,7 @@ select date("1997-13-31 23:59:59.000001");
select time("1997-12-31 23:59:59.000001");
select time("1997-12-31 25:59:59.000001");
select microsecond("1997-12-31 23:59:59.000001");
+--enable_ps_protocol
create table t1
select makedate(1997,1) as f1,
@@ -81,7 +88,10 @@ select makedate(1997,1) as f1,
date("1997-12-31 23:59:59.000001") as f8,
time("1997-12-31 23:59:59.000001") as f9;
describe t1;
+# PS doesn't support fractional seconds
+--disable_ps_protocol
select * from t1;
+--enable_ps_protocol
create table test(t1 datetime, t2 time, t3 time, t4 datetime);
insert into test values
@@ -94,7 +104,10 @@ insert into test values
('2001-01-01 01:01:01', '01:01:01', '1 01:01:01', '2001-01-01 01:01:01');
SELECT ADDTIME(t1,t2) As ttt, ADDTIME(t2, t3) As qqq from test;
+# PS doesn't support fractional seconds
+--disable_ps_protocol
SELECT TIMEDIFF(t1,t4) As ttt, TIMEDIFF(t2, t3) As qqq from test;
+--enable_ps_protocol
drop table t1, test;
@@ -102,4 +115,7 @@ select addtime("-01:01:01.01", "-23:59:59.1") as a;
select microsecond("1997-12-31 23:59:59.01") as a;
select microsecond(19971231235959.01) as a;
select date_add("1997-12-31",INTERVAL "10.09" SECOND_MICROSECOND) as a;
+# PS doesn't support fractional seconds
+--disable_ps_protocol
select str_to_date("2003-01-02 10:11:12.0012", "%Y-%m-%d %H:%i:%S.%f");
+--enable_ps_protocol
diff --git a/mysql-test/t/innodb-lock-master.opt b/mysql-test/t/innodb-lock-master.opt
deleted file mode 100644
index 403fcde87ed..00000000000
--- a/mysql-test/t/innodb-lock-master.opt
+++ /dev/null
@@ -1 +0,0 @@
---innodb-table-lock=1
diff --git a/mysql-test/t/innodb-lock.test b/mysql-test/t/innodb-lock.test
index 2bbbac82ad5..a3b6f8993f2 100644
--- a/mysql-test/t/innodb-lock.test
+++ b/mysql-test/t/innodb-lock.test
@@ -4,6 +4,8 @@
# Check and select innodb lock type
#
+set global innodb_table_locks=1;
+
select @@innodb_table_locks;
#
diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test
index fd728c453aa..54379685731 100644
--- a/mysql-test/t/insert.test
+++ b/mysql-test/t/insert.test
@@ -92,6 +92,8 @@ drop database mysqltest;
# Test of wrong values for float data (bug #2082)
#
+# PS gives sligthly different numbers for max-float/max-double
+--disable_ps_protocol
use test;
create table t1(number int auto_increment primary key, original_value varchar(50), f_double double, f_float float, f_double_7_2 double(7,2), f_float_4_3 float (4,3), f_double_u double unsigned, f_float_u float unsigned, f_double_15_1_u double(15,1) unsigned, f_float_3_1_u float (3,1) unsigned);
@@ -140,3 +142,4 @@ insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@val
--query_vertical select * from t1 where number =last_insert_id()
drop table t1;
+--enable_ps_protocol
diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test
index 234a5ec0eef..db5dc8d91da 100644
--- a/mysql-test/t/insert_select.test
+++ b/mysql-test/t/insert_select.test
@@ -122,7 +122,10 @@ insert into t2 values (2,"t2:2"), (3,"t2:3");
--error 1062
insert into t1 select * from t2;
select * from t1;
+# REPLACE .. SELECT is not yet supported by PS
+--disable_ps_protocol
replace into t1 select * from t2;
+--enable_ps_protocol
select * from t1;
drop table t1,t2;
diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test
index d2a70208022..fc54ce88f8a 100644
--- a/mysql-test/t/insert_update.test
+++ b/mysql-test/t/insert_update.test
@@ -35,10 +35,10 @@ create table t1(a int primary key, b int);
insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,5);
select * from t1;
-enable_info;
+--enable_info
insert into t1 values(4,14),(5,15),(6,16),(7,17),(8,18)
on duplicate key update b=b+10;
-disable_info;
+--disable_info
select * from t1;
diff --git a/mysql-test/t/metadata.test b/mysql-test/t/metadata.test
index c426ab9864b..d11cb62b04e 100644
--- a/mysql-test/t/metadata.test
+++ b/mysql-test/t/metadata.test
@@ -6,6 +6,8 @@
drop table if exists t1,t2;
--enable_warnings
--enable_metadata
+# PS protocol gives slightly different metadata
+--disable_ps_protocol
#
# First some simple tests
diff --git a/mysql-test/t/multi_statement.test b/mysql-test/t/multi_statement.test
index bd90275c9f5..862f2294641 100644
--- a/mysql-test/t/multi_statement.test
+++ b/mysql-test/t/multi_statement.test
@@ -1,3 +1,6 @@
+# PS doesn't support multi-statements
+--disable_ps_protocol
+
select 1;
delimiter ||||;
select 2;
diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test
index f27aca7a452..9e4acc2bf24 100644
--- a/mysql-test/t/ps_1general.test
+++ b/mysql-test/t/ps_1general.test
@@ -501,6 +501,8 @@ prepare stmt1 from ' KILL 0 ';
## simple explain
# cases derived from client_test.c: test_explain_bug()
prepare stmt1 from ' explain select a from t1 order by b ';
+# PS protocol gives slightly different metadata
+--disable_ps_protocol
--enable_metadata
execute stmt1;
--disable_metadata
@@ -509,6 +511,7 @@ prepare stmt1 from ' explain select a from t1 where a > ? order by b ';
--enable_metadata
execute stmt1 using @arg00;
--disable_metadata
+--enable_ps_protocol
## parameters with probably problematic characters (quote, double quote)
# cases derived from client_test.c: test_logs()
diff --git a/mysql-test/t/rollback.test b/mysql-test/t/rollback.test
index 87f59417d90..3cb1ea3024b 100644
--- a/mysql-test/t/rollback.test
+++ b/mysql-test/t/rollback.test
@@ -5,6 +5,8 @@
--disable_warnings
drop table if exists t1;
--enable_warnings
+# PS doesn't work with BEGIN ... ROLLBACK
+--disable_ps_protocol
create table t1 (n int not null primary key) engine=myisam;
begin work;
diff --git a/mysql-test/t/rpl_redirect.test b/mysql-test/t/rpl_redirect.test
index 3b5ad6ba88d..c533c0052f0 100644
--- a/mysql-test/t/rpl_redirect.test
+++ b/mysql-test/t/rpl_redirect.test
@@ -3,6 +3,8 @@
#
source include/master-slave.inc;
+# We disable this for now as PS doesn't handle redirection
+--disable_ps_protocol
#first, make sure the slave has had enough time to register
save_master_pos;
diff --git a/mysql-test/t/rpl_user_variables.test b/mysql-test/t/rpl_user_variables.test
index 35fbec72ac8..73b3ace473e 100644
--- a/mysql-test/t/rpl_user_variables.test
+++ b/mysql-test/t/rpl_user_variables.test
@@ -2,6 +2,9 @@
# Test of replicating user variables
#
source include/master-slave.inc;
+# Disable PS as the log positions differs
+--disable_ps_protocol
+
# Clean up old slave's binlogs.
# The slave is started with --log-slave-updates
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index c260c7777e2..5bae44796dc 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -1706,12 +1706,18 @@ select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.compan
select count(*) from t2;
select count(*) from t2 where fld1 < 098024;
+# PS does correct pre-zero here. MySQL can't do it as it returns a number.
+--disable_ps_protocol
select min(fld1) from t2 where fld1>= 098024;
+--enable_ps_protocol
select max(fld1) from t2 where fld1>= 098024;
select count(*) from t3 where price2=76234234;
select count(*) from t3 where companynr=512 and price2=76234234;
explain select min(fld1),max(fld1),count(*) from t2;
+# PS does correct pre-zero here. MySQL can't do it as it returns a number.
+--disable_ps_protocol
select min(fld1),max(fld1),count(*) from t2;
+--enable_ps_protocol
select min(t2nr),max(t2nr) from t3 where t2nr=2115 and price2=823742;
select count(*),min(t2nr),max(t2nr) from t3 where name='spates' and companynr=78;
select t2nr,count(*) from t3 where name='gems' group by t2nr limit 20;
diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test
index 7be494bd0e7..31d9c8154d5 100644
--- a/mysql-test/t/status.test
+++ b/mysql-test/t/status.test
@@ -5,6 +5,8 @@
# connection in a separate thread.
#
--source include/not_embedded.inc
+# PS causes different statistics
+--disable_ps_protocol
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test
index bd571deff49..b67fa7a552d 100644
--- a/mysql-test/t/type_blob.test
+++ b/mysql-test/t/type_blob.test
@@ -16,7 +16,10 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7;
CREATE TABLE t1 (a blob, b text, c blob(250), d text(70000), e text(70000000));
show columns from t1;
+# PS doesn't give errors on prepare yet
+--disable_ps_protocol
CREATE TABLE t2 (a char(257), b varbinary(70000), c varchar(70000000));
+--enable_ps_protocol
show columns from t2;
create table t3 (a long, b long byte);
show create TABLE t3;
diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test
index 4b627ea9b99..216d5bbd286 100644
--- a/mysql-test/t/type_float.test
+++ b/mysql-test/t/type_float.test
@@ -39,7 +39,10 @@ create table t1 (c1 double, c2 varchar(20));
insert t1 values (121,"16");
select c1 + c1 * (c2 / 100) as col from t1;
create table t2 select c1 + c1 * (c2 / 100) as col1, round(c1, 5) as col2, round(c1, 35) as col3, sqrt(c1*1e-15) col4 from t1;
+# Floats are a bit different in PS
+--disable_ps_protocol
select * from t2;
+--enable_ps_protocol
show create table t2;
drop table t1,t2;
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 6e16a2b02aa..36027e8c4cb 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -5,6 +5,9 @@
--disable_warnings
drop table if exists t1,t2,t3,t4,t5,t6;
--enable_warnings
+# PS doesn't work correctly with found_rows: to be fixed
+--disable_ps_protocol
+
CREATE TABLE t1 (a int not null, b char (10) not null);
insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
@@ -73,6 +76,7 @@ select * from t1 union select SQL_BUFFER_RESULT * from t2;
# Test CREATE, INSERT and REPLACE
create table t3 select a,b from t1 union all select a,b from t2;
insert into t3 select a,b from t1 union all select a,b from t2;
+# PS can't handle REPLACE ... SELECT
replace into t3 select a,b as c from t1 union all select a,b from t2;
drop table t1,t2,t3;
diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test
index b6042df51f1..4bd659606f6 100644
--- a/mysql-test/t/warnings.test
+++ b/mysql-test/t/warnings.test
@@ -26,8 +26,11 @@ show warnings limit 1;
drop database if exists not_exists_db;
show count(*) warnings;
create table t1(id int);
+# PS doesn't give warnings on prepare
+--disable_ps_protocol
create table if not exists t1(id int);
select @@warning_count;
+--enable_ps_protocol
drop table t1;
#
@@ -36,7 +39,10 @@ drop table t1;
create table t1(a tinyint, b int not null, c date, d char(5));
load data infile '../../std_data/warnings_loaddata.dat' into table t1 fields terminated by ',';
+# PS doesn't work good with @@warning_count
+--disable_ps_protocol
select @@warning_count;
+--enable_ps_protocol
drop table t1;
#
@@ -74,7 +80,9 @@ enable_query_log;
alter table t1 add b char;
set max_error_count=10;
update t1 set b=a;
+--disable_ps_protocol
select @@warning_count;
+--enable_ps_protocol
#
# Test for handler type
@@ -87,12 +95,15 @@ drop table t1;
#
# Test for deprecated TYPE= syntax
#
+
+# PS doesn't give warnings on prepare
+--disable_ps_protocol
create table t1 (id int) type=heap;
alter table t1 type=myisam;
drop table t1;
+--enable_ps_protocol
#
# Test for deprecated table_type variable
#
set table_type=MYISAM;
-
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index f0bc62b10a0..d8c19d86e5c 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -158,6 +158,8 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
next->next= mem_root->used;
next->size= Size;
mem_root->used= next;
+ DBUG_PRINT("exit",("ptr: 0x%lx", (((char*) next)+
+ ALIGN_SIZE(sizeof(USED_MEM)))));
DBUG_RETURN((gptr) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM))));
#else
uint get_size, block_size;
diff --git a/sql-common/client.c b/sql-common/client.c
index 9fca38f3857..7bf9c90254d 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -727,6 +727,7 @@ void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate)
static void cli_flush_use_result(MYSQL *mysql)
{
/* Clear the current execution status */
+ DBUG_ENTER("cli_flush_use_result");
DBUG_PRINT("warning",("Not all packets read, clearing them"));
for (;;)
{
@@ -744,6 +745,7 @@ static void cli_flush_use_result(MYSQL *mysql)
break; /* End of data */
}
}
+ DBUG_VOID_RETURN;
}
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index 93549f7340c..be349285b88 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -742,9 +742,13 @@ void set_zero_time(MYSQL_TIME *tm)
int my_time_to_str(const MYSQL_TIME *l_time, char *to)
{
+ uint extra_hours= 0;
+ /* Get extra hours, if we are getting data from the server */
+ if (l_time->year == 0 && l_time->month == 0)
+ extra_hours= l_time->day*24;
return my_sprintf(to, (to, "%s%02d:%02d:%02d",
(l_time->neg ? "-" : ""),
- l_time->hour,
+ extra_hours+ l_time->hour,
l_time->minute,
l_time->second));
}
diff --git a/sql/field.cc b/sql/field.cc
index aae507cd0ec..55351ad9a87 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -3508,8 +3508,8 @@ bool Field_time::send_binary(Protocol *protocol)
{
TIME tm;
Field_time::get_time(&tm);
- tm.day= tm.hour/3600; // Move hours to days
- tm.hour-= tm.day*3600;
+ tm.day= tm.hour/24; // Move hours to days
+ tm.hour-= tm.day*24;
return protocol->store_time(&tm);
}
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index f6730c84979..c9396aaa67c 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1760,6 +1760,7 @@ void Item_func_in::fix_length_and_dec()
{
Item **arg, **arg_end;
uint const_itm= 1;
+ THD *thd= current_thd;
agg_cmp_type(&cmp_type, args, arg_count);
@@ -1797,6 +1798,9 @@ void Item_func_in::fix_length_and_dec()
Conversion is possible:
All IN arguments are constants.
*/
+ Item_arena *arena= thd->current_arena, backup;
+ if (arena->is_stmt_prepare())
+ thd->set_n_backup_item_arena(arena, &backup);
for (arg= args+1, arg_end= args+arg_count; arg < arg_end; arg++)
{
if (!my_charset_same(cmp_collation.collation,
@@ -1812,6 +1816,8 @@ void Item_func_in::fix_length_and_dec()
arg[0]= conv;
}
}
+ if (arena->is_stmt_prepare())
+ thd->restore_backup_item_arena(arena, &backup);
}
}
@@ -1839,7 +1845,7 @@ void Item_func_in::fix_length_and_dec()
DBUG_ASSERT(0);
return;
}
- if (array && !(current_thd->is_fatal_error)) // If not EOM
+ if (array && !(thd->is_fatal_error)) // If not EOM
{
uint j=0;
for (uint i=1 ; i < arg_count ; i++)
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index dfcc5789ea4..a869e2d24fb 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -365,9 +365,9 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
if (!(substitution= new Item_func_if(cond, substitution,
new Item_null())))
goto err;
+ if (arena->is_stmt_prepare())
+ thd->restore_backup_item_arena(arena, &backup);
}
- if (arena->is_stmt_prepare())
- thd->restore_backup_item_arena(arena, &backup);
return RES_REDUCE;
}
return RES_OK;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index fc3cf9d4aa9..e6c96dd6a9a 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1693,8 +1693,7 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
SQL_LIST *is_order,
String *is_separator)
:Item_sum(), tmp_table_param(0), max_elements_in_tree(0), warning(0),
- warning_available(0), key_length(0),
- tree_mode(0), distinct(is_distinct), warning_for_row(0),
+ key_length(0), tree_mode(0), distinct(is_distinct), warning_for_row(0),
separator(is_separator), tree(&tree_base), table(0),
order(0), tables_list(0),
arg_count_order(0), arg_count_field(0),
@@ -1752,7 +1751,6 @@ Item_func_group_concat::Item_func_group_concat(THD *thd,
tmp_table_param(item->tmp_table_param),
max_elements_in_tree(item->max_elements_in_tree),
warning(item->warning),
- warning_available(item->warning_available),
key_length(item->key_length),
tree_mode(item->tree_mode),
distinct(item->distinct),
@@ -1779,10 +1777,6 @@ void Item_func_group_concat::cleanup()
DBUG_ENTER("Item_func_group_concat::cleanup");
Item_sum::cleanup();
- /* fix order list */
- for (uint i= 0; i < arg_count_order ; i++)
- order[i]->item= &order[i]->item_ptr;
-
/*
Free table and tree if they belong to this item (if item have not pointer
to original item from which was made copy => it own its objects )
@@ -1802,6 +1796,13 @@ void Item_func_group_concat::cleanup()
tree_mode= 0;
delete_tree(tree);
}
+ if (warning)
+ {
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+ sprintf(warn_buff, ER(ER_CUT_VALUE_GROUP_CONCAT), count_cut_values);
+ warning->set_msg(thd, warn_buff);
+ warning= 0;
+ }
}
DBUG_VOID_RETURN;
}
@@ -1809,19 +1810,6 @@ void Item_func_group_concat::cleanup()
Item_func_group_concat::~Item_func_group_concat()
{
- /*
- Free table and tree if they belong to this item (if item have not pointer
- to original item from which was made copy => it own its objects )
- */
- if (!original)
- {
- if (warning_available)
- {
- char warn_buff[MYSQL_ERRMSG_SIZE];
- sprintf(warn_buff, ER(ER_CUT_VALUE_GROUP_CONCAT), count_cut_values);
- warning->set_msg(current_thd, warn_buff);
- }
- }
}
@@ -2072,12 +2060,10 @@ String* Item_func_group_concat::val_str(String* str)
DBUG_ASSERT(fixed == 1);
if (null_value)
return 0;
- if (count_cut_values && !warning_available)
- {
- warning_available= TRUE;
+ if (count_cut_values && !warning)
warning= push_warning(item_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_CUT_VALUE_GROUP_CONCAT, NULL);
- }
+ ER_CUT_VALUE_GROUP_CONCAT,
+ ER(ER_CUT_VALUE_GROUP_CONCAT));
if (result.length())
return &result;
if (tree_mode)
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 2e85ba87468..5aa0d37190b 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -674,7 +674,6 @@ class Item_func_group_concat : public Item_sum
TMP_TABLE_PARAM *tmp_table_param;
uint max_elements_in_tree;
MYSQL_ERROR *warning;
- bool warning_available;
uint key_length;
bool tree_mode;
bool distinct;
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 060dc14be10..887177c0a19 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -1141,6 +1141,13 @@ bool Protocol_prep::store_time(TIME *tm)
field_pos++;
pos= buff+1;
pos[0]= tm->neg ? 1 : 0;
+ if (tm->hour >= 24)
+ {
+ /* Fix if we come from Item::send */
+ uint days= tm->hour/24;
+ tm->hour-= days*24;
+ tm->day+= days;
+ }
int4store(pos+1, tm->day);
pos[5]= (uchar) tm->hour;
pos[6]= (uchar) tm->minute;
diff --git a/sql/set_var.cc b/sql/set_var.cc
index b5e479b9985..b16676de80e 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -2959,7 +2959,8 @@ void sys_var_thd_table_type::warn_deprecated(THD *thd)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DEPRECATED_SYNTAX,
- ER(ER_WARN_DEPRECATED_SYNTAX), "table_type", "storage_engine");
+ ER(ER_WARN_DEPRECATED_SYNTAX), "table_type",
+ "storage_engine");
}
void sys_var_thd_table_type::set_default(THD *thd, enum_var_type type)
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index cd7b643e146..9313f8e2c1b 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -363,6 +363,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
{
+ bool found_old_table;
DBUG_ENTER("close_thread_tables");
if (thd->derived_tables && !skip_derived)
@@ -385,8 +386,6 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
DBUG_VOID_RETURN; // LOCK TABLES in use
}
- bool found_old_table=0;
-
if (thd->lock)
{
mysql_unlock_tables(thd, thd->lock);
@@ -399,6 +398,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables));
+ found_old_table= 0;
while (thd->open_tables)
found_old_table|=close_thread_table(thd, &thd->open_tables);
thd->some_tables_deleted=0;
@@ -2305,22 +2305,26 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list,
uint wild_num)
{
+ bool is_stmt_prepare;
+ DBUG_ENTER("setup_wild");
if (!wild_num)
- return 0;
+ DBUG_RETURN(0);
+
Item_arena *arena= thd->current_arena, backup;
/*
If we are in preparing prepared statement phase then we have change
temporary mem_root to statement mem root to save changes of SELECT list
*/
- if (arena->is_stmt_prepare())
+ if ((is_stmt_prepare= arena->is_stmt_prepare()))
thd->set_n_backup_item_arena(arena, &backup);
reg2 Item *item;
List_iterator<Item> it(fields);
while ( wild_num && (item= it++))
{
- if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name &&
+ if (item->type() == Item::FIELD_ITEM &&
+ ((Item_field*) item)->field_name &&
((Item_field*) item)->field_name[0] == '*' &&
!((Item_field*) item)->field)
{
@@ -2339,9 +2343,9 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
else if (insert_fields(thd,tables,((Item_field*) item)->db_name,
((Item_field*) item)->table_name, &it))
{
- if (arena->is_stmt_prepare())
+ if (is_stmt_prepare)
thd->restore_backup_item_arena(arena, &backup);
- return (-1);
+ DBUG_RETURN(-1);
}
if (sum_func_list)
{
@@ -2355,9 +2359,9 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
wild_num--;
}
}
- if (arena->is_stmt_prepare())
- thd->restore_backup_item_arena(arena, &backup);
- return 0;
+ if (is_stmt_prepare)
+ thd->restore_backup_item_arena(arena, &backup);
+ DBUG_RETURN(0);
}
/****************************************************************************
@@ -2398,19 +2402,20 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
SYNOPSIS
setup_tables()
- tables - tables list
+ tables table list
- RETURN
- 0 ok; In this case *map will includes the choosed index
- 1 error
- NOTE
- Remap table numbers if INSERT ... SELECT
- Check also that the 'used keys' and 'ignored keys' exists and set up the
- table structure accordingly
+ NOTE
+ Remap table numbers if INSERT ... SELECT
+ Check also that the 'used keys' and 'ignored keys' exists and set up the
+ table structure accordingly
+
+ This has to be called for all tables that are used by items, as otherwise
+ table->map is not set and all Item_field will be regarded as const items.
- This has to be called for all tables that are used by items, as otherwise
- table->map is not set and all Item_field will be regarded as const items.
+ RETURN
+ 0 ok; In this case *map will includes the choosed index
+ 1 error
*/
bool setup_tables(TABLE_LIST *tables)
@@ -2584,7 +2589,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{
table_map not_null_tables= 0;
Item_arena *arena= thd->current_arena, backup;
-
+ bool is_stmt_prepare= arena->is_stmt_prepare();
DBUG_ENTER("setup_conds");
thd->set_query_id=1;
@@ -2622,11 +2627,11 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
!(specialflag & SPECIAL_NO_NEW_FUNC)))
{
table->outer_join= 0;
- if (arena->is_stmt_prepare())
+ if (is_stmt_prepare)
thd->set_n_backup_item_arena(arena, &backup);
*conds= and_conds(*conds, table->on_expr);
table->on_expr=0;
- if (arena->is_stmt_prepare())
+ if (is_stmt_prepare)
thd->restore_backup_item_arena(arena, &backup);
if ((*conds) && !(*conds)->fixed &&
(*conds)->fix_fields(thd, tables, conds))
@@ -2635,7 +2640,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
}
if (table->natural_join)
{
- if (arena->is_stmt_prepare())
+ if (is_stmt_prepare)
thd->set_n_backup_item_arena(arena, &backup);
/* Make a join of all fields with have the same name */
TABLE *t1= table->table;
@@ -2677,7 +2682,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{
*conds= and_conds(*conds, cond_and);
// fix_fields() should be made with temporary memory pool
- if (arena->is_stmt_prepare())
+ if (is_stmt_prepare)
thd->restore_backup_item_arena(arena, &backup);
if (*conds && !(*conds)->fixed)
{
@@ -2689,7 +2694,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{
table->on_expr= and_conds(table->on_expr, cond_and);
// fix_fields() should be made with temporary memory pool
- if (arena->is_stmt_prepare())
+ if (is_stmt_prepare)
thd->restore_backup_item_arena(arena, &backup);
if (table->on_expr && !table->on_expr->fixed)
{
@@ -2698,10 +2703,12 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
}
}
}
+ else if (is_stmt_prepare)
+ thd->restore_backup_item_arena(arena, &backup);
}
}
- if (arena->is_stmt_prepare())
+ if (is_stmt_prepare)
{
/*
We are in prepared statement preparation code => we should store
@@ -2714,7 +2721,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
DBUG_RETURN(test(thd->net.report_error));
err:
- if (arena->is_stmt_prepare())
+ if (is_stmt_prepare)
thd->restore_backup_item_arena(arena, &backup);
DBUG_RETURN(1);
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index f1c75a3b365..aa9d96e8b2a 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -841,7 +841,8 @@ bool select_send::send_eof()
/* Unlock tables before sending packet to gain some speed */
if (thd->lock)
{
- mysql_unlock_tables(thd, thd->lock); thd->lock=0;
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock=0;
}
if (!thd->net.report_error)
{
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index c94d5e52bcf..87644300535 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -102,12 +102,11 @@ void mysql_reset_errors(THD *thd)
MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
uint code, const char *msg)
{
+ MYSQL_ERROR *err= 0;
DBUG_ENTER("push_warning");
if (thd->query_id != thd->warn_id)
mysql_reset_errors(thd);
- MYSQL_ERROR *err= NULL;
-
if (thd->warn_list.elements < thd->variables.max_error_count)
{
/*
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index a0496a04bb2..2c48d1dca8f 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1680,7 +1680,12 @@ bool select_create::send_eof()
We should be able to just keep the table in the table cache.
*/
if (!table->tmp_table)
+ {
hash_delete(&open_cache,(byte*) table);
+ /* Tell threads waiting for refresh that something has happened */
+ if (table->version != refresh_version)
+ VOID(pthread_cond_broadcast(&COND_refresh));
+ }
lock=0;
table=0;
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -1705,6 +1710,9 @@ void select_create::abort()
hash_delete(&open_cache,(byte*) table);
if (!create_info->table_existed)
quick_rm_table(table_type, db, name);
+ /* Tell threads waiting for refresh that something has happened */
+ if (table->version != refresh_version)
+ VOID(pthread_cond_broadcast(&COND_refresh));
}
else if (!create_info->table_existed)
close_temporary_table(thd, db, name);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 040a52ae30e..268198f74a2 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -290,6 +290,7 @@ class THD;
class select_result;
class JOIN;
class select_union;
+class Procedure;
class st_select_lex_unit: public st_select_lex_node {
protected:
TABLE_LIST result_table_list;
@@ -336,6 +337,7 @@ public:
st_select_lex *union_distinct; /* pointer to the last UNION DISTINCT */
bool describe; /* union exec() called for EXPLAIN */
+ Procedure *last_procedure; /* Pointer to procedure, if such exists */
void init_query();
bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index a01b8c895c3..e727eced38f 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3590,8 +3590,8 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
bool dont_check_global_grants, bool no_errors)
{
DBUG_ENTER("check_access");
- DBUG_PRINT("enter",("want_access: %lu master_access: %lu", want_access,
- thd->master_access));
+ DBUG_PRINT("enter",("db: '%s' want_access: %lu master_access: %lu",
+ db ? db : "", want_access, thd->master_access));
#ifndef NO_EMBEDDED_ACCESS_CHECKS
ulong db_access;
#endif
@@ -3645,7 +3645,8 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
thd->priv_user, db, test(want_access & GRANT_ACL));
else
db_access=thd->db_access;
- // Remove SHOW attribute and access rights we already have
+ DBUG_PRINT("info",("db_access: %lu", db_access));
+ /* Remove SHOW attribute and access rights we already have */
want_access &= ~(thd->master_access | EXTRA_ACL);
db_access= ((*save_priv=(db_access | thd->master_access)) & want_access);
@@ -4617,6 +4618,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->db= empty_c_string;
ptr->db_length= 0;
}
+ if (thd->current_arena->is_stmt_prepare())
+ ptr->db= thd->strdup(ptr->db);
ptr->alias= alias_str;
if (lower_case_table_names && table->table.length)
@@ -5142,9 +5145,12 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
*/
for (table= update_list; table; table= table->next)
{
- if ((check_access(thd, UPDATE_ACL, table->db,
- &table->grant.privilege, 0, 1) ||
- grant_option && check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) &&
+ if (table->derived)
+ table->grant.privilege= SELECT_ACL;
+ else if ((check_access(thd, UPDATE_ACL, table->db,
+ &table->grant.privilege, 0, 1) ||
+ grant_option &&
+ check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) &&
(check_access(thd, SELECT_ACL, table->db,
&table->grant.privilege, 0, 0) ||
grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0)))
@@ -5162,6 +5168,7 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
*/
if (&lex->select_lex != lex->all_selects_list)
{
+ DBUG_PRINT("info",("Checking sub query list"));
for (table= tables; table; table= table->next)
{
if (table->table_in_update_from_clause)
@@ -5174,7 +5181,7 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
if (table->table_list)
table->grant= table->table_list->grant;
}
- else
+ else if (!table->derived)
{
if (check_access(thd, SELECT_ACL, table->db,
&table->grant.privilege, 0, 0) ||
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 0e939498925..5a311eefacd 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1093,7 +1093,14 @@ static int mysql_test_select(Prepared_statement *stmt,
}
else
{
- List<Item> &fields= lex->select_lex.item_list;
+ /* Make copy of item list, as change_columns may change it */
+ List<Item> fields(lex->select_lex.item_list);
+
+ /* Change columns if a procedure like analyse() */
+ if (unit->last_procedure &&
+ unit->last_procedure->change_columns(fields))
+ goto err_prep;
+
/*
We can use lex->result as it should've been
prepared in unit->prepare call above.
@@ -1596,6 +1603,8 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
thd->current_arena= stmt;
mysql_init_query(thd, (uchar *) thd->query, thd->query_length);
+ /* Reset warnings from previous command */
+ mysql_reset_errors(thd);
lex= thd->lex;
lex->safe_to_cache_query= 0;
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index f9a1908355b..0be554f58a2 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -229,8 +229,12 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
(ORDER*) 0 : (ORDER *)sl->order_list.first,
(ORDER*) sl->group_list.first,
sl->having,
- (ORDER*) NULL,
+ (is_union ? (ORDER*) 0 :
+ (ORDER*) thd_arg->lex->proc_list.first),
sl, this);
+ /* There are no * in the statement anymore (for PS) */
+ sl->with_wild= 0;
+ last_procedure= join->procedure;
if (res || thd_arg->is_fatal_error)
goto err;
if (sl == first_select)
@@ -344,7 +348,8 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
0, 0,
fake_select_lex->order_list.elements,
(ORDER*) fake_select_lex->order_list.first,
- (ORDER*) NULL, NULL, (ORDER*) NULL,
+ (ORDER*) NULL, NULL,
+ (ORDER*) NULL,
fake_select_lex, this);
fake_select_lex->table_list.empty();
}