summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <hf@deer.(none)>2003-06-09 14:51:40 +0500
committerunknown <hf@deer.(none)>2003-06-09 14:51:40 +0500
commit5551e0df2a5208ead3ca7d024083e572e21f8845 (patch)
treec4c3d3834aeb10d9d1a1125f7259c7d0e1ff6bed
parentf6722eac25d7ef63f31e8470d8f2cbde98931026 (diff)
parent0bb5b9eadddfc911bfaa7c6ee69db92fc7785c94 (diff)
downloadmariadb-git-5551e0df2a5208ead3ca7d024083e572e21f8845.tar.gz
Merge abotchkov@bk-internal.mysql.com:/home/bk/mysql-4.1
into deer.(none):/home/hf/work/mysql-4.1.2way BitKeeper/etc/logging_ok: auto-union include/mysql.h: Auto merged include/mysql_com.h: Auto merged
-rw-r--r--.bzrignore4
-rw-r--r--BUILD/SETUP.sh18
-rw-r--r--BitKeeper/etc/logging_ok1
-rw-r--r--VC++Files/sql/mysqld.dsp4
-rw-r--r--client/mysql.cc56
-rw-r--r--client/mysqltest.c12
-rw-r--r--configure.in14
-rw-r--r--dbug/dbug.c24
-rw-r--r--include/config-win.h8
-rw-r--r--include/m_string.h10
-rw-r--r--include/my_global.h14
-rw-r--r--include/mysql.h3
-rw-r--r--include/mysql_com.h1
-rw-r--r--include/mysql_version.h.in1
-rw-r--r--include/mysqld_error.h2
-rw-r--r--include/sql_common.h1
-rw-r--r--include/sql_state.h164
-rw-r--r--include/thr_alarm.h2
-rw-r--r--innobase/com/com0shm.c9
-rw-r--r--innobase/include/os0file.h7
-rw-r--r--innobase/include/os0sync.h78
-rw-r--r--innobase/include/os0sync.ic1
-rw-r--r--innobase/include/os0thread.h11
-rw-r--r--innobase/include/srv0srv.h6
-rw-r--r--innobase/include/srv0start.h7
-rw-r--r--innobase/include/univ.i4
-rw-r--r--innobase/log/log0log.c27
-rw-r--r--innobase/os/os0file.c131
-rw-r--r--innobase/os/os0sync.c293
-rw-r--r--innobase/os/os0thread.c35
-rw-r--r--innobase/row/row0ins.c5
-rw-r--r--innobase/srv/srv0srv.c118
-rw-r--r--innobase/srv/srv0start.c119
-rw-r--r--innobase/sync/sync0sync.c27
-rw-r--r--innobase/ut/ut0mem.c2
-rw-r--r--libmysql/libmysql.c202
-rw-r--r--libmysqld/Makefile.am2
-rw-r--r--libmysqld/libmysqld.c11
-rw-r--r--man/mysql_fix_privilege_tables.17
-rw-r--r--mysql-test/mysql-test-run.sh14
-rw-r--r--mysql-test/r/alter_table.result5
-rw-r--r--mysql-test/r/analyse.result30
-rw-r--r--mysql-test/r/ansi.result10
-rw-r--r--mysql-test/r/auto_increment.result4
-rw-r--r--mysql-test/r/bdb-deadlock.result2
-rw-r--r--mysql-test/r/bdb.result18
-rw-r--r--mysql-test/r/comments.result2
-rw-r--r--mysql-test/r/create.result42
-rw-r--r--mysql-test/r/ctype_collate.result12
-rw-r--r--mysql-test/r/delayed.result2
-rw-r--r--mysql-test/r/delete.result2
-rw-r--r--mysql-test/r/derived.result27
-rw-r--r--mysql-test/r/distinct.result4
-rw-r--r--mysql-test/r/drop.result6
-rw-r--r--mysql-test/r/err000001.result25
-rw-r--r--mysql-test/r/errors.result25
-rw-r--r--mysql-test/r/explain.result4
-rw-r--r--mysql-test/r/flush.result2
-rw-r--r--mysql-test/r/fulltext.result6
-rw-r--r--mysql-test/r/func_gconcat.result4
-rw-r--r--mysql-test/r/func_str.result2
-rw-r--r--mysql-test/r/func_system.result4
-rw-r--r--mysql-test/r/grant.result35
-rw-r--r--mysql-test/r/grant_cache.result12
-rw-r--r--mysql-test/r/group_by.result6
-rw-r--r--mysql-test/r/handler.result12
-rw-r--r--mysql-test/r/have_mest_timezone.require2
-rw-r--r--mysql-test/r/heap.result4
-rw-r--r--mysql-test/r/heap_btree.result4
-rw-r--r--mysql-test/r/heap_hash.result4
-rw-r--r--mysql-test/r/innodb.result20
-rw-r--r--mysql-test/r/innodb_handler.result8
-rw-r--r--mysql-test/r/insert_select.result13
-rw-r--r--mysql-test/r/insert_update.result2
-rw-r--r--mysql-test/r/join.result2
-rw-r--r--mysql-test/r/join_outer.result12
-rw-r--r--mysql-test/r/key.result2
-rw-r--r--mysql-test/r/loaddata.result12
-rw-r--r--mysql-test/r/lock.result4
-rw-r--r--mysql-test/r/lock_multi.result2
-rw-r--r--mysql-test/r/lowercase_table.result14
-rw-r--r--mysql-test/r/merge.result4
-rw-r--r--mysql-test/r/multi_update.result10
-rw-r--r--mysql-test/r/myisam.result10
-rw-r--r--mysql-test/r/null.result16
-rw-r--r--mysql-test/r/olap.result283
-rw-r--r--mysql-test/r/order_by.result14
-rw-r--r--mysql-test/r/packet.result2
-rw-r--r--mysql-test/r/query_cache.result64
-rw-r--r--mysql-test/r/repair_part1.result (renamed from mysql-test/r/repair.result)0
-rw-r--r--mysql-test/r/row.result14
-rw-r--r--mysql-test/r/rpl000001.result2
-rw-r--r--mysql-test/r/rpl000009.result2
-rw-r--r--mysql-test/r/rpl_empty_master_crash.result4
-rw-r--r--mysql-test/r/rpl_insert_id.result30
-rw-r--r--mysql-test/r/rpl_loaddata.result6
-rw-r--r--mysql-test/r/rpl_log.result24
-rw-r--r--mysql-test/r/rpl_replicate_do.result2
-rw-r--r--mysql-test/r/rpl_rotate_logs.result4
-rw-r--r--mysql-test/r/select.result12
-rw-r--r--mysql-test/r/select_safe.result16
-rw-r--r--mysql-test/r/show_check.result2
-rw-r--r--mysql-test/r/sql_mode.result8
-rw-r--r--mysql-test/r/subselect.result121
-rw-r--r--mysql-test/r/temp_table.result6
-rw-r--r--mysql-test/r/timezone.result25
-rw-r--r--mysql-test/r/truncate.result4
-rw-r--r--mysql-test/r/type_blob.result6
-rw-r--r--mysql-test/r/type_decimal.result6
-rw-r--r--mysql-test/r/type_float.result2
-rw-r--r--mysql-test/r/type_ranges.result2
-rw-r--r--mysql-test/r/union.result26
-rw-r--r--mysql-test/r/update.result6
-rw-r--r--mysql-test/r/user_var.result2
-rw-r--r--mysql-test/r/varbinary.result4
-rw-r--r--mysql-test/r/variables.result36
-rw-r--r--mysql-test/t/alter_table.test9
-rw-r--r--mysql-test/t/ansi.test5
-rw-r--r--mysql-test/t/derived.test9
-rw-r--r--mysql-test/t/errors.test (renamed from mysql-test/t/err000001.test)0
-rw-r--r--mysql-test/t/func_system.test2
-rw-r--r--mysql-test/t/grant.test38
-rw-r--r--mysql-test/t/insert_select.test17
-rw-r--r--mysql-test/t/loaddata.test8
-rw-r--r--mysql-test/t/lowercase_table.test10
-rw-r--r--mysql-test/t/olap.test96
-rw-r--r--mysql-test/t/query_cache.test35
-rw-r--r--mysql-test/t/raid.test2
-rw-r--r--mysql-test/t/repair_part1.test (renamed from mysql-test/t/repair.test)0
-rw-r--r--mysql-test/t/rpl_insert_id.test23
-rw-r--r--mysql-test/t/rpl_loaddata.test17
-rw-r--r--mysql-test/t/rpl_log.test22
-rw-r--r--mysql-test/t/sql_mode.test4
-rw-r--r--mysql-test/t/subselect.test14
-rw-r--r--mysql-test/t/timezone-master.opt1
-rw-r--r--mysql-test/t/timezone.test28
-rw-r--r--mysys/default.c29
-rw-r--r--mysys/thr_alarm.c136
-rw-r--r--scripts/Makefile.am7
-rw-r--r--scripts/mysql_fix_privilege_tables.sh344
-rw-r--r--scripts/mysql_fix_privilege_tables.sql89
-rw-r--r--sql-common/client.c52
-rw-r--r--sql/Makefile.am3
-rw-r--r--sql/field.cc3
-rw-r--r--sql/ha_innodb.cc222
-rw-r--r--sql/handler.cc8
-rw-r--r--sql/item.cc34
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_strfunc.cc8
-rw-r--r--sql/item_sum.cc160
-rw-r--r--sql/item_sum.h79
-rw-r--r--sql/item_uniq.h2
-rw-r--r--sql/lex.h2
-rw-r--r--sql/log.cc51
-rw-r--r--sql/log_event.cc39
-rw-r--r--sql/mysql_priv.h14
-rw-r--r--sql/mysqld.cc137
-rw-r--r--sql/net_serv.cc20
-rw-r--r--sql/protocol.cc7
-rw-r--r--sql/set_var.cc136
-rw-r--r--sql/set_var.h6
-rw-r--r--sql/share/czech/errmsg.txt2
-rw-r--r--sql/share/danish/errmsg.txt2
-rw-r--r--sql/share/dutch/errmsg.txt2
-rw-r--r--sql/share/english/errmsg.txt2
-rw-r--r--sql/share/estonian/errmsg.txt2
-rw-r--r--sql/share/french/errmsg.txt2
-rw-r--r--sql/share/german/errmsg.txt2
-rw-r--r--sql/share/greek/errmsg.txt2
-rw-r--r--sql/share/hungarian/errmsg.txt2
-rw-r--r--sql/share/italian/errmsg.txt2
-rw-r--r--sql/share/japanese/errmsg.txt2
-rw-r--r--sql/share/korean/errmsg.txt2
-rw-r--r--sql/share/norwegian-ny/errmsg.txt2
-rw-r--r--sql/share/norwegian/errmsg.txt2
-rw-r--r--sql/share/polish/errmsg.txt2
-rw-r--r--sql/share/portuguese/errmsg.txt2
-rw-r--r--sql/share/romanian/errmsg.txt2
-rw-r--r--sql/share/russian/errmsg.txt2
-rw-r--r--sql/share/serbian/errmsg.txt2
-rw-r--r--sql/share/slovak/errmsg.txt2
-rw-r--r--sql/share/spanish/errmsg.txt2
-rw-r--r--sql/share/swedish/errmsg.txt2
-rw-r--r--sql/share/ukrainian/errmsg.txt2
-rw-r--r--sql/slave.cc38
-rw-r--r--sql/sql_acl.cc288
-rw-r--r--sql/sql_acl.h2
-rw-r--r--sql/sql_base.cc27
-rw-r--r--sql/sql_cache.cc19
-rw-r--r--sql/sql_help.cc6
-rw-r--r--sql/sql_insert.cc24
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_list.h3
-rw-r--r--sql/sql_parse.cc41
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--sql/sql_repl.cc8
-rw-r--r--sql/sql_select.cc489
-rw-r--r--sql/sql_select.h49
-rw-r--r--sql/sql_show.cc27
-rw-r--r--sql/sql_state.c53
-rw-r--r--sql/sql_string.cc4
-rw-r--r--sql/sql_string.h5
-rw-r--r--sql/sql_table.cc138
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sql_update.cc1
-rw-r--r--sql/sql_yacc.yy66
-rw-r--r--sql/time.cc56
-rw-r--r--sql/unireg.h13
-rw-r--r--strings/Makefile.am2
-rw-r--r--strings/ctype.c2
-rw-r--r--strings/str_test.c4
-rw-r--r--strings/strings-x86.s86
-rw-r--r--strings/strings.asm16
-rw-r--r--support-files/mysql.server.sh2
-rw-r--r--support-files/mysql.spec.sh12
-rw-r--r--tests/client_test.c238
216 files changed, 4591 insertions, 1748 deletions
diff --git a/.bzrignore b/.bzrignore
index dd77bcb1d12..4e9ce4e41ab 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -399,6 +399,7 @@ libmysqld/sql_rename.cc
libmysqld/sql_repl.cc
libmysqld/sql_select.cc
libmysqld/sql_show.cc
+libmysqld/sql_state.c
libmysqld/sql_string.cc
libmysqld/sql_table.cc
libmysqld/sql_test.cc
@@ -552,6 +553,7 @@ sql-bench/test-select
sql-bench/test-transactions
sql-bench/test-wisconsin
sql/.gdbinit
+sql/client.c
sql/gen_lex_hash
sql/gmon.out
sql/lex_hash.h
@@ -586,6 +588,7 @@ stamp-h4
strings/conf_to_src
strings/ctype_autoconf.c
strings/ctype_extra_sources.c
+strings/str_test
support-files/MacOSX/Description.plist
support-files/MacOSX/Info.plist
support-files/MacOSX/ReadMe.txt
@@ -619,4 +622,3 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
-sql/client.c
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh
index 4a19c490e5d..4d41f514704 100644
--- a/BUILD/SETUP.sh
+++ b/BUILD/SETUP.sh
@@ -71,6 +71,22 @@ else
make=make
fi
-if test -z $CXX ; then
+if test -z "$CXX" ; then
CXX=gcc
fi
+
+# If ccache (a compiler cache which reduces build time)
+# (http://samba.org/ccache) is installed, use it.
+# We use 'grep' and hope 'grep' will work as expected
+# (returns 0 if finds lines)
+if ccache -V > /dev/null 2>&1
+then
+ if ! (echo "$CC" | grep "ccache" > /dev/null)
+ then
+ CC="ccache $CC"
+ fi
+ if ! (echo "$CXX" | grep "ccache" > /dev/null)
+ then
+ CXX="ccache $CXX"
+ fi
+fi
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 5fc0be183e1..a94b9c2045e 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -40,6 +40,7 @@ jani@hynda.mysql.fi
jani@janikt.pp.saunalahti.fi
jani@rhols221.adsl.netsonic.fi
jani@rhols221.arenanet.fi
+jani@ua126d19.elisa.omakaista.fi
jcole@abel.spaceapes.com
jcole@main.burghcom.com
jcole@mugatu.spaceapes.com
diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp
index a475c44e948..6aab591120a 100644
--- a/VC++Files/sql/mysqld.dsp
+++ b/VC++Files/sql/mysqld.dsp
@@ -1137,6 +1137,10 @@ SOURCE=.\sql_show.cpp
# End Source File
# Begin Source File
+SOURCE=.\sql_state.c
+# End Source File
+# Begin Source File
+
SOURCE=.\sql_string.cpp
!IF "$(CFG)" == "mysqld - Win32 Release"
diff --git a/client/mysql.cc b/client/mysql.cc
index 1bfadb37eb2..a957f804537 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -44,7 +44,7 @@
#include <locale.h>
#endif
-const char *VER= "14.0";
+const char *VER= "14.1";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
@@ -200,7 +200,9 @@ static int com_nopager(String *str, char*), com_pager(String *str, char*),
static int read_lines(bool execute_commands);
static int sql_connect(char *host,char *database,char *user,char *password,
uint silent);
-static int put_info(const char *str,INFO_TYPE info,uint error=0);
+static int put_info(const char *str,INFO_TYPE info,uint error=0,
+ const char *sql_state=0);
+static int put_error(MYSQL *mysql);
static void safe_put_field(const char *pos,ulong length);
static void xmlencode_print(const char *src, uint length);
static void init_pager();
@@ -1437,7 +1439,7 @@ int mysql_real_query_for_lazy(const char *buf, int length)
{
if (!mysql_real_query(&mysql,buf,length))
return 0;
- uint error=put_info(mysql_error(&mysql),INFO_ERROR, mysql_errno(&mysql));
+ int error= put_error(&mysql);
if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 ||
!opt_reconnect)
return error;
@@ -1452,8 +1454,7 @@ int mysql_store_result_for_lazy(MYSQL_RES **result)
return 0;
if (mysql_error(&mysql)[0])
- return put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql));
-
+ return put_error(&mysql);
return 0;
}
@@ -1664,9 +1665,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
if (quick)
{
if (!(result=mysql_use_result(&mysql)) && mysql_field_count(&mysql))
- {
- return put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql));
- }
+ return put_error(&mysql);
}
else
{
@@ -1728,7 +1727,7 @@ com_go(String *buffer,char *line __attribute__((unused)))
put_info("",INFO_RESULT); // Empty row
if (result && !mysql_eof(result)) /* Something wrong when using quick */
- error=put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql));
+ error= put_error(&mysql);
else if (unbuffered)
fflush(stdout);
mysql_free_result(result);
@@ -2442,12 +2441,12 @@ com_use(String *buffer __attribute__((unused)), char *line)
if (mysql_select_db(&mysql,tmp))
{
if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR)
- return put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql));
+ return put_error(&mysql);
if (reconnect())
return opt_reconnect ? -1 : 1; // Fatal error
if (mysql_select_db(&mysql,tmp))
- return put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql));
+ return put_error(&mysql);
}
my_free(current_db,MYF(MY_ALLOW_ZERO_PTR));
current_db=my_strdup(tmp,MYF(MY_WME));
@@ -2569,7 +2568,7 @@ sql_real_connect(char *host,char *database,char *user,char *password,
(mysql_errno(&mysql) != CR_CONN_HOST_ERROR &&
mysql_errno(&mysql) != CR_CONNECTION_ERROR))
{
- put_info(mysql_error(&mysql),INFO_ERROR,mysql_errno(&mysql));
+ (void) put_error(&mysql);
(void) fflush(stdout);
return ignore_errors ? -1 : 1; // Abort
}
@@ -2719,7 +2718,7 @@ select_limit, max_join_size);
static int
-put_info(const char *str,INFO_TYPE info_type,uint error)
+put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
{
FILE *file= (info_type == INFO_ERROR ? stderr : stdout);
static int inited=0;
@@ -2764,7 +2763,12 @@ put_info(const char *str,INFO_TYPE info_type,uint error)
putchar('\007'); /* This should make a bell */
vidattr(A_STANDOUT);
if (error)
- (void) tee_fprintf(file, "ERROR %d: ", error);
+ {
+ if (sqlstate)
+ (void) tee_fprintf(file, "ERROR %d (%s): ", error, sqlstate);
+ else
+ (void) tee_fprintf(file, "ERROR %d: ", error);
+ }
else
tee_puts("ERROR: ", file);
}
@@ -2779,6 +2783,14 @@ put_info(const char *str,INFO_TYPE info_type,uint error)
}
+static int
+put_error(MYSQL *mysql)
+{
+ return put_info(mysql_error(mysql), INFO_ERROR, mysql_errno(mysql),
+ mysql_sqlstate(mysql));
+}
+
+
static void remove_cntrl(String &buffer)
{
char *start,*end;
@@ -2929,14 +2941,18 @@ static const char* construct_prompt()
add_int_to_prompt(++prompt_counter);
break;
case 'v':
- processed_prompt.append(mysql_get_server_info(&mysql));
+ if (connected)
+ processed_prompt.append(mysql_get_server_info(&mysql));
+ else
+ processed_prompt.append("not_connected");
break;
case 'd':
processed_prompt.append(current_db ? current_db : "(none)");
break;
case 'h':
{
- const char *prompt=mysql_get_host_info(&mysql);
+ const char *prompt;
+ prompt= connected ? mysql_get_host_info(&mysql) : "not_connected";
if (strstr(prompt, "Localhost"))
processed_prompt.append("localhost");
else
@@ -2948,8 +2964,13 @@ static const char* construct_prompt()
}
case 'p':
#ifndef EMBEDDED_LIBRARY
+ if (!connected)
+ {
+ processed_prompt.append("not_connected");
+ break;
+ }
if (strstr(mysql_get_host_info(&mysql),"TCP/IP") ||
- ! mysql.unix_socket)
+ !mysql.unix_socket)
add_int_to_prompt(mysql.port);
else
{
@@ -3097,4 +3118,3 @@ void sql_element_free(void *ptr)
my_free((gptr) ptr,MYF(0));
}
#endif /* EMBEDDED_LIBRARY */
-
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 9889d365335..517c41c2b18 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -42,7 +42,7 @@
**********************************************************************/
-#define MTEST_VERSION "1.27"
+#define MTEST_VERSION "1.28"
#include <my_global.h>
#include <mysql_embed.h>
@@ -523,8 +523,12 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname)
if (!my_stat(eval_file, &stat_info, MYF(MY_WME)))
die(NullS);
- if (!eval_result && stat_info.st_size != ds->length)
+ if (!eval_result && (uint) stat_info.st_size != ds->length)
+ {
+ DBUG_PRINT("info",("Size differs: result size: %u file size: %u",
+ ds->length, stat_info.st_size));
DBUG_RETURN(2);
+ }
if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME))))
die(NullS);
@@ -2147,6 +2151,10 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
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_sqlstate(mysql),
+ strlen(mysql_sqlstate(mysql)));
+ dynstr_append_mem(ds,": ",2);
replace_dynstr_append_mem(ds,mysql_error(mysql),
strlen(mysql_error(mysql)));
dynstr_append_mem(ds,"\n",1);
diff --git a/configure.in b/configure.in
index f25cb213e0b..bddeeb6c989 100644
--- a/configure.in
+++ b/configure.in
@@ -359,7 +359,7 @@ then
# we will gets some problems when linking static programs.
# The following code is used to fix this problem.
- if test "$CXX" = "gcc"
+ if test "$CXX" = "gcc" -o "$CXX" = "ccache gcc"
then
if $CXX -v 2>&1 | grep 'version 3' > /dev/null 2>&1
then
@@ -1023,8 +1023,16 @@ case $SYSTEM_TYPE in
;;
*freebsd*)
echo "Adding fix for interrupted reads"
- CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH"
- CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH"
+ OSVERSION=`sysctl -a | grep osreldate | awk '{ print $2 }'`
+ if test "$OSVERSION" -gt "480100" && \
+ test "$OSVERSION" -lt "500000" || \
+ test "$OSVERSION" -gt "500109"
+ then
+ CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000"
+ else
+ CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH"
+ CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH"
+ fi
;;
*netbsd*)
echo "Adding flag -Dunix"
diff --git a/dbug/dbug.c b/dbug/dbug.c
index a4f9d5ecd4b..f7b2fb75ba0 100644
--- a/dbug/dbug.c
+++ b/dbug/dbug.c
@@ -280,7 +280,7 @@ static BOOLEAN Writable(char *pathname);
static void ChangeOwner(char *pathname);
/* Allocate memory for runtime support */
#endif
-static char *DbugMalloc(int size);
+static char *DbugMalloc(size_t size);
/* Remove leading pathname components */
static char *BaseName(const char *pathname);
static void DoPrefix(uint line);
@@ -1120,7 +1120,7 @@ static void PushState ()
init_done=TRUE;
}
(void) code_state(); /* Alloc memory */
- new_malloc = (struct state *) DbugMalloc (sizeof (struct state));
+ new_malloc = (struct state *) DbugMalloc(sizeof (struct state));
new_malloc -> flags = 0;
new_malloc -> delay = 0;
new_malloc -> maxdepth = MAXDEPTH;
@@ -1341,11 +1341,10 @@ struct link *linkp)
*/
-static char *StrDup (
-const char *str)
+static char *StrDup (const char *str)
{
reg1 char *new_malloc;
- new_malloc = DbugMalloc ((int) strlen (str) + 1);
+ new_malloc = DbugMalloc((size_t) strlen (str) + 1);
(void) strcpy (new_malloc, str);
return (new_malloc);
}
@@ -1606,14 +1605,13 @@ static void DbugExit (const char *why)
*
*/
-static char *DbugMalloc (
-int size)
+static char *DbugMalloc (size_t size)
{
- register char *new_malloc;
+ register char *new_malloc;
- if (!(new_malloc = (char*) malloc ((unsigned int) size)))
- DbugExit ("out of memory");
- return (new_malloc);
+ if (!(new_malloc = (char*) malloc((size_t) size)))
+ DbugExit ("out of memory");
+ return (new_malloc);
}
@@ -1622,9 +1620,7 @@ int size)
* separator (to allow directory-paths in dos).
*/
-static char *static_strtok (
-char *s1,
-pchar separator)
+static char *static_strtok (char *s1, pchar separator)
{
static char *end = NULL;
reg1 char *rtnval,*cpy;
diff --git a/include/config-win.h b/include/config-win.h
index d76233c39f2..c4e9588666e 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -138,6 +138,11 @@ typedef uint rf_SetTimer;
#define SIZEOF_LONG 4
#define SIZEOF_LONG_LONG 8
#define SIZEOF_OFF_T 8
+#ifdef _WIN64
+#define SIZEOF_CHARP 8
+#else
+#define SIZEOF_CHARP 4
+#endif
#define HAVE_BROKEN_NETINET_INCLUDES
#ifdef __NT__
#define HAVE_NAMED_PIPE /* We can only create pipes on NT */
@@ -203,6 +208,7 @@ inline double ulonglong2double(ulonglong value)
/* Optimized store functions for Intel x86 */
+#ifndef _WIN64
#define sint2korr(A) (*((int16 *) (A)))
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
(((uint32) 255L << 24) | \
@@ -243,7 +249,7 @@ inline double ulonglong2double(ulonglong value)
#define float8get(V,M) doubleget((V),(M))
#define float4store(V,M) memcpy((byte*) V,(byte*) (&M),sizeof(float))
#define float8store(V,M) doublestore((V),(M))
-
+#endif /* _WIN64 */
#define HAVE_PERROR
#define HAVE_VFPRINT
diff --git a/include/m_string.h b/include/m_string.h
index 15a488fe72a..5863bb51b73 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -74,14 +74,14 @@
/* Unixware 7 */
#if !defined(HAVE_BFILL)
# define bfill(A,B,C) memset((A),(C),(B))
-# define bmove_allign(A,B,C) memcpy((A),(B),(C))
+# define bmove_align(A,B,C) memcpy((A),(B),(C))
#endif
#if !defined(HAVE_BCMP)
# define bcopy(s, d, n) memcpy((d), (s), (n))
# define bcmp(A,B,C) memcmp((A),(B),(C))
# define bzero(A,B) memset((A),0,(B))
-# define bmove_allign(A,B,C) memcpy((A),(B),(C))
+# define bmove_align(A,B,C) memcpy((A),(B),(C))
#endif
#if defined(__cplusplus) && !defined(OS2)
@@ -111,11 +111,11 @@ extern char NEAR _dig_vec[]; /* Declared in int2str() */
#endif
#ifdef MSDOS
-#undef bmove_allign
-#define bmove512(A,B,C) bmove_allign(A,B,C)
+#undef bmove_align
+#define bmove512(A,B,C) bmove_align(A,B,C)
#define my_itoa(A,B,C) itoa(A,B,C)
#define my_ltoa(A,B,C) ltoa(A,B,C)
-extern void bmove_allign(gptr dst,const gptr src,uint len);
+extern void bmove_align(gptr dst,const gptr src,uint len);
#endif
#if (!defined(USE_BMOVE512) || defined(HAVE_purify)) && !defined(bmove512)
diff --git a/include/my_global.h b/include/my_global.h
index 86fb2a5ee4d..9de8e310d79 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -266,7 +266,7 @@ C_MODE_END
# endif
#endif /* TIME_WITH_SYS_TIME */
#ifdef HAVE_UNISTD_H
-#if defined(HAVE_OPENSSL) && !defined(__FreeBSD__) && !defined(NeXT)
+#if defined(HAVE_OPENSSL) && !defined(__FreeBSD__) && !defined(NeXT) && !defined(__OpenBSD__)
#define crypt unistd_crypt
#endif
#include <unistd.h>
@@ -654,7 +654,13 @@ extern double my_atof(const char*);
Max size that must be added to a so that we know Size to make
adressable obj.
*/
+#if SIZEOF_CHARP == 4
typedef long my_ptrdiff_t;
+#else
+typedef long long my_ptrdiff_t;
+#endif
+
+
#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1))
#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double))
/* Size to make adressable obj. */
@@ -731,6 +737,8 @@ typedef unsigned __int64 my_ulonglong;
typedef unsigned long long my_ulonglong;
#endif
+/* typedef used for length of string; Should be unsigned! */
+typedef ulong size_str;
#ifdef USE_RAID
/*
@@ -869,7 +877,7 @@ typedef char bool; /* Ordinary boolean values 0 1 */
*/
/* Optimized store functions for Intel x86 */
-#ifdef __i386__
+#if defined(__i386__) && !defined(_WIN64)
#define sint2korr(A) (*((int16 *) (A)))
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
(((uint32) 255L << 24) | \
diff --git a/include/mysql.h b/include/mysql.h
index becdf22067d..7e472a120b3 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -274,7 +274,8 @@ typedef struct st_mysql
my_bool free_me; /* If free in mysql_close */
my_ulonglong insert_id; /* id if insert on table with NEXTNR */
unsigned int last_errno;
- char *last_error;
+ char *last_error; /* Used by embedded server */
+ char sqlstate[SQLSTATE_LENGTH+1]; /* Used by embedded server */
} MYSQL;
#endif
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 0d8211106a2..0624782c075 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -324,6 +324,7 @@ my_bool check_scramble(const char *, const char *message,
unsigned long *salt,my_bool old_ver);
char *get_tty_password(char *opt_message);
void hash_password(unsigned long *result, const char *password);
+const char *mysql_errno_to_sqlstate(unsigned int mysql_errno);
/* Some other useful functions */
diff --git a/include/mysql_version.h.in b/include/mysql_version.h.in
index 91cf3ecc074..31bf2bdd00d 100644
--- a/include/mysql_version.h.in
+++ b/include/mysql_version.h.in
@@ -10,6 +10,7 @@
#else
#define PROTOCOL_VERSION @PROTOCOL_VERSION@
#define MYSQL_SERVER_VERSION "@VERSION@"
+#define MYSQL_BASE_VERSION "mysqld-@MYSQL_BASE_VERSION@"
#ifndef MYSQL_SERVER_SUFFIX
#define MYSQL_SERVER_SUFFIX "@MYSQL_SERVER_SUFFIX@"
#endif
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index d2fc5bbc77f..ccccb188037 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -282,4 +282,6 @@
#define ER_WARN_DATA_TRUNCATED 1263
#define ER_WARN_USING_OTHER_HANDLER 1264
#define ER_CANT_AGGREGATE_COLLATIONS 1265
+#define ER_DROP_USER 1266
+#define ER_REVOKE_GRANTS 1267
#define ER_ERROR_MESSAGES 266
diff --git a/include/sql_common.h b/include/sql_common.h
index 3a668a8dd41..65283486fb4 100644
--- a/include/sql_common.h
+++ b/include/sql_common.h
@@ -16,6 +16,7 @@
extern const char *unknown_sqlstate;
+extern const char *not_error_sqlstate;
#ifdef __cplusplus
extern "C" {
diff --git a/include/sql_state.h b/include/sql_state.h
new file mode 100644
index 00000000000..cc0fab7bfce
--- /dev/null
+++ b/include/sql_state.h
@@ -0,0 +1,164 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ This file includes a mapping from mysql_errno.h to sql_state (as used by
+ MyODBC) and jdbc_state.
+ It's suitable to include into a C struct for further processing
+
+ The first column is the mysqld server error (declared in mysqld_error.h),
+ the second column is the ODBC state (which the 4.1 server sends out by
+ default) and the last is the state used by the JDBC driver.
+ If the last column is "" then it means that the JDBC driver is using the
+ ODBC state
+
+ The errors in this file is sorted in the same order as in mysqld_error.h
+ to allow on to do binary searches for the sqlstate.
+*/
+
+ER_DUP_KEY, "23000", "",
+ER_OUTOFMEMORY, "HY001", "S1001",
+ER_OUT_OF_SORTMEMORY, "HY001", "S1001",
+ER_CON_COUNT_ERROR, "08004", "",
+ER_BAD_HOST_ERROR, "08S01", "",
+ER_HANDSHAKE_ERROR, "08S01", "",
+ER_DBACCESS_DENIED_ERROR, "42000", "",
+ER_ACCESS_DENIED_ERROR, "42000", "28000",
+ER_NO_DB_ERROR, "42000", "",
+ER_UNKNOWN_COM_ERROR, "08S01", "",
+ER_BAD_NULL_ERROR, "23000", "",
+ER_BAD_DB_ERROR, "42000", "",
+ER_TABLE_EXISTS_ERROR, "42S01", "",
+ER_BAD_TABLE_ERROR, "42S02", "",
+ER_NON_UNIQ_ERROR, "23000", "",
+ER_SERVER_SHUTDOWN, "08S01", "",
+ER_BAD_FIELD_ERROR, "42S22", "S0022",
+ER_WRONG_FIELD_WITH_GROUP, "42000", "S1009",
+ER_WRONG_GROUP_FIELD, "42000", "S1009",
+ER_WRONG_SUM_SELECT, "42000", "S1009",
+ER_WRONG_VALUE_COUNT, "21S01", "",
+ER_TOO_LONG_IDENT, "42000", "S1009",
+ER_DUP_FIELDNAME, "42S21", "S1009",
+ER_DUP_KEYNAME, "42000", "S1009",
+ER_DUP_ENTRY, "23000", "S1009",
+ER_WRONG_FIELD_SPEC, "42000", "S1009",
+ER_PARSE_ERROR, "42000", "",
+ER_EMPTY_QUERY, "42000" , "",
+ER_NONUNIQ_TABLE, "42000", "S1009",
+ER_INVALID_DEFAULT, "42000", "S1009",
+ER_MULTIPLE_PRI_KEY, "42000", "S1009",
+ER_TOO_MANY_KEYS, "42000", "S1009",
+ER_TOO_MANY_KEY_PARTS, "42000", "S1009",
+ER_TOO_LONG_KEY, "42000", "S1009",
+ER_KEY_COLUMN_DOES_NOT_EXITS, "42000", "S1009",
+ER_BLOB_USED_AS_KEY, "42000", "S1009",
+ER_TOO_BIG_FIELDLENGTH, "42000", "S1009",
+ER_WRONG_AUTO_KEY, "42000", "S1009",
+ER_FORCING_CLOSE, "08S01", "",
+ER_IPSOCK_ERROR, "088S01", "",
+ER_NO_SUCH_INDEX, "42S12", "S1009",
+ER_WRONG_FIELD_TERMINATORS, "42000", "S1009",
+ER_BLOBS_AND_NO_TERMINATED, "42000", "S1009",
+ER_CANT_REMOVE_ALL_FIELDS, "42000", "",
+ER_CANT_DROP_FIELD_OR_KEY, "42000", "",
+ER_BLOB_CANT_HAVE_DEFAULT, "42000", "",
+ER_WRONG_DB_NAME, "42000", "",
+ER_WRONG_TABLE_NAME, "42000", "",
+ER_TOO_BIG_SELECT, "42000", "",
+ER_UNKNOWN_PROCEDURE, "42000", "",
+ER_WRONG_PARAMCOUNT_TO_PROCEDURE, "42000", "",
+ER_UNKNOWN_TABLE, "42S02", "",
+ER_FIELD_SPECIFIED_TWICE, "42000", "",
+ER_UNSUPPORTED_EXTENSION, "42000", "",
+ER_TABLE_MUST_HAVE_COLUMNS, "42000", "",
+ER_UNKNOWN_CHARACTER_SET, "42000", "",
+ER_TOO_BIG_ROWSIZE, "42000", "",
+ER_STACK_OVERRUN, "HY000", "",
+ER_WRONG_OUTER_JOIN, "42000", "",
+ER_NULL_COLUMN_IN_INDEX, "42000", "",
+ER_PASSWORD_ANONYMOUS_USER, "42000", "",
+ER_PASSWORD_NOT_ALLOWED, "42000", "",
+ER_PASSWORD_NO_MATCH, "42000", "",
+ER_WRONG_VALUE_COUNT_ON_ROW, "21S01", "",
+ER_INVALID_USE_OF_NULL, "42000", "",
+ER_REGEXP_ERROR, "42000", "",
+ER_MIX_OF_GROUP_FUNC_AND_FIELDS,"42000", "",
+ER_NONEXISTING_GRANT, "42000", "",
+ER_TABLEACCESS_DENIED_ERROR, "42000", "",
+ER_COLUMNACCESS_DENIED_ERROR, "42000", "",
+ER_ILLEGAL_GRANT_FOR_TABLE, "42000", "",
+ER_GRANT_WRONG_HOST_OR_USER, "42000", "",
+ER_NO_SUCH_TABLE, "42S02", "",
+ER_NONEXISTING_TABLE_GRANT, "42000", "",
+ER_NOT_ALLOWED_COMMAND, "42000", "",
+ER_SYNTAX_ERROR, "42000", "",
+ER_ABORTING_CONNECTION, "08S01", "",
+ER_NET_PACKET_TOO_LARGE, "08S01", "",
+ER_NET_READ_ERROR_FROM_PIPE, "08S01", "",
+ER_NET_FCNTL_ERROR, "08S01", "",
+ER_NET_PACKETS_OUT_OF_ORDER, "08S01", "",
+ER_NET_UNCOMPRESS_ERROR, "08S01", "",
+ER_NET_READ_ERROR, "08S01", "",
+ER_NET_READ_INTERRUPTED, "08S01", "",
+ER_NET_ERROR_ON_WRITE, "08S01", "",
+ER_NET_WRITE_INTERRUPTED, "08S01", "",
+ER_TOO_LONG_STRING, "42000", "",
+ER_TABLE_CANT_HANDLE_BLOB, "42000", "",
+ER_TABLE_CANT_HANDLE_AUTO_INCREMENT, "42000", "",
+ER_WRONG_COLUMN_NAME, "42000", "",
+ER_WRONG_KEY_COLUMN, "42000", "",
+ER_DUP_UNIQUE, "23000", "",
+ER_BLOB_KEY_WITHOUT_LENGTH, "42000", "",
+ER_PRIMARY_CANT_HAVE_NULL, "42000", "",
+ER_TOO_MANY_ROWS, "42000", "",
+ER_REQUIRES_PRIMARY_KEY, "42000", "",
+ER_CHECK_NO_SUCH_TABLE, "42000", "",
+ER_CHECK_NOT_IMPLEMENTED, "42000", "",
+ER_CANT_DO_THIS_DURING_AN_TRANSACTION, "25000", "",
+ER_ERROR_DURING_COMMIT, "HY000", "",
+ER_ERROR_DURING_ROLLBACK, "HY000", "",
+ER_NEW_ABORTING_CONNECTION, "08S01", "",
+ER_MASTER_NET_READ, "08S01", "",
+ER_MASTER_NET_WRITE, "08S01", "",
+ER_TOO_MANY_USER_CONNECTIONS, "42000", "",
+ER_READ_ONLY_TRANSACTION, "25000", "",
+ER_NO_PERMISSION_TO_CREATE_USER,"42000", "",
+ER_LOCK_DEADLOCK, "40001", "",
+ER_NO_REFERENCED_ROW, "23000", "",
+ER_ROW_IS_REFERENCED, "23000", "",
+ER_CONNECT_TO_MASTER, "08S01", "",
+ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,"21000", "",
+ER_USER_LIMIT_REACHED, "42000", "",
+ER_NO_DEFAULT, "42000", "",
+ER_WRONG_VALUE_FOR_VAR, "42000", "",
+ER_WRONG_TYPE_FOR_VAR, "42000", "",
+ER_CANT_USE_OPTION_HERE, "42000", "",
+ER_NOT_SUPPORTED_YET, "42000", "",
+ER_WRONG_FK_DEF, "42000", "",
+ER_CARDINALITY_COL, "21000", "",
+ER_SUBSELECT_NO_1_ROW, "21000", "",
+ER_ILLEGAL_REFERENCE, "42S22", "",
+ER_DERIVED_MUST_HAVE_ALIAS, "42000", "",
+ER_SELECT_REDUCED, "01000", "",
+ER_TABLENAME_NOT_ALLOWED_HERE, "42000", "",
+ER_NOT_SUPPORTED_AUTH_MODE, "08004", "",
+ER_SPATIAL_CANT_HAVE_NULL, "42000", "",
+ER_COLLATION_CHARSET_MISMATCH, "42000", "",
+ER_WARN_TOO_FEW_RECORDS, "01000", "",
+ER_WARN_TOO_MANY_RECORDS, "01000", "",
+ER_WARN_NULL_TO_NOTNULL, "01000", "",
+ER_WARN_DATA_OUT_OF_RANGE, "01000", "",
+ER_WARN_DATA_TRUNCATED, "01000", "",
diff --git a/include/thr_alarm.h b/include/thr_alarm.h
index 30825d49158..439f046252f 100644
--- a/include/thr_alarm.h
+++ b/include/thr_alarm.h
@@ -103,7 +103,7 @@ void init_thr_alarm(uint max_alarm);
bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff);
void thr_alarm_kill(pthread_t thread_id);
void thr_end_alarm(thr_alarm_t *alarmed);
-void end_thr_alarm(void);
+void end_thr_alarm(my_bool free_structures);
sig_handler process_alarm(int);
#ifndef thr_got_alarm
bool thr_got_alarm(thr_alarm_t *alrm);
diff --git a/innobase/com/com0shm.c b/innobase/com/com0shm.c
index 72ab23b9be8..ed185ccdf47 100644
--- a/innobase/com/com0shm.c
+++ b/innobase/com/com0shm.c
@@ -103,7 +103,8 @@ struct com_shm_endpoint_struct{
the area currently may contain a datagram;
NOTE: automatic event */
os_event_t empty; /* this is in the signaled state if the area
- currently may be empty; NOTE: automatic event */
+ currently may be empty; NOTE: automatic
+ event */
ip_mutex_hdl_t* ip_mutex; /* handle to the interprocess mutex
protecting the shared memory */
UT_LIST_NODE_T(com_shm_endpoint_t) list; /* If the endpoint struct
@@ -793,16 +794,18 @@ com_shm_create_or_open(
ut_strcpy(buf + len, (char*)"_IBSHM_EV_NE"),
- event_ne = os_event_create_auto(buf);
+ event_ne = os_event_create(buf);
ut_ad(event_ne);
ut_strcpy(buf + len, (char*)"_IBSHM_EV_EM"),
- event_em = os_event_create_auto(buf);
+ event_em = os_event_create(buf);
ut_ad(event_em);
+ ut_a(0); /* event_ne and event_em should be auto events! */
+
com_shm_endpoint_set_shm(ep, shm);
com_shm_endpoint_set_map(ep, map);
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index a7624a90d5e..86f27a2d3eb 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -301,6 +301,13 @@ os_aio(
are ignored */
void* message2);
/****************************************************************************
+Wakes up all async i/o threads so that they know to exit themselves in
+shutdown. */
+
+void
+os_aio_wake_all_threads_at_shutdown(void);
+/*=====================================*/
+/****************************************************************************
Waits until there are no pending writes in os_aio_write_array. There can
be other, synchronous, pending writes. */
diff --git a/innobase/include/os0sync.h b/innobase/include/os0sync.h
index b2d613c4619..634507467f9 100644
--- a/innobase/include/os0sync.h
+++ b/innobase/include/os0sync.h
@@ -10,15 +10,29 @@ Created 9/6/1995 Heikki Tuuri
#define os0sync_h
#include "univ.i"
+#include "ut0lst.h"
#ifdef __WIN__
#define os_fast_mutex_t CRITICAL_SECTION
-typedef void* os_event_t;
-#else
+typedef HANDLE os_native_event_t;
+
+typedef struct os_event_struct os_event_struct_t;
+typedef os_event_struct_t* os_event_t;
+struct os_event_struct {
+ os_native_event_t handle;
+ /* Windows event */
+ UT_LIST_NODE_T(os_event_struct_t) os_event_list;
+ /* list of all created events */
+};
+#else
typedef pthread_mutex_t os_fast_mutex_t;
+
+typedef struct os_event_struct os_event_struct_t;
+typedef os_event_struct_t* os_event_t;
+
struct os_event_struct {
os_fast_mutex_t os_mutex; /* this mutex protects the next
fields */
@@ -26,9 +40,9 @@ struct os_event_struct {
not reserved */
pthread_cond_t cond_var; /* condition variable is used in
waiting for the event */
+ UT_LIST_NODE_T(os_event_struct_t) os_event_list;
+ /* list of all created events */
};
-typedef struct os_event_struct os_event_struct_t;
-typedef os_event_struct_t* os_event_t;
#endif
typedef struct os_mutex_struct os_mutex_str_t;
@@ -38,10 +52,32 @@ typedef os_mutex_str_t* os_mutex_t;
#define OS_SYNC_TIME_EXCEEDED 1
+/* Mutex protecting counts and the event and OS 'slow' mutex lists */
+extern os_mutex_t os_sync_mutex;
+
+/* This is incremented by 1 in os_thread_create and decremented by 1 in
+os_thread_exit */
+extern ulint os_thread_count;
+
+extern ulint os_event_count;
+extern ulint os_mutex_count;
+extern ulint os_fast_mutex_count;
+
+/*************************************************************
+Initializes global event and OS 'slow' mutex lists. */
+
+void
+os_sync_init(void);
+/*==============*/
/*************************************************************
-Creates an event semaphore, i.e., a semaphore which may
-just have two states: signaled and nonsignaled.
-The created event is manual reset: it must be reset
+Frees created events and OS 'slow' mutexes. */
+
+void
+os_sync_free(void);
+/*==============*/
+/*************************************************************
+Creates an event semaphore, i.e., a semaphore which may just have two states:
+signaled and nonsignaled. The created event is manual reset: it must be reset
explicitly by calling sync_os_reset_event. */
os_event_t
@@ -50,10 +86,10 @@ os_event_create(
/* out: the event handle */
char* name); /* in: the name of the event, if NULL
the event is created without a name */
+#ifdef __WIN__
/*************************************************************
-Creates an auto-reset event semaphore, i.e., an event
-which is automatically reset when a single thread is
-released. */
+Creates an auto-reset event semaphore, i.e., an event which is automatically
+reset when a single thread is released. Works only in Windows. */
os_event_t
os_event_create_auto(
@@ -61,6 +97,7 @@ os_event_create_auto(
/* out: the event handle */
char* name); /* in: the name of the event, if NULL
the event is created without a name */
+#endif
/**************************************************************
Sets an event semaphore to the signaled state: lets waiting threads
proceed. */
@@ -85,7 +122,10 @@ os_event_free(
/*==========*/
os_event_t event); /* in: event to free */
/**************************************************************
-Waits for an event object until it is in the signaled state. */
+Waits for an event object until it is in the signaled state. If
+srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
+waiting thread when the event becomes signaled (or immediately if the
+event is already in the signaled state). */
void
os_event_wait(
@@ -93,7 +133,7 @@ os_event_wait(
os_event_t event); /* in: event to wait */
/**************************************************************
Waits for an event object until it is in the signaled state or
-a timeout is exceeded. */
+a timeout is exceeded. In Unix the timeout is always infinite. */
ulint
os_event_wait_time(
@@ -104,8 +144,9 @@ os_event_wait_time(
os_event_t event, /* in: event to wait */
ulint time); /* in: timeout in microseconds, or
OS_SYNC_INFINITE_TIME */
+#ifdef __WIN__
/**************************************************************
-Waits for any event in an event array. Returns if even a single
+Waits for any event in an OS native event array. Returns if even a single
one is signaled or becomes signaled. */
ulint
@@ -113,14 +154,15 @@ os_event_wait_multiple(
/*===================*/
/* out: index of the event
which was signaled */
- ulint n, /* in: number of events in the
+ ulint n, /* in: number of events in the
array */
- os_event_t* event_array); /* in: pointer to an array of event
+ os_native_event_t* native_event_array);
+ /* in: pointer to an array of event
handles */
+#endif
/*************************************************************
-Creates an operating system mutex semaphore.
-Because these are slow, the mutex semaphore of the database
-itself (sync_mutex_t) should be used where possible. */
+Creates an operating system mutex semaphore. Because these are slow, the
+mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
os_mutex_t
os_mutex_create(
diff --git a/innobase/include/os0sync.ic b/innobase/include/os0sync.ic
index 10b85c435e3..1337e97152a 100644
--- a/innobase/include/os0sync.ic
+++ b/innobase/include/os0sync.ic
@@ -44,4 +44,3 @@ os_fast_mutex_trylock(
#endif
#endif
}
-
diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h
index 629cfef23a8..491d8866af4 100644
--- a/innobase/include/os0thread.h
+++ b/innobase/include/os0thread.h
@@ -41,7 +41,6 @@ typedef os_thread_t os_thread_id_t; /* In Unix we use the thread
the thread */
#endif
-
/* Define a function pointer type to use in a typecast */
typedef void* (*os_posix_f_t) (void*);
@@ -66,7 +65,9 @@ os_thread_pf(
/********************************************************************
Creates a new thread of execution. The execution starts from
the function given. The start function takes a void* parameter
-and returns a ulint. */
+and returns a ulint.
+NOTE: We count the number of threads in os_thread_exit(). A created
+thread should always use that to exit and not use return() to exit. */
os_thread_t
os_thread_create(
@@ -83,12 +84,13 @@ os_thread_create(
os_thread_id_t* thread_id); /* out: id of the created
thread */
/*********************************************************************
-A thread calling this function ends its execution. */
+Exits the current thread. */
void
os_thread_exit(
/*===========*/
- ulint code); /* in: exit code */
+ void* exit_value); /* in: exit value; in Windows this void*
+ is cast as a DWORD */
/*********************************************************************
Returns the thread identifier of current thread. */
@@ -144,7 +146,6 @@ ulint
os_thread_get_last_error(void);
/*==========================*/
-
#ifndef UNIV_NONINL
#include "os0thread.ic"
#endif
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 121e9c44a24..8fd0fc2dd6d 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -212,6 +212,12 @@ void
srv_init(void);
/*==========*/
/*************************************************************************
+Frees the OS fast mutex created in srv_init(). */
+
+void
+srv_free(void);
+/*==========*/
+/*************************************************************************
Initializes the synchronization primitives, memory system, and the thread
local storage. */
diff --git a/innobase/include/srv0start.h b/innobase/include/srv0start.h
index aec3ebfeea9..8d2c3fa12c5 100644
--- a/innobase/include/srv0start.h
+++ b/innobase/include/srv0start.h
@@ -86,11 +86,12 @@ extern ibool srv_startup_is_before_trx_rollback_phase;
extern ibool srv_is_being_shut_down;
/* At a shutdown the value first climbs from 0 to SRV_SHUTDOWN_CLEANUP
-and then to SRV_SHUTDOWN_LAST_PHASE */
+and then to SRV_SHUTDOWN_LAST_PHASE, and so on */
extern ulint srv_shutdown_state;
-#define SRV_SHUTDOWN_CLEANUP 1
-#define SRV_SHUTDOWN_LAST_PHASE 2
+#define SRV_SHUTDOWN_CLEANUP 1
+#define SRV_SHUTDOWN_LAST_PHASE 2
+#define SRV_SHUTDOWN_EXIT_THREADS 3
#endif
diff --git a/innobase/include/univ.i b/innobase/include/univ.i
index e29f3ec92e1..4854e5a7b78 100644
--- a/innobase/include/univ.i
+++ b/innobase/include/univ.i
@@ -187,7 +187,11 @@ management to ensure correct alignment for doubles etc. */
/* Another basic type we use is unsigned long integer which is intended to be
equal to the word size of the machine. */
+#ifdef _WIN64
+typedef unsigned __int64 ulint;
+#else
typedef unsigned long int ulint;
+#endif
typedef long int lint;
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index e717d897e41..6892e6fc6c1 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -375,7 +375,7 @@ log_pad_current_log_block(void)
log_close();
log_release();
- ut_a((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE)
+ ut_ad((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE)
== LOG_BLOCK_HDR_SIZE);
}
@@ -998,6 +998,8 @@ log_group_file_header_flush(
{
byte* buf;
ulint dest_offset;
+
+ UT_NOT_USED(type);
ut_ad(mutex_own(&(log_sys->mutex)));
@@ -1068,8 +1070,8 @@ log_group_write_buf(
ulint i;
ut_ad(mutex_own(&(log_sys->mutex)));
- ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0);
- ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
+ ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0);
+ ut_ad(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
if (new_data_offset == 0) {
write_header = TRUE;
@@ -2901,10 +2903,9 @@ logs_empty_and_mark_files_at_shutdown(void)
dulint lsn;
ulint arch_log_no;
- if (srv_print_verbose_log)
- {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Starting shutdown...\n");
+ if (srv_print_verbose_log) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Starting shutdown...\n");
}
/* Wait until the master thread and all other operations are idle: our
algorithm only works if the server is idle at shutdown */
@@ -3006,15 +3007,17 @@ loop:
goto loop;
}
+ /* Make some checks that the server really is quiet */
+ ut_a(buf_all_freed());
+ ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
+
fil_write_flushed_lsn_to_data_files(lsn, arch_log_no);
fil_flush_file_spaces(FIL_TABLESPACE);
- if (srv_print_verbose_log)
- {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Shutdown completed\n");
- }
+ /* Make some checks that the server really is quiet */
+ ut_a(buf_all_freed());
+ ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
}
/**********************************************************
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 53224eb59c5..e401503c4e3 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -80,6 +80,8 @@ struct os_aio_slot_struct{
which pending aio operation was
completed */
#ifdef WIN_ASYNC_IO
+ os_event_t event; /* event object we need in the
+ OVERLAPPED struct */
OVERLAPPED control; /* Windows control block for the
aio request */
#elif defined(POSIX_ASYNC_IO)
@@ -107,11 +109,14 @@ struct os_aio_array_struct{
ulint n_reserved;/* Number of reserved slots in the
aio array outside the ibuf segment */
os_aio_slot_t* slots; /* Pointer to the slots in the array */
- os_event_t* events; /* Pointer to an array of event handles
- where we copied the handles from slots,
- in the same order. This can be used in
- WaitForMultipleObjects; used only in
+#ifdef __WIN__
+ os_native_event_t* native_events;
+ /* Pointer to an array of OS native event
+ handles where we copied the handles from
+ slots, in the same order. This can be used
+ in WaitForMultipleObjects; used only in
Windows */
+#endif
};
/* Array of events used in simulated aio */
@@ -295,7 +300,8 @@ os_file_handle_error(
/* out: TRUE if we should retry the
operation */
os_file_t file, /* in: file pointer */
- char* name) /* in: name of a file or NULL */
+ char* name, /* in: name of a file or NULL */
+ const char* operation)/* in: operation */
{
ulint err;
@@ -338,6 +344,7 @@ os_file_handle_error(
fprintf(stderr, "InnoDB: File name %s\n", name);
}
+ fprintf(stderr, "InnoDB: System call %s.\n", operation);
fprintf(stderr, "InnoDB: Cannot continue operation.\n");
fflush(stderr);
@@ -419,8 +426,9 @@ try_again:
if (file == INVALID_HANDLE_VALUE) {
*success = FALSE;
- retry = os_file_handle_error(file, name);
-
+ retry = os_file_handle_error(file, name,
+ create_mode == OS_FILE_OPEN ?
+ "open" : "create");
if (retry) {
goto try_again;
}
@@ -460,8 +468,9 @@ try_again:
if (file == -1) {
*success = FALSE;
- retry = os_file_handle_error(file, name);
-
+ retry = os_file_handle_error(file, name,
+ create_mode == OS_FILE_OPEN ?
+ "open" : "create");
if (retry) {
goto try_again;
}
@@ -568,8 +577,9 @@ try_again:
if (file == INVALID_HANDLE_VALUE) {
*success = FALSE;
- retry = os_file_handle_error(file, name);
-
+ retry = os_file_handle_error(file, name,
+ create_mode == OS_FILE_OPEN ?
+ "open" : "create");
if (retry) {
goto try_again;
}
@@ -615,8 +625,9 @@ try_again:
if (file == -1) {
*success = FALSE;
- retry = os_file_handle_error(file, name);
-
+ retry = os_file_handle_error(file, name,
+ create_mode == OS_FILE_OPEN ?
+ "open" : "create");
if (retry) {
goto try_again;
}
@@ -649,7 +660,7 @@ os_file_close(
return(TRUE);
}
- os_file_handle_error(file, NULL);
+ os_file_handle_error(file, NULL, "close");
return(FALSE);
#else
int ret;
@@ -657,7 +668,7 @@ os_file_close(
ret = close(file);
if (ret == -1) {
- os_file_handle_error(file, NULL);
+ os_file_handle_error(file, NULL, "close");
return(FALSE);
}
@@ -825,7 +836,7 @@ os_file_flush(
return(TRUE);
}
- os_file_handle_error(file, NULL);
+ os_file_handle_error(file, NULL, "flush");
/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
@@ -858,7 +869,7 @@ os_file_flush(
fprintf(stderr,
" InnoDB: Error: the OS said file flush did not succeed\n");
- os_file_handle_error(file, NULL);
+ os_file_handle_error(file, NULL, "flush");
/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
@@ -1099,7 +1110,7 @@ try_again:
#ifdef __WIN__
error_handling:
#endif
- retry = os_file_handle_error(file, NULL);
+ retry = os_file_handle_error(file, NULL, "read");
if (retry) {
goto try_again;
@@ -1295,7 +1306,6 @@ os_aio_array_create(
#endif
ut_a(n > 0);
ut_a(n_segments > 0);
- ut_a(n % n_segments == 0);
array = ut_malloc(sizeof(os_aio_array_t));
@@ -1309,19 +1319,22 @@ os_aio_array_create(
array->n_segments = n_segments;
array->n_reserved = 0;
array->slots = ut_malloc(n * sizeof(os_aio_slot_t));
- array->events = ut_malloc(n * sizeof(os_event_t));
-
+#ifdef __WIN__
+ array->native_events = ut_malloc(n * sizeof(os_native_event_t));
+#endif
for (i = 0; i < n; i++) {
slot = os_aio_array_get_nth_slot(array, i);
slot->pos = i;
slot->reserved = FALSE;
#ifdef WIN_ASYNC_IO
+ slot->event = os_event_create(NULL);
+
over = &(slot->control);
- over->hEvent = os_event_create(NULL);
+ over->hEvent = slot->event->handle;
- *((array->events) + i) = over->hEvent;
+ *((array->native_events) + i) = over->hEvent;
#endif
}
@@ -1404,6 +1417,50 @@ os_aio_init(
pthread_sigmask(SIG_BLOCK, &sigset, NULL); */
#endif
}
+
+#ifdef WIN_ASYNC_IO
+/****************************************************************************
+Wakes up all async i/o threads in the array in Windows async i/o at
+shutdown. */
+static
+void
+os_aio_array_wake_win_aio_at_shutdown(
+/*==================================*/
+ os_aio_array_t* array) /* in: aio array */
+{
+ ulint i;
+
+ for (i = 0; i < array->n_slots; i++) {
+
+ os_event_set((array->slots + i)->event);
+ }
+}
+#endif
+
+/****************************************************************************
+Wakes up all async i/o threads so that they know to exit themselves in
+shutdown. */
+
+void
+os_aio_wake_all_threads_at_shutdown(void)
+/*=====================================*/
+{
+ ulint i;
+
+#ifdef WIN_ASYNC_IO
+ /* This code wakes up all ai/o threads in Windows native aio */
+ os_aio_array_wake_win_aio_at_shutdown(os_aio_read_array);
+ os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array);
+ os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array);
+ os_aio_array_wake_win_aio_at_shutdown(os_aio_log_array);
+#endif
+ /* This loop wakes up all simulated ai/o threads */
+
+ for (i = 0; i < os_aio_n_segments; i++) {
+
+ os_event_set(os_aio_segment_wait_events[i]);
+ }
+}
/****************************************************************************
Waits until there are no pending writes in os_aio_write_array. There can
@@ -1635,7 +1692,7 @@ loop:
control = &(slot->control);
control->Offset = (DWORD)offset;
control->OffsetHigh = (DWORD)offset_high;
- os_event_reset(control->hEvent);
+ os_event_reset(slot->event);
#elif defined(POSIX_ASYNC_IO)
@@ -1693,7 +1750,7 @@ os_aio_array_free_slot(
}
#ifdef WIN_ASYNC_IO
- os_event_reset(slot->control.hEvent);
+ os_event_reset(slot->event);
#endif
os_mutex_exit(array->mutex);
}
@@ -1818,7 +1875,7 @@ os_aio(
offset where to read or write */
ulint offset_high, /* in: most significant 32 bits of
offset */
- ulint n, /* in: number of bytes to read or write */
+ ulint n, /* in: number of bytes to read or write */
void* message1,/* in: messages for the aio handler (these
can be used to identify a completed aio
operation); if mode is OS_AIO_SYNC, these
@@ -1862,7 +1919,8 @@ os_aio(
wait in the Windows case. */
if (type == OS_FILE_READ) {
- return(os_file_read(file, buf, offset, offset_high, n));
+ return(os_file_read(file, buf, offset,
+ offset_high, n));
}
ut_a(type == OS_FILE_WRITE);
@@ -1940,8 +1998,7 @@ try_again:
#ifdef WIN_ASYNC_IO
if (os_aio_use_native_aio) {
if ((ret && len == n)
- || (!ret && GetLastError() == ERROR_IO_PENDING)) {
-
+ || (!ret && GetLastError() == ERROR_IO_PENDING)) {
/* aio was queued successfully! */
if (mode == OS_AIO_SYNC) {
@@ -1971,8 +2028,8 @@ try_again:
os_aio_array_free_slot(array, slot);
- retry = os_file_handle_error(file, name);
-
+ retry = os_file_handle_error(file, name,
+ type == OS_FILE_READ ? "aio read" : "aio write");
if (retry) {
goto try_again;
@@ -2037,15 +2094,15 @@ os_aio_windows_handle(
n = array->n_slots / array->n_segments;
if (array == os_aio_sync_array) {
- srv_io_thread_op_info[orig_seg] = "wait Windows aio for 1 page";
-
- ut_ad(pos < array->n_slots);
- os_event_wait(array->events[pos]);
+ srv_io_thread_op_info[orig_seg] =
+ "wait Windows aio for 1 page";
+ os_event_wait(os_aio_array_get_nth_slot(array, pos)->event);
i = pos;
} else {
srv_io_thread_op_info[orig_seg] =
"wait Windows aio";
- i = os_event_wait_multiple(n, (array->events) + segment * n);
+ i = os_event_wait_multiple(n,
+ (array->native_events) + segment * n);
}
os_mutex_enter(array->mutex);
@@ -2070,7 +2127,7 @@ os_aio_windows_handle(
ut_a(TRUE == os_file_flush(slot->file));
}
} else {
- os_file_handle_error(slot->file, slot->name);
+ os_file_handle_error(slot->file, slot->name, "Windows aio");
ret_val = FALSE;
}
diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c
index 407b280f805..bf5fc57bf57 100644
--- a/innobase/os/os0sync.c
+++ b/innobase/os/os0sync.c
@@ -17,6 +17,7 @@ Created 9/6/1995 Heikki Tuuri
#endif
#include "ut0mem.h"
+#include "srv0start.h"
/* Type definition for an operating system mutex struct */
struct os_mutex_struct{
@@ -26,14 +27,84 @@ struct os_mutex_struct{
recursively lock the mutex: we
do not assume that the OS mutex
supports recursive locking, though
- NT seems to do that */
+ NT seems to do that */
+ UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list;
+ /* list of all 'slow' OS mutexes created */
};
+/* Mutex protecting counts and the lists of OS mutexes and events */
+os_mutex_t os_sync_mutex;
+ibool os_sync_mutex_inited = FALSE;
+
+/* This is incremented by 1 in os_thread_create and decremented by 1 in
+os_thread_exit */
+ulint os_thread_count = 0;
+
+/* The list of all events created */
+UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
+
+/* The list of all OS 'slow' mutexes */
+UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list;
+
+ulint os_event_count = 0;
+ulint os_mutex_count = 0;
+ulint os_fast_mutex_count = 0;
+
+
+/*************************************************************
+Initializes global event and OS 'slow' mutex lists. */
+
+void
+os_sync_init(void)
+/*==============*/
+{
+ UT_LIST_INIT(os_event_list);
+ UT_LIST_INIT(os_mutex_list);
+
+ os_sync_mutex = os_mutex_create(NULL);
+
+ os_sync_mutex_inited = TRUE;
+}
+
+/*************************************************************
+Frees created events and OS 'slow' mutexes. */
+
+void
+os_sync_free(void)
+/*==============*/
+{
+ os_event_t event;
+ os_mutex_t mutex;
+
+ event = UT_LIST_GET_FIRST(os_event_list);
+
+ while (event) {
+
+ os_event_free(event);
+
+ event = UT_LIST_GET_FIRST(os_event_list);
+ }
+
+ mutex = UT_LIST_GET_FIRST(os_mutex_list);
+
+ while (mutex) {
+ if (mutex == os_sync_mutex) {
+ /* Set the flag to FALSE so that we do not try to
+ reserve os_sync_mutex any more in remaining freeing
+ operations in shutdown */
+ os_sync_mutex_inited = FALSE;
+ }
+
+ os_mutex_free(mutex);
+
+ mutex = UT_LIST_GET_FIRST(os_mutex_list);
+ }
+}
+
/*************************************************************
-Creates an event semaphore, i.e., a semaphore which may
-just have two states: signaled and nonsignaled.
-The created event is manual reset: it must be reset
-explicitly by calling sync_os_reset_event. */
+Creates an event semaphore, i.e., a semaphore which may just have two
+states: signaled and nonsignaled. The created event is manual reset: it
+must be reset explicitly by calling sync_os_reset_event. */
os_event_t
os_event_create(
@@ -43,22 +114,20 @@ os_event_create(
the event is created without a name */
{
#ifdef __WIN__
- HANDLE event;
-
- event = CreateEvent(NULL, /* No security attributes */
+ os_event_t event;
+
+ event = ut_malloc(sizeof(struct os_event_struct));
+
+ event->handle = CreateEvent(NULL,/* No security attributes */
TRUE, /* Manual reset */
FALSE, /* Initial state nonsignaled */
name);
- if (!event) {
+ if (!event->handle) {
fprintf(stderr,
"InnoDB: Could not create a Windows event semaphore; Windows error %lu\n",
(ulint)GetLastError());
}
-
- ut_a(event);
-
- return(event);
-#else
+#else /* Unix */
os_event_t event;
UT_NOT_USED(name);
@@ -74,15 +143,24 @@ os_event_create(
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
#endif
event->is_set = FALSE;
+#endif /* __WIN__ */
+
+ /* Put to the list of events */
+ os_mutex_enter(os_sync_mutex);
+
+ UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
+
+ os_event_count++;
+
+ os_mutex_exit(os_sync_mutex);
return(event);
-#endif
}
+#ifdef __WIN__
/*************************************************************
-Creates an auto-reset event semaphore, i.e., an event
-which is automatically reset when a single thread is
-released. */
+Creates an auto-reset event semaphore, i.e., an event which is automatically
+reset when a single thread is released. Works only in Windows. */
os_event_t
os_event_create_auto(
@@ -91,24 +169,33 @@ os_event_create_auto(
char* name) /* in: the name of the event, if NULL
the event is created without a name */
{
-#ifdef __WIN__
- HANDLE event;
+ os_event_t event;
+
+ event = ut_malloc(sizeof(struct os_event_struct));
- event = CreateEvent(NULL, /* No security attributes */
+ event->handle = CreateEvent(NULL,/* No security attributes */
FALSE, /* Auto-reset */
FALSE, /* Initial state nonsignaled */
name);
- ut_a(event);
- return(event);
-#else
- /* Does nothing in Posix because we do not need this with MySQL */
+ if (!event->handle) {
+ fprintf(stderr,
+"InnoDB: Could not create a Windows auto event semaphore; Windows error %lu\n",
+ (ulint)GetLastError());
+ }
- UT_NOT_USED(name);
+ /* Put to the list of events */
+ os_mutex_enter(os_sync_mutex);
- return(NULL);
-#endif
+ UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
+
+ os_event_count++;
+
+ os_mutex_exit(os_sync_mutex);
+
+ return(event);
}
+#endif
/**************************************************************
Sets an event semaphore to the signaled state: lets waiting threads
@@ -121,7 +208,7 @@ os_event_set(
{
#ifdef __WIN__
ut_a(event);
- ut_a(SetEvent(event));
+ ut_a(SetEvent(event->handle));
#else
ut_a(event);
@@ -150,7 +237,7 @@ os_event_reset(
#ifdef __WIN__
ut_a(event);
- ut_a(ResetEvent(event));
+ ut_a(ResetEvent(event->handle));
#else
ut_a(event);
@@ -178,19 +265,31 @@ os_event_free(
#ifdef __WIN__
ut_a(event);
- ut_a(CloseHandle(event));
+ ut_a(CloseHandle(event->handle));
#else
ut_a(event);
os_fast_mutex_free(&(event->os_mutex));
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
+#endif
+ /* Remove from the list of events */
+
+ os_mutex_enter(os_sync_mutex);
+
+ UT_LIST_REMOVE(os_event_list, os_event_list, event);
+
+ os_event_count--;
+
+ os_mutex_exit(os_sync_mutex);
ut_free(event);
-#endif
}
/**************************************************************
-Waits for an event object until it is in the signaled state. */
+Waits for an event object until it is in the signaled state. If
+srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
+waiting thread when the event becomes signaled (or immediately if the
+event is already in the signaled state). */
void
os_event_wait(
@@ -203,15 +302,23 @@ os_event_wait(
ut_a(event);
/* Specify an infinite time limit for waiting */
- err = WaitForSingleObject(event, INFINITE);
+ err = WaitForSingleObject(event->handle, INFINITE);
ut_a(err == WAIT_OBJECT_0);
+
+ if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+ os_thread_exit(NULL);
+ }
#else
os_fast_mutex_lock(&(event->os_mutex));
loop:
if (event->is_set == TRUE) {
os_fast_mutex_unlock(&(event->os_mutex));
+ if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+
+ os_thread_exit(NULL);
+ }
/* Ok, we may return */
return;
@@ -228,7 +335,7 @@ loop:
/**************************************************************
Waits for an event object until it is in the signaled state or
-a timeout is exceeded. */
+a timeout is exceeded. In Unix the timeout is always infinite. */
ulint
os_event_wait_time(
@@ -245,9 +352,9 @@ os_event_wait_time(
ut_a(event);
if (time != OS_SYNC_INFINITE_TIME) {
- err = WaitForSingleObject(event, time / 1000);
+ err = WaitForSingleObject(event->handle, time / 1000);
} else {
- err = WaitForSingleObject(event, INFINITE);
+ err = WaitForSingleObject(event->handle, INFINITE);
}
if (err == WAIT_OBJECT_0) {
@@ -271,8 +378,9 @@ os_event_wait_time(
#endif
}
+#ifdef __WIN__
/**************************************************************
-Waits for any event in an event array. Returns if even a single
+Waits for any event in an OS native event array. Returns if even a single
one is signaled or becomes signaled. */
ulint
@@ -280,41 +388,35 @@ os_event_wait_multiple(
/*===================*/
/* out: index of the event
which was signaled */
- ulint n, /* in: number of events in the
+ ulint n, /* in: number of events in the
array */
- os_event_t* event_array) /* in: pointer to an array of event
+ os_native_event_t* native_event_array)
+ /* in: pointer to an array of event
handles */
{
-#ifdef __WIN__
DWORD index;
- ut_a(event_array);
+ ut_a(native_event_array);
ut_a(n > 0);
- index = WaitForMultipleObjects(n,
- event_array,
+ index = WaitForMultipleObjects(n, native_event_array,
FALSE, /* Wait for any 1 event */
INFINITE); /* Infinite wait time
limit */
ut_a(index >= WAIT_OBJECT_0);
ut_a(index < WAIT_OBJECT_0 + n);
- return(index - WAIT_OBJECT_0);
-#else
- ut_a(n == 0);
-
- /* In Posix we can only wait for a single event */
-
- os_event_wait(*event_array);
+ if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+ os_thread_exit(NULL);
+ }
- return(0);
-#endif
+ return(index - WAIT_OBJECT_0);
}
+#endif
/*************************************************************
-Creates an operating system mutex semaphore.
-Because these are slow, the mutex semaphore of the database
-itself (sync_mutex_t) should be used where possible. */
+Creates an operating system mutex semaphore. Because these are slow, the
+mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
os_mutex_t
os_mutex_create(
@@ -331,30 +433,35 @@ os_mutex_create(
FALSE, /* Initial state: no owner */
name);
ut_a(mutex);
-
- mutex_str = ut_malloc(sizeof(os_mutex_str_t));
-
- mutex_str->handle = mutex;
- mutex_str->count = 0;
-
- return(mutex_str);
#else
- os_fast_mutex_t* os_mutex;
+ os_fast_mutex_t* mutex;
os_mutex_t mutex_str;
UT_NOT_USED(name);
- os_mutex = ut_malloc(sizeof(os_fast_mutex_t));
-
- os_fast_mutex_init(os_mutex);
+ mutex = ut_malloc(sizeof(os_fast_mutex_t));
+ os_fast_mutex_init(mutex);
+#endif
mutex_str = ut_malloc(sizeof(os_mutex_str_t));
- mutex_str->handle = os_mutex;
+ mutex_str->handle = mutex;
mutex_str->count = 0;
+ if (os_sync_mutex_inited) {
+ /* When creating os_sync_mutex itself we cannot reserve it */
+ os_mutex_enter(os_sync_mutex);
+ }
+
+ UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
+
+ os_mutex_count++;
+
+ if (os_sync_mutex_inited) {
+ os_mutex_exit(os_sync_mutex);
+ }
+
return(mutex_str);
-#endif
}
/**************************************************************
@@ -394,21 +501,14 @@ os_mutex_exit(
/*==========*/
os_mutex_t mutex) /* in: mutex to release */
{
-#ifdef __WIN__
ut_a(mutex);
ut_a(mutex->count == 1);
(mutex->count)--;
-
+#ifdef __WIN__
ut_a(ReleaseMutex(mutex->handle));
#else
- ut_a(mutex);
-
- ut_a(mutex->count == 1);
-
- (mutex->count)--;
-
os_fast_mutex_unlock(mutex->handle);
#endif
}
@@ -421,10 +521,23 @@ os_mutex_free(
/*==========*/
os_mutex_t mutex) /* in: mutex to free */
{
-#ifdef __WIN__
ut_a(mutex);
+ if (os_sync_mutex_inited) {
+ os_mutex_enter(os_sync_mutex);
+ }
+
+ UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
+
+ os_mutex_count--;
+
+ if (os_sync_mutex_inited) {
+ os_mutex_exit(os_sync_mutex);
+ }
+
+#ifdef __WIN__
ut_a(CloseHandle(mutex->handle));
+
ut_free(mutex);
#else
os_fast_mutex_free(mutex->handle);
@@ -452,6 +565,18 @@ os_fast_mutex_init(
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
#endif
#endif
+ if (os_sync_mutex_inited) {
+ /* When creating os_sync_mutex itself (in Unix) we cannot
+ reserve it */
+
+ os_mutex_enter(os_sync_mutex);
+ }
+
+ os_fast_mutex_count++;
+
+ if (os_sync_mutex_inited) {
+ os_mutex_exit(os_sync_mutex);
+ }
}
/**************************************************************
@@ -499,4 +624,16 @@ os_fast_mutex_free(
#else
ut_a(0 == pthread_mutex_destroy(fast_mutex));
#endif
+ if (os_sync_mutex_inited) {
+ /* When freeing the last mutexes, we have
+ already freed os_sync_mutex */
+
+ os_mutex_enter(os_sync_mutex);
+ }
+
+ os_fast_mutex_count--;
+
+ if (os_sync_mutex_inited) {
+ os_mutex_exit(os_sync_mutex);
+ }
}
diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c
index b0076921e43..9af98760ad1 100644
--- a/innobase/os/os0thread.c
+++ b/innobase/os/os0thread.c
@@ -1,6 +1,5 @@
/******************************************************
-The interface to the operating system
-process and thread control primitives
+The interface to the operating system thread control primitives
(c) 1995 Innobase Oy
@@ -17,6 +16,7 @@ Created 9/8/1995 Heikki Tuuri
#endif
#include "srv0srv.h"
+#include "os0sync.h"
/*******************************************************************
Compares two thread ids for equality. */
@@ -102,6 +102,10 @@ os_thread_create(
os_thread_t thread;
ulint win_thread_id;
+ os_mutex_enter(os_sync_mutex);
+ os_thread_count++;
+ os_mutex_exit(os_sync_mutex);
+
thread = CreateThread(NULL, /* no security attributes */
0, /* default size stack */
(LPTHREAD_START_ROUTINE)start_f,
@@ -144,6 +148,9 @@ os_thread_create(
exit(1);
}
#endif
+ os_mutex_enter(os_sync_mutex);
+ os_thread_count++;
+ os_mutex_exit(os_sync_mutex);
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
@@ -171,6 +178,30 @@ os_thread_create(
}
/*********************************************************************
+Exits the current thread. */
+
+void
+os_thread_exit(
+/*===========*/
+ void* exit_value) /* in: exit value; in Windows this void*
+ is cast as a DWORD */
+{
+#ifdef UNIV_DEBUG_THREAD_CREATION
+ printf("A thread exits.\n");
+ printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
+#endif
+ os_mutex_enter(os_sync_mutex);
+ os_thread_count--;
+ os_mutex_exit(os_sync_mutex);
+
+#ifdef __WIN__
+ ExitThread((DWORD)exit_value);
+#else
+ pthread_exit(exit_value);
+#endif
+}
+
+/*********************************************************************
Returns handle to the current thread. */
os_thread_t
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 3af9e1b752b..e96c08a715b 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -1275,6 +1275,10 @@ row_ins_unique_report_err(
dtuple_t* entry, /* in: index entry to insert in the index */
dict_index_t* index) /* in: index */
{
+#ifdef notdefined
+ /* Disable reporting to test if the slowdown of REPLACE in 4.0.13 was
+ caused by this! */
+
char* buf = dict_unique_err_buf;
/* The foreign err mutex protects also dict_unique_err_buf */
@@ -1303,6 +1307,7 @@ row_ins_unique_report_err(
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
+#endif
}
/*******************************************************************
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 7cd831fe239..90331157289 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -868,6 +868,7 @@ srv_release_max_if_no_queries(void)
mutex_exit(&kernel_mutex);
}
+#ifdef notdefined
/***********************************************************************
Releases one utility thread if no queries are active and
the high-water mark 2 for the utility is exceeded. */
@@ -902,7 +903,6 @@ srv_release_one_if_no_queries(void)
mutex_exit(&kernel_mutex);
}
-#ifdef notdefined
/***********************************************************************
Decrements the utility meter by the value given and suspends the calling
thread, which must be an utility thread of the type given, if necessary. */
@@ -1012,6 +1012,8 @@ srv_communication_init(
ut_a(ret == 0);
}
+
+#ifdef notdefined
/*************************************************************************
Implements the recovery utility. */
@@ -1072,6 +1074,7 @@ srv_purge_thread(
return(0);
}
+#endif /* notdefined */
/*************************************************************************
Creates the utility threads. */
@@ -1102,6 +1105,7 @@ srv_create_utility_threads(void)
ut_a(thread); */
}
+#ifdef notdefined
/*************************************************************************
Implements the communication threads. */
static
@@ -1151,6 +1155,7 @@ srv_com_thread(
return(0);
}
+#endif
/*************************************************************************
Creates the communication threads. */
@@ -1171,6 +1176,7 @@ srv_create_com_threads(void)
}
}
+#ifdef notdefined
/*************************************************************************
Implements the worker threads. */
static
@@ -1215,6 +1221,7 @@ srv_worker_thread(
return(0);
}
+#endif
/*************************************************************************
Creates the worker threads. */
@@ -1705,76 +1712,33 @@ srv_init(void)
ut_a(conc_slot->event);
}
}
-
+
/*************************************************************************
-Initializes the synchronization primitives, memory system, and the thread
-local storage. */
+Frees the OS fast mutex created in srv_init(). */
void
-srv_general_init(void)
-/*==================*/
+srv_free(void)
+/*==========*/
{
- sync_init();
- mem_init(srv_mem_pool_size);
- thr_local_init();
+ os_fast_mutex_free(&srv_conc_mutex);
}
-
-#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
-/* NetWare requires some cleanup of mutexes */
-
/*************************************************************************
-Deinitializes the synchronization primitives, memory system, and the thread
+Initializes the synchronization primitives, memory system, and the thread
local storage. */
void
-srv_general_free(void)
+srv_general_init(void)
/*==================*/
{
- sync_close();
+ os_sync_init();
+ sync_init();
+ mem_init(srv_mem_pool_size);
+ thr_local_init();
}
-#endif /* __NETWARE__ */
-
/*======================= InnoDB Server FIFO queue =======================*/
-#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
-/* NetWare requires some cleanup of mutexes */
-
-/*************************************************************************
-Deinitializes the server. */
-
-void
-srv_free(void)
-/*==========*/
-{
- srv_conc_slot_t* conc_slot;
- srv_slot_t* slot;
- ulint i;
-
- for (i = 0; i < OS_THREAD_MAX_N; i++)
- {
- slot = srv_table_get_nth_slot(i);
- os_event_free(slot->event);
- }
-
- /* TODO: free(srv_sys->threads); */
-
- for (i = 0; i < OS_THREAD_MAX_N; i++)
- {
- slot = srv_mysql_table + i;
- os_event_free(slot->event);
- }
-
- /* TODO: free(srv_mysql_table); */
-
- for (i = 0; i < OS_THREAD_MAX_N; i++)
- {
- conc_slot = srv_conc_slots + i;
- os_event_free(conc_slot->event);
- }
-}
-#endif /* __NETWARE__ */
/*************************************************************************
Puts an OS thread to wait if there are too many concurrent threads
@@ -2533,6 +2497,10 @@ srv_lock_timeout_and_monitor_thread(
char* buf;
ulint i;
+#ifdef UNIV_DEBUG_THREAD_CREATION
+ printf("Lock timeout thread starts\n");
+ printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
+#endif
UT_NOT_USED(arg);
srv_last_monitor_time = time(NULL);
last_table_monitor_time = time(NULL);
@@ -2673,6 +2641,10 @@ loop:
exit_func:
srv_lock_timeout_and_monitor_active = FALSE;
+ /* We count the number of threads in os_thread_exit(). A created
+ thread should always use that to exit and not use return() to exit. */
+
+ os_thread_exit(NULL);
#ifndef __WIN__
return(NULL);
#else
@@ -2698,6 +2670,10 @@ srv_error_monitor_thread(
ulint cnt = 0;
UT_NOT_USED(arg);
+#ifdef UNIV_DEBUG_THREAD_CREATION
+ printf("Error monitor thread starts\n");
+ printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
+#endif
loop:
srv_error_monitor_active = TRUE;
@@ -2734,6 +2710,11 @@ loop:
srv_error_monitor_active = FALSE;
+ /* We count the number of threads in os_thread_exit(). A created
+ thread should always use that to exit and not use return() to exit. */
+
+ os_thread_exit(NULL);
+
#ifndef __WIN__
return(NULL);
#else
@@ -2812,6 +2793,10 @@ srv_master_thread(
UT_NOT_USED(arg);
+#ifdef UNIV_DEBUG_THREAD_CREATION
+ printf("Master thread starts\n");
+ printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
+#endif
srv_main_thread_process_no = os_proc_get_number();
srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
@@ -3047,6 +3032,15 @@ background_loop:
n_tables_to_drop = row_drop_tables_for_mysql_in_background();
+ if (n_tables_to_drop > 0) {
+ /* Do not monopolize the CPU even if there are tables waiting
+ in the background drop queue. (It is essentially a bug if
+ MySQL tries to drop a table while there are still open handles
+ to it and we had to put it to the background drop queue.) */
+
+ os_thread_sleep(100000);
+ }
+
srv_main_thread_op_info = (char*)"purging";
if (srv_fast_shutdown && srv_shutdown_state > 0) {
@@ -3173,11 +3167,25 @@ suspend_thread:
os_event_wait(event);
+ if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+ /* This is only extra safety, the thread should exit
+ already when the event wait ends */
+
+ os_thread_exit(NULL);
+ }
+
/* When there is user activity, InnoDB will set the event and the main
thread goes back to loop: */
goto loop;
+ /* We count the number of threads in os_thread_exit(). A created
+ thread should always use that to exit and not use return() to exit.
+ The thread actually never comes here because it is exited in an
+ os_event_wait(). */
+
+ os_thread_exit(NULL);
+
#ifndef __WIN__
return(NULL);
#else
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 536aa5b67e4..ad985d8282d 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -414,8 +414,10 @@ io_handler_thread(
segment = *((ulint*)arg);
-/* printf("Io handler thread %lu starts\n", segment); */
-
+#ifdef UNIV_DEBUG_THREAD_CREATION
+ printf("Io handler thread %lu starts\n", segment);
+ printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
+#endif
for (i = 0;; i++) {
fil_aio_wait(segment);
@@ -424,6 +426,13 @@ io_handler_thread(
mutex_exit(&ios_mutex);
}
+ /* We count the number of threads in os_thread_exit(). A created
+ thread should always use that to exit and not use return() to exit.
+ The thread actually never comes here because it is exited in an
+ os_event_wait(). */
+
+ os_thread_exit(NULL);
+
#ifndef __WIN__
return(NULL);
#else
@@ -1481,9 +1490,7 @@ innobase_start_or_create_for_mysql(void)
os_fast_mutex_unlock(&srv_os_test_mutex);
-#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
- os_fast_mutex_free(&srv_os_test_mutex); /* all platforms? */
-#endif /* __NETWARE__ */
+ os_fast_mutex_free(&srv_os_test_mutex);
if (srv_print_verbose_log) {
ut_print_timestamp(stderr);
@@ -1509,6 +1516,8 @@ innobase_shutdown_for_mysql(void)
/*=============================*/
/* out: DB_SUCCESS or error code */
{
+ ulint i;
+
if (!srv_was_started) {
if (srv_is_being_started) {
ut_print_timestamp(stderr);
@@ -1521,7 +1530,7 @@ innobase_shutdown_for_mysql(void)
return(DB_SUCCESS);
}
- /* Flush buffer pool to disk, write the current lsn to
+ /* 1. Flush buffer pool to disk, write the current lsn to
the tablespace header(s), and copy all log data to archive */
logs_empty_and_mark_files_at_shutdown();
@@ -1533,30 +1542,88 @@ innobase_shutdown_for_mysql(void)
srv_conc_n_threads);
}
-#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
- /*
- TODO: Fix this temporary solution
- We are having a race condition occure with io_handler_thread threads.
- When they yield in os_aio_simulated_handle during shutdown, this
- thread was able to free the memory early.
- */
- os_thread_yield();
+ /* 2. Make all threads created by InnoDB to exit */
+
+ srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
+
+ /* All threads end up waiting for certain events. Put those events
+ to the signaled state. Then the threads will exit themselves in
+ os_thread_event_wait(). */
+
+ for (i = 0; i < 1000; i++) {
+ /* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM
+ HERE OR EARLIER */
+
+ /* 1. Let the lock timeout thread exit */
+ os_event_set(srv_lock_timeout_thread_event);
+
+ /* 2. srv error monitor thread exits automatically, no need
+ to do anything here */
+
+ /* 3. We wake the master thread so that it exits */
+ srv_wake_master_thread();
+
+ /* 4. Exit the i/o threads */
+
+ os_aio_wake_all_threads_at_shutdown();
+
+ os_mutex_enter(os_sync_mutex);
+
+ if (os_thread_count == 0) {
+ /* All the threads have exited or are just exiting;
+ NOTE that the threads may not have completed their
+ exit yet. Should we use pthread_join() to make sure
+ they have exited? Now we just sleep 0.1 seconds and
+ hope that is enough! */
+
+ os_mutex_exit(os_sync_mutex);
+
+ os_thread_sleep(100000);
+
+ break;
+ }
+
+ os_mutex_exit(os_sync_mutex);
+
+ os_thread_sleep(100000);
+ }
+
+ if (i == 1000) {
+ fprintf(stderr,
+"InnoDB: Warning: %lu threads created by InnoDB had not exited at shutdown!\n",
+ os_thread_count);
+ }
+
+ /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside
+ them */
+
+ sync_close();
+
+ /* 4. Free the os_conc_mutex and all os_events and os_mutexes */
- /* TODO: Where should this be called? */
srv_free();
+ os_sync_free();
+
+ /* 5. Free all allocated memory and the os_fast_mutex created in
+ ut0mem.c */
- /* TODO: Where should this be called? */
- srv_general_free();
-#endif
- /*
- TODO: We should exit the i/o-handler and other utility threads
- before freeing all memory. Now this can potentially cause a seg
- fault!
- */
-#if defined(NOT_WORKING_YET) || defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
- /* NetWare requires this free */
ut_free_all_mem();
-#endif
+
+ if (os_thread_count != 0
+ || os_event_count != 0
+ || os_mutex_count != 0
+ || os_fast_mutex_count != 0) {
+ fprintf(stderr,
+"InnoDB: Warning: some resources were not cleaned up in shutdown:\n"
+"InnoDB: threads %lu, events %lu, os_mutexes %lu, os_fast_mutexes %lu\n",
+ os_thread_count, os_event_count, os_mutex_count,
+ os_fast_mutex_count);
+ }
+
+ if (srv_print_verbose_log) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Shutdown completed\n");
+ }
return((int) DB_SUCCESS);
}
diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c
index 20d68ba5a9f..32615ce88ac 100644
--- a/innobase/sync/sync0sync.c
+++ b/innobase/sync/sync0sync.c
@@ -235,8 +235,7 @@ mutex_create_func(
mutex->cline = cline;
/* Check that lock_word is aligned; this is important on Intel */
-
- ut_a(((ulint)(&(mutex->lock_word))) % 4 == 0);
+ ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0);
/* NOTE! The very first mutexes are not put to the mutex list */
@@ -266,11 +265,14 @@ mutex_free(
ut_a(mutex_get_lock_word(mutex) == 0);
ut_a(mutex_get_waiters(mutex) == 0);
- mutex_enter(&mutex_list_mutex);
+ if (mutex != &mutex_list_mutex && mutex != &sync_thread_mutex) {
- UT_LIST_REMOVE(list, mutex_list, mutex);
+ mutex_enter(&mutex_list_mutex);
- mutex_exit(&mutex_list_mutex);
+ UT_LIST_REMOVE(list, mutex_list, mutex);
+
+ mutex_exit(&mutex_list_mutex);
+ }
#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
os_fast_mutex_free(&(mutex->os_fast_mutex));
@@ -1230,13 +1232,26 @@ sync_init(void)
}
/**********************************************************************
-Frees the resources in synchronization data structures. */
+Frees the resources in InnoDB's own synchronization data structures. Use
+os_sync_free() after calling this. */
void
sync_close(void)
/*===========*/
{
+ mutex_t* mutex;
+
sync_array_free(sync_primary_wait_array);
+
+ mutex = UT_LIST_GET_FIRST(mutex_list);
+
+ while (mutex) {
+ mutex_free(mutex);
+ mutex = UT_LIST_GET_FIRST(mutex_list);
+ }
+
+ mutex_free(&mutex_list_mutex);
+ mutex_free(&sync_thread_mutex);
}
/***********************************************************************
diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c
index 23deed0fa55..2609b8f5241 100644
--- a/innobase/ut/ut0mem.c
+++ b/innobase/ut/ut0mem.c
@@ -225,6 +225,8 @@ ut_free_all_mem(void)
os_fast_mutex_unlock(&ut_list_mutex);
ut_a(ut_total_allocated_memory == 0);
+
+ os_fast_mutex_free(&ut_list_mutex);
}
/**************************************************************************
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index f8aece76d28..7e379ab63ba 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -86,9 +86,9 @@ ulong net_write_timeout= NET_WRITE_TIMEOUT;
#endif /* __WIN__ */
const char *sql_protocol_names_lib[] =
-{ "TCP", "SOCKET", "PIPE", "MEMORY",NullS };
+{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS };
TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
- sql_protocol_names_lib};
+ sql_protocol_names_lib};
/*
If allowed through some configuration, then this needs to
be changed
@@ -123,16 +123,16 @@ void STDCALL mysql_server_end()
my_bool STDCALL mysql_thread_init()
{
#ifdef THREAD
- return my_thread_init();
+ return my_thread_init();
#else
- return 0;
+ return 0;
#endif
}
void STDCALL mysql_thread_end()
{
#ifdef THREAD
- my_thread_end();
+ my_thread_end();
#endif
}
@@ -142,7 +142,7 @@ void STDCALL mysql_thread_end()
*/
#if !defined(__WIN__) && defined(SIGPIPE) && !defined(THREAD)
-#define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0;
+#define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0
#define set_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) old_signal_handler=signal(SIGPIPE,pipe_sig_handler)
#define reset_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) signal(SIGPIPE,old_signal_handler);
#else
@@ -236,7 +236,7 @@ pipe_sig_handler(int sig __attribute__((unused)))
/* perform query on master */
my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q,
- unsigned long length)
+ unsigned long length)
{
DBUG_ENTER("mysql_master_query");
if (mysql_master_send_query(mysql, q, length))
@@ -283,7 +283,7 @@ my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
*/
mysql->last_used_con = mysql->last_used_slave = slave_to_use;
if (!slave_to_use->net.vio && !mysql_real_connect(slave_to_use, 0,0,0,
- 0,0,0,0))
+ 0,0,0,0))
DBUG_RETURN(1);
DBUG_RETURN(simple_command(slave_to_use, COM_QUERY, q, length, 1));
}
@@ -420,7 +420,7 @@ static my_bool get_slaves_from_master(MYSQL* mysql)
}
if (!(slave = spawn_init(mysql, row[1], atoi(row[port_ind]),
- tmp_user, tmp_pass)))
+ tmp_user, tmp_pass)))
goto err;
/* Now add slave into the circular linked list */
@@ -430,7 +430,7 @@ static my_bool get_slaves_from_master(MYSQL* mysql)
error = 0;
err:
if (res)
- mysql_free_result(res);
+ mysql_free_result(res);
DBUG_RETURN(error);
}
@@ -593,7 +593,7 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
if (!passwd)
passwd="";
- /* Store user into the buffer */
+ /* Store user into the buffer */
end=strmov(end,user)+1;
/*
@@ -610,15 +610,15 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
*end=0;
}
- else /* For empty password*/
- *end=0; /* Store zero length scramble */
+ else /* For empty password */
+ *end=0; /* zero length scramble */
}
else
{
- /*
- Real scramble is only sent to old servers. This can be blocked
- by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1);
- */
+ /*
+ Real scramble is only sent to old servers. This can be blocked
+ by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1);
+ */
end=scramble(end, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9));
}
@@ -824,9 +824,9 @@ STDCALL mysql_set_master(MYSQL* mysql, const char* host,
int
STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
- unsigned int port,
- const char* user,
- const char* passwd)
+ unsigned int port,
+ const char* user,
+ const char* passwd)
{
MYSQL* slave;
if (!(slave = spawn_init(mysql, host, port, user, passwd)))
@@ -990,7 +990,7 @@ mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128);
if (simple_command(mysql,COM_FIELD_LIST,buff,(ulong) (end-buff),1) ||
!(query = read_rows(mysql,(MYSQL_FIELD*) 0,
- protocol_41(mysql) ? 7 : 6)))
+ protocol_41(mysql) ? 8 : 6)))
DBUG_RETURN(NULL);
free_old_query(mysql);
@@ -1027,7 +1027,7 @@ mysql_list_processes(MYSQL *mysql)
pos=(uchar*) mysql->net.read_pos;
field_count=(uint) net_field_length(&pos);
if (!(fields = read_rows(mysql,(MYSQL_FIELD*) 0,
- protocol_41(mysql) ? 6 : 5)))
+ protocol_41(mysql) ? 7 : 5)))
DBUG_RETURN(NULL);
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,field_count,0,
mysql->server_capabilities)))
@@ -1302,7 +1302,7 @@ mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
if (use_mb_flag && (l = my_ismbchar(charset_info, from, end)))
{
while (l--)
- *to++ = *from++;
+ *to++ = *from++;
from--;
continue;
}
@@ -1677,13 +1677,15 @@ unsigned int alloc_stmt_fields(MYSQL_STMT *stmt)
like SHOW and DESCRIBE commands
*/
if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc,
- sizeof(MYSQL_FIELD) * stmt->field_count)) ||
+ sizeof(MYSQL_FIELD) *
+ stmt->field_count)) ||
!(stmt->bind= (MYSQL_BIND *) alloc_root(alloc,
- sizeof(MYSQL_BIND ) * stmt->field_count)))
+ sizeof(MYSQL_BIND) *
+ stmt->field_count)))
return 0;
for (fields= mysql->fields, end= fields+stmt->field_count,
- field= stmt->fields;
+ field= stmt->fields;
field && fields < end; fields++, field++)
{
field->db = strdup_root(alloc,fields->db);
@@ -2413,7 +2415,7 @@ static void send_data_long(MYSQL_BIND *param, longlong value)
{
char *buffer= param->buffer;
- switch(param->buffer_type) {
+ switch (param->buffer_type) {
case MYSQL_TYPE_NULL: /* do nothing */
break;
case MYSQL_TYPE_TINY:
@@ -2429,33 +2431,34 @@ static void send_data_long(MYSQL_BIND *param, longlong value)
int8store(buffer, value);
break;
case MYSQL_TYPE_FLOAT:
- {
- float data= (float)value;
- float4store(buffer, data);
- break;
- }
+ {
+ float data= (float)value;
+ float4store(buffer, data);
+ break;
+ }
case MYSQL_TYPE_DOUBLE:
- {
- double data= (double)value;
- float8store(buffer, data);
- break;
- }
+ {
+ double data= (double)value;
+ float8store(buffer, data);
+ break;
+ }
default:
- {
- char tmp[12];
- uint length= (uint)(longlong10_to_str(value,(char *)tmp,10)-tmp);
- ulong copy_length= min((ulong)length-param->offset, param->buffer_length);
- memcpy(buffer, (char *)tmp+param->offset, copy_length);
- *param->length= length;
+ {
+ char tmp[12];
+ uint length= (uint)(longlong10_to_str(value,(char *)tmp,10)-tmp);
+ ulong copy_length= min((ulong)length-param->offset, param->buffer_length);
+ memcpy(buffer, (char *)tmp+param->offset, copy_length);
+ *param->length= length;
- if (copy_length != param->buffer_length)
- *(buffer+copy_length)= '\0';
- }
+ if (copy_length != param->buffer_length)
+ *(buffer+copy_length)= '\0';
+ }
}
}
/* Convert Double to buffer types */
+
static void send_data_double(MYSQL_BIND *param, double value)
{
char *buffer= param->buffer;
@@ -2476,32 +2479,34 @@ static void send_data_double(MYSQL_BIND *param, double value)
int8store(buffer, (longlong)value);
break;
case MYSQL_TYPE_FLOAT:
- {
- float data= (float)value;
- float4store(buffer, data);
- break;
- }
+ {
+ float data= (float)value;
+ float4store(buffer, data);
+ break;
+ }
case MYSQL_TYPE_DOUBLE:
- {
- double data= (double)value;
- float8store(buffer, data);
- break;
- }
+ {
+ double data= (double)value;
+ float8store(buffer, data);
+ break;
+ }
default:
- {
- char tmp[12];
- uint length= my_sprintf(tmp,(tmp,"%g",value));
- ulong copy_length= min((ulong)length-param->offset, param->buffer_length);
- memcpy(buffer, (char *)tmp+param->offset, copy_length);
- *param->length= length;
+ {
+ char tmp[12];
+ uint length= my_sprintf(tmp,(tmp,"%g",value));
+ ulong copy_length= min((ulong)length-param->offset, param->buffer_length);
+ memcpy(buffer, (char *)tmp+param->offset, copy_length);
+ *param->length= length;
- if (copy_length != param->buffer_length)
- *(buffer+copy_length)= '\0';
- }
+ if (copy_length != param->buffer_length)
+ *(buffer+copy_length)= '\0';
+ }
}
}
+
/* Convert string to buffer types */
+
static void send_data_str(MYSQL_BIND *param, char *value, uint length)
{
char *buffer= param->buffer;
@@ -2566,6 +2571,7 @@ static void send_data_str(MYSQL_BIND *param, char *value, uint length)
}
}
+
static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
uint length)
{
@@ -2601,7 +2607,7 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
switch (ltime.time_type) {
case MYSQL_TIMESTAMP_DATE:
length= my_sprintf(buff,(buff, "%04d-%02d-%02d", ltime.year,
- ltime.month,ltime.day));
+ ltime.month,ltime.day));
break;
case MYSQL_TIMESTAMP_FULL:
length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
@@ -2610,7 +2616,7 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
break;
case MYSQL_TIMESTAMP_TIME:
length= my_sprintf(buff, (buff, "%02d:%02d:%02d",
- ltime.hour,ltime.minute,ltime.second));
+ ltime.hour,ltime.minute,ltime.second));
break;
default:
length= 0;
@@ -2622,8 +2628,8 @@ static void send_data_time(MYSQL_BIND *param, MYSQL_TIME ltime,
}
-
/* Fetch data to buffers */
+
static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row,
my_bool field_is_unsigned)
{
@@ -2633,8 +2639,8 @@ static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row,
case MYSQL_TYPE_TINY:
{
char value= (char) **row;
- longlong data= (field_is_unsigned) ? (longlong) (unsigned char) value:
- (longlong) value;
+ longlong data= ((field_is_unsigned) ? (longlong) (unsigned char) value:
+ (longlong) value);
send_data_long(param,data);
length= 1;
break;
@@ -2643,8 +2649,8 @@ static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row,
case MYSQL_TYPE_YEAR:
{
short value= sint2korr(*row);
- longlong data= (field_is_unsigned) ? (longlong) (unsigned short) value:
- (longlong) value;
+ longlong data= ((field_is_unsigned) ? (longlong) (unsigned short) value:
+ (longlong) value);
send_data_long(param,data);
length= 2;
break;
@@ -2652,8 +2658,8 @@ static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row,
case MYSQL_TYPE_LONG:
{
long value= sint4korr(*row);
- longlong data= (field_is_unsigned) ? (longlong) (unsigned long) value:
- (longlong) value;
+ longlong data= ((field_is_unsigned) ? (longlong) (unsigned long) value:
+ (longlong) value);
send_data_long(param,data);
length= 4;
break;
@@ -2717,6 +2723,7 @@ static void fetch_results(MYSQL_BIND *param, uint field_type, uchar **row,
*row+= length;
}
+
static void fetch_result_tinyint(MYSQL_BIND *param, uchar **row)
{
*param->buffer= (uchar) **row;
@@ -2929,6 +2936,7 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
DBUG_RETURN(0);
}
+
/*
Fetch row data to bind buffers
*/
@@ -2948,8 +2956,8 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
/* Copy complete row to application buffers */
for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count,
- field= stmt->fields,
- field_end= (MYSQL_FIELD *)stmt->fields+stmt->field_count;
+ field= stmt->fields,
+ field_end= (MYSQL_FIELD *)stmt->fields+stmt->field_count;
bind < end && field < field_end;
bind++, field++)
{
@@ -2976,6 +2984,7 @@ static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
return 0;
}
+
/*
Fetch and return row data to bound buffers, if any
*/
@@ -3026,6 +3035,7 @@ no_data:
DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
}
+
/*
Fetch only specified column data to buffers
*/
@@ -3045,7 +3055,8 @@ int STDCALL mysql_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
#ifdef CHECK_EXTRA_ARGUMENTS
if (!bind || icol >= stmt->field_count)
{
- DBUG_PRINT("error",("Invalid column position"));
+ set_stmt_errmsg(stmt, "Invalid column descriptor or offset",1,
+ unknown_sqlstate);
DBUG_RETURN(1);
}
#endif
@@ -3100,7 +3111,8 @@ int STDCALL mysql_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *bind,
for (i=0; i < icol; i++)
{
- if (!(length= default_binary_field_length((uint)(stmt->fields[i].type))))
+ if (!(length= default_binary_field_length((uint)(stmt->fields[i].
+ type))))
length= net_field_length(&row);
row+= length;
}
@@ -3135,7 +3147,7 @@ no_data:
}
-/*
+/*
Read all rows of data from server (binary format)
*/
@@ -3177,7 +3189,7 @@ static MYSQL_DATA *read_binary_rows(MYSQL_STMT *stmt)
result->rows++;
if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,sizeof(MYSQL_ROWS))) ||
- !(cur->data= ((MYSQL_ROW) alloc_root(&result->alloc, pkt_len))))
+ !(cur->data= ((MYSQL_ROW) alloc_root(&result->alloc, pkt_len))))
{
free_rows(result);
set_stmt_errmsg(stmt, ER(CR_OUT_OF_MEMORY), CR_OUT_OF_MEMORY,
@@ -3204,6 +3216,7 @@ static MYSQL_DATA *read_binary_rows(MYSQL_STMT *stmt)
DBUG_RETURN(result);
}
+
/*
Store or buffer the binary results to stmt
*/
@@ -3225,9 +3238,9 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
}
mysql->status= MYSQL_STATUS_READY; /* server is ready */
if (!(result= (MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+
- sizeof(ulong) *
- stmt->field_count),
- MYF(MY_WME | MY_ZEROFILL))))
+ sizeof(ulong) *
+ stmt->field_count),
+ MYF(MY_WME | MY_ZEROFILL))))
{
set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate);
DBUG_RETURN(1);
@@ -3246,6 +3259,7 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
DBUG_RETURN(0); /* Data buffered, must be fetched with mysql_fetch() */
}
+
/*
Seek to desired row in the statement result set
*/
@@ -3268,6 +3282,7 @@ mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET row)
DBUG_RETURN(0);
}
+
/*
Return the current statement row cursor position
*/
@@ -3284,6 +3299,7 @@ mysql_stmt_row_tell(MYSQL_STMT *stmt)
DBUG_RETURN(0);
}
+
/*
Move the stmt result set data cursor to specified row
*/
@@ -3307,6 +3323,7 @@ mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong row)
DBUG_PRINT("exit", ("stmt doesn't contain any resultset"));
}
+
/*
Return total rows the current statement result set
*/
@@ -3361,9 +3378,13 @@ my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
mysql->status= MYSQL_STATUS_READY;
}
mysql_free_result(stmt->result);
+ stmt->result= 0;
+ stmt->result_buffered= 0;
+ stmt->current_row= 0;
DBUG_RETURN(0);
}
+
my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list)
{
MYSQL *mysql;
@@ -3399,6 +3420,7 @@ my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list)
DBUG_RETURN(0);
}
+
my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
{
return stmt_close(stmt, 0);
@@ -3481,16 +3503,16 @@ my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode)
my_bool STDCALL mysql_more_results(MYSQL *mysql)
{
- my_bool result;
+ my_bool res;
DBUG_ENTER("mysql_more_results");
- result= (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) ?
- 1: 0;
-
- DBUG_PRINT("exit",("More results exists ? %d", result));
- DBUG_RETURN(result);
+ res= ((mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) ?
+ 1: 0);
+ DBUG_PRINT("exit",("More results exists ? %d", res));
+ DBUG_RETURN(res);
}
+
/*
Reads and returns the next query results
*/
@@ -3501,7 +3523,7 @@ my_bool STDCALL mysql_next_result(MYSQL *mysql)
mysql->net.last_error[0]= 0;
mysql->net.last_errno= 0;
- strmov(mysql->net.sqlstate, unknown_sqlstate);
+ strmov(mysql->net.sqlstate, not_error_sqlstate);
mysql->affected_rows= ~(my_ulonglong) 0;
if (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS)
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index c3c99583ad9..92fc588eda3 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -43,7 +43,7 @@ sqlsources = derror.cc field.cc field_conv.cc filesort.cc \
item.cc item_buff.cc item_cmpfunc.cc item_create.cc \
item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \
item_geofunc.cc item_uniq.cc item_subselect.cc item_row.cc\
- key.cc lock.cc log.cc log_event.cc \
+ key.cc lock.cc log.cc log_event.cc sql_state.c \
protocol.cc net_serv.cc opt_ft.cc opt_range.cc \
opt_sum.cc procedure.cc records.cc sql_acl.cc \
sql_load.cc sql_olap.cc \
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index e6166f6bbe5..a2d69b30c0d 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -450,6 +450,7 @@ static inline int mysql_init_charset(MYSQL *mysql)
if (!mysql->charset)
{
mysql->last_errno=CR_CANT_READ_CHARSET;
+ strmov(mysql->sqlstate, "HY0000");
if (mysql->options.charset_dir)
sprintf(mysql->last_error,ER(mysql->last_errno),
charset_name ? charset_name : "unknown",
@@ -1130,6 +1131,7 @@ mysql_stat(MYSQL *mysql)
if (!mysql->net.read_pos[0])
{
mysql->net.last_errno=CR_WRONG_HOST_INFO;
+ strmov(mysql->sqlstate, unknown_sqlstate);
strmov(mysql->net.last_error, ER(mysql->net.last_errno));
return mysql->net.last_error;
}
@@ -1284,12 +1286,12 @@ unsigned int STDCALL mysql_field_count(MYSQL *mysql)
my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql)
{
- return (mysql)->affected_rows;
+ return mysql->affected_rows;
}
my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql)
{
- return (mysql)->insert_id;
+ return mysql->insert_id;
}
uint STDCALL mysql_errno(MYSQL *mysql)
@@ -1297,6 +1299,11 @@ uint STDCALL mysql_errno(MYSQL *mysql)
return mysql->last_errno;
}
+const char *STDCALL mysql_sqlstate(MYSQL *mysql)
+{
+ return mysql->sqlstate;
+}
+
const char * STDCALL mysql_error(MYSQL *mysql)
{
return mysql->last_error;
diff --git a/man/mysql_fix_privilege_tables.1 b/man/mysql_fix_privilege_tables.1
index bf4e0e15dfa..4ed81368098 100644
--- a/man/mysql_fix_privilege_tables.1
+++ b/man/mysql_fix_privilege_tables.1
@@ -2,7 +2,7 @@
.SH NAME
mysql_fix_privilege_tables \- Fixes MySQL privilege tables.
.SH SYNOPSIS
-mysql_fix_privilege_tables [options]
+mysql_fix_privilege_tables [mysql_root_password]
.SH DESCRIPTION
This scripts updates the mysql.user, mysql.db, mysql.host and the
mysql.func tables to MySQL 3.22.14 and above.
@@ -10,10 +10,9 @@ mysql.func tables to MySQL 3.22.14 and above.
This is needed if you want to use the new GRANT functions,
CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 3.23
-If you get 'Access denied' errors, you should run this script again
-and give the MySQL root user password as an argument!
+If you get 'Access denied' errors, run the script again
+and give the MySQL root user password as an argument.
-For more information start the program with '--help'.
.SH "SEE ALSO"
mysql (1), mysqld (1)
.SH AUTHOR
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 81e3f866709..137e99f48b3 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -13,12 +13,15 @@ DB=test
DBPASSWD=
VERBOSE=""
USE_MANAGER=0
-TZ=GMT-3; export TZ # for UNIX_TIMESTAMP tests to work
+MY_TZ=GMT-3
+TZ=$MY_TZ; export TZ # for UNIX_TIMESTAMP tests to work
#++
# Program Definitions
#--
+LC_COLLATE=C
+export LC_COLLATE
PATH=/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin:/usr/openwin/bin:/usr/bin/X11:$PATH
MASTER_40_ARGS="--rpl-recovery-rank=1 --init-rpl-role=master"
@@ -1163,9 +1166,18 @@ run_testcase ()
if [ -f $master_opt_file ] ;
then
EXTRA_MASTER_OPT=`$CAT $master_opt_file | $SED -e "s;\\$MYSQL_TEST_DIR;$MYSQL_TEST_DIR;"`
+ case "$EXTRA_MASTER_OPT" in
+ --timezone=*)
+ TZ=`$ECHO "$EXTRA_MASTER_OPT" | $SED -e "s;--timezone=;;"`
+ export TZ
+ # Note that this must be set to space, not "" for test-reset to work
+ EXTRA_MASTER_OPT=" "
+ ;;
+ esac
stop_master
echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
start_master
+ TZ=$MY_TZ; export TZ
else
if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] || [ -f $master_init_script ]
then
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index 6c5e06a289f..cb11e680910 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -276,3 +276,8 @@ t1 0 a 1 a A 3 NULL NULL YES BTREE
t1 0 a 2 b A 300 NULL NULL YES BTREE
t1 1 b 1 b A 100 NULL NULL YES BTREE
drop table t1;
+CREATE TABLE t1 (i int(10), index(i) );
+ALTER TABLE t1 DISABLE KEYS;
+INSERT DELAYED INTO t1 VALUES(1),(2),(3);
+ALTER TABLE t1 ENABLE KEYS;
+drop table t1;
diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result
index 60764494417..f18b925460c 100644
--- a/mysql-test/r/analyse.result
+++ b/mysql-test/r/analyse.result
@@ -6,26 +6,26 @@ Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_
count(*) 4 4 1 1 0 0 4.0000 0.0000 ENUM('4') NOT NULL
select * from t1 procedure analyse();
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
-t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL
-t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL
-t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL
-t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL
-t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL
+test.t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL
+test.t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL
+test.t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL
+test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL
+test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL
select * from t1 procedure analyse(2);
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
-t1.i 1 7 1 1 0 0 4.0000 2.2361 TINYINT(1) UNSIGNED NOT NULL
-t1.j 2 8 1 1 0 0 5.0000 2.2361 TINYINT(1) UNSIGNED NOT NULL
-t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL
-t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL
-t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL
+test.t1.i 1 7 1 1 0 0 4.0000 2.2361 TINYINT(1) UNSIGNED NOT NULL
+test.t1.j 2 8 1 1 0 0 5.0000 2.2361 TINYINT(1) UNSIGNED NOT NULL
+test.t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL
+test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL
+test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL
create table t2 select * from t1 procedure analyse();
select * from t2;
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
-t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL
-t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL
-t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL
-t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL
-t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL
+test.t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL
+test.t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL
+test.t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL
+test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL
+test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL
drop table t1,t2;
EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE();
id select_type table type possible_keys key key_len ref rows Extra
diff --git a/mysql-test/r/ansi.result b/mysql-test/r/ansi.result
index f9f96310b73..6ec909f84bb 100644
--- a/mysql-test/r/ansi.result
+++ b/mysql-test/r/ansi.result
@@ -6,5 +6,13 @@ CREATE TABLE t1 (id INT, id2 int);
SELECT id,NULL,1,1.1,'a' FROM t1 GROUP BY id;
id NULL 1 1.1 a
SELECT id FROM t1 GROUP BY id2;
-'t1.id' isn't in GROUP BY
+ERROR 42000: 'test.t1.id' isn't in GROUP BY
drop table t1;
+set sql_mode="MySQL40";
+select @@sql_mode;
+@@sql_mode
+NO_FIELD_OPTIONS,MYSQL40
+set sql_mode="ANSI";
+select @@sql_mode;
+@@sql_mode
+REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI
diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result
index c993a47198a..bd15c913d2e 100644
--- a/mysql-test/r/auto_increment.result
+++ b/mysql-test/r/auto_increment.result
@@ -112,7 +112,7 @@ select last_insert_id();
last_insert_id()
255
insert into t1 set i = null;
-Duplicate entry '255' for key 1
+ERROR 23000: Duplicate entry '255' for key 1
select last_insert_id();
last_insert_id()
255
@@ -140,7 +140,7 @@ select last_insert_id();
last_insert_id()
2
insert into t1 values (NULL, 10);
-Duplicate entry '10' for key 2
+ERROR 23000: Duplicate entry '10' for key 2
select last_insert_id();
last_insert_id()
3
diff --git a/mysql-test/r/bdb-deadlock.result b/mysql-test/r/bdb-deadlock.result
index 55b3d3ea2a5..6606b0d9b38 100644
--- a/mysql-test/r/bdb-deadlock.result
+++ b/mysql-test/r/bdb-deadlock.result
@@ -9,7 +9,7 @@ set autocommit=0;
update t2 set x = 1 where id = 0;
select x from t1 where id = 0;
select x from t2 where id = 0;
-Deadlock found when trying to get lock; Try restarting transaction
+ERROR 40001: Deadlock found when trying to get lock; Try restarting transaction
commit;
x
1
diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result
index 7f0612a011f..b0566011996 100644
--- a/mysql-test/r/bdb.result
+++ b/mysql-test/r/bdb.result
@@ -48,7 +48,7 @@ id parent_id level
15 102 2
update t1 set id=id+1000;
update t1 set id=1024 where id=1009;
-Duplicate entry '1024' for key 1
+ERROR 23000: Duplicate entry '1024' for key 1
select * from t1;
id parent_id level
1001 100 0
@@ -270,7 +270,7 @@ n after commit
commit;
insert into t1 values (5);
insert into t1 values (4);
-Duplicate entry '4' for key 1
+ERROR 23000: Duplicate entry '4' for key 1
commit;
select n, "after commit" from t1;
n after commit
@@ -279,7 +279,7 @@ n after commit
set autocommit=1;
insert into t1 values (6);
insert into t1 values (4);
-Duplicate entry '4' for key 1
+ERROR 23000: Duplicate entry '4' for key 1
select n from t1;
n
4
@@ -309,7 +309,7 @@ drop table t1;
CREATE TABLE t1 (id char(8) not null primary key, val int not null) type=bdb;
insert into t1 values ('pippo', 12);
insert into t1 values ('pippo', 12);
-Duplicate entry 'pippo' for key 1
+ERROR 23000: Duplicate entry 'pippo' for key 1
delete from t1;
delete from t1 where id = 'pippo';
select * from t1;
@@ -464,9 +464,9 @@ UNIQUE ggid (ggid)
insert into t1 (ggid,passwd) values ('test1','xxx');
insert into t1 (ggid,passwd) values ('test2','yyy');
insert into t1 (ggid,passwd) values ('test2','this will fail');
-Duplicate entry 'test2' for key 2
+ERROR 23000: Duplicate entry 'test2' for key 2
insert into t1 (ggid,id) values ('this will fail',1);
-Duplicate entry '1' for key 1
+ERROR 23000: Duplicate entry '1' for key 1
select * from t1 where ggid='test1';
id ggid email passwd
1 test1 xxx
@@ -479,7 +479,7 @@ id ggid email passwd
replace into t1 (ggid,id) values ('this will work',1);
replace into t1 (ggid,passwd) values ('test2','this will work');
update t1 set id=100,ggid='test2' where id=1;
-Duplicate entry 'test2' for key 2
+ERROR 23000: Duplicate entry 'test2' for key 2
select * from t1;
id ggid email passwd
1 this will work
@@ -1008,7 +1008,7 @@ create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(3
insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
LOCK TABLES t1 WRITE;
insert into t1 values (99,1,2,'D'),(1,1,2,'D');
-Duplicate entry '1-1' for key 1
+ERROR 23000: Duplicate entry '1-1' for key 1
select id from t1;
id
0
@@ -1026,7 +1026,7 @@ insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJ
LOCK TABLES t1 WRITE;
begin;
insert into t1 values (99,1,2,'D'),(1,1,2,'D');
-Duplicate entry '1-1' for key 1
+ERROR 23000: Duplicate entry '1-1' for key 1
select id from t1;
id
0
diff --git a/mysql-test/r/comments.result b/mysql-test/r/comments.result
index 8092f789954..a9106ce0538 100644
--- a/mysql-test/r/comments.result
+++ b/mysql-test/r/comments.result
@@ -6,7 +6,7 @@ multi line comment */;
1
1
;
-Query was empty
+ERROR 42000: Query was empty
select 1 /*!32301 +1 */;
1 /*!32301 +1
2
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 45b37dfb719..70814aa899e 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -17,29 +17,29 @@ b
drop table t1;
create table t2 type=heap select * from t1;
-Table 'test.t1' doesn't exist
+ERROR 42S02: Table 'test.t1' doesn't exist
create table t2 select auto+1 from t1;
-Table 'test.t1' doesn't exist
+ERROR 42S02: Table 'test.t1' doesn't exist
drop table if exists t1,t2;
Warnings:
Note 1051 Unknown table 't1'
Note 1051 Unknown table 't2'
create table t1 (b char(0) not null, index(b));
-The used storage engine can't index column 'b'
+ERROR 42000: The used storage engine can't index column 'b'
create table t1 (a int not null auto_increment,primary key (a)) type=heap;
create table t1 (a int not null,b text) type=heap;
-The used table type doesn't support BLOB/TEXT columns
+ERROR 42000: The used table type doesn't support BLOB/TEXT columns
drop table if exists t1;
create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
-Incorrect table definition; There can only be one auto column and it must be defined as a key
+ERROR 42000: Incorrect table definition; There can only be one auto column and it must be defined as a key
create table not_existing_database.test (a int);
Got one of the listed errors
create table `a/a` (a int);
-Incorrect table name 'a/a'
+ERROR 42000: Incorrect table name 'a/a'
create table `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa int);
-Incorrect table name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+ERROR 42000: Incorrect table name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
create table a (`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` int);
-Identifier name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long
+ERROR 42000: Identifier name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' is too long
create table 1ea10 (1a20 int,1e int);
insert into 1ea10 values(1,1);
select 1ea10.1a20,1e+ 1e+10 from 1ea10;
@@ -61,11 +61,11 @@ create table test_$1.test2$ (a int);
drop table test_$1.test2$;
drop database test_$1;
create table `` (a int);
-Incorrect table name ''
+ERROR 42000: Incorrect table name ''
drop table if exists ``;
-Incorrect table name ''
+ERROR 42000: Incorrect table name ''
create table t1 (`` int);
-Incorrect column name ''
+ERROR 42000: Incorrect column name ''
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
@@ -115,17 +115,17 @@ Field Type Null Key Default Extra
a int(11) YES NULL
drop table if exists t2;
create table t2 (a int, a float) select * from t1;
-Duplicate column name 'a'
+ERROR 42S21: Duplicate column name 'a'
drop table if exists t2;
Warnings:
Note 1051 Unknown table 't2'
create table t2 (a int) select a as b, a+1 as b from t1;
-Duplicate column name 'b'
+ERROR 42S21: Duplicate column name 'b'
drop table if exists t2;
Warnings:
Note 1051 Unknown table 't2'
create table t2 (b int) select a as b, a+1 as b from t1;
-Duplicate column name 'b'
+ERROR 42S21: Duplicate column name 'b'
drop table if exists t1,t2;
Warnings:
Note 1051 Unknown table 't2'
@@ -204,11 +204,11 @@ drop table t1;
create table t1 ( k1 varchar(2), k2 int, primary key(k1,k2));
insert into t1 values ("a", 1), ("b", 2);
insert into t1 values ("c", NULL);
-Column 'k2' cannot be null
+ERROR 23000: Column 'k2' cannot be null
insert into t1 values (NULL, 3);
-Column 'k1' cannot be null
+ERROR 23000: Column 'k1' cannot be null
insert into t1 values (NULL, NULL);
-Column 'k1' cannot be null
+ERROR 23000: Column 'k1' cannot be null
drop table t1;
create table t1 (a int, key(a));
create table t2 (b int, foreign key(b) references t1(a), key(b));
@@ -273,15 +273,15 @@ select * from t2;
id name
create table t3 like t1;
create table t3 like test_$1.t3;
-Table 't3' already exists
+ERROR 42S01: Table 't3' already exists
create table non_existing_database.t1 like t1;
Got one of the listed errors
create table t3 like non_existing_table;
-Unknown table 'non_existing_table'
+ERROR 42S02: Unknown table 'non_existing_table'
create temporary table t3 like t1;
-Table 't3' already exists
+ERROR 42S01: Table 't3' already exists
create table t3 like `a/a`;
-Incorrect table name 'a/a'
+ERROR 42000: Incorrect table name 'a/a'
drop table t1, t2, t3;
drop table t3;
drop database test_$1;
diff --git a/mysql-test/r/ctype_collate.result b/mysql-test/r/ctype_collate.result
index 00a642d9ee6..f895107239f 100644
--- a/mysql-test/r/ctype_collate.result
+++ b/mysql-test/r/ctype_collate.result
@@ -6,7 +6,7 @@ latin1_f CHAR(32) CHARACTER SET latin1 NOT NULL
CREATE TABLE t2 (
latin1_f CHAR(32) CHARACTER SET latin1 COLLATE koi8r_general_ci NOT NULL
);
-COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1'
+ERROR 42000: COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1'
INSERT INTO t1 (latin1_f) VALUES (_latin1'A');
INSERT INTO t1 (latin1_f) VALUES (_latin1'a');
INSERT INTO t1 (latin1_f) VALUES (_latin1'AD');
@@ -180,7 +180,7 @@ z
å
ü
SELECT latin1_f FROM t1 ORDER BY latin1_f COLLATE koi8r_general_ci;
-COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1'
+ERROR 42000: COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1'
SELECT latin1_f COLLATE latin1_swedish_ci AS latin1_f_as FROM t1 ORDER BY latin1_f_as;
latin1_f_as
A
@@ -298,7 +298,7 @@ z
å
ü
SELECT latin1_f COLLATE koi8r_general_ci AS latin1_f_as FROM t1 ORDER BY latin1_f_as;
-COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1'
+ERROR 42000: COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1'
SELECT latin1_f,count(*) FROM t1 GROUP BY latin1_f;
latin1_f count(*)
A 2
@@ -390,7 +390,7 @@ z 1
å 1
ü 1
SELECT latin1_f,count(*) FROM t1 GROUP BY latin1_f COLLATE koi8r_general_ci;
-COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1'
+ERROR 42000: COLLATION 'koi8r_general_ci' is not valid for CHARACTER SET 'latin1'
SELECT DISTINCT latin1_f FROM t1;
latin1_f
A
@@ -482,7 +482,7 @@ y
Z
z
SELECT DISTINCT latin1_f COLLATE koi8r FROM t1;
-COLLATION 'koi8r' is not valid for CHARACTER SET 'latin1'
+ERROR 42000: COLLATION 'koi8r' is not valid for CHARACTER SET 'latin1'
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -524,5 +524,5 @@ SELECT charset('a'),collation('a'),coercibility('a'),'a'='A';
charset('a') collation('a') coercibility('a') 'a'='A'
latin1 latin1_swedish_ci 3 1
SET CHARACTER SET 'DEFAULT';
-Unknown character set: 'DEFAULT'
+ERROR 42000: Unknown character set: 'DEFAULT'
DROP TABLE t1;
diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result
index 8e4b52a8366..ceb511a7891 100644
--- a/mysql-test/r/delayed.result
+++ b/mysql-test/r/delayed.result
@@ -21,7 +21,7 @@ insert delayed into t1 values (1,"b");
insert delayed into t1 values (null,"c");
insert delayed into t1 values (3,"d"),(null,"e");
insert delayed into t1 values (3,"this will give an","error");
-Column count doesn't match value count at row 1
+ERROR 21S01: Column count doesn't match value count at row 1
select * from t1;
a b
1 b
diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result
index c87fa8fb927..cd45cf03853 100644
--- a/mysql-test/r/delete.result
+++ b/mysql-test/r/delete.result
@@ -30,7 +30,7 @@ CREATE TABLE `t1` (
PRIMARY KEY (`i`)
);
DELETE FROM t1 USING t1 WHERE post='1';
-Unknown column 'post' in 'where clause'
+ERROR 42S22: Unknown column 'post' in 'where clause'
drop table t1;
CREATE TABLE t1 (
bool char(0) default NULL,
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index bfd4c544131..5f405d83fa5 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -3,9 +3,9 @@ select * from (select 2 from DUAL) b;
2
2
SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b;
-Unknown column 'a' in 'field list'
+ERROR 42S22: Unknown column 'a' in 'field list'
SELECT 1 as a FROM (SELECT a UNION SELECT 1) b;
-Unknown column 'a' in 'field list'
+ERROR 42S22: Unknown column 'a' in 'field list'
CREATE TABLE t1 (a int not null, b char (10) not null);
insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
CREATE TABLE t2 (a int not null, b char (10) not null);
@@ -25,18 +25,18 @@ a y
3 3
3 3
SELECT a FROM (SELECT 1 FROM (SELECT 1) a HAVING a=1) b;
-Unknown column 'a' in 'having clause'
+ERROR 42S22: Unknown column 'a' in 'having clause'
SELECT a,b as a FROM (SELECT '1' as a,'2' as b) b HAVING a=1;
-Column: 'a' in having clause is ambiguous
+ERROR 23000: Column: 'a' in having clause is ambiguous
SELECT a,2 as a FROM (SELECT '1' as a) b HAVING a=2;
a a
1 2
SELECT a,2 as a FROM (SELECT '1' as a) b HAVING a=1;
a a
SELECT 1 FROM (SELECT 1) a WHERE a=2;
-Unknown column 'a' in 'where clause'
+ERROR 42S22: Unknown column 'a' in 'where clause'
SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) as a;
-Unknown column 'a' in 'having clause'
+ERROR 42S22: Unknown column 'a' in 'having clause'
select * from t1 as x1, (select * from t1) as x2;
a b a b
1 a 1 a
@@ -146,10 +146,17 @@ select * from (select 1 as a) b left join (select 2 as a) c using(a);
a a
1 NULL
SELECT * FROM (SELECT 1 UNION SELECT a) b;
-Unknown column 'a' in 'field list'
+ERROR 42S22: Unknown column 'a' in 'field list'
SELECT 1 as a FROM (SELECT a UNION SELECT 1) b;
-Unknown column 'a' in 'field list'
+ERROR 42S22: Unknown column 'a' in 'field list'
SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b;
-Unknown column 'a' in 'field list'
+ERROR 42S22: Unknown column 'a' in 'field list'
select 1 from (select 2) a order by 0;
-Unknown column '0' in 'order clause'
+ERROR 42S22: Unknown column '0' in 'order clause'
+create table t1 (id int);
+insert into t1 values (1),(2),(3);
+describe select * from (select * from t1 group by id) bar;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
+2 DERIVED t1 ALL NULL NULL NULL NULL 3 Using temporary; Using filesort
+drop table t1;
diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result
index 1f459faa8f4..9ebcd1fb915 100644
--- a/mysql-test/r/distinct.result
+++ b/mysql-test/r/distinct.result
@@ -175,7 +175,7 @@ explain SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 index a a 5 NULL 6 Using index; Using temporary
1 SIMPLE t2 index a a 4 NULL 5 Using index; Distinct
-1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 t2.a 1 Using where; Distinct
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 Using where; Distinct
SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a;
a
1
@@ -190,7 +190,7 @@ insert into t3 select * from t4;
explain select distinct t1.a from t1,t3 where t1.a=t3.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 2 Using index; Using temporary
-1 SIMPLE t3 ref a a 5 t1.a 10 Using where; Using index; Distinct
+1 SIMPLE t3 ref a a 5 test.t1.a 10 Using where; Using index; Distinct
select distinct t1.a from t1,t3 where t1.a=t3.a;
a
1
diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result
index a9048b65d51..2b878455bea 100644
--- a/mysql-test/r/drop.result
+++ b/mysql-test/r/drop.result
@@ -1,12 +1,12 @@
drop table if exists t1;
drop table t1;
-Unknown table 't1'
+ERROR 42S02: Unknown table 't1'
create table t1(n int);
insert into t1 values(1);
create temporary table t1( n int);
insert into t1 values(2);
create table t1(n int);
-Table 't1' already exists
+ERROR 42S01: Table 't1' already exists
drop table t1;
select * from t1;
n
@@ -48,4 +48,4 @@ Database
mysql
test
drop database mysqltest;
-Can't drop database 'mysqltest'. Database doesn't exist
+ERROR HY000: Can't drop database 'mysqltest'. Database doesn't exist
diff --git a/mysql-test/r/err000001.result b/mysql-test/r/err000001.result
deleted file mode 100644
index 5afecc6d600..00000000000
--- a/mysql-test/r/err000001.result
+++ /dev/null
@@ -1,25 +0,0 @@
-drop table if exists t1;
-insert into t1 values(1);
-Table 'test.t1' doesn't exist
-delete from t1;
-Table 'test.t1' doesn't exist
-update t1 set a=1;
-Table 'test.t1' doesn't exist
-create table t1 (a int);
-select count(test.t1.b) from t1;
-Unknown column 'test.t1.b' in 'field list'
-select count(not_existing_database.t1) from t1;
-Unknown table 'not_existing_database' in field list
-select count(not_existing_database.t1.a) from t1;
-Unknown table 'not_existing_database.t1' in field list
-select count(not_existing_database.t1.a) from not_existing_database.t1;
-Got one of the listed errors
-select 1 from t1 order by 2;
-Unknown column '2' in 'order clause'
-select 1 from t1 group by 2;
-Unknown column '2' in 'group statement'
-select 1 from t1 order by t1.b;
-Unknown column 't1.b' in 'order clause'
-select count(*),b from t1;
-Unknown column 'b' in 'field list'
-drop table t1;
diff --git a/mysql-test/r/errors.result b/mysql-test/r/errors.result
new file mode 100644
index 00000000000..d0011c8deb6
--- /dev/null
+++ b/mysql-test/r/errors.result
@@ -0,0 +1,25 @@
+drop table if exists t1;
+insert into t1 values(1);
+ERROR 42S02: Table 'test.t1' doesn't exist
+delete from t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+update t1 set a=1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+create table t1 (a int);
+select count(test.t1.b) from t1;
+ERROR 42S22: Unknown column 'test.t1.b' in 'field list'
+select count(not_existing_database.t1) from t1;
+ERROR 42S02: Unknown table 'not_existing_database' in field list
+select count(not_existing_database.t1.a) from t1;
+ERROR 42S02: Unknown table 'not_existing_database.t1' in field list
+select count(not_existing_database.t1.a) from not_existing_database.t1;
+Got one of the listed errors
+select 1 from t1 order by 2;
+ERROR 42S22: Unknown column '2' in 'order clause'
+select 1 from t1 group by 2;
+ERROR 42S22: Unknown column '2' in 'group statement'
+select 1 from t1 order by t1.b;
+ERROR 42S22: Unknown column 't1.b' in 'order clause'
+select count(*),b from t1;
+ERROR 42S22: Unknown column 'b' in 'field list'
+drop table t1;
diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result
index 63e4f4030d3..02e1ace71e1 100644
--- a/mysql-test/r/explain.result
+++ b/mysql-test/r/explain.result
@@ -24,9 +24,9 @@ explain select * from t1 use key (str,str) where str="foo";
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const str str 11 const 1
explain select * from t1 use key (str,str,foo) where str="foo";
-Key column 'foo' doesn't exist in table
+ERROR 42000: Key column 'foo' doesn't exist in table
explain select * from t1 ignore key (str,str,foo) where str="foo";
-Key column 'foo' doesn't exist in table
+ERROR 42000: Key column 'foo' doesn't exist in table
drop table t1;
explain select 1;
id select_type table type possible_keys key key_len ref rows Extra
diff --git a/mysql-test/r/flush.result b/mysql-test/r/flush.result
index 4e7e4769f1b..bab9b543307 100644
--- a/mysql-test/r/flush.result
+++ b/mysql-test/r/flush.result
@@ -8,7 +8,7 @@ n
3
flush tables with read lock;
drop table t2;
-Table 't2' was locked with a READ lock and can't be updated
+ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
drop table t2;
unlock tables;
create database mysqltest;
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index 5b410396390..caf93e7e973 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -162,11 +162,11 @@ KEY tig (ticket),
fulltext index tix (inhalt)
);
select * from t2 where MATCH inhalt AGAINST (t2.inhalt);
-Wrong arguments to AGAINST
+ERROR HY000: Wrong arguments to AGAINST
select * from t2 where MATCH ticket AGAINST ('foobar');
-Can't find FULLTEXT index matching the column list
+ERROR HY000: Can't find FULLTEXT index matching the column list
select * from t2,t3 where MATCH (t2.inhalt,t3.inhalt) AGAINST ('foobar');
-Wrong arguments to MATCH
+ERROR HY000: Wrong arguments to MATCH
drop table t1,t2,t3;
CREATE TABLE t1 (
id int(11) auto_increment,
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index 0dc84f090f1..51b61dbb3e6 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -155,7 +155,7 @@ show warnings;
Level Code Message
Warning 1258 1 line(s) was(were) cut by group_concat()
select group_concat(sum(a)) from t1 group by grp;
-Invalid use of group function
+ERROR HY000: Invalid use of group function
select grp,group_concat(c order by 2) from t1 group by grp;
-Unknown column '2' in 'group statement'
+ERROR 42S22: Unknown column '2' in 'group statement'
drop table if exists t1;
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 1a1de0ee3d5..c61563e6010 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -64,7 +64,7 @@ concat_ws(NULL,'a') concat_ws(',',NULL,'')
NULL
select concat_ws(',','',NULL,'a');
concat_ws(',','',NULL,'a')
-a
+,a
SELECT CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),repeat('d',100)), '"');
CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),repeat('d',100)), '"')
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
diff --git a/mysql-test/r/func_system.result b/mysql-test/r/func_system.result
index 15ff34a6d80..cde21ead33c 100644
--- a/mysql-test/r/func_system.result
+++ b/mysql-test/r/func_system.result
@@ -37,13 +37,13 @@ version()>=_latin1"3.23.29"
select charset(version());
charset(version())
utf8
-create table t1 select database(), user(), version();
+create table t1 (version char(40)) select database(), user(), version() as 'version';
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`database()` char(102) character set utf8 NOT NULL default '',
`user()` char(231) character set utf8 NOT NULL default '',
- `version()` char(21) character set utf8 NOT NULL default ''
+ `version` char(40) character set utf8 default NULL
) TYPE=MyISAM CHARSET=latin1
drop table t1;
select TRUE,FALSE,NULL;
diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result
index c1dcd5c29e9..715deac7965 100644
--- a/mysql-test/r/grant.result
+++ b/mysql-test/r/grant.result
@@ -1,3 +1,5 @@
+drop table if exists t1;
+create table t1 (a int);
delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1';
flush privileges;
@@ -69,3 +71,36 @@ show grants for user@localhost;
Grants for user@localhost
GRANT USAGE ON *.* TO 'user'@'localhost'
GRANT USAGE ON `test`.* TO 'user'@'localhost' WITH GRANT OPTION
+grant ALL PRIVILEGES on *.* to drop_user2@localhost with GRANT OPTION;
+show grants for drop_user2@localhost;
+Grants for drop_user2@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user2'@'localhost' WITH GRANT OPTION
+revoke all privileges, grant from drop_user2@localhost;
+drop user drop_user2@localhost;
+grant ALL PRIVILEGES on *.* to drop_user@localhost with GRANT OPTION;
+grant ALL PRIVILEGES on test.* to drop_user@localhost with GRANT OPTION;
+grant select(a) on test.t1 to drop_user@localhost;
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT ALL PRIVILEGES ON `test`.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON `test`.`t1` TO 'drop_user'@'localhost'
+revoke all privileges, grant from drop_user@localhost;
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT USAGE ON *.* TO 'drop_user'@'localhost'
+drop user drop_user@localhost;
+revoke all privileges, grant from drop_user@localhost;
+Can't revoke all privileges, grant for one or more of the requested users
+grant select(a) on test.t1 to drop_user1@localhost;
+grant select on test.t1 to drop_user2@localhost;
+grant select on test.* to drop_user3@localhost;
+grant select on *.* to drop_user4@localhost;
+drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
+drop_user4@localhost;
+Can't drop one or more of the requested users
+revoke all privileges, grant from drop_user1@localhost, drop_user2@localhost,
+drop_user3@localhost, drop_user4@localhost;
+drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
+drop_user4@localhost;
+drop table t1;
diff --git a/mysql-test/r/grant_cache.result b/mysql-test/r/grant_cache.result
index 3892765f587..0ffc48ad879 100644
--- a/mysql-test/r/grant_cache.result
+++ b/mysql-test/r/grant_cache.result
@@ -84,7 +84,7 @@ a b c a
1 1 1 test.t1
2 2 2 test.t1
select * from t2;
-select command denied to user: 'mysqltest_2@localhost' for table 't2'
+ERROR 42000: select command denied to user: 'mysqltest_2@localhost' for table 't2'
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 6
@@ -98,17 +98,17 @@ select "user3";
user3
user3
select * from t1;
-select command denied to user: 'mysqltest_3@localhost' for column 'b' in table 't1'
+ERROR 42000: select command denied to user: 'mysqltest_3@localhost' for column 'b' in table 't1'
select a from t1;
a
1
2
select c from t1;
-SELECT command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1'
+ERROR 42000: SELECT command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1'
select * from t2;
-select command denied to user: 'mysqltest_3@localhost' for table 't2'
+ERROR 42000: select command denied to user: 'mysqltest_3@localhost' for table 't2'
select mysqltest.t1.c from test.t1,mysqltest.t1;
-SELECT command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1'
+ERROR 42000: SELECT command denied to user: 'mysqltest_3@localhost' for column 'c' in table 't1'
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 6
@@ -122,7 +122,7 @@ select "user4";
user4
user4
select a from t1;
-No Database Selected
+ERROR 42000: No Database Selected
select * from mysqltest.t1,test.t1;
a b c a
1 1 1 test.t1
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 9e89f2c0e5a..23f82532d06 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -1,6 +1,6 @@
drop table if exists t1,t2,t3;
SELECT 1 FROM (SELECT 1) as a GROUP BY SUM(1);
-Invalid use of group function
+ERROR HY000: Invalid use of group function
CREATE TABLE t1 (
spID int(10) unsigned,
userID int(10) unsigned,
@@ -56,7 +56,7 @@ userid MIN(t1.score+0.0)
EXPLAIN SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where; Using temporary
-1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 t1.userID 1 Using index
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.userID 1 Using index
drop table t1,t2;
CREATE TABLE t1 (
PID int(10) unsigned NOT NULL auto_increment,
@@ -79,7 +79,7 @@ KEY payDate (payDate)
);
INSERT INTO t1 VALUES (1,'1970-01-01','1997-10-17 00:00:00',2529,1,21000,11886,'check',0,'F',16200,6);
SELECT COUNT(P.URID),SUM(P.amount),P.method, MIN(PP.recdate+0) > 19980501000000 AS IsNew FROM t1 AS P JOIN t1 as PP WHERE P.URID = PP.URID GROUP BY method,IsNew;
-Can't group on 'IsNew'
+ERROR 42000: Can't group on 'IsNew'
drop table t1;
CREATE TABLE t1 (
cid mediumint(9) NOT NULL auto_increment,
diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result
index d8381ccc626..26b3c700d59 100644
--- a/mysql-test/r/handler.result
+++ b/mysql-test/r/handler.result
@@ -6,7 +6,7 @@ insert into t1 values
(20,"ggg"),(21,"hhh"),(22,"iii");
handler t1 open as t2;
handler t2 read a=(SELECT 1);
-You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1)' at line 1
+ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1)' at line 1
handler t2 read a first;
a b
14 aaa
@@ -51,7 +51,7 @@ handler t2 read a=(16);
a b
16 ccc
handler t2 read a=(19,"fff");
-Too many key parts specified. Max 1 parts allowed
+ERROR 42000: Too many key parts specified. Max 1 parts allowed
handler t2 read b=(19,"fff");
a b
19 fff
@@ -62,7 +62,7 @@ handler t2 read b=(19);
a b
19 fff
handler t1 read a last;
-Unknown table 't1' in HANDLER
+ERROR 42S02: Unknown table 't1' in HANDLER
handler t2 read a=(11);
a b
handler t2 read a>=(11);
@@ -135,16 +135,16 @@ handler t2 read next;
a b
19 fff
handler t2 read last;
-You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
+ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
handler t2 close;
handler t1 open as t2;
drop table t1;
create table t1 (a int);
insert into t1 values (17);
handler t2 read first;
-Unknown table 't2' in HANDLER
+ERROR 42S02: Unknown table 't2' in HANDLER
handler t1 open as t2;
alter table t1 type=MyISAM;
handler t2 read first;
-Unknown table 't2' in HANDLER
+ERROR 42S02: Unknown table 't2' in HANDLER
drop table t1;
diff --git a/mysql-test/r/have_mest_timezone.require b/mysql-test/r/have_mest_timezone.require
new file mode 100644
index 00000000000..2a219f39b7e
--- /dev/null
+++ b/mysql-test/r/have_mest_timezone.require
@@ -0,0 +1,2 @@
+Variable_name Value
+timezone MEST
diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result
index ab5870357f9..7d929f50801 100644
--- a/mysql-test/r/heap.result
+++ b/mysql-test/r/heap.result
@@ -86,7 +86,7 @@ x y x y
explain select * from t1,t1 as t2 where t1.x=t2.y;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL x NULL NULL NULL 6
-1 SIMPLE t2 eq_ref y y 4 t1.x 1
+1 SIMPLE t2 eq_ref y y 4 test.t1.x 1
drop table t1;
create table t1 (a int) type=heap;
insert into t1 values(1);
@@ -201,7 +201,7 @@ SELECT * FROM t1 WHERE b<=>NULL;
a b
99 NULL
INSERT INTO t1 VALUES (1,3);
-Duplicate entry '3' for key 1
+ERROR 23000: Duplicate entry '3' for key 1
DROP TABLE t1;
CREATE TABLE t1 (a int not null, primary key(a)) type=heap;
INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11);
diff --git a/mysql-test/r/heap_btree.result b/mysql-test/r/heap_btree.result
index 7f6c9f8e591..6ae00c89a3a 100644
--- a/mysql-test/r/heap_btree.result
+++ b/mysql-test/r/heap_btree.result
@@ -89,7 +89,7 @@ x y x y
explain select * from t1,t1 as t2 where t1.x=t2.y;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL x NULL NULL NULL 6
-1 SIMPLE t2 eq_ref y y 4 t1.x 1
+1 SIMPLE t2 eq_ref y y 4 test.t1.x 1
drop table t1;
create table t1 (a int) type=heap;
insert into t1 values(1);
@@ -217,7 +217,7 @@ SELECT * FROM t1 WHERE b<=>NULL;
a b
99 NULL
INSERT INTO t1 VALUES (1,3);
-Duplicate entry '3' for key 1
+ERROR 23000: Duplicate entry '3' for key 1
DROP TABLE t1;
CREATE TABLE t1 (a int, b int, c int, key using BTREE (a, b, c)) type=heap;
INSERT INTO t1 VALUES (1, NULL, NULL), (1, 1, NULL), (1, NULL, 1);
diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result
index 9554990aa34..72278c5da67 100644
--- a/mysql-test/r/heap_hash.result
+++ b/mysql-test/r/heap_hash.result
@@ -86,7 +86,7 @@ x y x y
explain select * from t1,t1 as t2 where t1.x=t2.y;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL x NULL NULL NULL 6
-1 SIMPLE t2 eq_ref y y 4 t1.x 1
+1 SIMPLE t2 eq_ref y y 4 test.t1.x 1
drop table t1;
create table t1 (a int) type=heap;
insert into t1 values(1);
@@ -201,7 +201,7 @@ SELECT * FROM t1 WHERE b<=>NULL;
a b
99 NULL
INSERT INTO t1 VALUES (1,3);
-Duplicate entry '3' for key 1
+ERROR 23000: Duplicate entry '3' for key 1
DROP TABLE t1;
CREATE TABLE t1 (a int not null, primary key using HASH (a)) type=heap;
INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11);
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 71dceddab29..4fb6efe6a14 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -224,7 +224,7 @@ n after commit
commit;
insert into t1 values (5);
insert into t1 values (4);
-Duplicate entry '4' for key 1
+ERROR 23000: Duplicate entry '4' for key 1
commit;
select n, "after commit" from t1;
n after commit
@@ -233,7 +233,7 @@ n after commit
set autocommit=1;
insert into t1 values (6);
insert into t1 values (4);
-Duplicate entry '4' for key 1
+ERROR 23000: Duplicate entry '4' for key 1
select n from t1;
n
4
@@ -263,7 +263,7 @@ drop table t1;
CREATE TABLE t1 (id char(8) not null primary key, val int not null) type=innodb;
insert into t1 values ('pippo', 12);
insert into t1 values ('pippo', 12);
-Duplicate entry 'pippo' for key 1
+ERROR 23000: Duplicate entry 'pippo' for key 1
delete from t1;
delete from t1 where id = 'pippo';
select * from t1;
@@ -427,9 +427,9 @@ UNIQUE ggid (ggid)
insert into t1 (ggid,passwd) values ('test1','xxx');
insert into t1 (ggid,passwd) values ('test2','yyy');
insert into t1 (ggid,passwd) values ('test2','this will fail');
-Duplicate entry 'test2' for key 2
+ERROR 23000: Duplicate entry 'test2' for key 2
insert into t1 (ggid,id) values ('this will fail',1);
-Duplicate entry '1' for key 1
+ERROR 23000: Duplicate entry '1' for key 1
select * from t1 where ggid='test1';
id ggid email passwd
1 test1 xxx
@@ -442,7 +442,7 @@ id ggid email passwd
replace into t1 (ggid,id) values ('this will work',1);
replace into t1 (ggid,passwd) values ('test2','this will work');
update t1 set id=100,ggid='test2' where id=1;
-Duplicate entry 'test2' for key 2
+ERROR 23000: Duplicate entry 'test2' for key 2
select * from t1;
id ggid email passwd
1 this will work
@@ -753,7 +753,7 @@ create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(3
insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
LOCK TABLES t1 WRITE;
insert into t1 values (99,1,2,'D'),(1,1,2,'D');
-Duplicate entry '1-1' for key 1
+ERROR 23000: Duplicate entry '1-1' for key 1
select id from t1;
id
0
@@ -771,7 +771,7 @@ insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJ
LOCK TABLES t1 WRITE;
begin;
insert into t1 values (99,1,2,'D'),(1,1,2,'D');
-Duplicate entry '1-1' for key 1
+ERROR 23000: Duplicate entry '1-1' for key 1
select id from t1;
id
0
@@ -788,7 +788,7 @@ id id3
UNLOCK TABLES;
DROP TABLE t1;
create table t1 (a char(20), unique (a(5))) type=innodb;
-Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the store engine doesn't support unique sub keys
+ERROR HY000: Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the store engine doesn't support unique sub keys
create table t1 (a char(20), index (a(5))) type=innodb;
show create table t1;
Table Create Table
@@ -851,7 +851,7 @@ set autocommit=0;
create table t1 (a int not null) type= innodb;
insert into t1 values(1),(2);
truncate table t1;
-Can't execute the given command because you have active locked tables or an active transaction
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
commit;
truncate table t1;
select * from t1;
diff --git a/mysql-test/r/innodb_handler.result b/mysql-test/r/innodb_handler.result
index 38c39e2936f..1fadc3a61de 100644
--- a/mysql-test/r/innodb_handler.result
+++ b/mysql-test/r/innodb_handler.result
@@ -49,7 +49,7 @@ handler t2 read a=(16);
a b
16 ccc
handler t2 read a=(19,"fff");
-Too many key parts specified. Max 1 parts allowed
+ERROR 42000: Too many key parts specified. Max 1 parts allowed
handler t2 read b=(19,"fff");
a b
19 fff
@@ -60,7 +60,7 @@ handler t2 read b=(19);
a b
19 fff
handler t1 read a last;
-Unknown table 't1' in HANDLER
+ERROR 42S02: Unknown table 't1' in HANDLER
handler t2 read a=(11);
a b
handler t2 read a>=(11);
@@ -130,7 +130,7 @@ handler t2 read next;
a b
18 eee
handler t2 read last;
-You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
+ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
handler t2 close;
handler t1 open as t2;
handler t2 read first;
@@ -138,7 +138,7 @@ a b
17 ddd
alter table t1 type=innodb;
handler t2 read first;
-Unknown table 't2' in HANDLER
+ERROR 42S02: Unknown table 't2' in HANDLER
drop table t1;
CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY (no1,no2)) TYPE=InnoDB;
INSERT INTO t1 VALUES (1,274),(1,275),(2,6),(2,8),(4,1),(4,2);
diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result
index 9a65eaee573..04c3bc9027d 100644
--- a/mysql-test/r/insert_select.result
+++ b/mysql-test/r/insert_select.result
@@ -4,7 +4,7 @@ insert into t1 (bandID,payoutID) VALUES (1,6),(2,6),(3,4),(4,9),(5,10),(6,1),(7,
create table t2 (payoutID SMALLINT UNSIGNED NOT NULL PRIMARY KEY);
insert into t2 (payoutID) SELECT DISTINCT payoutID FROM t1;
insert into t2 (payoutID) SELECT payoutID+10 FROM t1;
-Duplicate entry '16' for key 1
+ERROR 23000: Duplicate entry '16' for key 1
insert ignore into t2 (payoutID) SELECT payoutID+10 FROM t1;
select * from t2;
payoutID
@@ -65,3 +65,14 @@ INSERT INTO t1 (numeropost,icone,contenu,pseudo,date,signature,ip)
SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM t2
WHERE numeropost=9 ORDER BY numreponse ASC;
DROP TABLE IF EXISTS t1,t2;
+create table t1(a int, unique(a));
+insert into t1 values(2);
+create table t2(a int);
+insert into t2 values(1),(2);
+reset master;
+insert into t1 select * from t2;
+ERROR 23000: Duplicate entry '2' for key 1
+show binlog events;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.000001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
+drop table t1, t2;
diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result
index 068f7c68286..4ef25781331 100644
--- a/mysql-test/r/insert_update.result
+++ b/mysql-test/r/insert_update.result
@@ -26,7 +26,7 @@ a b c
3 4 1020
5 6 130
INSERT t1 VALUES (1,9,70) ON DUPLICATE KEY UPDATE c=c+100000, b=4;
-Duplicate entry '4' for key 2
+ERROR 23000: Duplicate entry '4' for key 2
SELECT * FROM t1;
a b c
1 2 10010
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index 4bc045aa2f7..05dac389ada 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -128,7 +128,7 @@ a
1
2
select t1.a from t1 as t1 left join t1 as t2 using (a) left join t1 as t3 using (a) left join t1 as t4 using (a) left join t1 as t5 using (a) left join t1 as t6 using (a) left join t1 as t7 using (a) left join t1 as t8 using (a) left join t1 as t9 using (a) left join t1 as t10 using (a) left join t1 as t11 using (a) left join t1 as t12 using (a) left join t1 as t13 using (a) left join t1 as t14 using (a) left join t1 as t15 using (a) left join t1 as t16 using (a) left join t1 as t17 using (a) left join t1 as t18 using (a) left join t1 as t19 using (a) left join t1 as t20 using (a) left join t1 as t21 using (a) left join t1 as t22 using (a) left join t1 as t23 using (a) left join t1 as t24 using (a) left join t1 as t25 using (a) left join t1 as t26 using (a) left join t1 as t27 using (a) left join t1 as t28 using (a) left join t1 as t29 using (a) left join t1 as t30 using (a) left join t1 as t31 using (a) left join t1 as t32 using (a) left join t1 as t33 using (a) left join t1 as t34 using (a) left join t1 as t35 using (a) left join t1 as t36 using (a) left join t1 as t37 using (a) left join t1 as t38 using (a) left join t1 as t39 using (a) left join t1 as t40 using (a) left join t1 as t41 using (a) left join t1 as t42 using (a) left join t1 as t43 using (a) left join t1 as t44 using (a) left join t1 as t45 using (a) left join t1 as t46 using (a) left join t1 as t47 using (a) left join t1 as t48 using (a) left join t1 as t49 using (a) left join t1 as t50 using (a) left join t1 as t51 using (a) left join t1 as t52 using (a) left join t1 as t53 using (a) left join t1 as t54 using (a) left join t1 as t55 using (a) left join t1 as t56 using (a) left join t1 as t57 using (a) left join t1 as t58 using (a) left join t1 as t59 using (a) left join t1 as t60 using (a) left join t1 as t61 using (a) left join t1 as t62 using (a) left join t1 as t63 using (a) left join t1 as t64 using (a) left join t1 as t65 using (a);
-Too many tables. MySQL can only use XX tables in a join
+ERROR HY000: Too many tables. MySQL can only use XX tables in a join
drop table t1;
CREATE TABLE t1 (
a int(11) NOT NULL,
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index 123de82fe09..9e494fc88c2 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -95,7 +95,7 @@ id select_type table type possible_keys key key_len ref rows Extra
explain select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 7
-1 SIMPLE t2 eq_ref PRIMARY PRIMARY 8 t1.a 1 Using where
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 8 test.t1.a 1 Using where
select t1.*,t2.*,t3.a from t1 left join t2 on (t1.a=t2.a) left join t1 as t3 on (t2.a=t3.a);
grp a c id a c d a
1 1 a 1 1 a 1 1
@@ -106,11 +106,11 @@ grp a c id a c d a
3 6 D 3 6 C 6 6
NULL NULL NULL NULL NULL NULL NULL
explain select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a);
-Cross dependency found in OUTER JOIN. Examine your ON conditions
+ERROR 42000: Cross dependency found in OUTER JOIN. Examine your ON conditions
select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a);
-Cross dependency found in OUTER JOIN. Examine your ON conditions
+ERROR 42000: Cross dependency found in OUTER JOIN. Examine your ON conditions
select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t2.a=t3.a);
-Cross dependency found in OUTER JOIN. Examine your ON conditions
+ERROR 42000: Cross dependency found in OUTER JOIN. Examine your ON conditions
select t1.*,t2.* from t1 inner join t2 using (a);
grp a c id a c d
1 1 a 1 1 a 1
@@ -169,7 +169,7 @@ usr_id uniq_id increment usr2_id c_amount max
3 4 84676 NULL NULL NULL
INSERT INTO t2 VALUES (2,3,3000,6000,0,0,746584,837484,'yes');
INSERT INTO t2 VALUES (2,3,3000,6000,0,0,746584,837484,'yes');
-Duplicate entry '2-3' for key 1
+ERROR 23000: Duplicate entry '2-3' for key 1
INSERT INTO t2 VALUES (7,3,1000,2000,0,0,746294,937484,'yes');
SELECT t1.usr_id,t1.uniq_id,t1.increment,t2.usr2_id,t2.c_amount,t2.max FROM t1 LEFT JOIN t2 ON t2.id = t1.uniq_id WHERE t1.uniq_id = 4 ORDER BY t2.c_amount;
usr_id uniq_id increment usr2_id c_amount max
@@ -406,7 +406,7 @@ insert into t3 values (1);
insert into t4 values (1,1);
insert into t5 values (1,1);
explain select * from t3 left join t4 on t4.seq_1_id = t2.t2_id left join t1 on t1.t1_id = t4.seq_0_id left join t5 on t5.seq_0_id = t1.t1_id left join t2 on t2.t2_id = t5.seq_1_id where t3.t3_id = 23;
-Cross dependency found in OUTER JOIN. Examine your ON conditions
+ERROR 42000: Cross dependency found in OUTER JOIN. Examine your ON conditions
drop table t1,t2,t3,t4,t5;
create table t1 (n int, m int, o int, key(n));
create table t2 (n int not null, m int, o int, primary key(n));
diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result
index 5060fbff5e8..e0b2b84ac16 100644
--- a/mysql-test/r/key.result
+++ b/mysql-test/r/key.result
@@ -127,7 +127,7 @@ primary key (SEQNO, MOTYPEID, MOINSTANCEID, ATTRID, VALUE )
INSERT INTO t1 VALUES (1, 1, 1, 1, 'a');
INSERT INTO t1 VALUES (1, 1, 1, 1, 'b');
INSERT INTO t1 VALUES (1, 1, 1, 1, 'a');
-Duplicate entry '1-1-1-1-a' for key 1
+ERROR 23000: Duplicate entry '1-1-1-1-a' for key 1
drop table t1;
CREATE TABLE t1 (
a tinytext NOT NULL,
diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result
index 7b4802136f3..3cd62d8b678 100644
--- a/mysql-test/r/loaddata.result
+++ b/mysql-test/r/loaddata.result
@@ -15,4 +15,16 @@ a b c d
0000-00-00 0000-00-00 0000-00-00 0000-00-00
2003-03-03 2003-03-03 2003-03-03 NULL
2003-03-03 2003-03-03 2003-03-03 NULL
+truncate table t1;
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d);
+Warnings:
+Warning 1263 Data truncated for column 'c' at row 1
+Warning 1263 Data truncated for column 'd' at row 1
+Warning 1263 Data truncated for column 'b' at row 2
+Warning 1263 Data truncated for column 'd' at row 2
+SELECT * from t1;
+a b c d
+NULL NULL 0000-00-00 0000-00-00
+NULL 0000-00-00 0000-00-00 0000-00-00
+NULL 2003-03-03 2003-03-03 NULL
drop table t1;
diff --git a/mysql-test/r/lock.result b/mysql-test/r/lock.result
index ad5251b9110..68feb9c44d7 100644
--- a/mysql-test/r/lock.result
+++ b/mysql-test/r/lock.result
@@ -8,9 +8,9 @@ NULL 1
update t1 set id=-1 where id=1;
LOCK TABLE t1 READ;
update t1 set id=1 where id=1;
-Table 't1' was locked with a READ lock and can't be updated
+ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
create table t2 SELECT * from t1;
-Table 't2' was not locked with LOCK TABLES
+ERROR HY000: Table 't2' was not locked with LOCK TABLES
create temporary table t2 SELECT * from t1;
drop table if exists t2;
unlock tables;
diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result
index b808fca0acf..a0efce727d3 100644
--- a/mysql-test/r/lock_multi.result
+++ b/mysql-test/r/lock_multi.result
@@ -22,5 +22,5 @@ create table t2 (a int);
lock table t1 write, t2 write;
insert t1 select * from t2;
drop table t2;
-Table 'test.t2' doesn't exist
+ERROR 42S02: Table 'test.t2' doesn't exist
drop table t1;
diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result
index 1caaf317c96..af4e2300088 100644
--- a/mysql-test/r/lowercase_table.result
+++ b/mysql-test/r/lowercase_table.result
@@ -13,3 +13,17 @@ show tables like 't_';
Tables_in_test (t_)
t3
drop table t3;
+create table t1 (a int);
+select count(*) from T1;
+count(*)
+0
+select count(*) from t1;
+count(*)
+0
+select count(T1.a) from t1;
+count(T1.a)
+0
+select count(bags.a) from t1 as Bags;
+count(bags.a)
+0
+drop table t1;
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index b28607218d1..323931ae3eb 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -177,9 +177,9 @@ t3 CREATE TABLE `t3` (
) TYPE=MRG_MyISAM CHARSET=latin1 UNION=(t1,t2)
create table t4 (a int not null, b char(10), key(a)) type=MERGE UNION=(t1,t2);
select * from t4;
-Can't open file: 't4.MRG'. (errno: 143)
+ERROR HY000: Can't open file: 't4.MRG'. (errno: 143)
create table t5 (a int not null, b char(10), key(a)) type=MERGE UNION=(test.t1,test_2.t2);
-Incorrect table definition; All MERGE tables must be in the same database
+ERROR HY000: Incorrect table definition; All MERGE tables must be in the same database
drop table if exists t5,t4,t3,t1,t2;
Warnings:
Note 1051 Unknown table 't5'
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index 2aa7db1599e..15d04422f9d 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -147,11 +147,11 @@ insert into t1 values(1,1);
insert into t2 values(1,10),(2,20);
LOCK TABLES t1 write, t2 read;
DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n;
-Table 't2' was locked with a READ lock and can't be updated
+ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
-Table 't2' was locked with a READ lock and can't be updated
+ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
-Table 't2' was locked with a READ lock and can't be updated
+ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
unlock tables;
LOCK TABLES t1 write, t2 write;
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
@@ -172,7 +172,7 @@ create table t2 (n int(10), d int(10));
insert into t1 values(1,1);
insert into t2 values(1,10),(2,20);
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
-You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
+ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
set sql_safe_updates=0;
drop table t1,t2;
set timestamp=1038401397;
@@ -190,7 +190,7 @@ n d unix_timestamp(t)
1 10 1038401397
2 20 1038401397
UPDATE t1,t2 SET 1=2 WHERE t1.n=t2.n;
-You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '1=2 WHERE t1.n=t2.n' at line 1
+ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '1=2 WHERE t1.n=t2.n' at line 1
drop table t1,t2;
set timestamp=0;
set sql_safe_updates=0;
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index 5cfd1afd867..fd9ff2c90cf 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -339,10 +339,10 @@ Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), KEY t1 (a, b, c));
-Specified key was too long. Max key length is 500
+ERROR 42000: Specified key was too long. Max key length is 500
CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255));
ALTER TABLE t1 ADD INDEX t1 (a, b, c);
-Specified key was too long. Max key length is 500
+ERROR 42000: Specified key was too long. Max key length is 500
DROP TABLE t1;
CREATE TABLE t1 (a int not null, b int, c int, key(b), key(c), key(a,b), key(c,a));
INSERT into t1 values (0, null, 0), (0, null, 1), (0, null, 2), (0, null,3), (1,1,4);
@@ -370,11 +370,11 @@ id select_type table type possible_keys key key_len ref rows Extra
explain select * from t1 force index(a),t2 force index(a) where t1.a=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL a NULL NULL NULL 2
-1 SIMPLE t1 ref a a 4 t2.a 3
+1 SIMPLE t1 ref a a 4 test.t2.a 3
explain select * from t1,t2 where t1.b=t2.b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL b NULL NULL NULL 2
-1 SIMPLE t1 ref b b 5 t2.b 1 Using where
+1 SIMPLE t1 ref b b 5 test.t2.b 1 Using where
explain select * from t1,t2 force index(c) where t1.a=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a NULL NULL NULL 5
@@ -393,7 +393,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
drop table t1,t2;
CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) TYPE=MyISAM;
-This version of MySQL doesn't yet support 'RTREE INDEX'
+ERROR 42000: This version of MySQL doesn't yet support 'RTREE INDEX'
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index d6dfb4621ab..fd621d06c2b 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -82,33 +82,33 @@ UPDATE t1 SET d=NULL;
Warnings:
Warning 1261 Data truncated, NULL supplied to NOT NULL column 'd' at row 1
INSERT INTO t1 (a) values (null);
-Column 'a' cannot be null
+ERROR 23000: Column 'a' cannot be null
INSERT INTO t1 (a) values (1/null);
-Column 'a' cannot be null
+ERROR 23000: Column 'a' cannot be null
INSERT INTO t1 (a) values (null),(null);
Warnings:
Warning 1261 Data truncated, NULL supplied to NOT NULL column 'a' at row 1
Warning 1261 Data truncated, NULL supplied to NOT NULL column 'a' at row 2
INSERT INTO t1 (b) values (null);
-Column 'b' cannot be null
+ERROR 23000: Column 'b' cannot be null
INSERT INTO t1 (b) values (1/null);
-Column 'b' cannot be null
+ERROR 23000: Column 'b' cannot be null
INSERT INTO t1 (b) values (null),(null);
Warnings:
Warning 1261 Data truncated, NULL supplied to NOT NULL column 'b' at row 1
Warning 1261 Data truncated, NULL supplied to NOT NULL column 'b' at row 2
INSERT INTO t1 (c) values (null);
-Column 'c' cannot be null
+ERROR 23000: Column 'c' cannot be null
INSERT INTO t1 (c) values (1/null);
-Column 'c' cannot be null
+ERROR 23000: Column 'c' cannot be null
INSERT INTO t1 (c) values (null),(null);
Warnings:
Warning 1261 Data truncated, NULL supplied to NOT NULL column 'c' at row 1
Warning 1261 Data truncated, NULL supplied to NOT NULL column 'c' at row 2
INSERT INTO t1 (d) values (null);
-Column 'd' cannot be null
+ERROR 23000: Column 'd' cannot be null
INSERT INTO t1 (d) values (1/null);
-Column 'd' cannot be null
+ERROR 23000: Column 'd' cannot be null
INSERT INTO t1 (d) values (null),(null);
Warnings:
Warning 1261 Data truncated, NULL supplied to NOT NULL column 'd' at row 1
diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result
index 428d1052d19..0b7a98e3fb3 100644
--- a/mysql-test/r/olap.result
+++ b/mysql-test/r/olap.result
@@ -1,27 +1,256 @@
-drop table if exists t1;
-create table t1 ( product varchar(32), country varchar(32), year int, profit int);
-insert into t1 values ( 'Computer', 'India',2000, 1200),
-( 'TV', 'United States', 1999, 150),
-( 'Calculator', 'United States', 1999,50),
-( 'Computer', 'United States', 1999,1500),
-( 'Computer', 'United States', 2000,1500),
-( 'TV', 'United States', 2000, 150),
-( 'TV', 'India', 2000, 100),
-( 'TV', 'India', 2000, 100),
-( 'Calculator', 'United States', 2000,75),
-( 'Calculator', 'India', 2000,75),
-( 'TV', 'India', 1999, 100),
-( 'Computer', 'India', 1999,1200),
-( 'Computer', 'United States', 2000,1500),
-( 'Calculator', 'United States', 2000,75);
-select product, country , year, sum(profit) from t1 group by product, country, year with cube;
-This version of MySQL doesn't yet support 'CUBE'
-explain select product, country , year, sum(profit) from t1 group by product, country, year with cube;
-This version of MySQL doesn't yet support 'CUBE'
-select product, country , year, sum(profit) from t1 group by product, country, year with rollup;
-This version of MySQL doesn't yet support 'ROLLUP'
-explain select product, country , year, sum(profit) from t1 group by product, country, year with rollup;
-This version of MySQL doesn't yet support 'ROLLUP'
-select product, country , year, sum(profit) from t1 group by product, country, year with cube union all select product, country , year, sum(profit) from t1 group by product, country, year with rollup;
-This version of MySQL doesn't yet support 'CUBE'
-drop table t1;
+drop table if exists t1,t2;
+create table t1 (product varchar(32), country_id int not null, year int, profit int);
+insert into t1 values ( 'Computer', 2,2000, 1200),
+( 'TV', 1, 1999, 150),
+( 'Calculator', 1, 1999,50),
+( 'Computer', 1, 1999,1500),
+( 'Computer', 1, 2000,1500),
+( 'TV', 1, 2000, 150),
+( 'TV', 2, 2000, 100),
+( 'TV', 2, 2000, 100),
+( 'Calculator', 1, 2000,75),
+( 'Calculator', 2, 2000,75),
+( 'TV', 1, 1999, 100),
+( 'Computer', 1, 1999,1200),
+( 'Computer', 2, 2000,1500),
+( 'Calculator', 2, 2000,75),
+( 'Phone', 3, 2003,10)
+;
+create table t2 (country_id int primary key, country char(20) not null);
+insert into t2 values (1, 'USA'),(2,'India'), (3,'Finland');
+select product, sum(profit) from t1 group by product;
+product sum(profit)
+Calculator 275
+Computer 6900
+Phone 10
+TV 600
+select product, sum(profit) from t1 group by product with rollup;
+product sum(profit)
+Calculator 275
+Computer 6900
+Phone 10
+TV 600
+NULL 7785
+select product, sum(profit) from t1 group by 1 with rollup;
+product sum(profit)
+Calculator 275
+Computer 6900
+Phone 10
+TV 600
+NULL 7785
+select product, sum(profit),avg(profit) from t1 group by product with rollup;
+product sum(profit) avg(profit)
+Calculator 275 68.7500
+Computer 6900 1380.0000
+Phone 10 10.0000
+TV 600 120.0000
+NULL 7785 519.0000
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year;
+product country_id year sum(profit)
+Calculator 1 1999 50
+Calculator 1 2000 75
+Calculator 2 2000 150
+Computer 1 1999 2700
+Computer 1 2000 1500
+Computer 2 2000 2700
+Phone 3 2003 10
+TV 1 1999 250
+TV 1 2000 150
+TV 2 2000 200
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup;
+product country_id year sum(profit)
+Calculator 1 1999 50
+Calculator 1 2000 75
+Calculator 1 NULL 125
+Calculator 2 2000 150
+Calculator 2 NULL 150
+Calculator NULL NULL 275
+Computer 1 1999 2700
+Computer 1 2000 1500
+Computer 1 NULL 4200
+Computer 2 2000 2700
+Computer 2 NULL 2700
+Computer NULL NULL 6900
+Phone 3 2003 10
+Phone 3 NULL 10
+Phone NULL NULL 10
+TV 1 1999 250
+TV 1 2000 150
+TV 1 NULL 400
+TV 2 2000 200
+TV 2 NULL 200
+TV NULL NULL 600
+NULL NULL NULL 7785
+explain select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 15 Using temporary; Using filesort
+select product, country_id , sum(profit) from t1 group by product desc, country_id with rollup;
+product country_id sum(profit)
+TV 1 400
+TV 2 200
+TV NULL 600
+Phone 3 10
+Phone NULL 10
+Computer 1 4200
+Computer 2 2700
+Computer NULL 6900
+Calculator 1 125
+Calculator 2 150
+Calculator NULL 275
+NULL NULL 7785
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup limit 5;
+product country_id year sum(profit)
+Calculator 1 1999 50
+Calculator 1 2000 75
+Calculator 1 NULL 125
+Calculator 2 2000 150
+Calculator 2 NULL 150
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup limit 3,3;
+product country_id year sum(profit)
+Calculator 2 2000 150
+Calculator 2 NULL 150
+Calculator NULL NULL 275
+select product, country_id, count(*), count(distinct year) from t1 group by product, country_id;
+product country_id count(*) count(distinct year)
+Calculator 1 2 2
+Calculator 2 2 1
+Computer 1 3 2
+Computer 2 2 1
+Phone 3 1 1
+TV 1 3 2
+TV 2 2 1
+select product, country_id, count(*), count(distinct year) from t1 group by product, country_id with rollup;
+product country_id count(*) count(distinct year)
+Calculator 1 2 2
+Calculator 2 2 1
+Calculator NULL 4 2
+Computer 1 3 2
+Computer 2 2 1
+Computer NULL 5 2
+Phone 3 1 1
+Phone NULL 1 1
+TV 1 3 2
+TV 2 2 1
+TV NULL 5 2
+NULL NULL 15 3
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup having country_id = 1;
+product country_id year sum(profit)
+Calculator 1 1999 50
+Calculator 1 2000 75
+Calculator 1 NULL 125
+Computer 1 1999 2700
+Computer 1 2000 1500
+Computer 1 NULL 4200
+TV 1 1999 250
+TV 1 2000 150
+TV 1 NULL 400
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup having sum(profit) > 200;
+product country_id year sum(profit)
+Calculator NULL NULL 275
+Computer 1 1999 2700
+Computer 1 2000 1500
+Computer 1 NULL 4200
+Computer 2 2000 2700
+Computer 2 NULL 2700
+Computer NULL NULL 6900
+TV 1 1999 250
+TV 1 NULL 400
+TV NULL NULL 600
+NULL NULL NULL 7785
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup having sum(profit) > 7000;
+product country_id year sum(profit)
+NULL NULL NULL 7785
+select concat(product,':',country_id) as 'prod', concat(":",year,":") as 'year',1+1, sum(profit)/count(*) from t1 group by 1,2 with rollup;
+prod year 1+1 sum(profit)/count(*)
+Calculator:1 :1999: 2 50.00
+Calculator:1 :2000: 2 75.00
+Calculator:1 NULL 2 62.50
+Calculator:2 :2000: 2 75.00
+Calculator:2 NULL 2 75.00
+Computer:1 :1999: 2 1350.00
+Computer:1 :2000: 2 1500.00
+Computer:1 NULL 2 1400.00
+Computer:2 :2000: 2 1350.00
+Computer:2 NULL 2 1350.00
+Phone:3 :2003: 2 10.00
+Phone:3 NULL 2 10.00
+TV:1 :1999: 2 125.00
+TV:1 :2000: 2 150.00
+TV:1 NULL 2 133.33
+TV:2 :2000: 2 100.00
+TV:2 NULL 2 100.00
+NULL NULL 2 519.00
+select product, sum(profit)/count(*) from t1 group by product with rollup;
+product sum(profit)/count(*)
+Calculator 68.75
+Computer 1380.00
+Phone 10.00
+TV 120.00
+NULL 519.00
+select left(product,4) as prod, sum(profit)/count(*) from t1 group by prod with rollup;
+prod sum(profit)/count(*)
+Calc 68.75
+Comp 1380.00
+Phon 10.00
+TV 120.00
+NULL 519.00
+select concat(product,':',country_id), 1+1, sum(profit)/count(*) from t1 group by concat(product,':',country_id) with rollup;
+concat(product,':',country_id) 1+1 sum(profit)/count(*)
+Calculator:1 2 62.50
+Calculator:2 2 75.00
+Computer:1 2 1400.00
+Computer:2 2 1350.00
+Phone:3 2 10.00
+TV:1 2 133.33
+TV:2 2 100.00
+NULL 2 519.00
+select product, country , year, sum(profit) from t1,t2 where t1.country_id=t2.country_id group by product, country, year with rollup;
+product country year sum(profit)
+Calculator India 2000 150
+Calculator India NULL 150
+Calculator USA 1999 50
+Calculator USA 2000 75
+Calculator USA NULL 125
+Calculator NULL NULL 275
+Computer India 2000 2700
+Computer India NULL 2700
+Computer USA 1999 2700
+Computer USA 2000 1500
+Computer USA NULL 4200
+Computer NULL NULL 6900
+Phone Finland 2003 10
+Phone Finland NULL 10
+Phone NULL NULL 10
+TV India 2000 200
+TV India NULL 200
+TV USA 1999 250
+TV USA 2000 150
+TV USA NULL 400
+TV NULL NULL 600
+NULL NULL NULL 7785
+select product, `sum` from (select product, sum(profit) as 'sum' from t1 group by product with rollup) as tmp where product is null;
+product sum
+NULL 7785
+select product from t1 where exists (select product, country_id , sum(profit) from t1 as t2 where t1.product=t2.product group by product, country_id with rollup having sum(profit) > 6000);
+product
+Computer
+Computer
+Computer
+Computer
+Computer
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year having country_id is NULL;
+product country_id year sum(profit)
+select concat(':',product,':'), sum(profit),avg(profit) from t1 group by product with rollup;
+concat(':',product,':') sum(profit) avg(profit)
+:Calculator: 275 68.7500
+:Computer: 6900 1380.0000
+:Phone: 10 10.0000
+:TV: 600 120.0000
+:TV: 7785 519.0000
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube;
+ERROR 42000: This version of MySQL doesn't yet support 'CUBE'
+explain select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube;
+ERROR 42000: This version of MySQL doesn't yet support 'CUBE'
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube union all select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup;
+ERROR 42000: This version of MySQL doesn't yet support 'CUBE'
+drop table t1,t2;
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index 3524b38e659..1e940351a4a 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -466,25 +466,25 @@ gid sid uid
EXPLAIN select t1.gid, t2.sid, t3.uid from t3, t2, t1 where t2.gid = t1.gid and t2.uid = t3.uid order by t1.gid, t3.uid;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index
-1 SIMPLE t2 eq_ref PRIMARY,uid PRIMARY 4 t1.gid 1
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 Using where; Using index
+1 SIMPLE t2 eq_ref PRIMARY,uid PRIMARY 4 test.t1.gid 1
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t2.uid 1 Using where; Using index
EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.gid = t3.uid order by t1.gid,t3.skr;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t1.gid 1 Using where
EXPLAIN SELECT t1.gid, t2.sid, t3.uid from t2, t1, t3 where t2.gid = t1.gid and t2.uid = t3.uid order by t3.uid, t1.gid;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index; Using temporary; Using filesort
-1 SIMPLE t2 eq_ref PRIMARY,uid PRIMARY 4 t1.gid 1
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 Using where; Using index
+1 SIMPLE t2 eq_ref PRIMARY,uid PRIMARY 4 test.t1.gid 1
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t2.uid 1 Using where; Using index
EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.gid = t3.uid order by t3.skr,t1.gid;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index; Using temporary; Using filesort
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t1.gid 1 Using where
EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.skr = t3.uid order by t1.gid,t3.skr;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.skr 1 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t1.skr 1 Using where
drop table t1,t2,t3;
CREATE TABLE t1 (
`titre` char(80) NOT NULL default '',
diff --git a/mysql-test/r/packet.result b/mysql-test/r/packet.result
index e994e4d63da..6e3c459b39d 100644
--- a/mysql-test/r/packet.result
+++ b/mysql-test/r/packet.result
@@ -12,7 +12,7 @@ select @@net_buffer_length, @@max_allowed_packet;
@@net_buffer_length @@max_allowed_packet
1024 80
SELECT length("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") as len;
-Got a packet bigger than 'max_allowed_packet'
+ERROR 08S01: Got a packet bigger than 'max_allowed_packet'
set global max_allowed_packet=default;
set max_allowed_packet=default;
set global net_buffer_length=default;
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 1d46d1dcf25..3b3e52d8240 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -561,22 +561,62 @@ set GLOBAL query_cache_min_res_unit=default;
show global variables like "query_cache_min_res_unit";
Variable_name Value
query_cache_min_res_unit 4096
+create table t1 (a int);
set GLOBAL query_cache_size=1000;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
-set GLOBAL query_cache_size=1100;
-set GLOBAL query_cache_size=1200;
-set GLOBAL query_cache_size=1300;
-set GLOBAL query_cache_size=1400;
-set GLOBAL query_cache_size=1500;
-set GLOBAL query_cache_size=1600;
-set GLOBAL query_cache_size=1700;
-set GLOBAL query_cache_size=1800;
-set GLOBAL query_cache_size=1900;
+select * from t1;
+a
+set GLOBAL query_cache_size=1024;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 0
+select * from t1;
+a
+set GLOBAL query_cache_size=10240;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 0
+select * from t1;
+a
+set GLOBAL query_cache_size=20480;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 0
+select * from t1;
+a
+set GLOBAL query_cache_size=40960;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 0
+select * from t1;
+a
+set GLOBAL query_cache_size=51200;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 51200
+select * from t1;
+a
+set GLOBAL query_cache_size=61440;
show global variables like "query_cache_size";
Variable_name Value
-query_cache_size 1024
+query_cache_size 61440
+select * from t1;
+a
+set GLOBAL query_cache_size=81920;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 81920
+select * from t1;
+a
+set GLOBAL query_cache_size=102400;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 102400
+select * from t1;
+a
+drop table t1;
set GLOBAL query_cache_size=1048576;
create table t1 (i int not null);
create table t2 (i int not null);
@@ -615,10 +655,10 @@ id
2
alter table t1 rename to t2;
select * from t1 where id=2;
-Table 'test.t1' doesn't exist
+ERROR 42S02: Table 'test.t1' doesn't exist
drop table t2;
select * from t1 where id=2;
-Table 'test.t1' doesn't exist
+ERROR 42S02: Table 'test.t1' doesn't exist
create table t1 (word char(20) not null);
select * from t1;
word
diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair_part1.result
index eb46622dcc1..eb46622dcc1 100644
--- a/mysql-test/r/repair.result
+++ b/mysql-test/r/repair_part1.result
diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result
index 79eb6cc7e59..94186f254c4 100644
--- a/mysql-test/r/row.result
+++ b/mysql-test/r/row.result
@@ -36,7 +36,7 @@ select (1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4)));
(1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4)))
1
select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4));
-Cardinality error (more/less than 2 columns)
+ERROR 21000: Cardinality error (more/less than 2 columns)
select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)));
row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)))
NULL
@@ -86,7 +86,7 @@ SELECT ROW('test',2,3.33)=ROW('test',2,3.33);
ROW('test',2,3.33)=ROW('test',2,3.33)
1
SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4);
-Cardinality error (more/less than 3 columns)
+ERROR 21000: Cardinality error (more/less than 3 columns)
SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33));
ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33))
1
@@ -97,7 +97,7 @@ SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL));
ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL))
NULL
SELECT ROW('test',2,ROW(3,33))=ROW('test',2,4);
-Cardinality error (more/less than 2 columns)
+ERROR 21000: Cardinality error (more/less than 2 columns)
create table t1 ( a int, b int, c int);
insert into t1 values (1,2,3), (2,3,1), (3,2,1), (1,2,NULL);
select * from t1 where ROW(1,2,3)=ROW(a,b,c);
@@ -135,14 +135,14 @@ ROW(1,2,3) IN(row(a,b,c), row(1,2,3))
1
drop table t1;
select ROW(1,1);
-Cardinality error (more/less than 1 columns)
+ERROR 21000: Cardinality error (more/less than 1 columns)
create table t1 (i int);
select 1 from t1 where ROW(1,1);
-Cardinality error (more/less than 1 columns)
+ERROR 21000: Cardinality error (more/less than 1 columns)
select count(*) from t1 order by ROW(1,1);
-Cardinality error (more/less than 1 columns)
+ERROR 21000: Cardinality error (more/less than 1 columns)
select count(*) from t1 having (1,1) order by i;
-Cardinality error (more/less than 1 columns)
+ERROR 21000: Cardinality error (more/less than 1 columns)
drop table t1;
create table t1 (a int, b int);
insert into t1 values (1, 4);
diff --git a/mysql-test/r/rpl000001.result b/mysql-test/r/rpl000001.result
index 8aa667df063..79438f8fa40 100644
--- a/mysql-test/r/rpl000001.result
+++ b/mysql-test/r/rpl000001.result
@@ -55,7 +55,7 @@ select (@id := id) - id from t2;
0
kill @id;
drop table t2;
-Server shutdown in progress
+ERROR 08S01: Server shutdown in progress
set global sql_slave_skip_counter=1;
start slave;
select count(*) from t1;
diff --git a/mysql-test/r/rpl000009.result b/mysql-test/r/rpl000009.result
index 06f34842577..dc1d8c4872e 100644
--- a/mysql-test/r/rpl000009.result
+++ b/mysql-test/r/rpl000009.result
@@ -21,7 +21,7 @@ n m
drop database mysqltest;
drop database if exists mysqltest2;
drop database mysqltest;
-Can't drop database 'mysqltest'. Database doesn't exist
+ERROR HY000: Can't drop database 'mysqltest'. Database doesn't exist
drop database mysqltest2;
set sql_log_bin = 0;
create database mysqltest2;
diff --git a/mysql-test/r/rpl_empty_master_crash.result b/mysql-test/r/rpl_empty_master_crash.result
index 8818029ab99..39ab1c2d9b4 100644
--- a/mysql-test/r/rpl_empty_master_crash.result
+++ b/mysql-test/r/rpl_empty_master_crash.result
@@ -7,6 +7,6 @@ start slave;
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
load table t1 from master;
-Error connecting to master: Master is not configured
+ERROR 08S01: Error connecting to master: Master is not configured
load table t1 from master;
-Error from master: 'Table 'test.t1' doesn't exist'
+ERROR HY000: Error from master: 'Table 'test.t1' doesn't exist'
diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result
index 82015bdf538..3d7a2a0dd75 100644
--- a/mysql-test/r/rpl_insert_id.result
+++ b/mysql-test/r/rpl_insert_id.result
@@ -22,10 +22,12 @@ drop table t1;
drop table t2;
create table t1(a int auto_increment, key(a));
create table t2(b int auto_increment, c int, key(b));
+SET FOREIGN_KEY_CHECKS=0;
insert into t1 values (10);
insert into t1 values (null),(null),(null);
insert into t2 values (5,0);
insert into t2 values (null,last_insert_id());
+SET FOREIGN_KEY_CHECKS=1;
select * from t1;
a
10
@@ -38,3 +40,31 @@ b c
6 11
drop table t1;
drop table t2;
+create table t1(a int auto_increment, key(a));
+create table t2(b int auto_increment, c int, key(b));
+insert into t1 values (10);
+insert into t1 values (null),(null),(null);
+insert into t2 values (5,0);
+insert into t2 (c) select * from t1;
+select * from t2;
+b c
+5 0
+6 10
+7 11
+8 12
+9 13
+select * from t1;
+a
+10
+11
+12
+13
+select * from t2;
+b c
+5 0
+6 10
+7 11
+8 12
+9 13
+drop table t1;
+drop table t2;
diff --git a/mysql-test/r/rpl_loaddata.result b/mysql-test/r/rpl_loaddata.result
index 5b7aab3df74..f4b003d6cc3 100644
--- a/mysql-test/r/rpl_loaddata.result
+++ b/mysql-test/r/rpl_loaddata.result
@@ -22,3 +22,9 @@ day id category name
drop table t1;
drop table t2;
drop table t3;
+create table t1(a int, b int, unique(b));
+insert into t1 values(1,10);
+load data infile '../../std_data/rpl_loaddata.dat' into table t1;
+show status like 'slave_running';
+Variable_name Value
+Slave_running OFF
diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result
index 6f438c6c34a..df2ef4e3d8a 100644
--- a/mysql-test/r/rpl_log.result
+++ b/mysql-test/r/rpl_log.result
@@ -36,6 +36,8 @@ show binlog events from 79 limit 2,1;
Log_name Pos Event_type Server_id Orig_log_pos Info
master-bin.000001 200 Query 1 200 use `test`; insert into t1 values (NULL)
flush logs;
+create table t5 (a int);
+drop table t5;
start slave;
flush logs;
stop slave;
@@ -56,9 +58,11 @@ master-bin.000001 1079 Query 1 1079 use `test`; drop table t1
master-bin.000001 1127 Rotate 1 1127 master-bin.000002;pos=4
show binlog events in 'master-bin.000002';
Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.000002 4 Query 1 4 use `test`; create table t1 (n int)
-master-bin.000002 62 Query 1 62 use `test`; insert into t1 values (1)
-master-bin.000002 122 Query 1 122 use `test`; drop table t1
+master-bin.000002 4 Query 1 4 use `test`; create table t5 (a int)
+master-bin.000002 62 Query 1 62 use `test`; drop table t5
+master-bin.000002 110 Query 1 110 use `test`; create table t1 (n int)
+master-bin.000002 168 Query 1 168 use `test`; insert into t1 values (1)
+master-bin.000002 228 Query 1 228 use `test`; drop table t1
show binary logs;
Log_name
master-bin.000001
@@ -79,14 +83,16 @@ slave-bin.000001 311 Query 1 311 use `test`; create table t1 (word char(20) not
slave-bin.000001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=581
slave-bin.000001 1065 Exec_load 1 1056 ;file_id=1
slave-bin.000001 1088 Query 1 1079 use `test`; drop table t1
-slave-bin.000001 1136 Rotate 2 1136 slave-bin.000002;pos=4
+slave-bin.000001 1136 Query 1 4 use `test`; create table t5 (a int)
+slave-bin.000001 1194 Query 1 62 use `test`; drop table t5
+slave-bin.000001 1242 Rotate 2 1242 slave-bin.000002;pos=4
show binlog events in 'slave-bin.000002' from 4;
Log_name Pos Event_type Server_id Orig_log_pos Info
-slave-bin.000002 4 Query 1 4 use `test`; create table t1 (n int)
-slave-bin.000002 62 Query 1 62 use `test`; insert into t1 values (1)
-slave-bin.000002 122 Query 1 122 use `test`; drop table t1
+slave-bin.000002 4 Query 1 110 use `test`; create table t1 (n int)
+slave-bin.000002 62 Query 1 168 use `test`; insert into t1 values (1)
+slave-bin.000002 122 Query 1 228 use `test`; drop table t1
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
-127.0.0.1 root MASTER_PORT 1 master-bin.000002 170 slave-relay-bin.000002 1469 master-bin.000002 Yes Yes 0 0 170 1473
+127.0.0.1 root MASTER_PORT 1 master-bin.000002 276 slave-relay-bin.000002 1531 master-bin.000002 Yes Yes 0 0 276 1535
show binlog events in 'slave-bin.000005' from 4;
-Error when executing command SHOW BINLOG EVENTS: Could not find target log
+ERROR HY000: Error when executing command SHOW BINLOG EVENTS: Could not find target log
diff --git a/mysql-test/r/rpl_replicate_do.result b/mysql-test/r/rpl_replicate_do.result
index 9ae292c2709..a91a0a2b819 100644
--- a/mysql-test/r/rpl_replicate_do.result
+++ b/mysql-test/r/rpl_replicate_do.result
@@ -24,5 +24,5 @@ select * from t2;
n
4
select * from t11;
-Table 'test.t11' doesn't exist
+ERROR 42S02: Table 'test.t11' doesn't exist
drop table if exists t1,t2,t11;
diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result
index c4023832921..66209d2b852 100644
--- a/mysql-test/r/rpl_rotate_logs.result
+++ b/mysql-test/r/rpl_rotate_logs.result
@@ -1,9 +1,9 @@
drop table if exists t1, t2, t3, t4;
drop table if exists t1, t2, t3, t4;
start slave;
-Could not initialize master info structure, check permisions on master.info
+ERROR HY000: Could not initialize master info structure, check permisions on master.info
start slave;
-Could not initialize master info structure, check permisions on master.info
+ERROR HY000: Could not initialize master info structure, check permisions on master.info
change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root';
Could not initialize master info
reset slave;
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 8be189752ea..fbce0e9290a 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -1341,9 +1341,9 @@ explain select fld3 from t2 use index (fld1,fld3) where fld3 = 'honeysuckle';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
explain select fld3 from t2 ignore index (fld3,not_used);
-Key column 'not_used' doesn't exist in table
+ERROR 42000: Key column 'not_used' doesn't exist in table
explain select fld3 from t2 use index (not_used);
-Key column 'not_used' doesn't exist in table
+ERROR 42000: Key column 'not_used' doesn't exist in table
select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3;
fld3
honeysuckle
@@ -1807,19 +1807,19 @@ fld3
explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by t3.t2nr,fld3;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 t2.fld1 1 Using where; Using index
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index
explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using temporary; Using filesort
-1 SIMPLE t3 ref period period 4 t1.period 4181
+1 SIMPLE t3 ref period period 4 test.t1.period 4181
explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 index period period 4 NULL 41810
-1 SIMPLE t1 ref period period 4 t3.period 4181
+1 SIMPLE t1 ref period period 4 test.t3.period 4181
explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index period period 4 NULL 41810
-1 SIMPLE t3 ref period period 4 t1.period 4181
+1 SIMPLE t3 ref period period 4 test.t1.period 4181
select period from t1;
period
9410
diff --git a/mysql-test/r/select_safe.result b/mysql-test/r/select_safe.result
index 3303f19d9c7..e73161996b8 100644
--- a/mysql-test/r/select_safe.result
+++ b/mysql-test/r/select_safe.result
@@ -20,17 +20,17 @@ select 1 from t1,t1 as t2,t1 as t3,t1 as t4;
1
1
update t1 set b="a";
-You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
+ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
update t1 set b="a" where b="test";
-You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
+ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
delete from t1;
-You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
+ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
delete from t1 where b="test";
-You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
+ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
delete from t1 where a+0=1;
-You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
+ERROR HY000: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
select 1 from t1,t1 as t2,t1 as t3,t1 as t4,t1 as t5;
-The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok
+ERROR 42000: The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok
update t1 set b="a" limit 1;
update t1 set b="a" where b="b" limit 2;
delete from t1 where b="test" limit 1;
@@ -41,7 +41,7 @@ SELECT @@MAX_JOIN_SIZE, @@SQL_BIG_SELECTS;
2 0
insert into t1 values (null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a");
SELECT * from t1;
-The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok
+ERROR 42000: The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok
SET SQL_BIG_SELECTS=1;
SELECT * from t1;
a b
@@ -51,7 +51,7 @@ a b
5 a
SET MAX_JOIN_SIZE=2;
SELECT * from t1;
-The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok
+ERROR 42000: The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok
SET MAX_JOIN_SIZE=DEFAULT;
SELECT * from t1;
a b
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index b867eae5e8d..201d1b541ae 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -26,7 +26,7 @@ t1 0 PRIMARY 1 a A 5 NULL NULL BTREE
t1 1 b 1 b A 1 NULL NULL BTREE
t1 1 b 2 c A 5 NULL NULL BTREE
insert into t1 values (5,5,5);
-Duplicate entry '5' for key 1
+ERROR 23000: Duplicate entry '5' for key 1
optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index 8ded3daf114..9b80b965d10 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -71,10 +71,10 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`a`),
UNIQUE KEY `email` (`email`)
) TYPE=HEAP ROW_FORMAT=DYNAMIC
-set @@sql_mode="postgresql,oracle,mssql,db2,sapdb";
-show variables like 'sql_mode';
-Variable_name Value
-sql_mode POSTGRESQL,ORACLE,MSSQL,DB2,SAPDB
+set sql_mode="postgresql,oracle,mssql,db2,sapdb";
+select @@sql_mode;
+@@sql_mode
+PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,POSTGRESQL,ORACLE,MSSQL,DB2,SAPDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS
show create table t1;
Table Create Table
t1 CREATE TABLE "t1" (
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 511517ebdfd..c41434336e5 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -29,14 +29,14 @@ id select_type table type possible_keys key key_len ref rows Extra
Warnings:
Note 1247 Select 2 was reduced during optimisation
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
-Reference 'a' not supported (forward reference in item list)
+ERROR 42S22: Reference 'a' not supported (forward reference in item list)
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
-Reference 'b' not supported (forward reference in item list)
+ERROR 42S22: Reference 'b' not supported (forward reference in item list)
SELECT (SELECT 1),MAX(1) FROM (SELECT 1) as a;
(SELECT 1) MAX(1)
1 1
SELECT (SELECT a) as a;
-Reference 'a' not supported (forward reference in item list)
+ERROR 42S22: Reference 'a' not supported (forward reference in item list)
EXPLAIN SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
@@ -46,17 +46,17 @@ SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
SELECT (SELECT 1), a;
-Unknown column 'a' in 'field list'
+ERROR 42S22: Unknown column 'a' in 'field list'
SELECT 1 as a FROM (SELECT 1) as b HAVING (SELECT a)=1;
a
1
SELECT 1 FROM (SELECT (SELECT a) b) c;
-Unknown column 'a' in 'field list'
+ERROR 42S22: Unknown column 'a' in 'field list'
SELECT * FROM (SELECT 1 as id) b WHERE id IN (SELECT * FROM (SELECT 1 as id) c ORDER BY id);
id
1
SELECT * FROM (SELECT 1) a WHERE 1 IN (SELECT 1,1);
-Cardinality error (more/less than 1 columns)
+ERROR 21000: Cardinality error (more/less than 1 columns)
SELECT 1 IN (SELECT 1);
1 IN (SELECT 1)
1
@@ -64,9 +64,9 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
1
1
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
-Wrong usage of PROCEDURE and subquery
+ERROR HY000: Wrong usage of PROCEDURE and subquery
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
-Incorrect parameters to procedure 'ANALYSE'
+ERROR HY000: Incorrect parameters to procedure 'ANALYSE'
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
a
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
@@ -121,19 +121,19 @@ SELECT (SELECT 1.5,'c','a') = ROW(1.5,2,'a');
(SELECT 1.5,'c','a') = ROW(1.5,2,'a')
0
SELECT (SELECT * FROM (SELECT 'test' a,'test' b) a);
-Cardinality error (more/less than 1 columns)
+ERROR 21000: Cardinality error (more/less than 1 columns)
SELECT 1 as a,(SELECT a+a) b,(SELECT b);
a b (SELECT b)
1 2 2
create table t1 (a int);
create table t2 (a int, b int);
create table t3 (a int);
-create table t4 (a int, b int);
+create table t4 (a int not null, b int not null);
insert into t1 values (2);
insert into t2 values (1,7),(2,7);
insert into t4 values (4,8),(3,8),(5,9);
select (select a from t1 where t1.a = a1) as a2, (select b from t2 where t2.b=a2) as a1;
-Reference 'a1' not supported (forward reference in item list)
+ERROR 42S22: Reference 'a1' not supported (forward reference in item list)
select (select a from t1 where t1.a=t2.a), a from t2;
(select a from t1 where t1.a=t2.a) a
NULL 1
@@ -252,15 +252,18 @@ a
7
delete from t2 where a=100;
select * from t3 where a in (select a,b from t2);
-Cardinality error (more/less than 1 columns)
+ERROR 21000: Cardinality error (more/less than 1 columns)
select * from t3 where a in (select * from t2);
-Cardinality error (more/less than 1 columns)
-insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
-select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
-from t2 where t2.b=t4.b);
+ERROR 21000: Cardinality error (more/less than 1 columns)
+insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9),(1,10);
+select b,max(a) as ma from t4 group by b having b < (select max(t2.a) from t2 where t2.b=t4.b);
b ma
-select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
-from t2 where t2.b=t4.b);
+insert into t2 values (2,10);
+select b,max(a) as ma from t4 group by b having ma < (select max(t2.a) from t2 where t2.b=t4.b);
+b ma
+10 1
+delete from t2 where a=2 and b=10;
+select b,max(a) as ma from t4 group by b having b >= (select max(t2.a) from t2 where t2.b=t4.b);
b ma
7 12
create table t5 (a int);
@@ -284,7 +287,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 1
3 DEPENDENT UNION t5 ALL NULL NULL NULL NULL 2 Using where
select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
-Subselect returns more than 1 record
+ERROR 21000: Subselect returns more than 1 record
create table t6 (patient_uq int, clinic_uq int, index i1 (clinic_uq));
create table t7( uq int primary key, name char(25));
insert into t7 values(1,"Oblastnaia bolnitsa"),(2,"Bolnitsa Krasnogo Kresta");
@@ -297,9 +300,9 @@ patient_uq clinic_uq
explain select * from t6 where exists (select * from t7 where uq = clinic_uq);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t6 ALL NULL NULL NULL NULL 4 Using where
-2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 t6.clinic_uq 1
+2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 test.t6.clinic_uq 1
select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
-Column: 'a' in field list is ambiguous
+ERROR 23000: Column: 'a' in field list is ambiguous
drop table if exists t1,t2,t3;
CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0');
INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b');
@@ -333,15 +336,15 @@ id select_type table type possible_keys key key_len ref rows Extra
3 SUBQUERY t8 const PRIMARY PRIMARY 35 1
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce');
-Cardinality error (more/less than 1 columns)
+ERROR 21000: Cardinality error (more/less than 1 columns)
SELECT pseudo FROM t8 WHERE pseudo=(SELECT * FROM t8 WHERE
pseudo='joce');
-Cardinality error (more/less than 1 columns)
+ERROR 21000: Cardinality error (more/less than 1 columns)
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
pseudo
joce
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo LIKE '%joce%');
-Subselect returns more than 1 record
+ERROR 21000: Subselect returns more than 1 record
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
CREATE TABLE `t1` (
`topic` mediumint(8) unsigned NOT NULL default '0',
@@ -371,7 +374,7 @@ SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1) UNION ALL SELECT 1;
1
1
SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION ALL SELECT 1) UNION SELECT 1;
-Subselect returns more than 1 record
+ERROR 21000: Subselect returns more than 1 record
EXPLAIN SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL topic 3 NULL 2 Using index
@@ -401,9 +404,9 @@ numeropost maxnumrep
43506 2
40143 1
SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) b;
-Unknown column 'a' in 'having clause'
+ERROR 42S22: Unknown column 'a' in 'having clause'
SELECT 1 IN (SELECT 1 FROM t2 HAVING a);
-Unknown column 'a' in 'having clause'
+ERROR 42S22: Unknown column 'a' in 'having clause'
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic);
mot topic date pseudo
joce 40143 2002-10-22 joce
@@ -458,9 +461,9 @@ UNIQUE KEY `maxnumrep` (`maxnumrep`)
) TYPE=MyISAM ROW_FORMAT=FIXED;
INSERT INTO t1 (numeropost,maxnumrep) VALUES (1,0),(2,1);
select numeropost as a FROM t1 GROUP BY (SELECT 1 FROM t1 HAVING a=1);
-Subselect returns more than 1 record
+ERROR 21000: Subselect returns more than 1 record
select numeropost as a FROM t1 ORDER BY (SELECT 1 FROM t1 HAVING a=1);
-Subselect returns more than 1 record
+ERROR 21000: Subselect returns more than 1 record
drop table t1;
create table t1 (a int);
insert into t1 values (1),(2),(3);
@@ -473,7 +476,7 @@ drop table t1;
CREATE TABLE t1 (field char(1) NOT NULL DEFAULT 'b');
INSERT INTO t1 VALUES ();
SELECT field FROM t1 WHERE 1=(SELECT 1 UNION ALL SELECT 1 FROM (SELECT 1) a HAVING field='b');
-Subselect returns more than 1 record
+ERROR 21000: Subselect returns more than 1 record
drop table t1;
CREATE TABLE `t1` (
`numeropost` mediumint(8) unsigned NOT NULL default '0',
@@ -484,14 +487,14 @@ UNIQUE KEY `numreponse` (`numreponse`),
KEY `pseudo` (`pseudo`,`numeropost`)
) TYPE=MyISAM;
SELECT (SELECT numeropost FROM t1 HAVING numreponse=a),numreponse FROM (SELECT * FROM t1) as a;
-Reference 'numreponse' not supported (forward reference in item list)
+ERROR 42S22: Reference 'numreponse' not supported (forward reference in item list)
SELECT numreponse, (SELECT numeropost FROM t1 HAVING numreponse=a) FROM (SELECT * FROM t1) as a;
-Unknown column 'a' in 'having clause'
+ERROR 42S22: Unknown column 'a' in 'having clause'
SELECT numreponse, (SELECT numeropost FROM t1 HAVING numreponse=1) FROM (SELECT * FROM t1) as a;
numreponse (SELECT numeropost FROM t1 HAVING numreponse=1)
INSERT INTO t1 (numeropost,numreponse,pseudo) VALUES (1,1,'joce'),(1,2,'joce'),(1,3,'test');
EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT 1 FROM t1 WHERE numeropost='1');
-Subselect returns more than 1 record
+ERROR 21000: Subselect returns more than 1 record
EXPLAIN SELECT MAX(numreponse) FROM t1 WHERE numeropost='1';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
@@ -516,9 +519,9 @@ a b
1 11
2 12
update t1 set b= (select b from t1);
-You can't specify target table 't1' for update in FROM clause
+ERROR HY000: You can't specify target table 't1' for update in FROM clause
update t1 set b= (select b from t2);
-Subselect returns more than 1 record
+ERROR 21000: Subselect returns more than 1 record
update t1 set b= (select b from t2 where t1.a = t2.a);
select * from t1;
a b
@@ -539,9 +542,9 @@ select * from t1 where b = (select b from t2 where t1.a = t2.a);
a b
2 12
delete from t1 where b = (select b from t1);
-You can't specify target table 't1' for update in FROM clause
+ERROR HY000: You can't specify target table 't1' for update in FROM clause
delete from t1 where b = (select b from t2);
-Subselect returns more than 1 record
+ERROR 21000: Subselect returns more than 1 record
delete from t1 where b = (select b from t2 where t1.a = t2.a);
select * from t1;
a b
@@ -565,9 +568,9 @@ a b
22 11
2 12
delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t12 where t11.a = t12.a);
-You can't specify target table 't12' for update in FROM clause
+ERROR HY000: You can't specify target table 't12' for update in FROM clause
delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2);
-Subselect returns more than 1 record
+ERROR 21000: Subselect returns more than 1 record
delete t11.*, t12.* from t11,t12 where t11.a = t12.a and t11.b = (select b from t2 where t11.a = t2.a);
select * from t11;
a b
@@ -584,9 +587,9 @@ create table t3 (a int);
insert into t2 values (1);
insert into t3 values (1),(2);
INSERT INTO t1 (x) VALUES ((SELECT x FROM t1));
-You can't specify target table 't1' for update in FROM clause
+ERROR HY000: You can't specify target table 't1' for update in FROM clause
INSERT INTO t1 (x) VALUES ((SELECT a FROM t3));
-Subselect returns more than 1 record
+ERROR 21000: Subselect returns more than 1 record
INSERT INTO t1 (x) VALUES ((SELECT a FROM t2));
select * from t1;
x
@@ -605,7 +608,7 @@ x
3
3
INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2;
-You can't specify target table 't1' for update in FROM clause
+ERROR HY000: You can't specify target table 't1' for update in FROM clause
INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2));
select * from t1;
x
@@ -623,9 +626,9 @@ insert into t3 values (1),(2);
select * from t1;
x y
replace into t1 (x, y) VALUES ((SELECT x FROM t1), (SELECT a+1 FROM t2));
-You can't specify target table 't1' for update in FROM clause
+ERROR HY000: You can't specify target table 't1' for update in FROM clause
replace into t1 (x, y) VALUES ((SELECT a FROM t3), (SELECT a+1 FROM t2));
-Subselect returns more than 1 record
+ERROR 21000: Subselect returns more than 1 record
replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+1 FROM t2));
select * from t1;
x y
@@ -652,7 +655,7 @@ x y
2 1
drop table t1, t2, t3;
SELECT * FROM (SELECT 1) b WHERE 1 IN (SELECT *);
-No tables used
+ERROR HY000: No tables used
CREATE TABLE t2 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1;
INSERT INTO t2 VALUES (1),(2);
SELECT * FROM t2 WHERE id IN (SELECT 1);
@@ -687,9 +690,9 @@ SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2);
id
2
INSERT INTO t2 VALUES ((SELECT * FROM t2));
-You can't specify target table 't2' for update in FROM clause
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
INSERT INTO t2 VALUES ((SELECT id FROM t2));
-You can't specify target table 't2' for update in FROM clause
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
SELECT * FROM t2;
id
1
@@ -697,7 +700,7 @@ id
CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1;
INSERT INTO t1 values (1),(1);
UPDATE t2 SET id=(SELECT * FROM t1);
-Subselect returns more than 1 record
+ERROR 21000: Subselect returns more than 1 record
drop table t2, t1;
create table t1 (a int);
insert into t1 values (1),(2),(3);
@@ -828,9 +831,9 @@ id select_type table type possible_keys key key_len ref rows Extra
drop table t1,t2;
create table t1 (a float);
select 10.5 IN (SELECT * from t1 LIMIT 1);
-This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
+ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
select 10.5 IN (SELECT * from t1 LIMIT 1 UNION SELECT 1.5);
-This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
+ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
drop table t1;
create table t1 (a int, b int, c varchar(10));
create table t2 (a int);
@@ -882,7 +885,7 @@ select ROW(1, 1, 'a') IN (select b,a,c from t1 where c='b' or c='a');
ROW(1, 1, 'a') IN (select b,a,c from t1 where c='b' or c='a')
1
select ROW(1, 1, 'a') IN (select b,a,c from t1 limit 2);
-This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
+ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
drop table t1;
create table t1 (a int);
insert into t1 values (1);
@@ -897,13 +900,13 @@ select @a;
1
drop table t1;
do (SELECT a from t1);
-Table 'test.t1' doesn't exist
+ERROR 42S02: Table 'test.t1' doesn't exist
set @a:=(SELECT a from t1);
-Table 'test.t1' doesn't exist
+ERROR 42S02: Table 'test.t1' doesn't exist
CREATE TABLE t1 (a int, KEY(a));
HANDLER t1 OPEN;
HANDLER t1 READ a=((SELECT 1));
-You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use
+ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use
HANDLER t1 CLOSE;
drop table t1;
create table t1 (a int);
@@ -926,7 +929,7 @@ drop table t1, t2;
CREATE TABLE `t1` (`i` int(11) NOT NULL default '0',PRIMARY KEY (`i`)) TYPE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES (1);
UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i));
-Invalid use of group function
+ERROR HY000: Invalid use of group function
drop table t1;
CREATE TABLE t1 (a int(1));
EXPLAIN SELECT (SELECT RAND() FROM t1) FROM t1;
@@ -1033,7 +1036,7 @@ id select_type table type possible_keys key key_len ref rows Extra
3 UNCACHEABLE SUBQUERY t1 ALL NULL NULL NULL NULL 3
drop table t1;
select t1.Continent, t2.Name, t2.Population from t1 LEFT JOIN t2 ON t1.Code = t2.Country where t2.Population IN (select max(t2.Population) AS Population from t2, t1 where t2.Country = t1.Code group by Continent);
-Table 'test.t1' doesn't exist
+ERROR 42S02: Table 'test.t1' doesn't exist
CREATE TABLE t1 (
ID int(11) NOT NULL auto_increment,
name char(35) NOT NULL default '',
@@ -1098,11 +1101,11 @@ PRIMARY KEY (`i`)
) TYPE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES (1);
UPDATE t1 SET i=i+(SELECT MAX(i) FROM (SELECT 1) t) WHERE i=(SELECT MAX(i));
-Invalid use of group function
+ERROR HY000: Invalid use of group function
UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i));
-Invalid use of group function
+ERROR HY000: Invalid use of group function
UPDATE t1 SET t.i=i+(SELECT MAX(i) FROM (SELECT 1) t);
-Unknown table 't' in field list
+ERROR 42S02: Unknown table 't' in field list
drop table t1;
CREATE TABLE t1 (
id int(11) default NULL
diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result
index 5568e5b25d8..fbc5c234256 100644
--- a/mysql-test/r/temp_table.result
+++ b/mysql-test/r/temp_table.result
@@ -24,9 +24,9 @@ a b
create TEMPORARY TABLE t2 type=heap select * from t1;
create TEMPORARY TABLE IF NOT EXISTS t2 (a int) type=heap;
CREATE TEMPORARY TABLE t1 (a int not null, b char (10) not null);
-Table 't1' already exists
+ERROR 42S01: Table 't1' already exists
ALTER TABLE t1 RENAME t2;
-Table 't2' already exists
+ERROR 42S01: Table 't2' already exists
select * from t2;
a b
4 e
@@ -74,7 +74,7 @@ drop table t1,t2;
create temporary table t1 (a int not null);
insert into t1 values (1),(1);
alter table t1 add primary key (a);
-Duplicate entry '1' for key 1
+ERROR 23000: Duplicate entry '1' for key 1
drop table t1;
CREATE TABLE t1 (
d datetime default NULL
diff --git a/mysql-test/r/timezone.result b/mysql-test/r/timezone.result
new file mode 100644
index 00000000000..b82b39da262
--- /dev/null
+++ b/mysql-test/r/timezone.result
@@ -0,0 +1,25 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (ts int);
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 03:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 02:59:59'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:00:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:59:59'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01'));
+SELECT ts,from_unixtime(ts) FROM t1;
+ts from_unixtime(ts)
+1035673200 2002-10-27 01:00:00
+1035680400 2002-10-27 02:00:00
+1035684000 2002-10-27 03:00:00
+1035680400 2002-10-27 02:00:00
+1035673200 2002-10-27 01:00:00
+1035680400 2002-10-27 02:00:00
+1048986000 2003-03-30 03:00:00
+1048986000 2003-03-30 03:00:00
+1048989599 2003-03-30 03:59:59
+1048989601 2003-03-30 04:00:01
+DROP TABLE t1;
diff --git a/mysql-test/r/truncate.result b/mysql-test/r/truncate.result
index ad390c9fa92..0e256c1bf8e 100644
--- a/mysql-test/r/truncate.result
+++ b/mysql-test/r/truncate.result
@@ -14,7 +14,7 @@ select * from t1;
a b c1
drop table t1;
select count(*) from t1;
-Table 'test.t1' doesn't exist
+ERROR 42S02: Table 'test.t1' doesn't exist
create temporary table t1 (n int);
insert into t1 values (1),(2),(3);
truncate table t1;
@@ -22,4 +22,4 @@ select * from t1;
n
drop table t1;
truncate non_existing_table;
-Table 'test.non_existing_table' doesn't exist
+ERROR 42S02: Table 'test.non_existing_table' doesn't exist
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index ce1cd392819..c16c83e3c53 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -27,9 +27,9 @@ t3 CREATE TABLE `t3` (
drop table t1,t2,t3
#;
CREATE TABLE t1 (a char(257) default "hello");
-Too big column length for column 'a' (max = 255). Use BLOB instead
+ERROR 42000: Too big column length for column 'a' (max = 255). Use BLOB instead
CREATE TABLE t2 (a blob default "hello");
-BLOB column 'a' can't have a default value
+ERROR 42000: BLOB column 'a' can't have a default value
drop table if exists t1,t2;
create table t1 (nr int(5) not null auto_increment,b blob,str char(10), primary key (nr));
insert into t1 values (null,"a","A");
@@ -347,7 +347,7 @@ a 1
hello 1
drop table t1;
create table t1 (a text, key (a(300)));
-Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the store engine doesn't support unique sub keys
+ERROR HY000: Incorrect sub part key. The used key part isn't a string, the used length is longer than the key part or the store engine doesn't support unique sub keys
create table t1 (a text, key (a(255)));
drop table t1;
CREATE TABLE t1 (
diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result
index c0e48fb42d8..57df0c67ac9 100644
--- a/mysql-test/r/type_decimal.result
+++ b/mysql-test/r/type_decimal.result
@@ -436,8 +436,8 @@ a
99999999999
drop table t1;
CREATE TABLE t1 (a_dec DECIMAL(-1,0));
-Too big column length for column 'a_dec' (max = 255). Use BLOB instead
+ERROR 42000: Too big column length for column 'a_dec' (max = 255). Use BLOB instead
CREATE TABLE t1 (a_dec DECIMAL(-2,1));
-Too big column length for column 'a_dec' (max = 255). Use BLOB instead
+ERROR 42000: Too big column length for column 'a_dec' (max = 255). Use BLOB instead
CREATE TABLE t1 (a_dec DECIMAL(-1,1));
-Too big column length for column 'a_dec' (max = 255). Use BLOB instead
+ERROR 42000: Too big column length for column 'a_dec' (max = 255). Use BLOB instead
diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result
index 92cf4f70843..76f82feb50e 100644
--- a/mysql-test/r/type_float.result
+++ b/mysql-test/r/type_float.result
@@ -100,5 +100,5 @@ min(a)
-0.010
drop table t1;
create table t1 (f float(54));
-Incorrect column specifier for column 'f'
+ERROR 42000: Incorrect column specifier for column 'f'
drop table if exists t1;
diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result
index c059d5b58a0..34ae1086e2c 100644
--- a/mysql-test/r/type_ranges.result
+++ b/mysql-test/r/type_ranges.result
@@ -285,7 +285,7 @@ create table t1 (c int);
insert into t1 values(1),(2);
create table t2 select * from t1;
create table t3 select * from t1, t2;
-Duplicate column name 'c'
+ERROR 42S21: Duplicate column name 'c'
create table t3 select t1.c AS c1, t2.c AS c2,1 as "const" from t1, t2;
show full columns from t3;
Field Type Collation Null Key Default Extra Privileges Comment
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 272ffdd330e..5b7b26bc1bb 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -85,7 +85,7 @@ a b
2 b
1 a
(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b;
-Table 't1' from one of SELECT's can not be used in global ORDER clause
+ERROR 42000: Table 't1' from one of SELECT's can not be used in global ORDER clause
explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
@@ -95,7 +95,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
2 UNION t2 ALL NULL NULL NULL NULL 4
explain select xx from t1 union select 1;
-Unknown column 'xx' in 'field list'
+ERROR 42S22: Unknown column 'xx' in 'field list'
explain select a,b from t1 union select 1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4
@@ -110,38 +110,38 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 UNION NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
select a,b from t1 into outfile 'skr' union select a,b from t2;
-Wrong usage of UNION and INTO
+ERROR HY000: Wrong usage of UNION and INTO
select a,b from t1 order by a union select a,b from t2;
-Wrong usage of UNION and ORDER BY
+ERROR HY000: Wrong usage of UNION and ORDER BY
insert into t3 select a from t1 order by a union select a from t2;
-Wrong usage of UNION and ORDER BY
+ERROR HY000: Wrong usage of UNION and ORDER BY
create table t3 select a,b from t1 union select a from t2;
-The used SELECT statements have a different number of columns
+ERROR 21000: The used SELECT statements have a different number of columns
select a,b from t1 union select a from t2;
-The used SELECT statements have a different number of columns
+ERROR 21000: The used SELECT statements have a different number of columns
select * from t1 union select a from t2;
-The used SELECT statements have a different number of columns
+ERROR 21000: The used SELECT statements have a different number of columns
select a from t1 union select * from t2;
-The used SELECT statements have a different number of columns
+ERROR 21000: The used SELECT statements have a different number of columns
select * from t1 union select SQL_BUFFER_RESULT * from t2;
-Wrong usage/placement of 'SQL_BUFFER_RESULT'
+ERROR 42000: Wrong usage/placement of 'SQL_BUFFER_RESULT'
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;
replace into t3 select a,b as c from t1 union all select a,b from t2;
drop table t1,t2,t3;
select * union select 1;
-No tables used
+ERROR HY000: No tables used
select 1 as a,(select a union select a);
a (select a union select a)
1 1
(select 1) union (select 2) order by 0;
-Unknown column '0' in 'order clause'
+ERROR 42S22: Unknown column '0' in 'order clause'
SELECT @a:=1 UNION SELECT @a:=@a+1;
@a:=1
1
2
(SELECT 1) UNION (SELECT 2) ORDER BY (SELECT a);
-Unknown column 'a' in 'field list'
+ERROR 42S22: Unknown column 'a' in 'field list'
(SELECT 1,3) UNION (SELECT 2,1) ORDER BY (SELECT 2);
1 3
1 3
diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result
index 1d483da2c77..a0370272396 100644
--- a/mysql-test/r/update.result
+++ b/mysql-test/r/update.result
@@ -5,11 +5,11 @@ update t1 set a=a+10 where a > 34;
update t1 set a=a+100 where a > 0;
update t1 set a=a+100 where a=1 and a=2;
update t1 set a=b+100 where a=1 and a=2;
-Unknown column 'b' in 'field list'
+ERROR 42S22: Unknown column 'b' in 'field list'
update t1 set a=b+100 where c=1 and a=2;
-Unknown column 'c' in 'where clause'
+ERROR 42S22: Unknown column 'c' in 'where clause'
update t1 set d=a+100 where a=1;
-Unknown column 'd' in 'field list'
+ERROR 42S22: Unknown column 'd' in 'field list'
select * from t1;
a
101
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index 6e3b9309351..3a53dbdded0 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -1,6 +1,6 @@
drop table if exists t1,t2;
set @a := foo;
-Unknown column 'foo' in 'field list'
+ERROR 42S22: Unknown column 'foo' in 'field list'
set @a := connection_id() + 3;
select @a - connection_id();
@a - connection_id()
diff --git a/mysql-test/r/varbinary.result b/mysql-test/r/varbinary.result
index 2d04da31caa..5464d741f70 100644
--- a/mysql-test/r/varbinary.result
+++ b/mysql-test/r/varbinary.result
@@ -16,9 +16,9 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const UNIQ UNIQ 8 const 1
drop table t1;
select x'hello';
-You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'x'hello'' at line 1
+ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'x'hello'' at line 1
select 0xfg;
-Unknown column '0xfg' in 'field list'
+ERROR 42S22: Unknown column '0xfg' in 'field list'
create table t1 select 1 as x, 2 as xx;
select x,xx from t1;
x xx
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index b5e05cf6953..1a773acd23e 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -164,42 +164,42 @@ select ROUND(RAND(),5);
ROUND(RAND(),5)
0.02887
set big_tables=OFFF;
-Variable 'big_tables' can't be set to the value of 'OFFF'
+ERROR 42000: Variable 'big_tables' can't be set to the value of 'OFFF'
set big_tables="OFFF";
-Variable 'big_tables' can't be set to the value of 'OFFF'
+ERROR 42000: Variable 'big_tables' can't be set to the value of 'OFFF'
set unknown_variable=1;
-Unknown system variable 'unknown_variable'
+ERROR HY000: Unknown system variable 'unknown_variable'
set max_join_size="hello";
-Wrong argument type to variable 'max_join_size'
+ERROR 42000: Wrong argument type to variable 'max_join_size'
set table_type=UNKNOWN_TABLE_TYPE;
-Variable 'table_type' can't be set to the value of 'UNKNOWN_TABLE_TYPE'
+ERROR 42000: Variable 'table_type' can't be set to the value of 'UNKNOWN_TABLE_TYPE'
set table_type=INNODB, big_tables=2;
-Variable 'big_tables' can't be set to the value of '2'
+ERROR 42000: Variable 'big_tables' can't be set to the value of '2'
show local variables like 'table_type';
Variable_name Value
table_type HEAP
set SESSION query_cache_size=10000;
-Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL
+ERROR HY000: Variable 'query_cache_size' is a GLOBAL variable and should be set with SET GLOBAL
set GLOBAL table_type=DEFAULT;
-Variable 'table_type' doesn't have a default value
+ERROR 42000: Variable 'table_type' doesn't have a default value
set character_set_client=UNKNOWN_CHARACTER_SET;
-Unknown character set: 'UNKNOWN_CHARACTER_SET'
+ERROR 42000: Unknown character set: 'UNKNOWN_CHARACTER_SET'
set global autocommit=1;
-Variable 'autocommit' is a LOCAL variable and can't be used with SET GLOBAL
+ERROR HY000: Variable 'autocommit' is a LOCAL variable and can't be used with SET GLOBAL
select @@global.timestamp;
-Variable 'timestamp' is a LOCAL variable and can't be used with SET GLOBAL
+ERROR HY000: Variable 'timestamp' is a LOCAL variable and can't be used with SET GLOBAL
set @@version='';
-Unknown system variable 'version'
+ERROR HY000: Unknown system variable 'version'
set @@concurrent_insert=1;
-Variable 'concurrent_insert' is a GLOBAL variable and should be set with SET GLOBAL
+ERROR HY000: Variable 'concurrent_insert' is a GLOBAL variable and should be set with SET GLOBAL
set @@global.sql_auto_is_null=1;
-Variable 'sql_auto_is_null' is a LOCAL variable and can't be used with SET GLOBAL
+ERROR HY000: Variable 'sql_auto_is_null' is a LOCAL variable and can't be used with SET GLOBAL
select @@global.sql_auto_is_null;
-Variable 'sql_auto_is_null' is a LOCAL variable and can't be used with SET GLOBAL
+ERROR HY000: Variable 'sql_auto_is_null' is a LOCAL variable and can't be used with SET GLOBAL
set myisam_max_sort_file_size=100;
-Variable 'myisam_max_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL
+ERROR HY000: Variable 'myisam_max_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL
set myisam_max_extra_sort_file_size=100;
-Variable 'myisam_max_extra_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL
+ERROR HY000: Variable 'myisam_max_extra_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL
set autocommit=1;
set big_tables=1;
select @@autocommit, @@big_tables;
@@ -325,7 +325,7 @@ test.t2 check status OK
select max(a) +1, max(a) +2 into @xx,@yy from t1;
drop table t1,t2;
select @@xxxxxxxxxx;
-Unknown system variable 'xxxxxxxxxx'
+ERROR HY000: Unknown system variable 'xxxxxxxxxx'
select 1;
1
1
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index fc22bc85aee..04229bd1882 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -135,3 +135,12 @@ analyze table t1;
show keys from t1;
drop table t1;
+#
+# Test of ALTER TABLE DELAYED
+#
+
+CREATE TABLE t1 (i int(10), index(i) );
+ALTER TABLE t1 DISABLE KEYS;
+INSERT DELAYED INTO t1 VALUES(1),(2),(3);
+ALTER TABLE t1 ENABLE KEYS;
+drop table t1;
diff --git a/mysql-test/t/ansi.test b/mysql-test/t/ansi.test
index da82b7a9e31..f4aef5c3f8e 100644
--- a/mysql-test/t/ansi.test
+++ b/mysql-test/t/ansi.test
@@ -17,3 +17,8 @@ SELECT id,NULL,1,1.1,'a' FROM t1 GROUP BY id;
--error 1055
SELECT id FROM t1 GROUP BY id2;
drop table t1;
+
+set sql_mode="MySQL40";
+select @@sql_mode;
+set sql_mode="ANSI";
+select @@sql_mode;
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index 2ce90c93bd9..4f0af1edbaa 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -65,3 +65,12 @@ SELECT 1 as a FROM (SELECT a UNION SELECT 1) b;
SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b;
--error 1054
select 1 from (select 2) a order by 0;
+
+#
+# Test of explain (bug #251)
+#
+
+create table t1 (id int);
+insert into t1 values (1),(2),(3);
+describe select * from (select * from t1 group by id) bar;
+drop table t1;
diff --git a/mysql-test/t/err000001.test b/mysql-test/t/errors.test
index b558c90b0c6..b558c90b0c6 100644
--- a/mysql-test/t/err000001.test
+++ b/mysql-test/t/errors.test
diff --git a/mysql-test/t/func_system.test b/mysql-test/t/func_system.test
index 41b776719dc..998b2a5c3f4 100644
--- a/mysql-test/t/func_system.test
+++ b/mysql-test/t/func_system.test
@@ -18,7 +18,7 @@ select version()>=_utf8"3.23.29";
select version()>=_latin1"3.23.29";
select charset(version());
-create table t1 select database(), user(), version();
+create table t1 (version char(40)) select database(), user(), version() as 'version';
show create table t1;
drop table t1;
diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test
index bd04b2e4c41..dcddbc99efa 100644
--- a/mysql-test/t/grant.test
+++ b/mysql-test/t/grant.test
@@ -1,3 +1,9 @@
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1 (a int);
+
#
# Test that SSL options works properly
#
@@ -42,3 +48,35 @@ flush privileges;
grant usage on test.* to user@localhost with grant option;
show grants for user@localhost;
+#
+# Test for 'drop user', 'revoke privileges, grant'
+#
+
+grant ALL PRIVILEGES on *.* to drop_user2@localhost with GRANT OPTION;
+show grants for drop_user2@localhost;
+revoke all privileges, grant from drop_user2@localhost;
+drop user drop_user2@localhost;
+
+grant ALL PRIVILEGES on *.* to drop_user@localhost with GRANT OPTION;
+grant ALL PRIVILEGES on test.* to drop_user@localhost with GRANT OPTION;
+grant select(a) on test.t1 to drop_user@localhost;
+show grants for drop_user@localhost;
+revoke all privileges, grant from drop_user@localhost;
+show grants for drop_user@localhost;
+drop user drop_user@localhost;
+--error 1267
+revoke all privileges, grant from drop_user@localhost;
+
+grant select(a) on test.t1 to drop_user1@localhost;
+grant select on test.t1 to drop_user2@localhost;
+grant select on test.* to drop_user3@localhost;
+grant select on *.* to drop_user4@localhost;
+--error 1266
+drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
+drop_user4@localhost;
+revoke all privileges, grant from drop_user1@localhost, drop_user2@localhost,
+drop_user3@localhost, drop_user4@localhost;
+drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
+drop_user4@localhost;
+
+drop table t1;
diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test
index 8fcb22e4684..5bd7b95f560 100644
--- a/mysql-test/t/insert_select.test
+++ b/mysql-test/t/insert_select.test
@@ -71,3 +71,20 @@ WHERE numeropost=9 ORDER BY numreponse ASC;
DROP TABLE IF EXISTS t1,t2;
+# Addendum by Guilhem:
+# Check if a partly-completed INSERT SELECT in a MyISAM table goes
+# into the binlog
+
+create table t1(a int, unique(a));
+insert into t1 values(2);
+create table t2(a int);
+insert into t2 values(1),(2);
+reset master;
+--error 1062
+insert into t1 select * from t2;
+# The above should produce an error, but still be in the binlog;
+# verify the binlog :
+let $VERSION=`select version()`;
+--replace_result $VERSION VERSION
+show binlog events;
+drop table t1, t2;
diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test
index d7e84590dc0..2f484d30ff7 100644
--- a/mysql-test/t/loaddata.test
+++ b/mysql-test/t/loaddata.test
@@ -10,4 +10,12 @@ create table t1 (a date, b date, c date not null, d date);
load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',';
load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES;
SELECT * from t1;
+truncate table t1;
+
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d);
+SELECT * from t1;
drop table t1;
+
+
+
+
diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test
index f3a747c4d61..2a3cc5b7e8f 100644
--- a/mysql-test/t/lowercase_table.test
+++ b/mysql-test/t/lowercase_table.test
@@ -14,4 +14,12 @@ ALTER TABLE T2 ADD new_col int not null;
ALTER TABLE T2 RENAME T3;
show tables like 't_';
drop table t3;
-
+#
+# Test alias
+#
+create table t1 (a int);
+select count(*) from T1;
+select count(*) from t1;
+select count(T1.a) from t1;
+select count(bags.a) from t1 as Bags;
+drop table t1;
diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test
index 99bb2656001..3b1e3fac7c2 100644
--- a/mysql-test/t/olap.test
+++ b/mysql-test/t/olap.test
@@ -1,31 +1,79 @@
--disable_warnings
-drop table if exists t1;
+drop table if exists t1,t2;
--enable_warnings
-create table t1 ( product varchar(32), country varchar(32), year int, profit int);
-insert into t1 values ( 'Computer', 'India',2000, 1200),
-( 'TV', 'United States', 1999, 150),
-( 'Calculator', 'United States', 1999,50),
-( 'Computer', 'United States', 1999,1500),
-( 'Computer', 'United States', 2000,1500),
-( 'TV', 'United States', 2000, 150),
-( 'TV', 'India', 2000, 100),
-( 'TV', 'India', 2000, 100),
-( 'Calculator', 'United States', 2000,75),
-( 'Calculator', 'India', 2000,75),
-( 'TV', 'India', 1999, 100),
-( 'Computer', 'India', 1999,1200),
-( 'Computer', 'United States', 2000,1500),
-( 'Calculator', 'United States', 2000,75);
---error 1235
-select product, country , year, sum(profit) from t1 group by product, country, year with cube;
---error 1235
-explain select product, country , year, sum(profit) from t1 group by product, country, year with cube;
+create table t1 (product varchar(32), country_id int not null, year int, profit int);
+insert into t1 values ( 'Computer', 2,2000, 1200),
+( 'TV', 1, 1999, 150),
+( 'Calculator', 1, 1999,50),
+( 'Computer', 1, 1999,1500),
+( 'Computer', 1, 2000,1500),
+( 'TV', 1, 2000, 150),
+( 'TV', 2, 2000, 100),
+( 'TV', 2, 2000, 100),
+( 'Calculator', 1, 2000,75),
+( 'Calculator', 2, 2000,75),
+( 'TV', 1, 1999, 100),
+( 'Computer', 1, 1999,1200),
+( 'Computer', 2, 2000,1500),
+( 'Calculator', 2, 2000,75),
+( 'Phone', 3, 2003,10)
+;
+
+create table t2 (country_id int primary key, country char(20) not null);
+insert into t2 values (1, 'USA'),(2,'India'), (3,'Finland');
+
+# First simple rollups, with just grand total
+select product, sum(profit) from t1 group by product;
+select product, sum(profit) from t1 group by product with rollup;
+select product, sum(profit) from t1 group by 1 with rollup;
+select product, sum(profit),avg(profit) from t1 group by product with rollup;
+
+# Sub totals
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year;
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup;
+explain select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup;
+select product, country_id , sum(profit) from t1 group by product desc, country_id with rollup;
+
+# limit
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup limit 5;
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup limit 3,3;
+
+select product, country_id, count(*), count(distinct year) from t1 group by product, country_id;
+select product, country_id, count(*), count(distinct year) from t1 group by product, country_id with rollup;
+
+# Test of having
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup having country_id = 1;
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup having sum(profit) > 200;
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup having sum(profit) > 7000;
+
+# Functions
+select concat(product,':',country_id) as 'prod', concat(":",year,":") as 'year',1+1, sum(profit)/count(*) from t1 group by 1,2 with rollup;
+select product, sum(profit)/count(*) from t1 group by product with rollup;
+select left(product,4) as prod, sum(profit)/count(*) from t1 group by prod with rollup;
+select concat(product,':',country_id), 1+1, sum(profit)/count(*) from t1 group by concat(product,':',country_id) with rollup;
+
+# Joins
+select product, country , year, sum(profit) from t1,t2 where t1.country_id=t2.country_id group by product, country, year with rollup;
+
+# Derived tables and sub selects
+select product, `sum` from (select product, sum(profit) as 'sum' from t1 group by product with rollup) as tmp where product is null;
+select product from t1 where exists (select product, country_id , sum(profit) from t1 as t2 where t1.product=t2.product group by product, country_id with rollup having sum(profit) > 6000);
+
+# The following doesn't return the expected answer, but this is a limitation
+# in the implementation so we should just document it
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year having country_id is NULL;
+select concat(':',product,':'), sum(profit),avg(profit) from t1 group by product with rollup;
+
+# Error handling
+
+# Cube is not yet implemented
--error 1235
-select product, country , year, sum(profit) from t1 group by product, country, year with rollup;
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube;
--error 1235
-explain select product, country , year, sum(profit) from t1 group by product, country, year with rollup;
+explain select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube;
--error 1235
-select product, country , year, sum(profit) from t1 group by product, country, year with cube union all select product, country , year, sum(profit) from t1 group by product, country, year with rollup;
-drop table t1;
+select product, country_id , year, sum(profit) from t1 group by product, country_id, year with cube union all select product, country_id , year, sum(profit) from t1 group by product, country_id, year with rollup;
+
+drop table t1,t2;
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index 1078d19533c..929146ba97a 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -371,18 +371,35 @@ show global variables like "query_cache_min_res_unit";
#
# Test of query cache resizing
#
+create table t1 (a int);
set GLOBAL query_cache_size=1000;
show global variables like "query_cache_size";
-set GLOBAL query_cache_size=1100;
-set GLOBAL query_cache_size=1200;
-set GLOBAL query_cache_size=1300;
-set GLOBAL query_cache_size=1400;
-set GLOBAL query_cache_size=1500;
-set GLOBAL query_cache_size=1600;
-set GLOBAL query_cache_size=1700;
-set GLOBAL query_cache_size=1800;
-set GLOBAL query_cache_size=1900;
+select * from t1;
+set GLOBAL query_cache_size=1024;
+show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=10240;
+show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=20480;
+show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=40960;
+show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=51200;
+show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=61440;
+show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=81920;
show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=102400;
+show global variables like "query_cache_size";
+select * from t1;
+drop table t1;
#
# Temporary tables
diff --git a/mysql-test/t/raid.test b/mysql-test/t/raid.test
index 235add63c22..395a04615cb 100644
--- a/mysql-test/t/raid.test
+++ b/mysql-test/t/raid.test
@@ -1,5 +1,7 @@
-- require r/have_raid.require
+disable_query_log;
show variables like "have_raid";
+enable_query_log;
#
# Test of raided tables
diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair_part1.test
index 2657f91cd02..2657f91cd02 100644
--- a/mysql-test/t/repair.test
+++ b/mysql-test/t/repair_part1.test
diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test
index 93062f39c20..3e84f86c092 100644
--- a/mysql-test/t/rpl_insert_id.test
+++ b/mysql-test/t/rpl_insert_id.test
@@ -1,5 +1,8 @@
# See if queries that use both auto_increment and LAST_INSERT_ID()
# are replicated well
+
+# We also check how the foreign_key_check variable is replicated
+
source include/master-slave.inc;
connection master;
create table t1(a int auto_increment, key(a));
@@ -20,10 +23,30 @@ drop table t1;
drop table t2;
create table t1(a int auto_increment, key(a));
create table t2(b int auto_increment, c int, key(b));
+SET FOREIGN_KEY_CHECKS=0;
insert into t1 values (10);
insert into t1 values (null),(null),(null);
insert into t2 values (5,0);
insert into t2 values (null,last_insert_id());
+SET FOREIGN_KEY_CHECKS=1;
+save_master_pos;
+connection slave;
+sync_with_master;
+select * from t1;
+select * from t2;
+connection master;
+
+# check if INSERT SELECT in auto_increment is well replicated (bug #490)
+
+drop table t1;
+drop table t2;
+create table t1(a int auto_increment, key(a));
+create table t2(b int auto_increment, c int, key(b));
+insert into t1 values (10);
+insert into t1 values (null),(null),(null);
+insert into t2 values (5,0);
+insert into t2 (c) select * from t1;
+select * from t2;
save_master_pos;
connection slave;
sync_with_master;
diff --git a/mysql-test/t/rpl_loaddata.test b/mysql-test/t/rpl_loaddata.test
index 1f34aa9d3f9..dc4eadda192 100644
--- a/mysql-test/t/rpl_loaddata.test
+++ b/mysql-test/t/rpl_loaddata.test
@@ -4,6 +4,9 @@
#
# check replication of load data for temporary tables with additional parameters
#
+# check if duplicate entries trigger an error (they should unless IGNORE or
+# REPLACE was used on the master) (bug 571).
+
source include/master-slave.inc;
create table t1(a int not null auto_increment, b int, primary key(a) );
@@ -27,7 +30,21 @@ connection master;
drop table t1;
drop table t2;
drop table t3;
+create table t1(a int, b int, unique(b));
save_master_pos;
connection slave;
sync_with_master;
+insert into t1 values(1,10);
+
+connection master;
+load data infile '../../std_data/rpl_loaddata.dat' into table t1;
+
+save_master_pos;
+connection slave;
+# don't sync_with_master because the slave SQL thread should be stopped because
+# of the error so MASTER_POS_WAIT() will not return; just sleep and hope the
+# slave SQL thread will have had time to stop.
+
+sleep 1;
+show status like 'slave_running';
diff --git a/mysql-test/t/rpl_log.test b/mysql-test/t/rpl_log.test
index faca1a6c339..f64aa292d30 100644
--- a/mysql-test/t/rpl_log.test
+++ b/mysql-test/t/rpl_log.test
@@ -32,10 +32,32 @@ show binlog events from 79 limit 2;
show binlog events from 79 limit 2,1;
flush logs;
+# We need an extra update before doing save_master_pos.
+# Otherwise, an unlikely scenario may occur:
+# * When the master's binlog_dump thread reads the end of master-bin.001,
+# it send the rotate event which is at this end, plus a fake rotate event
+# because it's starting to read a new binlog.
+# save_master_pos will record the position of the first of the two rotate
+# (because the fake one is not in the master's binlog anyway).
+# * Later the slave waits for the position of the first rotate event,
+# and it may quickly stop (in 'slave stop') without having received the fake
+# one.
+# So, depending on a few milliseconds, we end up with 2 rotate events in the
+# relay log or one, which influences the output of SHOW SLAVE STATUS, making
+# it not predictable and causing random test failures.
+# To make it predictable, we do a useless update now, but which has the interest
+# of making the slave catch both rotate events.
+
+create table t5 (a int);
+drop table t5;
+
# Sync slave and force it to start on another binary log
save_master_pos;
connection slave;
+# Note that the above 'slave start' will cause a 3rd rotate event (a fake one)
+# to go into the relay log (the master always sends a fake one when replication
+# starts).
start slave;
sync_with_master;
flush logs;
diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test
index fd464f74de4..d3531f0c440 100644
--- a/mysql-test/t/sql_mode.test
+++ b/mysql-test/t/sql_mode.test
@@ -24,7 +24,7 @@ show create table t1;
set @@sql_mode="no_field_options,mysql323,mysql40";
show variables like 'sql_mode';
show create table t1;
-set @@sql_mode="postgresql,oracle,mssql,db2,sapdb";
-show variables like 'sql_mode';
+set sql_mode="postgresql,oracle,mssql,db2,sapdb";
+select @@sql_mode;
show create table t1;
drop table t1;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index e47409046cd..1528f53ff0d 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -59,7 +59,7 @@ SELECT 1 as a,(SELECT a+a) b,(SELECT b);
create table t1 (a int);
create table t2 (a int, b int);
create table t3 (a int);
-create table t4 (a int, b int);
+create table t4 (a int not null, b int not null);
insert into t1 values (2);
insert into t2 values (1,7),(2,7);
insert into t4 values (4,8),(3,8),(5,9);
@@ -106,11 +106,13 @@ delete from t2 where a=100;
select * from t3 where a in (select a,b from t2);
-- error 1239
select * from t3 where a in (select * from t2);
-insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
-select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
-from t2 where t2.b=t4.b);
-select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
-from t2 where t2.b=t4.b);
+insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9),(1,10);
+-- empty set
+select b,max(a) as ma from t4 group by b having b < (select max(t2.a) from t2 where t2.b=t4.b);
+insert into t2 values (2,10);
+select b,max(a) as ma from t4 group by b having ma < (select max(t2.a) from t2 where t2.b=t4.b);
+delete from t2 where a=2 and b=10;
+select b,max(a) as ma from t4 group by b having b >= (select max(t2.a) from t2 where t2.b=t4.b);
create table t5 (a int);
select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
insert into t5 values (5);
diff --git a/mysql-test/t/timezone-master.opt b/mysql-test/t/timezone-master.opt
new file mode 100644
index 00000000000..0477f941e9d
--- /dev/null
+++ b/mysql-test/t/timezone-master.opt
@@ -0,0 +1 @@
+--timezone=MET
diff --git a/mysql-test/t/timezone.test b/mysql-test/t/timezone.test
new file mode 100644
index 00000000000..14facc0374a
--- /dev/null
+++ b/mysql-test/t/timezone.test
@@ -0,0 +1,28 @@
+#
+# Test of timezone handling. This script must be run with TZ=MEST
+
+-- require r/have_mest_timezone.require
+disable_query_log;
+show variables like "timezone";
+enable_query_log;
+
+# Initialization
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+
+CREATE TABLE t1 (ts int);
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 03:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 02:59:59'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:00:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:59:59'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01'));
+
+SELECT ts,from_unixtime(ts) FROM t1;
+DROP TABLE t1;
diff --git a/mysys/default.c b/mysys/default.c
index bbf429eb920..a592e8b42e1 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -72,6 +72,7 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args,MEM_ROOT *alloc,
const char *dir, const char *config_file,
const char *ext, TYPELIB *group);
+static char *remove_end_comment(char *ptr);
void load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv)
@@ -297,8 +298,9 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
}
if (!read_values)
continue;
- if (!(end=value=strchr(ptr,'=')))
- end=strend(ptr); /* Option without argument */
+ end= remove_end_comment(ptr);
+ if ((value= strchr(ptr, '=')))
+ end= value; /* Option without argument */
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
if (!value)
{
@@ -368,6 +370,29 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
}
+static char *remove_end_comment(char *ptr)
+{
+ char quote= 0;
+
+ for (; *ptr; ptr++)
+ {
+ if (*ptr == '\'' || *ptr == '\"')
+ {
+ if (!quote)
+ quote= *ptr;
+ else if (quote == *ptr)
+ quote= 0;
+ }
+ if (!quote && *ptr == '#') /* We are not inside a comment */
+ {
+ *ptr= 0;
+ return ptr;
+ }
+ }
+ return ptr;
+}
+
+
void print_defaults(const char *conf_file, const char **groups)
{
#ifdef __WIN__
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index add5335a7af..7a845e3eb00 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -27,6 +27,7 @@
#include <m_string.h>
#include <queues.h>
#include "thr_alarm.h"
+#include <assert.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h> /* AIX needs this for fd_set */
@@ -36,21 +37,22 @@
#define ETIME ETIMEDOUT
#endif
-static my_bool alarm_aborted=1;
-my_bool thr_alarm_inited=0;
+static int alarm_aborted=1; /* No alarm thread */
+my_bool thr_alarm_inited= 0;
+volatile my_bool alarm_thread_running= 0;
static sig_handler process_alarm_part2(int sig);
#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2)
static pthread_mutex_t LOCK_alarm;
+static pthread_cond_t COND_alarm;
static sigset_t full_signal_set;
static QUEUE alarm_queue;
static uint max_used_alarms=0;
pthread_t alarm_thread;
#ifdef USE_ALARM_THREAD
-static pthread_cond_t COND_alarm;
static void *alarm_handler(void *arg);
#define reschedule_alarms() pthread_cond_signal(&COND_alarm)
#else
@@ -77,6 +79,7 @@ void init_thr_alarm(uint max_alarms)
compare_ulong,NullS);
sigfillset(&full_signal_set); /* Neaded to block signals */
pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&COND_alarm,NULL);
#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD)
#if defined(HAVE_mit_thread)
sigset(THR_CLIENT_ALARM,thread_alarm); /* int. thread system calls */
@@ -96,7 +99,6 @@ void init_thr_alarm(uint max_alarms)
{
pthread_attr_t thr_attr;
pthread_attr_init(&thr_attr);
- pthread_cond_init(&COND_alarm,NULL);
pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&thr_attr,8196);
@@ -120,12 +122,24 @@ void init_thr_alarm(uint max_alarms)
/*
Request alarm after sec seconds.
- A pointer is returned with points to a non-zero int when the alarm has been
- given. This can't be called from the alarm-handling thread.
- Returns 0 if no more alarms are allowed (aborted by process)
+
+ SYNOPSIS
+ thr_alarm()
+ alrm Pointer to alarm detection
+ alarm_data Structure to store in alarm queue
+
+ NOTES
+ This function can't be called from the alarm-handling thread.
+
+ RETURN VALUES
+ 0 ok
+ 1 If no more alarms are allowed (aborted by process)
+
+ Stores in first argument a pointer to a non-zero int which is set to 0
+ when the alarm has been given
*/
-bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
+my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
{
ulong now;
sigset_t old_mask;
@@ -136,19 +150,24 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
now=(ulong) time((time_t*) 0);
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */
- if (alarm_aborted)
+ if (alarm_aborted > 0)
{ /* No signal thread */
DBUG_PRINT("info", ("alarm aborted"));
+ *alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1);
}
+ if (alarm_aborted < 0)
+ sec= 1; /* Abort mode */
+
if (alarm_queue.elements >= max_used_alarms)
{
if (alarm_queue.elements == alarm_queue.max_elements)
{
DBUG_PRINT("info", ("alarm queue full"));
fprintf(stderr,"Warning: thr_alarm queue is full\n");
+ *alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1);
@@ -163,6 +182,7 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME))))
{
DBUG_PRINT("info", ("failed my_malloc()"));
+ *alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1);
@@ -201,7 +221,7 @@ void thr_end_alarm(thr_alarm_t *alarmed)
ALARM *alarm_data;
sigset_t old_mask;
uint i;
- bool found=0;
+ my_bool found=0;
DBUG_ENTER("thr_end_alarm");
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
@@ -219,23 +239,16 @@ void thr_end_alarm(thr_alarm_t *alarmed)
break;
}
}
+ DBUG_ASSERT(!*alarmed || found);
if (!found)
{
-#ifdef MAIN
- printf("Warning: Didn't find alarm %lx in queue of %d alarms\n",
- (long) *alarmed, alarm_queue.elements);
-#endif
+ if (*alarmed)
+ fprintf(stderr,"Warning: Didn't find alarm %lx in queue of %d alarms\n",
+ (long) *alarmed, alarm_queue.elements);
DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n",
(long) *alarmed));
}
- if (alarm_aborted && !alarm_queue.elements)
- {
- delete_queue(&alarm_queue);
- pthread_mutex_unlock(&LOCK_alarm);
- pthread_mutex_destroy(&LOCK_alarm);
- }
- else
- pthread_mutex_unlock(&LOCK_alarm);
+ pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_VOID_RETURN;
}
@@ -365,31 +378,66 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
/*
- Shedule all alarms now.
- When all alarms are given, Free alarm memory and don't allow more alarms.
+ Schedule all alarms now and optionally free all structures
+
+ SYNPOSIS
+ end_thr_alarm()
+ free_structures Set to 1 if we should free memory used for
+ the alarm queue.
+ When we call this we should KNOW that there
+ is no active alarms
+ IMPLEMENTATION
+ Set alarm_abort to -1 which will change the behavior of alarms as follows:
+ - All old alarms will be rescheduled at once
+ - All new alarms will be rescheduled to one second
*/
-void end_thr_alarm(void)
+void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
- if (!alarm_aborted)
+ if (alarm_aborted != 1) /* If memory not freed */
{
- my_bool deleted=0;
pthread_mutex_lock(&LOCK_alarm);
DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements));
- alarm_aborted=1; /* mark aborted */
- if (!alarm_queue.elements)
+ alarm_aborted= -1; /* mark aborted */
+ if (alarm_queue.elements || (alarm_thread_running && free_structures))
{
- deleted= 1;
- delete_queue(&alarm_queue);
+ if (pthread_equal(pthread_self(),alarm_thread))
+ alarm(1); /* Shut down everything soon */
+ else
+ reschedule_alarms();
+ }
+ if (free_structures)
+ {
+ struct timespec abstime;
+ /*
+ The following test is just for safety, the caller should not
+ depend on this
+ */
+ DBUG_ASSERT(!alarm_queue.elements);
+ /* Wait until alarm thread dies */
+
+ set_timespec(abstime, 10); /* Wait up to 10 seconds */
+ while (alarm_thread_running)
+ {
+ int error= pthread_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime);
+ if (error == ETIME || error == ETIMEDOUT)
+ break; /* Don't wait forever */
+ }
+ if (!alarm_queue.elements)
+ {
+ delete_queue(&alarm_queue);
+ alarm_aborted= 1;
+ pthread_mutex_unlock(&LOCK_alarm);
+ if (!alarm_thread_running) /* Safety */
+ {
+ pthread_mutex_destroy(&LOCK_alarm);
+ pthread_cond_destroy(&COND_alarm);
+ }
+ }
}
- if (pthread_equal(pthread_self(),alarm_thread))
- alarm(1); /* Shut down everything soon */
else
- reschedule_alarms();
- pthread_mutex_unlock(&LOCK_alarm);
- if (deleted)
- pthread_mutex_destroy(&LOCK_alarm);
+ pthread_mutex_unlock(&LOCK_alarm);
}
DBUG_VOID_RETURN;
}
@@ -471,6 +519,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
puts("Starting alarm thread");
#endif
my_thread_init();
+ alarm_thread_running= 1;
pthread_mutex_lock(&LOCK_alarm);
for (;;)
{
@@ -495,7 +544,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
}
}
}
- else if (alarm_aborted)
+ else if (alarm_aborted == -1)
break;
else if ((error=pthread_cond_wait(&COND_alarm,&LOCK_alarm)))
{
@@ -507,6 +556,8 @@ static void *alarm_handler(void *arg __attribute__((unused)))
process_alarm(0);
}
bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */
+ alarm_thread_running= 0;
+ pthread_cond_signal(&COND_alarm);
pthread_mutex_unlock(&LOCK_alarm);
pthread_exit(0);
return 0; /* Impossible */
@@ -629,7 +680,7 @@ void thr_end_alarm(thr_alarm_t *alrm_ptr)
}
}
-void end_thr_alarm(void)
+void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
alarm_aborted=1; /* No more alarms */
@@ -708,7 +759,7 @@ void thr_end_alarm(thr_alarm_t *alrm_ptr)
}
}
-void end_thr_alarm(void)
+void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
alarm_aborted=1; /* No more alarms */
@@ -907,7 +958,7 @@ static void *signal_hand(void *arg __attribute__((unused)))
case SIGHUP:
#endif
printf("Aborting nicely\n");
- end_thr_alarm();
+ end_thr_alarm(0);
break;
#ifdef SIGTSTP
case SIGTSTP:
@@ -1004,10 +1055,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
if (thread_count == 1)
{
printf("Calling end_thr_alarm. This should cancel the last thread\n");
- end_thr_alarm();
+ end_thr_alarm(0);
}
}
pthread_mutex_unlock(&LOCK_thread_count);
+ end_thr_alarm(1);
thr_alarm_info(&alarm_info);
printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n",
alarm_info.active_alarms, alarm_info.max_used_alarms,
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 1134226bfaf..6006222992e 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -33,7 +33,6 @@ bin_SCRIPTS = @server_scripts@ \
mysql_explain_log \
mysql_tableinfo \
mysqld_multi \
- fill_help_tables \
mysql_create_system_tables
EXTRA_SCRIPTS = make_binary_distribution.sh \
@@ -63,6 +62,8 @@ EXTRA_DIST = $(EXTRA_SCRIPTS) \
mysqlaccess.conf \
mysqlbug
+pkgdata_DATA = fill_help_tables.sql mysql_fix_privilege_tables.sql
+
# mysqlbug should be distributed built so that people can report build
# failures with it.
CLEANFILES = @server_scripts@ \
@@ -138,5 +139,7 @@ SUFFIXES = .sh
# Don't update the files from bitkeeper
%::SCCS/s.%
-all: make_win_src_distribution make_binary_distribution
+all: fill_help_tables.sql make_win_src_distribution make_binary_distribution
+fill_help_tables.sql: fill_help_tables ../Docs/manual.texi
+ ./fill_help_tables < ../Docs/manual.texi > fill_help_tables.sql
diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh
index 05d6f3ffb71..5d392f719f0 100644
--- a/scripts/mysql_fix_privilege_tables.sh
+++ b/scripts/mysql_fix_privilege_tables.sh
@@ -1,212 +1,166 @@
#!/bin/sh
+# This script is a wrapper to pipe the mysql_fix_privilege_tables.sql
+# through the mysql client program to the mysqld server
-root_password="$1"
+# Default values (Can be changed in my.cnf)
+password=""
host="localhost"
user="root"
-
-if test -z $1 ; then
- cmd="@bindir@/mysql -f --user=$user --host=$host mysql"
+sql_only=0
+basedir=""
+verbose=0
+args=""
+
+file=mysql_fix_privilege_tables.sql
+
+# The following code is almost identical to the code in mysql_install_db.sh
+
+parse_arguments() {
+ # We only need to pass arguments through to the server if we don't
+ # handle them here. So, we collect unrecognized options (passed on
+ # the command line) into the args variable.
+ pick_args=
+ if test "$1" = PICK-ARGS-FROM-ARGV
+ then
+ pick_args=1
+ shift
+ fi
+
+ for arg do
+ case "$arg" in
+ --basedir=*) basedir=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
+ --user=*) user=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
+ --password=*) password=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
+ --host=*) host=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
+ --sql|--sql-only) sql_only=1;;
+ --verbose) verbose=1 ;;
+ *)
+ if test -n "$pick_args"
+ then
+ # This sed command makes sure that any special chars are quoted,
+ # so the arg gets passed exactly to the server.
+ args="$args "`echo "$arg" | sed -e 's,\([^a-zA-Z0-9_.-]\),\\\\\1,g'`
+ fi
+ ;;
+ esac
+ done
+}
+
+# Get first arguments from the my.cfg file, groups [mysqld] and
+# [mysql_install_db], and then merge with the command line arguments
+if test -x ./bin/my_print_defaults
+then
+ print_defaults="./bin/my_print_defaults"
+elif test -x @bindr@/my_print_defaults
+then
+ print_defaults="@bindir@/my_print_defaults"
+elif test -x @bindir@/mysql_print_defaults
+then
+ print_defaults="@bindir@/mysql_print_defaults"
else
- root_password="$1"
- cmd="@bindir@/mysql -f --user=$user --password=$root_password --host=$host mysql"
+ print_defaults="my_print_defaults"
fi
-# Debian addition
-if [ "$1" = "--sql-only" ]; then
- root_password=""
- cmd="/usr/share/mysql/echo_stderr"
-fi
+parse_arguments `$print_defaults $defaults mysql_install_db mysql_fix_privilege_tables`
+parse_arguments PICK-ARGS-FROM-ARGV "$@"
-echo "This scripts updates the mysql.user, mysql.db, mysql.host and the"
-echo "mysql.func tables to MySQL 3.22.14 and above."
-echo ""
-echo "This is needed if you want to use the new GRANT functions,"
-echo "CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 3.23"
-echo ""
-echo "If you get 'Access denied' errors, you should run this script again"
-echo "and give the MySQL root user password as an argument!"
-
-echo "Converting all privilege tables to MyISAM format"
-$cmd <<END_OF_DATA
-ALTER TABLE user type=MyISAM;
-ALTER TABLE db type=MyISAM;
-ALTER TABLE host type=MyISAM;
-ALTER TABLE func type=MyISAM;
-ALTER TABLE columns_priv type=MyISAM;
-ALTER TABLE tables_priv type=MyISAM;
-END_OF_DATA
-
-
-# Fix old password format, add File_priv and func table
-echo ""
-echo "If your tables are already up to date or partially up to date you will"
-echo "get some warnings about 'Duplicated column name'. You can safely ignore these!"
-
-$cmd <<END_OF_DATA
-alter table user change password password char(16) NOT NULL;
-alter table user add File_priv enum('N','Y') NOT NULL;
-CREATE TABLE if not exists func (
- name char(64) DEFAULT '' NOT NULL,
- ret tinyint(1) DEFAULT '0' NOT NULL,
- dl char(128) DEFAULT '' NOT NULL,
- type enum ('function','aggregate') NOT NULL,
- PRIMARY KEY (name)
-);
-END_OF_DATA
-echo ""
-
-# Add the new grant colums
-
-echo "Creating Grant Alter and Index privileges if they don't exists"
-echo "You can ignore any Duplicate column errors"
-$cmd <<END_OF_DATA
-alter table user add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') NOT NULL,add Index_priv enum('N','Y') NOT NULL,add Alter_priv enum('N','Y') NOT NULL;
-alter table host add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') NOT NULL,add Index_priv enum('N','Y') NOT NULL,add Alter_priv enum('N','Y') NOT NULL;
-alter table db add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') NOT NULL,add Index_priv enum('N','Y') NOT NULL,add Alter_priv enum('N','Y') NOT NULL;
-END_OF_DATA
-res=$?
-echo ""
-
-# If the new grant columns didn't exists, copy File -> Grant
-# and Create -> Alter, Index, References
-
-if test $res = 0
+if test -z "$basedir"
then
- echo "Setting default privileges for the new grant, index and alter privileges"
- $cmd <<END_OF_DATA
- UPDATE user SET Grant_priv=File_priv,References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv;
- UPDATE db SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv;
- UPDATE host SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv;
-END_OF_DATA
- echo ""
+ basedir=@prefix@
+ bindir=@bindir@
+ execdir=@libexecdir@
+ pkgdatadir=@pkgdatadir@
+else
+ bindir="$basedir/bin"
+ if test -x "$basedir/libexec/mysqld"
+ then
+ execdir="$basedir/libexec"
+ elif test -x "@libexecdir@/mysqld"
+ then
+ execdir="@libexecdir@"
+ else
+ execdir="$basedir/bin"
+ fi
fi
-#
-# The second alter changes ssl_type to new 4.0.2 format
-
-echo "Adding columns needed by GRANT .. REQUIRE (openssl)"
-echo "You can ignore any Duplicate column errors"
-$cmd <<END_OF_DATA
-ALTER TABLE user
-ADD ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL,
-ADD ssl_cipher BLOB NOT NULL,
-ADD x509_issuer BLOB NOT NULL,
-ADD x509_subject BLOB NOT NULL;
-ALTER TABLE user MODIFY ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL;
-END_OF_DATA
-echo ""
-
-#
-# Create tables_priv and columns_priv if they don't exists
-#
-
-echo "Creating the new table and column privilege tables"
-
-$cmd <<END_OF_DATA
-CREATE TABLE IF NOT EXISTS tables_priv (
- Host char(60) DEFAULT '' NOT NULL,
- Db char(60) DEFAULT '' NOT NULL,
- User char(16) DEFAULT '' NOT NULL,
- Table_name char(60) DEFAULT '' NOT NULL,
- Grantor char(77) DEFAULT '' NOT NULL,
- Timestamp timestamp(14),
- Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL,
- Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL,
- PRIMARY KEY (Host,Db,User,Table_name)
-);
-CREATE TABLE IF NOT EXISTS columns_priv (
- Host char(60) DEFAULT '' NOT NULL,
- Db char(60) DEFAULT '' NOT NULL,
- User char(16) DEFAULT '' NOT NULL,
- Table_name char(60) DEFAULT '' NOT NULL,
- Column_name char(59) DEFAULT '' NOT NULL,
- Timestamp timestamp(14),
- Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL,
- PRIMARY KEY (Host,Db,User,Table_name,Column_name)
-);
-END_OF_DATA
-
-#
-# Name change of Type -> Column_priv from MySQL 3.22.12
-#
-
-echo "Changing name of columns_priv.Type -> columns_priv.Column_priv"
-echo "You can ignore any Unknown column errors from this"
-
-$cmd <<END_OF_DATA
-ALTER TABLE columns_priv change Type Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL;
-END_OF_DATA
-echo ""
-
-#
-# Add the new 'type' column to the func table.
-#
-
-echo "Fixing the func table"
-echo "You can ignore any Duplicate column errors"
-
-$cmd <<EOF
-alter table func add type enum ('function','aggregate') NOT NULL;
-EOF
-echo ""
-
-#
-# Change the user,db and host tables to MySQL 4.0 format
-#
-
-echo "Adding new fields used by MySQL 4.0.2 to the privilege tables"
-echo "You can ignore any Duplicate column errors"
-
-$cmd <<END_OF_DATA
-alter table user
-add Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER alter_priv,
-add Super_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Show_db_priv,
-add Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Super_priv,
-add Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Create_tmp_table_priv,
-add Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Lock_tables_priv,
-add Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Execute_priv,
-add Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Repl_slave_priv;
-END_OF_DATA
-
-if test $? -eq "0"
+# The following test is to make this script compatible with the 4.0 where
+# the first argument was the password
+if test -z $password
then
- # Convert privileges so that users have similar privileges as before
- echo ""
- echo "Updating new privileges in MySQL 4.0.2 from old ones"
- $cmd <<END_OF_DATA
- update user set show_db_priv= select_priv, super_priv=process_priv, execute_priv=process_priv, create_tmp_table_priv='Y', Lock_tables_priv='Y', Repl_slave_priv=file_priv, Repl_client_priv=file_priv where user<>"";
-END_OF_DATA
- echo ""
+ password=`echo $args | sed -e 's/ *//g'`
fi
-# Add fields that can be used to limit number of questions and connections
-# for some users.
-
-$cmd <<END_OF_DATA
-alter table user
-add max_questions int(11) NOT NULL AFTER x509_subject,
-add max_updates int(11) unsigned NOT NULL AFTER max_questions,
-add max_connections int(11) unsigned NOT NULL AFTER max_updates;
-END_OF_DATA
-
-# Increase password length to handle new passwords
-
-@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
-alter table user
-change password password char(45) not null;
-END_OF_DATA
-
+if test -z $password ; then
+ cmd="$bindir/mysql -f --user=$user --host=$host mysql"
+else
+ cmd="$bindir/mysql -f --user=$user --password=$password --host=$host mysql"
+fi
+if test $sql_only = 1
+then
+ cmd="cat"
+fi
+# Find where mysql_fix_privilege_tables.sql is located
+for i in $basedir/support-files $basedir/share $basedir/share/mysql \
+ $basedir/scripts @pkgdatadir@ . ./scripts
+do
+ if test -f $i/$file
+ then
+ pkgdatadir=$i
+ fi
+done
+
+sql_file="$pkgdatadir/$file"
+if test ! -f $sql_file
+then
+ echo "Could not find file '$file'."
+ echo "Please use --basedir to specify the directory where MySQL is installed"
+ exit 1
+fi
-#
-# Add Create_tmp_table_priv and Lock_tables_priv to db and host
-#
+s_echo()
+{
+ if test $sql_only = 0
+ then
+ echo $1
+ fi
+}
+
+s_echo "This scripts updates all the mysql privilege tables to be usable by"
+s_echo "MySQL 4.0 and above."
+s_echo ""
+s_echo "This is needed if you want to use the new GRANT functions,"
+s_echo "CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 4.1"
+s_echo ""
+
+if test $verbose = 1
+then
+ s_echo "You can safely ignore all 'Duplicate column' and 'Unknown column' errors"
+ s_echo "as this just means that your tables where already up to date."
+ s_echo "This script is safe to run even if your tables are already up to date!"
+ s_echo ""
+fi
-$cmd <<END_OF_DATA
-alter table db
-add Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,
-add Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL;
-alter table host
-add Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,
-add Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL;
-END_OF_DATA
+if test $verbose = 0
+then
+ cat $sql_file | $cmd > /dev/null 2>&1
+else
+ cat $sql_file | $cmd > /dev/null
+fi
+if test $? = 0
+then
+ s_echo "done"
+else
+ s_echo "Got a failure from command:"
+ s_echo "$cmd"
+ s_echo "Please check the above output and try again."
+ if test $verbose = 0
+ then
+ s_echo ""
+ s_echo "Running the script with the --verbose option may give you some information"
+ s_echo "of what went wrong."
+ fi
+ s_echo ""
+ s_echo "If you get an 'Access denied' error, you should run this script again and"
+ s_echo "give the MySQL root user password as an argument with the --password= option"
+fi
diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql
new file mode 100644
index 00000000000..3466e3cf799
--- /dev/null
+++ b/scripts/mysql_fix_privilege_tables.sql
@@ -0,0 +1,89 @@
+ALTER TABLE user type=MyISAM;
+ALTER TABLE db type=MyISAM;
+ALTER TABLE host type=MyISAM;
+ALTER TABLE func type=MyISAM;
+ALTER TABLE columns_priv type=MyISAM;
+ALTER TABLE tables_priv type=MyISAM;
+ALTER TABLE user change password password char(45) not null;
+ALTER TABLE user add File_priv enum('N','Y') NOT NULL;
+CREATE TABLE IF NOT EXISTS func (
+ name char(64) DEFAULT '' NOT NULL,
+ ret tinyint(1) DEFAULT '0' NOT NULL,
+ dl char(128) DEFAULT '' NOT NULL,
+ type enum ('function','aggregate') NOT NULL,
+ PRIMARY KEY (name)
+);
+
+-- Detect whether or not we had the Grant_priv column
+SET @hadGrantPriv:=0;
+SELECT @hadGrantPriv:=1 FROM user WHERE Grant_priv LIKE '%';
+
+ALTER TABLE user add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') NOT NULL,add Index_priv enum('N','Y') NOT NULL,add Alter_priv enum('N','Y') NOT NULL;
+ALTER TABLE host add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') NOT NULL,add Index_priv enum('N','Y') NOT NULL,add Alter_priv enum('N','Y') NOT NULL;
+ALTER TABLE db add Grant_priv enum('N','Y') NOT NULL,add References_priv enum('N','Y') NOT NULL,add Index_priv enum('N','Y') NOT NULL,add Alter_priv enum('N','Y') NOT NULL;
+
+--- Fix privileges for old tables
+UPDATE user SET Grant_priv=File_priv,References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0;
+UPDATE db SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0;
+UPDATE host SET References_priv=Create_priv,Index_priv=Create_priv,Alter_priv=Create_priv WHERE @hadGrantPriv = 0;
+
+ALTER TABLE user
+ADD ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL,
+ADD ssl_cipher BLOB NOT NULL,
+ADD x509_issuer BLOB NOT NULL,
+ADD x509_subject BLOB NOT NULL;
+ALTER TABLE user MODIFY ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL;
+
+CREATE TABLE IF NOT EXISTS tables_priv (
+ Host char(60) DEFAULT '' NOT NULL,
+ Db char(60) DEFAULT '' NOT NULL,
+ User char(16) DEFAULT '' NOT NULL,
+ Table_name char(60) DEFAULT '' NOT NULL,
+ Grantor char(77) DEFAULT '' NOT NULL,
+ Timestamp timestamp(14),
+ Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL,
+ Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL,
+ PRIMARY KEY (Host,Db,User,Table_name)
+);
+
+CREATE TABLE IF NOT EXISTS columns_priv (
+ Host char(60) DEFAULT '' NOT NULL,
+ Db char(60) DEFAULT '' NOT NULL,
+ User char(16) DEFAULT '' NOT NULL,
+ Table_name char(60) DEFAULT '' NOT NULL,
+ Column_name char(59) DEFAULT '' NOT NULL,
+ Timestamp timestamp(14),
+ Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL,
+ PRIMARY KEY (Host,Db,User,Table_name,Column_name)
+);
+
+ALTER TABLE columns_priv change Type Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL;
+
+ALTER TABLE func add type enum ('function','aggregate') NOT NULL;
+
+# Detect whether we had Show_db_priv
+SET @hadShowDbPriv:=0;
+SELECT @hadShowDbPriv:=1 FROM user WHERE Show_db_priv LIKE '%';
+
+ALTER TABLE user
+ADD Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER alter_priv,
+ADD Super_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Show_db_priv,
+ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Super_priv,
+ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Create_tmp_table_priv,
+ADD Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Lock_tables_priv,
+ADD Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Execute_priv,
+ADD Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Repl_slave_priv;
+
+UPDATE user SET show_db_priv= select_priv, super_priv=process_priv, execute_priv=process_priv, create_tmp_table_priv='Y', Lock_tables_priv='Y', Repl_slave_priv=file_priv, Repl_client_priv=file_priv where user<>"" AND @hadShowDbPriv = 0;
+
+ALTER TABLE user
+ADD max_questions int(11) NOT NULL AFTER x509_subject,
+ADD max_updates int(11) unsigned NOT NULL AFTER max_questions,
+ADD max_connections int(11) unsigned NOT NULL AFTER max_updates;
+
+ALTER TABLE db
+ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL;
+ALTER TABLE host
+ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL;
diff --git a/sql-common/client.c b/sql-common/client.c
index 55013d4bd82..3c025d18bd6 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -99,7 +99,8 @@
#include "client_settings.h"
#include <sql_common.h>
-const char *unknown_sqlstate= "000000";
+const char *unknown_sqlstate= "HY0000";
+const char *not_error_sqlstate= "00000";
#ifdef MYSQL_CLIENT
extern my_bool stmt_close(MYSQL_STMT *stmt,my_bool skip_list);
@@ -339,10 +340,10 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
/*
The name of event and file-mapping events create agree next rule:
- shared_memory_base_name+unique_part
+ shared_memory_base_name+unique_part
Where:
- shared_memory_base_name is unique value for each server
- unique_part is uniquel value for each object (events and file-mapping)
+ shared_memory_base_name is unique value for each server
+ unique_part is uniquel value for each object (events and file-mapping)
*/
suffix_pos = strxmov(tmp,shared_memory_base_name,"_",NullS);
strmov(suffix_pos, "CONNECT_REQUEST");
@@ -369,36 +370,34 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR;
goto err;
}
- /*
- Send to server request of connection
- */
+
+ /* Send to server request of connection */
if (!SetEvent(event_connect_request))
{
error_allow = CR_SHARED_MEMORY_CONNECT_SET_ERROR;
goto err;
}
- /*
- Wait of answer from server
- */
+
+ /* Wait of answer from server */
if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) !=
WAIT_OBJECT_0)
{
error_allow = CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR;
goto err;
}
- /*
- Get number of connection
- */
+
+ /* Get number of connection */
connect_number = uint4korr(handle_connect_map);/*WAX2*/
p= int2str(connect_number, connect_number_char, 10);
/*
The name of event and file-mapping events create agree next rule:
shared_memory_base_name+unique_part+number_of_connection
+
Where:
- shared_memory_base_name is uniquel value for each server
- unique_part is uniquel value for each object (events and file-mapping)
- number_of_connection is number of connection between server and client
+ shared_memory_base_name is uniquel value for each server
+ unique_part is uniquel value for each object (events and file-mapping)
+ number_of_connection is number of connection between server and client
*/
suffix_pos = strxmov(tmp,shared_memory_base_name,"_",connect_number_char,
"_",NullS);
@@ -506,7 +505,7 @@ net_safe_read(MYSQL *mysql)
{
NET *net= &mysql->net;
ulong len=0;
- init_sigpipe_variables
+ init_sigpipe_variables;
/* Don't give sigpipe errors if the client doesn't want them */
set_sigpipe(mysql);
@@ -571,7 +570,7 @@ advanced_command(MYSQL *mysql, enum enum_server_command command,
{
NET *net= &mysql->net;
my_bool result= 1;
- init_sigpipe_variables
+ init_sigpipe_variables;
/* Don't give sigpipe errors if the client doesn't want them */
set_sigpipe(mysql);
@@ -589,8 +588,8 @@ advanced_command(MYSQL *mysql, enum enum_server_command command,
}
net->last_error[0]=0;
- net->last_errno=0;
- strmov(net->sqlstate, unknown_sqlstate);
+ net->last_errno= 0;
+ strmov(net->sqlstate, not_error_sqlstate);
mysql->net.report_error=0;
mysql->info=0;
mysql->affected_rows= ~(my_ulonglong) 0;
@@ -624,7 +623,7 @@ advanced_command(MYSQL *mysql, enum enum_server_command command,
if (!skip_check)
result= ((mysql->packet_length=net_safe_read(mysql)) == packet_error ?
1 : 0);
- end:
+end:
reset_sigpipe(mysql);
return result;
}
@@ -665,7 +664,7 @@ void end_server(MYSQL *mysql)
DBUG_ENTER("end_server");
if (mysql->net.vio != 0)
{
- init_sigpipe_variables
+ init_sigpipe_variables;
DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio)));
set_sigpipe(mysql);
vio_delete(mysql->net.vio);
@@ -1561,7 +1560,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE);
bzero((char*) &UNIXaddr,sizeof(UNIXaddr));
UNIXaddr.sun_family = AF_UNIX;
- strmov(UNIXaddr.sun_path, unix_socket);
+ strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1);
if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
mysql->options.connect_timeout))
{
@@ -2090,15 +2089,16 @@ static void mysql_fix_pointers(MYSQL* mysql, MYSQL* old_mysql)
#endif /*MYSQL_CLIENT*/
}
+
my_bool mysql_reconnect(MYSQL *mysql)
{
MYSQL tmp_mysql;
DBUG_ENTER("mysql_reconnect");
- if (!mysql->reconnect
- || (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
+ if (!mysql->reconnect ||
+ (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
{
- /* Allow reconnect next time */
+ /* Allow reconnect next time */
mysql->server_status&= ~SERVER_STATUS_IN_TRANS;
strmov(mysql->net.sqlstate, unknown_sqlstate);
mysql->net.last_errno=CR_SERVER_GONE_ERROR;
diff --git a/sql/Makefile.am b/sql/Makefile.am
index c3b7c77e252..7c98f1a9315 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -64,7 +64,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
thr_malloc.cc item_create.cc item_subselect.cc \
item_row.cc item_geofunc.cc \
field.cc key.cc sql_class.cc sql_list.cc \
- net_serv.cc protocol.cc lock.cc my_lock.c \
+ net_serv.cc protocol.cc sql_state.c \
+ lock.cc my_lock.c \
sql_string.cc sql_manager.cc sql_map.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \
set_var.cc sql_parse.cc sql_yacc.yy \
diff --git a/sql/field.cc b/sql/field.cc
index 044684b2675..484eab5e130 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2755,6 +2755,7 @@ int Field_timestamp::store(longlong nr)
if ((nr=fix_datetime(nr)))
{
+ long not_used;
part1=(long) (nr/LL(1000000));
part2=(long) (nr - (longlong) part1*LL(1000000));
l_time.year= (int) (part1/10000L); part1%=10000L;
@@ -2763,7 +2764,7 @@ int Field_timestamp::store(longlong nr)
l_time.hour= (int) (part2/10000L); part2%=10000L;
l_time.minute=(int) part2 / 100;
l_time.second=(int) part2 % 100;
- timestamp=my_gmt_sec(&l_time);
+ timestamp=my_gmt_sec(&l_time, &not_used);
}
else
timestamp=0;
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index bf4dc7e5066..1cf123dbec6 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -131,9 +131,11 @@ static void innobase_print_error(const char* db_errpfx, char* buffer);
/**********************************************************************
Releases possible search latch and InnoDB thread FIFO ticket. These should
-be released at each SQL statement end. It does no harm to release these
-also in the middle of an SQL statement. */
+be released at each SQL statement end, and also when mysqld passes the
+control to the client. It does no harm to release these also in the middle
+of an SQL statement. */
static
+inline
void
innobase_release_stat_resources(
/*============================*/
@@ -914,6 +916,11 @@ innobase_commit_low(
trx_t* trx) /* in: transaction handle */
{
#ifdef HAVE_REPLICATION
+ if (trx->conc_state == TRX_NOT_STARTED) {
+
+ return;
+ }
+
/* TODO: Guilhem should check if master_log_name, pending
etc. are right if the master log gets rotated! Possible bug here.
Comment by Heikki March 4, 2003. */
@@ -929,11 +936,13 @@ innobase_commit_low(
));
}
#endif /* HAVE_REPLICATION */
+
trx_commit_for_mysql(trx);
}
/*********************************************************************
-Commits a transaction in an InnoDB database. */
+Commits a transaction in an InnoDB database or marks an SQL statement
+ended. */
int
innobase_commit(
@@ -951,29 +960,45 @@ innobase_commit(
DBUG_ENTER("innobase_commit");
DBUG_PRINT("trans", ("ending transaction"));
- trx = check_trx_exists(thd);
+ /* The flag thd->transaction.all.innodb_active_trans is set to 1
+ in ::external_lock and ::start_stmt, and it is only set to 0 in
+ a commit or a rollback. If it is 0 we know there cannot be resources
+ to be freed and we can return immediately. */
- if (trx->auto_inc_lock) {
-
- /* If we had reserved the auto-inc lock for
- some table in this SQL statement, we release it now */
-
- srv_conc_enter_innodb(trx);
- row_unlock_table_autoinc_for_mysql(trx);
- srv_conc_exit_innodb(trx);
+ if (thd->transaction.all.innodb_active_trans == 0) {
+
+ DBUG_RETURN(0);
}
- if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
+ trx = check_trx_exists(thd);
+
+ if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle
+ || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
+
innobase_commit_low(trx);
- thd->transaction.all.innodb_active_trans=0;
+
+ thd->transaction.all.innodb_active_trans = 0;
+ } else {
+ if (trx->auto_inc_lock) {
+ /* If we had reserved the auto-inc lock for some
+ table in this SQL statement we release it now */
+
+ srv_conc_enter_innodb(trx);
+ row_unlock_table_autoinc_for_mysql(trx);
+ srv_conc_exit_innodb(trx);
+ }
+ /* Store the current undo_no of the transaction so that we
+ know where to roll back if we have to roll back the next
+ SQL statement */
+
+ trx_mark_sql_stat_end(trx);
}
- /* Release possible statement level resources */
+ /* Release a possible FIFO ticket and search latch */
innobase_release_stat_resources(trx);
- trx_mark_sql_stat_end(trx);
- /* Tell InnoDB server that there might be work for
- utility threads: */
+ /* Tell the InnoDB server that there might be work for utility
+ threads: */
srv_active_wake_master_thread();
@@ -1044,7 +1069,7 @@ innobase_commit_complete(
}
/*********************************************************************
-Rolls back a transaction in an InnoDB database. */
+Rolls back a transaction or the latest SQL statement in an InnoDB database. */
int
innobase_rollback(
@@ -1085,11 +1110,9 @@ innobase_rollback(
srv_conc_exit_innodb(trx);
- /* Release possible statement level resources */
+ /* Release a possible FIFO ticket and search latch */
innobase_release_stat_resources(trx);
- trx_mark_sql_stat_end(trx);
-
DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
}
@@ -3032,6 +3055,8 @@ create_index(
KEY* key;
KEY_PART_INFO* key_part;
ulint ind_type;
+ ulint col_type;
+ ulint prefix_len;
ulint i;
DBUG_ENTER("create_index");
@@ -3059,6 +3084,27 @@ create_index(
for (i = 0; i < n_fields; i++) {
key_part = key->key_part + i;
+ if (key_part->length != key_part->field->pack_length()) {
+ prefix_len = key_part->length;
+
+ col_type = get_innobase_type_from_mysql_type(
+ key_part->field);
+ if (col_type == DATA_INT
+ || col_type == DATA_FLOAT
+ || col_type == DATA_DOUBLE
+ || col_type == DATA_DECIMAL) {
+ fprintf(stderr,
+"InnoDB: error: MySQL is trying to create a column prefix index field\n"
+"InnoDB: on an inappropriate data type %lu. Table name %s, column name %s.\n",
+ col_type, table_name,
+ key_part->field->field_name);
+
+ prefix_len = 0;
+ }
+ } else {
+ prefix_len = 0;
+ }
+
/* We assume all fields should be sorted in ascending
order, hence the '0': */
dict_mem_index_add_field(index,
@@ -3600,8 +3646,7 @@ ha_innobase::records_in_range(
/*************************************************************************
Gives an UPPER BOUND to the number of rows in a table. This is used in
-filesort.cc and its better if the upper bound hold.
-*/
+filesort.cc. */
ha_rows
ha_innobase::estimate_number_of_rows(void)
@@ -3636,11 +3681,11 @@ ha_innobase::estimate_number_of_rows(void)
/* Calculate a minimum length for a clustered index record and from
that an upper bound for the number of rows. Since we only calculate
- new statistics in row0mysql.c when a tablehas grown
- by a threshold factor, we must add a safety factor 2 in front
- of the formula below. */
+ new statistics in row0mysql.c when a table has grown by a threshold
+ factor, we must add a safety factor 2 in front of the formula below. */
- estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index);
+ estimate = 2 * local_data_file_length /
+ dict_index_calc_min_rec_len(index);
prebuilt->trx->op_info = (char*)"";
@@ -3667,27 +3712,36 @@ ha_innobase::scan_time()
return((double) (prebuilt->table->stat_clustered_index_size));
}
-/*
- Calculate the time it takes to read a set of ranges through and index
- This enables us to optimise reads for clustered indexes.
-*/
+/**********************************************************************
+Calculate the time it takes to read a set of ranges through an index
+This enables us to optimise reads for clustered indexes. */
-double ha_innobase::read_time(uint index, uint ranges, ha_rows rows)
+double
+ha_innobase::read_time(
+/*===================*/
+ /* out: estimated time measured in disk seeks */
+ uint index, /* in: key number */
+ uint ranges, /* in: how many ranges */
+ ha_rows rows) /* in: estimated number of rows in the ranges */
{
- ha_rows total_rows;
- double time_for_scan;
- if (index != table->primary_key)
- return handler::read_time(index, ranges, rows); // Not clustered
- if (rows <= 2)
- return (double) rows;
- /*
- Assume that the read is proportional to scan time for all rows + one
- seek per range.
- */
- time_for_scan= scan_time();
- if ((total_rows= estimate_number_of_rows()) < rows)
- return time_for_scan;
- return (ranges + (double) rows / (double) total_rows * time_for_scan);
+ ha_rows total_rows;
+ double time_for_scan;
+
+ if (index != table->primary_key)
+ return handler::read_time(index, ranges, rows); // Not clustered
+
+ if (rows <= 2)
+ return (double) rows;
+
+ /* Assume that the read time is proportional to the scan time for all
+ rows + at most one seek per range. */
+
+ time_for_scan= scan_time();
+
+ if ((total_rows= estimate_number_of_rows()) < rows)
+ return time_for_scan;
+
+ return (ranges + (double) rows / (double) total_rows * time_for_scan);
}
/*************************************************************************
@@ -4040,10 +4094,10 @@ ha_innobase::reset(void)
}
/**********************************************************************
-Inside LOCK TABLES MySQL will not call external_lock() between SQL
-statements. It will call this function at the start of each SQL statement.
-Note also a spacial case: if a temporary table is created inside LOCK
-TABLES, MySQL has not called external_lock() at all on that table. */
+MySQL calls this function at the start of each SQL statement. Inside LOCK
+TABLES the ::external_lock method does not work to mark SQL statement
+borders. Note also a special case: if a temporary table is created inside
+LOCK TABLES, MySQL has not called external_lock() at all on that table. */
int
ha_innobase::start_stmt(
@@ -4058,8 +4112,14 @@ ha_innobase::start_stmt(
trx = prebuilt->trx;
+ /* Here we release the search latch and the InnoDB thread FIFO ticket
+ if they were reserved. They should have been released already at the
+ end of the previous statement, but because inside LOCK TABLES the
+ lock count method does not work to mark the end of a SELECT statement,
+ that may not be the case. We MUST release the search latch before an
+ INSERT, for example. */
+
innobase_release_stat_resources(trx);
- trx_mark_sql_stat_end(trx);
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
&& trx->read_view) {
@@ -4082,7 +4142,8 @@ ha_innobase::start_stmt(
prebuilt->select_lock_type = LOCK_X;
}
-
+
+ /* Set the MySQL flag to mark that there is an active transaction */
thd->transaction.all.innodb_active_trans = 1;
return(0);
@@ -4146,17 +4207,20 @@ ha_innobase::external_lock(
}
if (lock_type != F_UNLCK) {
- if (trx->n_mysql_tables_in_use == 0) {
- trx_mark_sql_stat_end(trx);
- }
+ /* MySQL is setting a new table lock */
+ /* Set the MySQL flag to mark that there is an active
+ transaction */
thd->transaction.all.innodb_active_trans = 1;
+
trx->n_mysql_tables_in_use++;
prebuilt->mysql_has_locked = TRUE;
- trx->isolation_level = innobase_map_isolation_level(
+ if (trx->n_mysql_tables_in_use == 1) {
+ trx->isolation_level = innobase_map_isolation_level(
(enum_tx_isolation)
thd->variables.tx_isolation);
+ }
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
&& prebuilt->select_lock_type == LOCK_NONE) {
@@ -4172,37 +4236,44 @@ ha_innobase::external_lock(
trx->mysql_n_tables_locked++;
}
- } else {
- trx->n_mysql_tables_in_use--;
- prebuilt->mysql_has_locked = FALSE;
- auto_inc_counter_for_this_stat = 0;
- if (trx->n_mysql_tables_in_use == 0) {
+ DBUG_RETURN(error);
+ }
- trx->mysql_n_tables_locked = 0;
+ /* MySQL is releasing a table lock */
- prebuilt->used_in_HANDLER = FALSE;
+ trx->n_mysql_tables_in_use--;
+ prebuilt->mysql_has_locked = FALSE;
+ auto_inc_counter_for_this_stat = 0;
- /* Here we release the search latch and InnoDB
- thread FIFO ticket if they were reserved. */
+ /* If the MySQL lock count drops to zero we know that the current SQL
+ statement has ended */
- innobase_release_stat_resources(trx);
+ if (trx->n_mysql_tables_in_use == 0) {
+ trx->mysql_n_tables_locked = 0;
+ prebuilt->used_in_HANDLER = FALSE;
+
+ if (!(thd->options
+ & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
+ if (thd->transaction.all.innodb_active_trans != 0) {
+ innobase_commit(thd, trx);
+ }
+ } else {
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
&& trx->read_view) {
- /* At low transaction isolation levels we let
+ /* At low transaction isolation levels we let
each consistent read set its own snapshot */
- read_view_close_for_mysql(trx);
+ read_view_close_for_mysql(trx);
}
-
- if (!(thd->options
- & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
-
- innobase_commit(thd, trx);
- }
}
+
+ /* Here we release the search latch and the InnoDB thread FIFO
+ ticket if they were reserved. */
+
+ innobase_release_stat_resources(trx);
}
DBUG_RETURN(error);
@@ -4513,4 +4584,3 @@ ha_innobase::get_auto_increment()
}
#endif /* HAVE_INNOBASE_DB */
-
diff --git a/sql/handler.cc b/sql/handler.cc
index db1857e938c..493959f0473 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -218,8 +218,12 @@ void ha_close_connection(THD* thd)
}
/*
- This is used to commit or rollback a single statement depending
- on the value of error
+ This is used to commit or rollback a single statement depending on the value
+ of error. Note that if the autocommit is on, then the following call inside
+ InnoDB will commit or rollback the whole transaction (= the statement). The
+ autocommit mechanism built into InnoDB is based on counting locks, but if
+ the user has used LOCK TABLES then that mechanism does not know to do the
+ commit.
*/
int ha_autocommit_or_rollback(THD *thd, int error)
diff --git a/sql/item.cc b/sql/item.cc
index 42a949287e5..cdd78572a0a 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -117,7 +117,9 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
/*
- This function is only called when comparing items in the WHERE clause
+ This function is called when:
+ - Comparing items in the WHERE clause (when doing where optimization)
+ - When trying to find an ORDER BY/GROUP BY item in the SELECT part
*/
bool Item::eq(const Item *item, bool binary_cmp) const
@@ -243,6 +245,7 @@ void Item_field::set_field(Field *field_par)
decimals= field->decimals();
table_name=field_par->table_name;
field_name=field_par->field_name;
+ db_name=field_par->table->table_cache_key;
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
set_charset(field_par->charset(), COER_IMPLICIT);
}
@@ -344,9 +347,34 @@ longlong Item_field::val_int_result()
return result_field->val_int();
}
+
bool Item_field::eq(const Item *item, bool binary_cmp) const
{
- return item->type() == FIELD_ITEM && ((Item_field*) item)->field == field;
+ if (item->type() != FIELD_ITEM)
+ return 0;
+
+ Item_field *item_field= (Item_field*) item;
+ if (item_field->field)
+ return item_field->field == field;
+ /*
+ We may come here when we are trying to find a function in a GROUP BY
+ clause from the select list.
+ In this case the '100 % correct' way to do this would be to first
+ run fix_fields() on the GROUP BY item and then retry this function, but
+ I think it's better to relax the checking a bit as we will in
+ most cases do the correct thing by just checking the field name.
+ (In cases where we would choose wrong we would have to generate a
+ ER_NON_UNIQ_ERROR).
+ */
+ return (!my_strcasecmp(system_charset_info, item_field->name,
+ field_name) &&
+ (!item_field->table_name ||
+ (!my_strcasecmp(table_alias_charset, item_field->table_name,
+ table_name) &&
+ (!item_field->db_name ||
+ (item_field->db_name && !my_strcasecmp(table_alias_charset,
+ item_field->db_name,
+ db_name))))));
}
table_map Item_field::used_tables() const
@@ -837,7 +865,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return rf->fix_fields(thd, tables, ref) || rf->check_cols(1);
}
}
- }
+ }
else if (!tmp)
return -1;
diff --git a/sql/item.h b/sql/item.h
index 2d285bbe434..5cfe8eb3907 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -29,6 +29,8 @@ class Item {
void operator=(Item &);
public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size, MEM_ROOT *mem_root)
+ { return (void*) alloc_root(mem_root, (uint) size); }
static void operator delete(void *ptr,size_t size) {} /*lint -e715 */
enum Type {FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM,
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 2a4f4e0c410..e5b73e7670f 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -515,18 +515,18 @@ String *Item_func_concat_ws::val_str(String *str)
str->length(0); // QQ; Should be removed
res=str;
- // Skip until non-null and non-empty argument is found.
+ // Skip until non-null argument is found.
// If not, return the empty string
for (i=0; i < arg_count; i++)
- if ((res= args[i]->val_str(str)) && res->length())
+ if ((res= args[i]->val_str(str)))
break;
if (i == arg_count)
return &empty_string;
for (i++; i < arg_count ; i++)
{
- if (!(res2= args[i]->val_str(use_as_buff)) || !res2->length())
- continue; // Skip NULL and empty string
+ if (!(res2= args[i]->val_str(use_as_buff)))
+ continue; // Skip NULL
if (res->length() + sep_str->length() + res2->length() >
current_thd->variables.max_allowed_packet)
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index fa8bf7e6e0f..a57291702bc 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -217,11 +217,19 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
** reset and add of sum_func
***********************************************************************/
-void Item_sum_sum::reset()
+Item *Item_sum_sum::copy_or_same(THD* thd)
{
- null_value=1; sum=0.0; Item_sum_sum::add();
+ return new (&thd->mem_root) Item_sum_sum(thd, *this);
}
+
+bool Item_sum_sum::reset()
+{
+ null_value=1; sum=0.0;
+ return Item_sum_sum::add();
+}
+
+
bool Item_sum_sum::add()
{
sum+=args[0]->val();
@@ -230,17 +238,26 @@ bool Item_sum_sum::add()
return 0;
}
+
double Item_sum_sum::val()
{
return sum;
}
-void Item_sum_count::reset()
+Item *Item_sum_count::copy_or_same(THD* thd)
{
- count=0; add();
+ return new (&thd->mem_root) Item_sum_count(thd, *this);
}
+
+bool Item_sum_count::reset()
+{
+ count=0;
+ return add();
+}
+
+
bool Item_sum_count::add()
{
if (!args[0]->maybe_null)
@@ -260,14 +277,22 @@ longlong Item_sum_count::val_int()
}
/*
-** Avgerage
+ Avgerage
*/
-void Item_sum_avg::reset()
+Item *Item_sum_avg::copy_or_same(THD* thd)
{
- sum=0.0; count=0; Item_sum_avg::add();
+ return new (&thd->mem_root) Item_sum_avg(thd, *this);
}
+
+bool Item_sum_avg::reset()
+{
+ sum=0.0; count=0;
+ return Item_sum_avg::add();
+}
+
+
bool Item_sum_avg::add()
{
double nr=args[0]->val();
@@ -292,7 +317,7 @@ double Item_sum_avg::val()
/*
-** Standard deviation
+ Standard deviation
*/
double Item_sum_std::val()
@@ -301,15 +326,27 @@ double Item_sum_std::val()
return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}
+Item *Item_sum_std::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_std(thd, *this);
+}
+
+
/*
-** variance
+ Variance
*/
-void Item_sum_variance::reset()
+Item *Item_sum_variance::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_variance(thd, *this);
+}
+
+
+bool Item_sum_variance::reset()
{
sum=sum_sqr=0.0;
count=0;
- (void) Item_sum_variance::add();
+ return Item_sum_variance::add();
}
bool Item_sum_variance::add()
@@ -440,6 +477,13 @@ Item_sum_hybrid::val_str(String *str)
return str; // Keep compiler happy
}
+
+Item *Item_sum_min::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_min(thd, *this);
+}
+
+
bool Item_sum_min::add()
{
switch (hybrid_type) {
@@ -487,6 +531,12 @@ bool Item_sum_min::add()
}
+Item *Item_sum_max::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_max(thd, *this);
+}
+
+
bool Item_sum_max::add()
{
switch (hybrid_type) {
@@ -541,11 +591,19 @@ longlong Item_sum_bit::val_int()
return (longlong) bits;
}
-void Item_sum_bit::reset()
+
+bool Item_sum_bit::reset()
+{
+ bits=reset_bits;
+ return add();
+}
+
+Item *Item_sum_or::copy_or_same(THD* thd)
{
- bits=reset_bits; add();
+ return new (&thd->mem_root) Item_sum_or(thd, *this);
}
+
bool Item_sum_or::add()
{
ulonglong value= (ulonglong) args[0]->val_int();
@@ -554,6 +612,12 @@ bool Item_sum_or::add()
return 0;
}
+Item *Item_sum_and::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_and(thd, *this);
+}
+
+
bool Item_sum_and::add()
{
ulonglong value= (ulonglong) args[0]->val_int();
@@ -1032,12 +1096,21 @@ Item_sum_count_distinct::~Item_sum_count_distinct()
bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables,
Item **ref)
{
- if (Item_sum_num::fix_fields(thd, tables, ref) ||
- !(tmp_table_param= new TMP_TABLE_PARAM))
+ if (Item_sum_num::fix_fields(thd, tables, ref))
return 1;
return 0;
}
+/* This is used by rollup to create a separate usable copy of the function */
+
+void Item_sum_count_distinct::make_unique()
+{
+ table=0;
+ original= 0;
+ tree= &tree_base;
+}
+
+
bool Item_sum_count_distinct::setup(THD *thd)
{
List<Item> list;
@@ -1045,6 +1118,9 @@ bool Item_sum_count_distinct::setup(THD *thd)
if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
return 1;
+ if (!(tmp_table_param= new TMP_TABLE_PARAM))
+ return 1;
+
/* Create a table with an unique key over all parameters */
for (uint i=0; i < arg_count ; i++)
{
@@ -1192,7 +1268,14 @@ int Item_sum_count_distinct::tree_to_myisam()
return 0;
}
-void Item_sum_count_distinct::reset()
+
+Item *Item_sum_count_distinct::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_count_distinct(thd, *this);
+}
+
+
+bool Item_sum_count_distinct::reset()
{
if (use_tree)
reset_tree(tree);
@@ -1202,7 +1285,7 @@ void Item_sum_count_distinct::reset()
table->file->delete_all_rows();
table->file->extra(HA_EXTRA_WRITE_CACHE);
}
- (void) add();
+ return add();
}
bool Item_sum_count_distinct::add()
@@ -1265,11 +1348,11 @@ longlong Item_sum_count_distinct::val_int()
#ifdef HAVE_DLOPEN
-void Item_udf_sum::reset()
+bool Item_udf_sum::reset()
{
DBUG_ENTER("Item_udf_sum::reset");
udf.reset(&null_value);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
}
bool Item_udf_sum::add()
@@ -1279,6 +1362,11 @@ bool Item_udf_sum::add()
DBUG_RETURN(0);
}
+Item *Item_sum_udf_float::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_udf_float(thd, *this);
+}
+
double Item_sum_udf_float::val()
{
DBUG_ENTER("Item_sum_udf_float::val");
@@ -1298,6 +1386,12 @@ String *Item_sum_udf_float::val_str(String *str)
}
+Item *Item_sum_udf_int::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_udf_int(thd, *this);
+}
+
+
longlong Item_sum_udf_int::val_int()
{
DBUG_ENTER("Item_sum_udf_int::val_int");
@@ -1306,6 +1400,7 @@ longlong Item_sum_udf_int::val_int()
DBUG_RETURN(udf.val_int(&null_value));
}
+
String *Item_sum_udf_int::val_str(String *str)
{
longlong nr=val_int();
@@ -1327,6 +1422,13 @@ void Item_sum_udf_str::fix_length_and_dec()
DBUG_VOID_RETURN;
}
+
+Item *Item_sum_udf_str::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_udf_str(thd, *this);
+}
+
+
String *Item_sum_udf_str::val_str(String *str)
{
DBUG_ENTER("Item_sum_udf_str::str");
@@ -1568,7 +1670,13 @@ Item_func_group_concat::~Item_func_group_concat()
}
-void Item_func_group_concat::reset()
+Item *Item_func_group_concat::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_func_group_concat(thd, *this);
+}
+
+
+bool Item_func_group_concat::reset()
{
result.length(0);
result.copy();
@@ -1582,7 +1690,7 @@ void Item_func_group_concat::reset()
}
if (tree_mode)
reset_tree(tree);
- add();
+ return add();
}
@@ -1768,6 +1876,16 @@ bool Item_func_group_concat::setup(THD *thd)
return 0;
}
+/* This is used by rollup to create a separate usable copy of the function */
+
+void Item_func_group_concat::make_unique()
+{
+ table=0;
+ original= 0;
+ tree= &tree_base;
+}
+
+
String* Item_func_group_concat::val_str(String* str)
{
if (null_value)
diff --git a/sql/item_sum.h b/sql/item_sum.h
index f996f980fff..c8614dda679 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -26,9 +26,11 @@
class Item_sum :public Item_result_field
{
public:
- enum Sumfunctype {COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC,
- MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC,
- UDF_SUM_FUNC, GROUP_CONCAT_FUNC };
+ enum Sumfunctype
+ { COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC,
+ MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC,
+ UDF_SUM_FUNC, GROUP_CONCAT_FUNC
+ };
Item **args,*tmp_args[2];
uint arg_count;
@@ -60,7 +62,7 @@ public:
enum Type type() const { return SUM_FUNC_ITEM; }
virtual enum Sumfunctype sum_func () const=0;
- virtual void reset()=0;
+ virtual bool reset()=0;
virtual bool add()=0;
virtual void reset_field()=0;
virtual void update_field(int offset)=0;
@@ -78,6 +80,7 @@ public:
void fix_num_length_and_dec();
void no_rows_in_result() { reset(); }
virtual bool setup(THD *thd) {return 0;}
+ virtual void make_unique() {}
Item *get_tmp_table_item(THD *thd);
};
@@ -121,14 +124,14 @@ class Item_sum_sum :public Item_sum_num
Item_sum_sum(THD *thd, Item_sum_sum &item)
:Item_sum_num(thd, item), sum(item.sum) {}
enum Sumfunctype sum_func () const {return SUM_FUNC;}
- void reset();
+ bool reset();
bool add();
double val();
void reset_field();
void update_field(int offset);
void no_rows_in_result() {}
const char *func_name() const { return "sum"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_sum(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -148,7 +151,7 @@ class Item_sum_count :public Item_sum_int
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
enum Sumfunctype sum_func () const { return COUNT_FUNC; }
- void reset();
+ bool reset();
void no_rows_in_result() { count=0; }
bool add();
void make_const(longlong count_arg) { count=count_arg; used_table_cache=0; }
@@ -156,7 +159,7 @@ class Item_sum_count :public Item_sum_int
void reset_field();
void update_field(int offset);
const char *func_name() const { return "count"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_count(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -222,17 +225,15 @@ class Item_sum_count_distinct :public Item_sum_int
table_map used_tables() const { return used_table_cache; }
enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; }
- void reset();
+ bool reset();
bool add();
longlong val_int();
void reset_field() { return ;} // Never called
void update_field(int offset) { return ; } // Never called
const char *func_name() const { return "count_distinct"; }
bool setup(THD *thd);
- Item *copy_or_same(THD* thd)
- {
- return new Item_sum_count_distinct(thd, *this);
- }
+ void make_unique();
+ Item *copy_or_same(THD* thd);
void no_rows_in_result() {}
};
@@ -268,7 +269,7 @@ class Item_sum_avg :public Item_sum_num
Item_sum_avg(THD *thd, Item_sum_avg &item)
:Item_sum_num(thd, item), sum(item.sum), count(item.count) {}
enum Sumfunctype sum_func () const {return AVG_FUNC;}
- void reset();
+ bool reset();
bool add();
double val();
void reset_field();
@@ -276,7 +277,7 @@ class Item_sum_avg :public Item_sum_num
Item *result_item(Field *field)
{ return new Item_avg_field(this); }
const char *func_name() const { return "avg"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_avg(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
class Item_sum_variance;
@@ -321,7 +322,7 @@ class Item_sum_variance : public Item_sum_num
Item_sum_num(thd, item), sum(item.sum), sum_sqr(item.sum_sqr),
count(item.count) {}
enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
- void reset();
+ bool reset();
bool add();
double val();
void reset_field();
@@ -329,7 +330,7 @@ class Item_sum_variance : public Item_sum_num
Item *result_item(Field *field)
{ return new Item_variance_field(this); }
const char *func_name() const { return "variance"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_variance(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
class Item_sum_std;
@@ -349,12 +350,16 @@ public:
class Item_sum_std :public Item_sum_variance
{
public:
- Item_sum_std(Item *item_par) :Item_sum_variance(item_par){}
+ Item_sum_std(Item *item_par) :Item_sum_variance(item_par) {}
+ Item_sum_std(THD *thd, Item_sum_std &item)
+ :Item_sum_variance(thd, item)
+ {}
enum Sumfunctype sum_func () const { return STD_FUNC; }
double val();
Item *result_item(Field *field)
{ return new Item_std_field(this); }
const char *func_name() const { return "std"; }
+ Item *copy_or_same(THD* thd);
};
// This class is a string or number function depending on num_func
@@ -386,13 +391,13 @@ class Item_sum_hybrid :public Item_sum
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
- void reset()
+ bool reset()
{
sum=0.0;
sum_int=0;
value.length(0);
null_value=1;
- add();
+ return add();
}
double val();
longlong val_int();
@@ -418,7 +423,7 @@ public:
bool add();
const char *func_name() const { return "min"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_min(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -431,7 +436,7 @@ public:
bool add();
const char *func_name() const { return "max"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_max(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -446,7 +451,7 @@ class Item_sum_bit :public Item_sum_int
Item_sum_bit(THD *thd, Item_sum_bit &item):
Item_sum_int(thd, item), reset_bits(item.reset_bits), bits(item.bits) {}
enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;}
- void reset();
+ bool reset();
longlong val_int();
void reset_field();
void fix_length_and_dec()
@@ -462,7 +467,7 @@ class Item_sum_or :public Item_sum_bit
bool add();
void update_field(int offset);
const char *func_name() const { return "bit_or"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_or(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -474,7 +479,7 @@ class Item_sum_and :public Item_sum_bit
bool add();
void update_field(int offset);
const char *func_name() const { return "bit_and"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_and(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
/*
@@ -504,7 +509,7 @@ public:
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
virtual bool have_field_update(void) const { return 0; }
- void reset();
+ bool reset();
bool add();
void reset_field() {};
void update_field(int offset_arg) {};
@@ -524,7 +529,7 @@ class Item_sum_udf_float :public Item_udf_sum
double val();
String *val_str(String*str);
void fix_length_and_dec() { fix_num_length_and_dec(); }
- Item *copy_or_same(THD* thd) { return new Item_sum_udf_float(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -542,7 +547,7 @@ public:
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() { decimals=0; max_length=21; }
- Item *copy_or_same(THD* thd) { return new Item_sum_udf_int(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -571,7 +576,7 @@ public:
}
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
- Item *copy_or_same(THD* thd) { return new Item_sum_udf_str(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
#else /* Dummy functions to get sql_yacc.cc compiled */
@@ -586,10 +591,9 @@ class Item_sum_udf_float :public Item_sum_num
~Item_sum_udf_float() {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
double val() { return 0.0; }
- void reset() {}
+ bool reset() { return 0; }
bool add() { return 0; }
void update_field(int offset) {}
- Item *copy_or_same(THD* thd) { return new Item_sum_udf_float(thd, *this); }
};
@@ -604,10 +608,9 @@ public:
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
longlong val_int() { return 0; }
double val() { return 0; }
- void reset() {}
+ bool reset() { return 0; }
bool add() { return 0; }
void update_field(int offset) {}
- Item *copy_or_same(THD* thd) { return new Item_sum_udf_int(thd, *this); }
};
@@ -625,10 +628,9 @@ public:
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec() { maybe_null=1; max_length=0; }
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
- void reset() {}
+ bool reset() { return 0; }
bool add() { return 0; }
void update_field(int offset) {}
- Item *copy_or_same(THD* thd) { return new Item_sum_udf_str(thd, *this); }
};
#endif /* HAVE_DLOPEN */
@@ -676,7 +678,7 @@ class Item_func_group_concat : public Item_sum
warning(item.warning),
warning_available(item.warning_available),
separator(item.separator),
- tree(item.tree),
+ tree(item.tree),
table(item.table),
expr(item.expr),
order(item.order),
@@ -700,11 +702,12 @@ class Item_func_group_concat : public Item_sum
enum Type type() const { return SUM_FUNC_ITEM; }
void fix_length_and_dec() { max_length=group_concat_max_len; }
virtual Item_result result_type () const { return STRING_RESULT; }
- void reset();
+ bool reset();
bool add();
void reset_field();
bool fix_fields(THD *, TABLE_LIST *, Item **);
bool setup(THD *thd);
+ void make_unique();
virtual void update_field(int offset) {};
double val()
{
@@ -717,5 +720,5 @@ class Item_func_group_concat : public Item_sum
return res ? strtoll(res->c_ptr(),(char**) 0,10) : (longlong) 0;
}
String* val_str(String* str);
- Item *copy_or_same(THD* thd) { return new Item_func_group_concat(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index 5ffd10be7a5..f2c64c4bde9 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -41,7 +41,7 @@ public:
:Item_sum_num(thd, item) {}
double val() { return 0.0; }
enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;}
- void reset() {}
+ bool reset() { return 0;}
bool add() { return 0; }
void reset_field() {}
void update_field(int offset) {}
diff --git a/sql/lex.h b/sql/lex.h
index e89c9f51520..064bab8acbb 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -396,6 +396,7 @@ static SYMBOL symbols[] = {
{ "UNSIGNED", SYM(UNSIGNED),0,0},
{ "USE", SYM(USE_SYM),0,0},
{ "USE_FRM", SYM(USE_FRM),0,0},
+ { "USER", SYM(USER),0,0},
{ "USING", SYM(USING),0,0},
{ "UPDATE", SYM(UPDATE_SYM),0,0},
{ "USAGE", SYM(USAGE),0,0},
@@ -632,7 +633,6 @@ static SYMBOL sql_functions[] = {
{ "UNIQUE_USERS", SYM(UNIQUE_USERS),0,0},
{ "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP),0,0},
{ "UPPER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
- { "USER", SYM(USER),0,0},
{ "VARIANCE", SYM(VARIANCE_SYM),0,0},
{ "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
{ "WEEK", SYM(WEEK_SYM),0,0},
diff --git a/sql/log.cc b/sql/log.cc
index c05d52bdc5d..0ccb40c5246 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1200,6 +1200,12 @@ bool MYSQL_LOG::write(Log_event* event_info)
No check for auto events flag here - this write method should
never be called if auto-events are enabled
*/
+
+ /*
+ 1. Write first log events which describe the 'run environment'
+ of the SQL command
+ */
+
if (thd)
{
if (thd->last_insert_id_used)
@@ -1245,7 +1251,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
goto err;
}
}
-#if 0
+#ifdef TO_BE_REMOVED
if (thd->variables.convert_set)
{
char buf[256], *p;
@@ -1257,12 +1263,39 @@ bool MYSQL_LOG::write(Log_event* event_info)
goto err;
}
#endif
+
+ /*
+ If the user has set FOREIGN_KEY_CHECKS=0 we wrap every SQL
+ command in the binlog inside:
+ SET FOREIGN_KEY_CHECKS=0;
+ <command>;
+ SET FOREIGN_KEY_CHECKS=1;
+ */
+
+ if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
+ {
+ Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=0", 24, 0);
+ e.set_log_pos(this);
+ if (e.write(file))
+ goto err;
+ }
}
+
+ /* Write the SQL command */
+
event_info->set_log_pos(this);
- if (event_info->write(file) ||
- file == &log_file && flush_io_cache(file))
+ if (event_info->write(file))
goto err;
- error=0;
+
+ /* Write log events to reset the 'run environment' of the SQL command */
+
+ if (thd && thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
+ {
+ Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0);
+ e.set_log_pos(this);
+ if (e.write(file))
+ goto err;
+ }
/*
Tell for transactional table handlers up to which position in the
@@ -1283,6 +1316,9 @@ bool MYSQL_LOG::write(Log_event* event_info)
if (file == &log_file) // we are writing to the real log (disk)
{
+ if (flush_io_cache(file))
+ goto err;
+
if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log))
{
/*
@@ -1292,8 +1328,8 @@ bool MYSQL_LOG::write(Log_event* event_info)
handler if the log event type is appropriate.
*/
- if (event_info->get_type_code() == QUERY_EVENT
- || event_info->get_type_code() == EXEC_LOAD_EVENT)
+ if (event_info->get_type_code() == QUERY_EVENT ||
+ event_info->get_type_code() == EXEC_LOAD_EVENT)
{
error = ha_report_binlog_offset_and_commit(thd, log_file_name,
file->pos_in_file);
@@ -1303,6 +1339,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
/* we wrote to the real log, check automatic rotation */
should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size);
}
+ error=0;
err:
if (error)
@@ -1329,7 +1366,7 @@ err:
Flush the transactional handler log file now that we have released
LOCK_log; the flush is placed here to eliminate the bottleneck on the
group commit
- */
+ */
if (called_handler_commit)
ha_commit_complete(thd);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index fb690efc364..3d500ede462 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1573,9 +1573,27 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
else
{
char llbuff[22];
- enum enum_duplicates handle_dup = DUP_IGNORE;
+ enum enum_duplicates handle_dup;
if (sql_ex.opt_flags & REPLACE_FLAG)
handle_dup= DUP_REPLACE;
+ else if (sql_ex.opt_flags & IGNORE_FLAG)
+ handle_dup= DUP_IGNORE;
+ else
+ /*
+ Note that when replication is running fine, if it was DUP_ERROR on the
+ master then we could choose DUP_IGNORE here, because if DUP_ERROR
+ suceeded on master, and data is identical on the master and slave,
+ then there should be no uniqueness errors on slave, so DUP_IGNORE is
+ the same as DUP_ERROR. But in the unlikely case of uniqueness errors
+ (because the data on the master and slave happen to be different (user
+ error or bug), we want LOAD DATA to print an error message on the
+ slave to discover the problem.
+
+ If reading from net (a 3.23 master), mysql_load() will change this
+ to DUP_IGNORE.
+ */
+ handle_dup= DUP_ERROR;
+
sql_exchange ex((char*)fname, sql_ex.opt_flags & DUMPFILE_FLAG);
String field_term(sql_ex.field_term,sql_ex.field_term_len,log_cs);
String enclosed(sql_ex.enclosed,sql_ex.enclosed_len,log_cs);
@@ -1637,12 +1655,19 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
close_thread_tables(thd);
if (thd->query_error)
{
- int sql_error= thd->net.last_errno;
- if (!sql_error)
- sql_error= ER_UNKNOWN_ERROR;
- slave_print_error(rli,sql_error,
- "Error '%s' running LOAD DATA INFILE",
- ER_SAFE(sql_error));
+ /* this err/sql_errno code is copy-paste from send_error() */
+ const char *err;
+ int sql_errno;
+ if ((err=thd->net.last_error)[0])
+ sql_errno=thd->net.last_errno;
+ else
+ {
+ sql_errno=ER_UNKNOWN_ERROR;
+ err=ER(sql_errno);
+ }
+ slave_print_error(rli,sql_errno,
+ "Error '%s' running load data infile",
+ err);
free_root(&thd->mem_root,0);
return 1;
}
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index a59f1d4b81a..0508d0aa986 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -66,9 +66,8 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#endif
#endif
-extern CHARSET_INFO *system_charset_info;
-extern CHARSET_INFO *files_charset_info;
-extern CHARSET_INFO *national_charset_info;
+extern CHARSET_INFO *system_charset_info, *files_charset_info ;
+extern CHARSET_INFO *national_charset_info, *table_alias_charset;
/***************************************************************************
Configuration parameters
@@ -208,7 +207,7 @@ extern CHARSET_INFO *national_charset_info;
#define MODE_PIPES_AS_CONCAT 2
#define MODE_ANSI_QUOTES 4
#define MODE_IGNORE_SPACE 8
-#define MODE_SERIALIZABLE 16
+#define MODE_NOT_USED 16
#define MODE_ONLY_FULL_GROUP_BY 32
#define MODE_NO_UNSIGNED_SUBTRACTION 64
#define MODE_POSTGRESQL 128
@@ -221,6 +220,7 @@ extern CHARSET_INFO *national_charset_info;
#define MODE_NO_FIELD_OPTIONS 16384
#define MODE_MYSQL323 32768
#define MODE_MYSQL40 65536
+#define MODE_ANSI (MODE_MYSQL40*2)
#define RAID_BLOCK_SIZE 1024
@@ -461,7 +461,6 @@ bool mysql_rename_table(enum db_type base,
const char * old_name,
const char *new_db,
const char * new_name);
-bool close_cached_table(THD *thd,TABLE *table);
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list);
@@ -501,6 +500,7 @@ Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
bool check_grant,bool allow_rowid);
#ifdef HAVE_OPENSSL
+#include <openssl/des.h>
struct st_des_keyblock
{
des_cblock key1, key2, key3;
@@ -723,7 +723,7 @@ extern ulong ha_read_rnd_count, ha_read_rnd_next_count;
extern ulong ha_commit_count, ha_rollback_count,table_cache_size;
extern ulong max_connections,max_connect_errors, connect_timeout;
extern ulong max_insert_delayed_threads, max_user_connections;
-extern ulong long_query_count, what_to_log,flush_time,opt_sql_mode;
+extern ulong long_query_count, what_to_log,flush_time;
extern ulong query_buff_size, thread_stack,thread_stack_min;
extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
extern ulong max_binlog_size, rpl_recovery_rank, thread_cache_size;
@@ -837,7 +837,7 @@ uint calc_days_in_year(uint year);
void get_date_from_daynr(long daynr,uint *year, uint *month,
uint *day);
void init_time(void);
-long my_gmt_sec(TIME *);
+long my_gmt_sec(TIME *, long *current_timezone);
time_t str_to_timestamp(const char *str,uint length);
bool str_to_time(const char *str,uint length,TIME *l_time);
longlong str_to_datetime(const char *str,uint length,bool fuzzy_date);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 1a595c46e81..3f3b2ee7c9f 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -208,9 +208,9 @@ const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
const char *sql_mode_names[] =
{
"REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
- "SERIALIZE", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
+ "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
"POSTGRESQL", "ORACLE", "MSSQL", "DB2", "SAPDB", "NO_KEY_OPTIONS",
- "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40",
+ "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
NullS
};
TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
@@ -267,7 +267,7 @@ ulong slave_net_timeout;
ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
ulong query_cache_size=0;
ulong com_stat[(uint) SQLCOM_END], com_other;
-ulong bytes_sent, bytes_received;
+ulong bytes_sent, bytes_received, net_big_packet_count;
ulong refresh_version=1L,flush_version=1L; /* Increments on each reload */
ulong query_id, long_query_count, aborted_threads, aborted_connects;
ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
@@ -324,6 +324,9 @@ MY_TMPDIR mysql_tmpdir_list;
DATE_FORMAT dayord;
MY_BITMAP temp_pool;
+CHARSET_INFO *system_charset_info, *files_charset_info ;
+CHARSET_INFO *national_charset_info, *table_alias_charset;
+
SHOW_COMP_OPTION have_berkeley_db, have_innodb, have_isam;
SHOW_COMP_OPTION have_raid, have_openssl, have_symlink, have_query_cache;
SHOW_COMP_OPTION have_crypt, have_compress;
@@ -562,7 +565,7 @@ static void close_connections(void)
unix_sock= INVALID_SOCKET;
}
#endif
- end_thr_alarm(); // Don't allow alarms
+ end_thr_alarm(0); // Abort old alarms.
end_slave();
/* First signal all threads that it's time to die */
@@ -871,6 +874,7 @@ void clean_up(bool print_message)
#endif
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
end_key_cache();
+ end_thr_alarm(1); /* Free allocated memory */
#ifdef USE_RAID
end_raid();
#endif
@@ -936,7 +940,6 @@ static void clean_up_mutexes()
(void) pthread_mutex_destroy(&LOCK_crypt);
(void) pthread_mutex_destroy(&LOCK_bytes_sent);
(void) pthread_mutex_destroy(&LOCK_bytes_received);
- (void) pthread_mutex_destroy(&LOCK_timezone);
(void) pthread_mutex_destroy(&LOCK_user_conn);
#ifdef HAVE_REPLICATION
(void) pthread_mutex_destroy(&LOCK_rpl_status);
@@ -984,14 +987,21 @@ static void set_ports()
static void set_user(const char *user)
{
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
- struct passwd *ent;
+ struct passwd *ent;
+ uid_t user_id= geteuid();
// don't bother if we aren't superuser
- if (geteuid())
+ if (user_id)
{
if (user)
- fprintf(stderr,
- "Warning: One can only use the --user switch if running as root\n");
+ {
+ /* Don't give a warning, if real user is same as given with --user */
+ struct passwd *user_info= getpwnam(user);
+
+ if (!user_info || user_id != user_info->pw_uid)
+ fprintf(stderr,
+ "Warning: One can only use the --user switch if running as root\n");
+ }
return;
}
else if (!user)
@@ -1497,7 +1507,6 @@ the problem, but since we have already crashed, something is definitely wrong\n\
and this may fail.\n\n");
fprintf(stderr, "key_buffer_size=%lu\n", (ulong) keybuff_size);
fprintf(stderr, "read_buffer_size=%ld\n", global_system_variables.read_buff_size);
- fprintf(stderr, "sort_buffer_size=%ld\n", thd->variables.sortbuff_size);
fprintf(stderr, "max_used_connections=%ld\n", max_used_connections);
fprintf(stderr, "max_connections=%ld\n", max_connections);
fprintf(stderr, "threads_connected=%d\n", thread_count);
@@ -1505,7 +1514,7 @@ and this may fail.\n\n");
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\
bytes of memory\n", ((ulong) keybuff_size +
(global_system_variables.read_buff_size +
- thd->variables.sortbuff_size) *
+ global_system_variables.sortbuff_size) *
max_connections)/ 1024);
fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
@@ -1534,14 +1543,9 @@ the thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n\n",
Some pointers may be invalid and cause the dump to abort...\n");
safe_print_str("thd->query", thd->query, 1024);
fprintf(stderr, "thd->thread_id=%ld\n", thd->thread_id);
- fprintf(stderr, "\n\
-Successfully dumped variables, if you ran with --log, take a look at the\n\
-details of what thread %ld did to cause the crash. In some cases of really\n\
-bad corruption, the values shown above may be invalid.\n\n",
- thd->thread_id);
}
fprintf(stderr, "\
-The manual page at http://www.mysql.com/doc/C/r/Crashing.html contains\n\
+The manual page at http://www.mysql.com/doc/en/Crashing.html contains\n\
information that should help you find out what is causing the crash.\n");
fflush(stderr);
#endif /* HAVE_STACKTRACE */
@@ -1565,6 +1569,7 @@ information that should help you find out what is causing the crash.\n");
static void init_signals(void)
{
sigset_t set;
+ struct sigaction sa;
DBUG_ENTER("init_signals");
sigset(THR_KILL_SIGNAL,end_thread_signal);
@@ -1572,7 +1577,6 @@ static void init_signals(void)
if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
{
- struct sigaction sa;
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
sigemptyset(&sa.sa_mask);
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
@@ -1614,15 +1618,23 @@ static void init_signals(void)
sigaddset(&set,SIGQUIT);
sigaddset(&set,SIGTERM);
sigaddset(&set,SIGHUP);
- sigset(SIGTERM, print_signal_warning); // If it's blocked by parent
- sigset(SIGHUP, print_signal_warning); // If it's blocked by parent
+
+ /* Fix signals if blocked by parents (can happen on Mac OS X) */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = print_signal_warning;
+ sigaction(SIGTERM, &sa, (struct sigaction*) 0);
+ sa.sa_flags = 0;
+ sa.sa_handler = print_signal_warning;
+ sigaction(SIGHUP, &sa, (struct sigaction*) 0);
#ifdef SIGTSTP
sigaddset(&set,SIGTSTP);
#endif
sigaddset(&set,THR_SERVER_ALARM);
sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT
sigdelset(&set,THR_CLIENT_ALARM); // For alarms
- (void) pthread_sigmask(SIG_SETMASK,&set,NULL);
+ sigprocmask(SIG_SETMASK,&set,NULL);
+ pthread_sigmask(SIG_SETMASK,&set,NULL);
DBUG_VOID_RETURN;
}
@@ -1890,7 +1902,7 @@ extern "C" pthread_handler_decl(handle_shutdown,arg)
#endif
-const char *load_default_groups[]= { "mysqld","server",0 };
+const char *load_default_groups[]= { "mysqld","server",MYSQL_BASE_VERSION,0 };
bool open_log(MYSQL_LOG *log, const char *hostname,
const char *opt_name, const char *extension,
@@ -1947,19 +1959,11 @@ static int init_common_variables(const char *conf_file_name, int argc,
}
#endif
#ifdef HAVE_TZNAME
-#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
{
struct tm tm_tmp;
localtime_r(&start_time,&tm_tmp);
strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]);
}
-#else
- {
- struct tm *start_tm;
- start_tm=localtime(&start_time);
- strmov(time_zone,tzname[start_tm->tm_isdst != 0 ? 1 : 0]);
- }
-#endif
#endif
if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
@@ -2073,7 +2077,6 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
@@ -2282,9 +2285,7 @@ static void handle_connections_methods()
#endif /* __NT__ */
if (have_tcpip && !opt_disable_networking)
{
-#ifdef __NT__
handler_count++;
-#endif
if (pthread_create(&hThread,&connection_attrib,
handle_connections_sockets, 0))
{
@@ -2295,9 +2296,7 @@ static void handle_connections_methods()
#ifdef HAVE_SMEM
if (opt_enable_shared_memory)
{
-#ifdef __NT__
handler_count++;
-#endif
if (pthread_create(&hThread,&connection_attrib,
handle_connections_shared_memory, 0))
{
@@ -2312,6 +2311,16 @@ static void handle_connections_methods()
pthread_mutex_unlock(&LOCK_thread_count);
DBUG_VOID_RETURN;
}
+
+void decrement_handler_count()
+{
+ pthread_mutex_lock(&LOCK_thread_count);
+ handler_count--;
+ pthread_mutex_unlock(&LOCK_thread_count);
+ pthread_cond_signal(&COND_handler_count);
+}
+#else
+#define decrement_handler_count()
#endif /* defined(__NT__) || defined(HAVE_SMEM) */
@@ -2429,18 +2438,18 @@ The server will not act as a slave.");
#endif
/* init_slave() must be called after the thread keys are created */
init_slave();
-
+
if (opt_bootstrap)
{
int error=bootstrap(stdin);
- end_thr_alarm(); // Don't allow alarms
+ end_thr_alarm(1); // Don't allow alarms
unireg_abort(error ? 1 : 0);
}
if (opt_init_file)
{
if (read_init_file(opt_init_file))
{
- end_thr_alarm(); // Don't allow alarms
+ end_thr_alarm(1); // Don't allow alarms
unireg_abort(1);
}
}
@@ -2612,9 +2621,12 @@ int main(int argc, char **argv)
return 0;
if (Service.IsService(argv[2]))
{
- /* start an optional service */
+ /*
+ mysqld was started as
+ mysqld --defaults-file=my_path\my.ini service-name
+ */
use_opt_args=1;
- opt_argc=argc;
+ opt_argc= 2; // Skip service-name
opt_argv=argv;
start_mode= 1;
Service.Init(argv[2], mysql_service);
@@ -3020,13 +3032,7 @@ extern "C" pthread_handler_decl(handle_connections_sockets,
// kill server must be invoked from thread 1!
kill_server(MYSQL_KILL_SIGNAL);
#endif
-
-#ifdef __NT__
- pthread_mutex_lock(&LOCK_thread_count);
- handler_count--;
- pthread_mutex_unlock(&LOCK_thread_count);
- pthread_cond_signal(&COND_handler_count);
-#endif
+ decrement_handler_count();
DBUG_RETURN(0);
}
@@ -3106,10 +3112,7 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg)
create_new_thread(thd);
}
- pthread_mutex_lock(&LOCK_thread_count);
- handler_count--;
- pthread_mutex_unlock(&LOCK_thread_count);
- pthread_cond_signal(&COND_handler_count);
+ decrement_handler_count();
DBUG_RETURN(0);
}
#endif /* __NT__ */
@@ -3323,12 +3326,8 @@ error:
if (!handle_connect_file_map) CloseHandle(handle_connect_file_map);
if (!event_connect_answer) CloseHandle(event_connect_answer);
if (!event_connect_request) CloseHandle(event_connect_request);
-#ifdef __NT__
- pthread_mutex_lock(&LOCK_thread_count);
- handler_count--;
- pthread_mutex_unlock(&LOCK_thread_count);
- pthread_cond_signal(&COND_handler_count);
-#endif
+
+ decrement_handler_count();
DBUG_RETURN(0);
}
#endif /* HAVE_SMEM */
@@ -3922,7 +3921,7 @@ replicating a LOAD DATA INFILE command",
(gptr*) &opt_sql_bin_update, (gptr*) &opt_sql_bin_update, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"sql-mode", OPT_SQL_MODE,
- "Syntax: sql-mode=option[,option[,option...]] where option can be one of: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, SERIALIZE, ONLY_FULL_GROUP_BY, NO_UNSIGNED_SUBTRACTION.",
+ "Syntax: sql-mode=option[,option[,option...]] where option can be one of: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, ONLY_FULL_GROUP_BY, NO_UNSIGNED_SUBTRACTION.",
(gptr*) &sql_mode_str, (gptr*) &sql_mode_str, 0, GET_STR, REQUIRED_ARG, 0,
0, 0, 0, 0, 0},
#ifdef HAVE_OPENSSL
@@ -4635,6 +4634,12 @@ static void mysql_init_variables(void)
bzero((gptr) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
bzero((gptr) &com_stat, sizeof(com_stat));
+ /* Character sets */
+ system_charset_info= &my_charset_utf8_general_ci;
+ files_charset_info= &my_charset_utf8_general_ci;
+ national_charset_info= &my_charset_utf8_general_ci;
+ table_alias_charset= &my_charset_bin;
+
/* Things with default values that are not zero */
delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
opt_specialflag= SPECIAL_ENGLISH;
@@ -4685,6 +4690,7 @@ static void mysql_init_variables(void)
default_collation_name= (char*) MYSQL_DEFAULT_COLLATION_NAME;
sys_charset_system.value= (char*) system_charset_info->csname;
+
/* Set default values for some option variables */
global_system_variables.character_set_server= default_charset_info;
global_system_variables.character_set_database= default_charset_info;
@@ -4792,10 +4798,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt_endinfo=1; /* unireg: memory allocation */
break;
case 'a':
- global_system_variables.sql_mode=
- (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT |
- MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_SERIALIZABLE |
- MODE_ONLY_FULL_GROUP_BY);
+ global_system_variables.sql_mode= fix_sql_mode(MODE_ANSI);
global_system_variables.tx_isolation= ISO_SERIALIZABLE;
break;
case 'b':
@@ -5273,11 +5276,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
fprintf(stderr, "Unknown option to sql-mode: %s\n", argument);
exit(1);
}
- global_system_variables.tx_isolation=
- ((global_system_variables.sql_mode & MODE_SERIALIZABLE) ?
- ISO_SERIALIZABLE :
- ISO_REPEATABLE_READ);
- break;
+ global_system_variables.sql_mode= fix_sql_mode(global_system_variables.
+ sql_mode);
}
case OPT_MASTER_PASSWORD:
master_password=argument;
@@ -5335,6 +5335,9 @@ static void get_options(int argc,char **argv)
/* Set global variables based on startup options */
myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
+ table_alias_charset= (lower_case_table_names ?
+ files_charset_info :
+ &my_charset_bin);
}
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 8271d971782..eb4d76bbf6e 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -15,6 +15,13 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
+ This file is the net layer API for the MySQL client/server protocol,
+ which is a tightly coupled, proprietary protocol owned by MySQL AB.
+ Any re-implementations of this protocol must also be under GPL
+ unless one has got an license from MySQL AB stating otherwise.
+*/
+
+/*
Write and read of logical packets to/from socket
Writes are cached into net_buffer_length big packets.
@@ -66,11 +73,13 @@ void sql_print_error(const char *format,...);
#define USE_QUERY_CACHE
extern uint test_flags;
extern void query_cache_insert(NET *net, const char *packet, ulong length);
-extern ulong bytes_sent, bytes_received;
+extern ulong bytes_sent, bytes_received, net_big_packet_count;
extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
#else
#undef statistic_add
+#undef statistic_increment
#define statistic_add(A,B,C)
+#define statistic_increment(A,B)
#endif
#define TEST_BLOCKING 8
@@ -555,7 +564,7 @@ static my_bool net_safe_read(NET *net, char *buff, uint32 length,
if ((tmp=vio_read(net->vio,(char*) net->buff, length)) <= 0)
{
my_bool interrupted = vio_should_retry(net->vio);
- if (!thr_got_alarm(&alarmed) && interrupted)
+ if (!thr_got_alarm(alarmed) && interrupted)
{ /* Probably in MIT threads */
if (retry_count++ < net->retry_count)
continue;
@@ -589,10 +598,13 @@ static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed,
DBUG_ENTER("my_net_skip_rest");
DBUG_PRINT("enter",("bytes_to_skip: %u", (uint) remain));
- if (!thr_alarm_in_use(&alarmed))
+ /* The following is good for debugging */
+ statistic_increment(net_big_packet_count,&LOCK_bytes_received);
+
+ if (!thr_alarm_in_use(alarmed))
{
my_bool old_mode;
- if (!thr_alarm(alarmed,net->read_timeout, alarm_buff) ||
+ if (thr_alarm(alarmed,net->read_timeout, alarm_buff) ||
vio_blocking(net->vio, TRUE, &old_mode) < 0)
DBUG_RETURN(1); /* Can't setup, abort */
}
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 7abbf3ce85b..10fe2c1725e 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -102,7 +102,8 @@ void send_error(THD *thd, uint sql_errno, const char *err)
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
/* The first # is to make the protocol backward compatible */
- strmov(buff+2, "#000000");
+ buff[2]= '#';
+ strmov(buff+3, mysql_errno_to_sqlstate(sql_errno));
pos= buff + 2 + SQLSTATE_LENGTH +1;
}
length= (uint) (strmake(pos, err, MYSQL_ERRMSG_SIZE-1) - buff);
@@ -222,8 +223,8 @@ net_printf(THD *thd, uint errcode, ...)
int2store(pos, errcode);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
- /* The first # is to make the protocol backward compatible */
- memcpy(pos+2, "#000000", SQLSTATE_LENGTH +1);
+ pos[2]= '#'; /* To make the protocol backward compatible */
+ memcpy(pos+3, mysql_errno_to_sqlstate(errcode), SQLSTATE_LENGTH);
}
}
VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset));
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 60b0d24430d..ad3966f76f9 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -89,6 +89,7 @@ static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
static void fix_key_buffer_size(THD *thd, enum_var_type type);
static void fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type);
static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
+void fix_sql_mode_var(THD *thd, enum_var_type type);
static byte *get_error_count(THD *thd);
static byte *get_warning_count(THD *thd);
@@ -207,6 +208,7 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count",
sys_var_thd_bool sys_new_mode("new", &SV::new_mode);
sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
&SV::read_buff_size);
+sys_var_bool_ptr sys_readonly("read_only", &opt_readonly);
sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size",
&SV::read_rnd_buff_size);
#ifdef HAVE_REPLICATION
@@ -235,7 +237,6 @@ sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol",
sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout",
&slave_net_timeout);
#endif
-sys_var_bool_ptr sys_readonly("read_only", &opt_readonly);
sys_var_long_ptr sys_slow_launch_time("slow_launch_time",
&slow_launch_time);
sys_var_thd_ulong sys_sort_buffer("sort_buffer_size",
@@ -599,6 +600,7 @@ struct show_var_st init_vars[]= {
{"protocol_version", (char*) &protocol_version, SHOW_INT},
{sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS},
{sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS},
+ {sys_readonly.name, (char*) &sys_readonly, SHOW_SYS},
{sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS},
#ifdef HAVE_REPLICATION
{sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS},
@@ -1168,40 +1170,6 @@ byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type)
}
-byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type)
-{
- ulong val;
- char buff[256];
- String tmp(buff, sizeof(buff), &my_charset_latin1);
- my_bool found= 0;
-
- tmp.length(0);
- val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
- thd->variables.*offset);
- for (uint i= 0; val; val>>= 1, i++)
- {
- if (val & 1)
- {
- tmp.append(enum_names->type_names[i]);
- tmp.append(',');
- }
- }
- if (tmp.length())
- tmp.length(tmp.length() - 1);
- return (byte*) thd->strmake(tmp.ptr(), tmp.length());
-}
-
-
-void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type)
-{
- if (type == OPT_GLOBAL)
- global_system_variables.*offset= 0;
- else
- thd->variables.*offset= global_system_variables.*offset;
-}
-
-
-
bool sys_var_thd_bit::update(THD *thd, set_var *var)
{
int res= (*update_func)(thd, var);
@@ -1857,7 +1825,105 @@ int set_var_password::update(THD *thd)
1 : 0);
}
+/****************************************************************************
+ Functions to handle sql_mode
+****************************************************************************/
+
+byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type)
+{
+ ulong val;
+ char buff[256];
+ String tmp(buff, sizeof(buff), &my_charset_latin1);
+ my_bool found= 0;
+
+ tmp.length(0);
+ val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
+ thd->variables.*offset);
+ for (uint i= 0; val; val>>= 1, i++)
+ {
+ if (val & 1)
+ {
+ tmp.append(enum_names->type_names[i]);
+ tmp.append(',');
+ }
+ }
+ if (tmp.length())
+ tmp.length(tmp.length() - 1);
+ return (byte*) thd->strmake(tmp.ptr(), tmp.length());
+}
+
+
+void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ global_system_variables.*offset= 0;
+ else
+ thd->variables.*offset= global_system_variables.*offset;
+}
+
+void fix_sql_mode_var(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ global_system_variables.sql_mode=
+ fix_sql_mode(global_system_variables.sql_mode);
+ else
+ thd->variables.sql_mode= fix_sql_mode(thd->variables.sql_mode);
+}
+
+/* Map database specific bits to function bits */
+ulong fix_sql_mode(ulong sql_mode)
+{
+ /*
+ Note that we dont set
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS
+ to allow one to get full use of MySQL in this mode.
+ */
+
+ if (sql_mode & MODE_ANSI)
+ sql_mode|= (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE | MODE_ONLY_FULL_GROUP_BY);
+ if (sql_mode & MODE_ORACLE)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_MSSQL)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_MSSQL)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_POSTGRESQL)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_DB2)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_DB2)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_SAPDB)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_MYSQL40)
+ sql_mode|= MODE_NO_FIELD_OPTIONS;
+ if (sql_mode & MODE_MYSQL323)
+ sql_mode|= MODE_NO_FIELD_OPTIONS;
+ return sql_mode;
+}
diff --git a/sql/set_var.h b/sql/set_var.h
index d016c3a7085..998d61ff2d1 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -309,11 +309,14 @@ public:
};
+extern void fix_sql_mode_var(THD *thd, enum_var_type type);
+
class sys_var_thd_sql_mode :public sys_var_thd_enum
{
public:
sys_var_thd_sql_mode(const char *name_arg, ulong SV::*offset_arg)
- :sys_var_thd_enum(name_arg, offset_arg, &sql_mode_typelib)
+ :sys_var_thd_enum(name_arg, offset_arg, &sql_mode_typelib,
+ fix_sql_mode_var)
{}
bool check(THD *thd, set_var *var)
{
@@ -636,6 +639,7 @@ void set_var_free();
sys_var *find_sys_var(const char *str, uint length=0);
int sql_set_variables(THD *thd, List<set_var_base> *var_list);
void fix_delay_key_write(THD *thd, enum_var_type type);
+ulong fix_sql_mode(ulong sql_mode);
extern sys_var_str sys_charset_system;
CHARSET_INFO *get_old_charset_by_name(const char *old_name);
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index e277c19e26f..273dfa0fcf5 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -271,3 +271,5 @@ v/*
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 01856ffed01..1d39a328154 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -265,3 +265,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 4b9b0b9f710..5b79f06b621 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -273,3 +273,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 89045b13985..ad15d55405f 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -267,3 +267,5 @@
"Data truncated for column '%s' at row %ld"
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index d5064b53790..506b5fc0188 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -267,3 +267,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index eb936243332..8882e4dceda 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -262,3 +262,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 2ac25216b8e..1e8f5bb2c05 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -271,3 +271,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 8e82559db5c..d322f3fbd6a 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -262,3 +262,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index de0e7da614e..162bfc5509c 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -264,3 +264,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index d9308faf8a6..26d916a968d 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -262,3 +262,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 45e78941906..a01a2b7ff6f 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -264,3 +264,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 43d291ae3a5..5f5526be04b 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -262,3 +262,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index c0c045438ec..bf1019d3d87 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -264,3 +264,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 03430ae546b..68c95bbf22b 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -264,3 +264,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 997ee08e66a..5b93403c757 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -266,3 +266,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index ef051d957cb..edd3e3b813f 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -262,3 +262,5 @@
"%d linha(s) foi(foram) cortada(s) por group_concat()",
"Usando engine de armazenamento %s para tabela '%s'",
"Combinação ilegal de collations (%s,%s) e (%s,%s) para operação '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 89c00b4bf15..873a708fa7b 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -266,3 +266,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index fac4dedb3ee..a05ecde6808 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -264,3 +264,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index d954e7998a2..c1c0de779c7 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -258,3 +258,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 8f7747c6bf6..26d673b847c 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -270,3 +270,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 4a7989ce7be..99a92f63c4e 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -263,3 +263,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 6734369d3ac..c613d205947 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -262,3 +262,5 @@
"%d rad(er) kapades av group_concat()",
"Använder handler %s för tabell '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 67c52dc8fee..6505c3c9cac 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -267,3 +267,5 @@
"%d line(s) was(were) cut by group_concat()",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
+"Can't drop one or more of the requested users"
+"Can't revoke all privileges, grant for one or more of the requested users"
diff --git a/sql/slave.cc b/sql/slave.cc
index 22c47bbdd05..cc27bb96ab7 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -287,7 +287,7 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
goto err;
rli->cur_log = &rli->cache_buf;
}
- if (pos > BIN_LOG_HEADER_SIZE)
+ if (pos >= BIN_LOG_HEADER_SIZE)
my_b_seek(rli->cur_log,(off_t)pos);
err:
@@ -1388,9 +1388,7 @@ static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli)
while (rli->log_space_limit < rli->log_space_total &&
!(slave_killed=io_slave_killed(thd,mi)) &&
!rli->ignore_log_space_limit)
- {
pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock);
- }
thd->proc_info = save_proc_info;
pthread_mutex_unlock(&rli->log_space_lock);
DBUG_RETURN(slave_killed);
@@ -2101,7 +2099,11 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
Log_event * ev = next_event(rli);
DBUG_ASSERT(rli->sql_thd==thd);
if (sql_slave_killed(thd,rli))
+ {
+ /* do not forget to free ev ! */
+ if (ev) delete ev;
return 1;
+ }
if (ev)
{
int type_code = ev->get_type_code();
@@ -2152,8 +2154,13 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
else
{
sql_print_error("\
-Could not parse log event entry, check the master for binlog corruption\n\
-This may also be a network problem, or just a bug in the master or slave code.\
+Could not parse relay log event entry. The possible reasons are: the master's \
+binary log is corrupted (you can check this by running 'mysqlbinlog' on the \
+binary log), the slave's relay log is corrupted (you can check this by running \
+'mysqlbinlog' on the relay log), a network problem, or a bug in the master's \
+or slave's MySQL code. If you want to check the master's binary log or slave's \
+relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' \
+on this slave.\
");
return 1;
}
@@ -2376,6 +2383,18 @@ reconnect done to recover from failed read");
goto err;
}
flush_master_info(mi);
+ /*
+ See if the relay logs take too much space.
+ We don't lock mi->rli.log_space_lock here; this dirty read saves time
+ and does not introduce any problem:
+ - if mi->rli.ignore_log_space_limit is 1 but becomes 0 just after (so
+ the clean value is 0), then we are reading only one more event as we
+ should, and we'll block only at the next event. No big deal.
+ - if mi->rli.ignore_log_space_limit is 0 but becomes 1 just after (so
+ the clean value is 1), then we are going into wait_for_relay_log_space()
+ for no reason, but this function will do a clean read, notice the clean
+ value and exit immediately.
+ */
if (mi->rli.log_space_limit && mi->rli.log_space_limit <
mi->rli.log_space_total &&
!mi->rli.ignore_log_space_limit)
@@ -2489,7 +2508,9 @@ slave_begin:
pthread_cond_broadcast(&rli->start_cond);
//tell the I/O thread to take relay_log_space_limit into account from now on
+ pthread_mutex_lock(&rli->log_space_lock);
rli->ignore_log_space_limit= 0;
+ pthread_mutex_unlock(&rli->log_space_lock);
if (init_relay_log_pos(rli,
rli->group_relay_log_name,
@@ -3223,7 +3244,12 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
pthread_mutex_lock(&rli->log_space_lock);
// prevent the I/O thread from blocking next times
rli->ignore_log_space_limit= 1;
- // If the I/O thread is blocked, unblock it
+ /*
+ If the I/O thread is blocked, unblock it.
+ Ok to broadcast after unlock, because the mutex is only destroyed in
+ ~st_relay_log_info(), i.e. when rli is destroyed, and rli will not be
+ destroyed before we exit the present function.
+ */
pthread_mutex_unlock(&rli->log_space_lock);
pthread_cond_broadcast(&rli->log_space_cond);
// Note that wait_for_update unlocks lock_log !
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index ec6db64ea73..49aad321702 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2179,11 +2179,6 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
{
int error;
GRANT_TABLE *grant_table;
- if (!Str->host.str)
- {
- Str->host.str=(char*) "%";
- Str->host.length=1;
- }
if (Str->host.length > HOSTNAME_LENGTH ||
Str->user.length > USERNAME_LENGTH)
{
@@ -2350,11 +2345,6 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list,
int result=0;
while ((Str = str_list++))
{
- if (!Str->host.str)
- {
- Str->host.str=(char*) "%";
- Str->host.length=1;
- }
if (Str->host.length > HOSTNAME_LENGTH ||
Str->user.length > USERNAME_LENGTH)
{
@@ -2855,11 +2845,6 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
send_error(thd, ER_UNKNOWN_COM_ERROR);
DBUG_RETURN(-1);
}
- if (!lex_user->host.str)
- {
- lex_user->host.str=(char*) "%";
- lex_user->host.length=1;
- }
if (lex_user->host.length > HOSTNAME_LENGTH ||
lex_user->user.length > USERNAME_LENGTH)
{
@@ -3202,6 +3187,279 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc)
bzero((char*) &uc->user_resources, sizeof(uc->user_resources));
}
+int open_grant_tables(THD *thd, TABLE_LIST *tables)
+{
+ DBUG_ENTER("open_grant_tables");
+
+ if (!initialized)
+ {
+ send_error(thd, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES));
+ DBUG_RETURN(-1);
+ }
+
+ bzero((char*) tables, 4*sizeof(*tables));
+ tables->alias= tables->real_name= (char*) "user";
+ (tables+1)->alias= (tables+1)->real_name= (char*) "db";
+ (tables+2)->alias= (tables+2)->real_name= (char*) "tables_priv";
+ (tables+3)->alias= (tables+3)->real_name= (char*) "columns_priv";
+ tables->next= tables+1;
+ (tables+1)->next= tables+2;
+ (tables+2)->next= tables+3;
+ (tables+3)->next= 0;
+ tables->lock_type= (tables+1)->lock_type=
+ (tables+2)->lock_type= (tables+3)->lock_type= TL_WRITE;
+ tables->db= (tables+1)->db= (tables+2)->db= (tables+3)->db=(char*) "mysql";
+
+#ifdef HAVE_REPLICATION
+ /*
+ GRANT and REVOKE are applied the slave in/exclusion rules as they are
+ some kind of updates to the mysql.% tables.
+ */
+ if (thd->slave_thread && table_rules_on && !tables_ok(0, tables))
+ DBUG_RETURN(1);
+#endif
+
+ if (open_and_lock_tables(thd, tables))
+ { // This should never happen
+ close_thread_tables(thd);
+ DBUG_RETURN(-1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+ACL_USER *check_acl_user(LEX_USER *user_name,
+ uint *acl_user_idx)
+{
+ ACL_USER *acl_user= 0;
+ uint counter;
+
+ for (counter= 0 ; counter < acl_users.elements ; counter++)
+ {
+ const char *user,*host;
+ acl_user= dynamic_element(&acl_users, counter, ACL_USER*);
+ if (!(user=acl_user->user))
+ user="";
+ if (!(host=acl_user->host.hostname))
+ host="%";
+ if (!strcmp(user_name->user.str,user) &&
+ !my_strcasecmp(system_charset_info, user_name->host.str, host))
+ break;
+ }
+ if (counter == acl_users.elements)
+ return 0;
+
+ *acl_user_idx= counter;
+ return acl_user;
+}
+
+int mysql_drop_user(THD *thd, List <LEX_USER> &list)
+{
+ uint counter, user_id;
+ int result;
+ ACL_USER *acl_user;
+ ACL_DB *acl_db;
+ TABLE_LIST tables[4];
+
+ DBUG_ENTER("mysql_drop_user");
+
+ if ((result= open_grant_tables(thd, tables)))
+ DBUG_RETURN(result == 1 ? 0 : -1);
+
+ rw_wrlock(&LOCK_grant);
+ VOID(pthread_mutex_lock(&acl_cache->lock));
+
+ LEX_USER *user_name;
+ List_iterator <LEX_USER> user_list(list);
+ while ((user_name=user_list++))
+ {
+ if (!(acl_user= check_acl_user(user_name, &counter)))
+ {
+ sql_print_error("DROP USER: Can't drop user: '%s'@'%s'",
+ user_name->user.str,
+ user_name->host.str);
+ result= -1;
+ continue;
+ }
+ if ((acl_user->access & ~0))
+ {
+ sql_print_error("DROP USER: Can't drop user: '%s'@'%s'",
+ user_name->user.str,
+ user_name->host.str);
+ result= -1;
+ continue;
+ }
+ user_id= counter;
+
+ for (counter= 0 ; counter < acl_dbs.elements ; counter++)
+ {
+ const char *user,*host;
+ acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*);
+ if (!(user= acl_db->user))
+ user="";
+ if (!(host= acl_db->host.hostname))
+ host="";
+
+ if (!strcmp(user_name->user.str,user) &&
+ !my_strcasecmp(system_charset_info, user_name->host.str, host))
+ break;
+ }
+ if (counter != acl_dbs.elements)
+ {
+ sql_print_error("DROP USER: Can't drop user: '%s'@'%s'",
+ user_name->user.str,
+ user_name->host.str);
+ result= -1;
+ continue;
+ }
+
+ for (counter= 0 ; counter < column_priv_hash.records ; counter++)
+ {
+ const char *user,*host;
+ GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
+ counter);
+ if (!(user=grant_table->user))
+ user="";
+ if (!(host=grant_table->host))
+ host="";
+
+ if (!strcmp(user_name->user.str,user) &&
+ !my_strcasecmp(system_charset_info, user_name->host.str, host))
+ break;
+ }
+ if (counter != column_priv_hash.records)
+ {
+ sql_print_error("DROP USER: Can't drop user: '%s'@'%s'",
+ user_name->user.str,
+ user_name->host.str);
+ result= -1;
+ continue;
+ }
+
+ tables[0].table->field[0]->store(user_name->host.str,(uint)
+ user_name->host.length, system_charset_info);
+ tables[0].table->field[1]->store(user_name->user.str,(uint)
+ user_name->user.length, system_charset_info);
+ if (!tables[0].table->file->index_read_idx(tables[0].table->record[0],0,
+ (byte*) tables[0].table->field[0]->ptr,0,
+ HA_READ_KEY_EXACT))
+ {
+ int error;
+ if ((error = tables[0].table->file->delete_row(tables[0].table->record[0])))
+ {
+ tables[0].table->file->print_error(error, MYF(0));
+ tables[0].table->file->index_end();
+ DBUG_RETURN(-1);
+ }
+ delete_dynamic_element(&acl_users, user_id);
+ }
+ tables[0].table->file->index_end();
+ }
+err:
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
+ rw_unlock(&LOCK_grant);
+ close_thread_tables(thd);
+ if (result)
+ my_error(ER_DROP_USER, MYF(0));
+ DBUG_RETURN(result);
+}
+
+int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
+{
+ uint counter;
+ int result;
+ ACL_USER *acl_user; ACL_DB *acl_db;
+ TABLE_LIST tables[4];
+ DBUG_ENTER("mysql_revoke_all");
+
+ if ((result= open_grant_tables(thd, tables)))
+ DBUG_RETURN(result == 1 ? 0 : -1);
+
+ rw_wrlock(&LOCK_grant);
+ VOID(pthread_mutex_lock(&acl_cache->lock));
+
+ LEX_USER *lex_user;
+ List_iterator <LEX_USER> user_list(list);
+ while ((lex_user=user_list++))
+ {
+ if (!(acl_user= check_acl_user(lex_user, &counter)))
+ {
+ sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' not exists",
+ lex_user->user.str,
+ lex_user->host.str);
+ result= -1;
+ continue;
+ }
+
+ if (replace_user_table(thd, tables[0].table,
+ *lex_user, ~0, 1, 0))
+ {
+ result= -1;
+ continue;
+ }
+
+ /* Remove db access privileges */
+ for (counter= 0 ; counter < acl_dbs.elements ; counter++)
+ {
+ const char *user,*host;
+
+ acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*);
+ if (!(user=acl_db->user))
+ user="";
+ if (!(host=acl_db->host.hostname))
+ host="";
+
+ if (!strcmp(lex_user->user.str,user) &&
+ !my_strcasecmp(system_charset_info, lex_user->host.str, host))
+ {
+ if (replace_db_table(tables[1].table, acl_db->db, *lex_user, ~0, 1))
+ result= -1;
+ }
+ }
+
+ /* Remove column access */
+ for (counter= 0 ; counter < column_priv_hash.records ; counter++)
+ {
+ const char *user,*host;
+ GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
+ counter);
+ if (!(user=grant_table->user))
+ user="";
+ if (!(host=grant_table->host))
+ host="";
+
+ if (!strcmp(lex_user->user.str,user) &&
+ !my_strcasecmp(system_charset_info, lex_user->host.str, host))
+ {
+ if (replace_table_table(thd,grant_table,tables[2].table,*lex_user,
+ grant_table->db,
+ grant_table->tname,
+ ~0, 0, 1))
+ {
+ result= -1;
+ continue;
+ }
+ if (grant_table->cols)
+ {
+ List<LEX_COLUMN> columns;
+ if (replace_column_table(grant_table,tables[3].table, *lex_user,
+ columns,
+ grant_table->db,
+ grant_table->tname,
+ ~0, 1))
+ result= -1;
+ }
+ }
+ }
+ }
+
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
+ rw_unlock(&LOCK_grant);
+ close_thread_tables(thd);
+ if (result)
+ my_error(ER_REVOKE_GRANTS, MYF(0));
+ DBUG_RETURN(result);
+}
/*****************************************************************************
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index d85a281cbb5..e6c6771253c 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -163,3 +163,5 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field);
int mysql_show_grants(THD *thd, LEX_USER *user);
void get_privilege_desc(char *to, uint max_length, ulong access);
void get_mqh(const char *user, const char *host, USER_CONN *uc);
+int mysql_drop_user(THD *thd, List <LEX_USER> &list);
+int mysql_revoke_all(THD *thd, List <LEX_USER> &list);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 81c620fdaf4..1ef4e9df020 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -544,7 +544,8 @@ TABLE_LIST * find_table_in_list(TABLE_LIST *table,
{
for (; table; table= table->next)
if ((!db_name || !strcmp(table->db, db_name)) &&
- (!table_name || !strcmp(table->alias, table_name)))
+ (!table_name || !my_strcasecmp(table_alias_charset,
+ table->alias, table_name)))
break;
return table;
}
@@ -1739,7 +1740,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
bool found_table=0;
for (; tables ; tables=tables->next)
{
- if (!strcmp(tables->alias,table_name) &&
+ if (!my_strcasecmp(table_alias_charset, tables->alias, table_name) &&
(!db || !tables->db || !tables->db[0] || !strcmp(db,tables->db)))
{
found_table=1;
@@ -1868,20 +1869,22 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
{
List_iterator<Item> li(items);
Item **found=0,*item;
+ const char *db_name=0;
const char *field_name=0;
const char *table_name=0;
if (find->type() == Item::FIELD_ITEM || find->type() == Item::REF_ITEM)
{
field_name= ((Item_ident*) find)->field_name;
table_name= ((Item_ident*) find)->table_name;
+ db_name= ((Item_ident*) find)->db_name;
}
for (uint i= 0; (item=li++); i++)
{
if (field_name && item->type() == Item::FIELD_ITEM)
{
- if (!my_strcasecmp(system_charset_info,
- ((Item_field*) item)->name,field_name))
+ Item_field *item_field= (Item_field*) item;
+ if (!my_strcasecmp(system_charset_info, item_field->name, field_name))
{
if (!table_name)
{
@@ -1897,11 +1900,16 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
found= li.ref();
*counter= i;
}
- else if (!strcmp(((Item_field*) item)->table_name,table_name))
+ else
{
- found= li.ref();
- *counter= i;
- break;
+ if (!strcmp(item_field->table_name,table_name) &&
+ (!db_name || (db_name && item_field->db_name &&
+ !strcmp(item_field->table_name,table_name))))
+ {
+ found= li.ref();
+ *counter= i;
+ break;
+ }
}
}
}
@@ -2094,7 +2102,8 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
for (; tables ; tables=tables->next)
{
TABLE *table=tables->table;
- if (!table_name || (!strcmp(table_name,tables->alias) &&
+ if (!table_name || (!my_strcasecmp(table_alias_charset, table_name,
+ tables->alias) &&
(!db_name || !strcmp(tables->db,db_name))))
{
/* Ensure that we have access right to all columns */
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index adc3d177fdf..ac6471e794c 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -739,7 +739,7 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
query_cache_size_arg));
free_cache(0);
query_cache_size= query_cache_size_arg;
- DBUG_RETURN(init_cache());
+ DBUG_RETURN(::query_cache_size= init_cache());
}
@@ -1318,6 +1318,12 @@ ulong Query_cache::init_cache()
mem_bin_steps = 1;
mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
prev_size = 0;
+ if (mem_bin_size <= min_allocation_unit)
+ {
+ DBUG_PRINT("qcache", ("too small query cache => query cache disabled"));
+ // TODO here (and above) should be warning in 4.1
+ goto err;
+ }
while (mem_bin_size > min_allocation_unit)
{
mem_bin_num += mem_bin_count;
@@ -1344,14 +1350,6 @@ ulong Query_cache::init_cache()
query_cache_size -= additional_data_size;
STRUCT_LOCK(&structure_guard_mutex);
- if (max_mem_bin_size <= min_allocation_unit)
- {
- DBUG_PRINT("qcache",
- (" max bin size (%lu) <= min_allocation_unit => cache disabled",
- max_mem_bin_size));
- STRUCT_UNLOCK(&structure_guard_mutex);
- goto err;
- }
if (!(cache = (byte *)
my_malloc_lock(query_cache_size+additional_data_size, MYF(0))))
@@ -1432,7 +1430,8 @@ ulong Query_cache::init_cache()
#else
// windows, OS/2 or other case insensitive file names work around
VOID(hash_init(&tables,
- lower_case_table_names ? &my_charset_bin : system_charset_info,
+ lower_case_table_names ? &my_charset_bin :
+ system_charset_info,
def_table_hash_size, 0, 0,query_cache_table_get_key, 0, 0));
#endif
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 9003d4b36cd..ba7c08ff15f 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -553,14 +553,14 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
String **pointers= (String**)alloc_root(mem_root,
sizeof(String*)*names->elements);
- String **pos= pointers;
+ String **pos;
+ String **end= pointers + names->elements;
List_iterator<String> it(*names);
- while ((*pos++= it++));
+ for ( pos= pointers; pos!=end; (*pos++= it++));
qsort(pointers,names->elements,sizeof(String*),string_ptr_cmp);
- String **end= pointers + names->elements;
for (pos= pointers; pos!=end; pos++)
{
protocol->prepare_for_resend();
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index c3a399cd5a7..f65ef4b968a 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1421,6 +1421,24 @@ void select_insert::send_error(uint errcode,const char *err)
::send_error(thd,errcode,err);
table->file->extra(HA_EXTRA_NO_CACHE);
table->file->activate_all_index(thd);
+ /*
+ If at least one row has been inserted/modified and will stay in the table
+ (the table doesn't have transactions) (example: we got a duplicate key
+ error while inserting into a MyISAM table) we must write to the binlog (and
+ the error code will make the slave stop).
+ */
+ if ((info.copied || info.deleted) && !table->file->has_transactions())
+ {
+ if (last_insert_id)
+ thd->insert_id(last_insert_id); // For binary log
+ mysql_update_log.write(thd,thd->query,thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ table->file->has_transactions());
+ mysql_bin_log.write(&qinfo);
+ }
+ }
if (info.copied || info.deleted)
query_cache_invalidate3(thd, table, 1);
ha_rollback_stmt(thd);
@@ -1442,7 +1460,10 @@ bool select_insert::send_eof()
if (info.copied || info.deleted)
query_cache_invalidate3(thd, table, 1);
+ if (last_insert_id)
+ thd->insert_id(last_insert_id); // For binary log
/* Write to binlog before commiting transaction */
+ mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
@@ -1467,10 +1488,7 @@ bool select_insert::send_eof()
else
sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted,
thd->cuted_fields);
- if (last_insert_id)
- thd->insert_id(last_insert_id); // For update log
::send_ok(thd,info.copied+info.deleted,last_insert_id,buff);
- mysql_update_log.write(thd,thd->query,thd->query_length);
return 0;
}
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index f31b3305e07..a01c98bb283 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -71,7 +71,7 @@ enum enum_sql_command {
SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_TABLE_TYPES, SQLCOM_SHOW_PRIVILEGES,
- SQLCOM_HELP,
+ SQLCOM_HELP, SQLCOM_DROP_USER, SQLCOM_REVOKE_ALL,
/* This should be the last !!! */
SQLCOM_END
diff --git a/sql/sql_list.h b/sql/sql_list.h
index ff21663576a..2450b2051f2 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -33,6 +33,8 @@ public:
{
return (void*) sql_alloc((uint) size);
}
+ static void *operator new(size_t size, MEM_ROOT *mem_root)
+ { return (void*) alloc_root(mem_root, (uint) size); }
static void operator delete(void *ptr, size_t size) {} /*lint -e715 */
static void operator delete[](void *ptr, size_t size) {}
#ifdef HAVE_purify
@@ -190,6 +192,7 @@ public:
inline void *replace(void *element)
{ // Return old element
void *tmp=current->info;
+ DBUG_ASSERT(current->info != 0);
current->info=element;
return tmp;
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f098ce0d0b6..a9a29904b60 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -891,7 +891,11 @@ pthread_handler_decl(handle_one_connection,arg)
send_error(thd,net->last_errno,NullS);
statistic_increment(aborted_threads,&LOCK_status);
}
-
+ else if (thd->killed)
+ {
+ statistic_increment(aborted_threads,&LOCK_status);
+ }
+
end_thread:
close_connection(thd, 0, 1);
end_thread(thd,1);
@@ -1068,7 +1072,10 @@ bool do_command(THD *thd)
vio_description(net->vio)));
/* Check if we can continue without closing the connection */
if (net->error != 3)
+ {
+ statistic_increment(aborted_threads,&LOCK_status);
DBUG_RETURN(TRUE); // We have to close it.
+ }
send_error(thd,net->last_errno,NullS);
net->error= 0;
DBUG_RETURN(FALSE);
@@ -2897,6 +2904,38 @@ mysql_execute_command(THD *thd)
res= -1;
#endif
break;
+ case SQLCOM_DROP_USER:
+ {
+ if (check_access(thd, GRANT_ACL,"mysql",0,1))
+ break;
+ if (!(res= mysql_drop_user(thd, lex->users_list)))
+ {
+ mysql_update_log.write(thd, thd->query, thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ mysql_bin_log.write(&qinfo);
+ }
+ send_ok(thd);
+ }
+ break;
+ }
+ case SQLCOM_REVOKE_ALL:
+ {
+ if (check_access(thd, GRANT_ACL ,"mysql",0,1))
+ break;
+ if (!(res = mysql_revoke_all(thd, lex->users_list)))
+ {
+ mysql_update_log.write(thd, thd->query, thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ mysql_bin_log.write(&qinfo);
+ }
+ send_ok(thd);
+ }
+ break;
+ }
case SQLCOM_REVOKE:
case SQLCOM_GRANT:
{
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 95ac57013da..fcddc2d2252 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -663,7 +663,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
thd->protocol_simple.send_fields(&fields, 0) ||
send_item_params(stmt))
DBUG_RETURN(1);
- join->cleanup(thd);
+ join->cleanup();
}
DBUG_RETURN(0);
}
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index fe47e553cf3..121411379f8 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -997,7 +997,7 @@ int show_binlog_events(THD* thd)
{
LEX_MASTER_INFO *lex_mi = &thd->lex.mi;
ha_rows event_count, limit_start, limit_end;
- my_off_t pos = lex_mi->pos;
+ my_off_t pos = max(BIN_LOG_HEADER_SIZE, lex_mi->pos); // user-friendly
char search_file_name[FN_REFLEN], *name;
const char *log_file_name = lex_mi->log_file_name;
pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock();
@@ -1025,12 +1025,6 @@ int show_binlog_events(THD* thd)
if ((file=open_binlog(&log, linfo.log_file_name, &errmsg)) < 0)
goto err;
- if (pos < 4)
- {
- errmsg = "Invalid log position";
- goto err;
- }
-
pthread_mutex_lock(log_lock);
my_b_seek(&log, pos);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4167da5802a..61a64573eaa 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -138,7 +138,6 @@ static bool test_if_subpart(ORDER *a,ORDER *b);
static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables);
static void calc_group_buffer(JOIN *join,ORDER *group);
static bool alloc_group_fields(JOIN *join,ORDER *group);
-static bool make_sum_func_list(JOIN *join,List<Item> &fields);
// Create list for using with tempory table
static bool change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
List<Item> &new_list1,
@@ -153,7 +152,7 @@ static void init_tmptable_sum_functions(Item_sum **func);
static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
static void copy_sum_funcs(Item_sum **func_ptr);
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
-static void init_sum_functions(Item_sum **func);
+static bool init_sum_functions(Item_sum **func, Item_sum **end);
static bool update_sum_func(Item_sum **func);
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
bool distinct, const char *message=NullS);
@@ -313,9 +312,11 @@ JOIN::prepare(Item ***rref_pointer_array,
if (having->with_sum_func)
having->split_sum_func(ref_pointer_array, all_fields);
}
-
+
if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
DBUG_RETURN(-1);
+
+
/*
Check if one one uses a not constant column with group functions
and no GROUP BY.
@@ -345,45 +346,47 @@ JOIN::prepare(Item ***rref_pointer_array,
for (table=tables_list ; table ; table=table->next)
tables++;
}
+ {
+ /* Caclulate the number of groups */
+ send_group_parts= 0;
+ for (ORDER *group= group_list ; group ; group= group->next)
+ send_group_parts++;
+ }
+
procedure= setup_procedure(thd, proc_param, result, fields_list, &error);
if (error)
- DBUG_RETURN(-1); /* purecov: inspected */
+ goto err; /* purecov: inspected */
if (procedure)
{
if (setup_new_fields(thd, tables_list, fields_list, all_fields,
procedure->param_fields))
- { /* purecov: inspected */
- delete procedure; /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
- }
+ goto err; /* purecov: inspected */
if (procedure->group)
{
if (!test_if_subpart(procedure->group,group_list))
{ /* purecov: inspected */
my_message(0,"Can't handle procedures with differents groups yet",
MYF(0)); /* purecov: inspected */
- delete procedure; /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ goto err; /* purecov: inspected */
}
}
#ifdef NOT_NEEDED
else if (!group_list && procedure->flags & PROC_GROUP)
{
my_message(0,"Select must have a group with this procedure",MYF(0));
- delete procedure;
- DBUG_RETURN(-1);
+ goto err;
}
#endif
if (order && (procedure->flags & PROC_NO_SORT))
- { /* purecov: inspected */
+ { /* purecov: inspected */
my_message(0,"Can't use order with this procedure",MYF(0)); /* purecov: inspected */
- delete procedure; /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ goto err; /* purecov: inspected */
}
}
/* Init join struct */
count_field_types(&tmp_table_param, all_fields, 0);
+ ref_pointer_array_size= all_fields.elements*sizeof(Item*);
this->group= group_list != 0;
row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
unit->select_limit_cnt);
@@ -398,15 +401,23 @@ JOIN::prepare(Item ***rref_pointer_array,
if (sum_func_count && !group_list && (func_count || field_count))
{
my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT),MYF(0));
- delete procedure;
- DBUG_RETURN(-1);
+ goto err;
}
#endif
if (!procedure && result->prepare(fields_list, unit))
- { /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
- }
+ goto err; /* purecov: inspected */
+
+ if (select_lex->olap == ROLLUP_TYPE && rollup_init())
+ goto err;
+ if (alloc_func_list())
+ goto err;
+
DBUG_RETURN(0); // All OK
+
+err:
+ delete procedure; /* purecov: inspected */
+ procedure= 0;
+ DBUG_RETURN(-1); /* purecov: inspected */
}
/*
@@ -638,7 +649,9 @@ JOIN::optimize()
else if (thd->is_fatal_error) // End of memory
DBUG_RETURN(1);
}
- group_list= remove_const(this, group_list, conds, &simple_group);
+ simple_group= 0;
+ if (rollup.state == ROLLUP::STATE_NONE)
+ group_list= remove_const(this, group_list, conds, &simple_group);
if (!group_list && group)
{
order=0; // The output has only one row
@@ -788,14 +801,14 @@ JOIN::optimize()
thd->proc_info="Sorting for group";
if (create_sort_index(thd, &join_tab[const_tables], group_list,
HA_POS_ERROR, HA_POS_ERROR) ||
- make_sum_func_list(this, all_fields) ||
- alloc_group_fields(this, group_list))
+ alloc_group_fields(this, group_list) ||
+ make_sum_func_list(all_fields, fields_list, 1))
DBUG_RETURN(1);
group_list=0;
}
else
{
- if (make_sum_func_list(this, all_fields))
+ if (make_sum_func_list(all_fields, fields_list, 0))
DBUG_RETURN(1);
if (!group_list && ! exec_tmp_table1->distinct && order && simple_order)
{
@@ -862,7 +875,7 @@ int
JOIN::reinit()
{
DBUG_ENTER("JOIN::reinit");
- //TODO move to unit reinit
+ /* TODO move to unit reinit */
unit->offset_limit_cnt =select_lex->offset_limit;
unit->select_limit_cnt =select_lex->select_limit+select_lex->offset_limit;
if (unit->select_limit_cnt < select_lex->select_limit)
@@ -873,7 +886,7 @@ JOIN::reinit()
if (setup_tables(tables_list))
DBUG_RETURN(1);
- // Reset of sum functions
+ /* Reset of sum functions */
first_record= 0;
if (sum_funcs)
{
@@ -897,7 +910,7 @@ JOIN::reinit()
filesort_free_buffers(exec_tmp_table2);
}
if (items0)
- memcpy(ref_pointer_array, items0, ref_pointer_array_size);
+ set_items_ref_array(items0);
if (tmp_join)
restore_tmp();
@@ -977,9 +990,6 @@ JOIN::exec()
DBUG_VOID_RETURN;
}
- /* Perform FULLTEXT search before all regular searches */
- //init_ftfuncs(thd, select_lex, test(order));
-
JOIN *curr_join= this;
List<Item> *curr_all_fields= &all_fields;
List<Item> *curr_fields_list= &fields_list;
@@ -1030,7 +1040,7 @@ JOIN::exec()
}
curr_all_fields= &tmp_all_fields1;
curr_fields_list= &tmp_fields_list1;
- memcpy(ref_pointer_array, items1, ref_pointer_array_size);
+ set_items_ref_array(items1);
if (sort_and_group || curr_tmp_table->group)
{
@@ -1079,7 +1089,8 @@ JOIN::exec()
if (make_simple_join(curr_join, curr_tmp_table))
DBUG_VOID_RETURN;
calc_group_buffer(curr_join, group_list);
- count_field_types(&curr_join->tmp_table_param, curr_join->tmp_all_fields1,
+ count_field_types(&curr_join->tmp_table_param,
+ curr_join->tmp_all_fields1,
curr_join->select_distinct && !curr_join->group_list);
curr_join->tmp_table_param.hidden_field_count=
(curr_join->tmp_all_fields1.elements-
@@ -1117,7 +1128,8 @@ JOIN::exec()
thd->proc_info="Copying to group table";
tmp_error= -1;
- if (make_sum_func_list(curr_join, *curr_all_fields) ||
+ if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
+ 1) ||
(tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
0)))
{
@@ -1141,7 +1153,7 @@ JOIN::exec()
}
curr_fields_list= &curr_join->tmp_fields_list2;
curr_all_fields= &curr_join->tmp_all_fields2;
- memcpy(ref_pointer_array, items2, ref_pointer_array_size);
+ set_items_ref_array(items2);
curr_join->tmp_table_param.field_count+=
curr_join->tmp_table_param.sum_func_count;
curr_join->tmp_table_param.sum_func_count= 0;
@@ -1169,9 +1181,7 @@ JOIN::exec()
}
if (procedure)
- {
count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0);
- }
if (curr_join->group || curr_join->tmp_table_param.sum_func_count ||
(procedure && (procedure->flags & PROC_GROUP)))
@@ -1201,10 +1211,10 @@ JOIN::exec()
}
curr_fields_list= &tmp_fields_list3;
curr_all_fields= &tmp_all_fields3;
- memcpy(ref_pointer_array, items3, ref_pointer_array_size);
+ set_items_ref_array(items3);
- if (make_sum_func_list(curr_join, *curr_all_fields) ||
- thd->is_fatal_error)
+ if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
+ 1) || thd->is_fatal_error)
DBUG_VOID_RETURN;
}
if (curr_join->group_list || curr_join->order)
@@ -1291,7 +1301,7 @@ JOIN::exec()
*/
int
-JOIN::cleanup(THD *thd)
+JOIN::cleanup()
{
DBUG_ENTER("JOIN::cleanup");
select_lex->join= 0;
@@ -1312,7 +1322,7 @@ JOIN::cleanup(THD *thd)
}
}
tmp_join->tmp_join= 0;
- DBUG_RETURN(tmp_join->cleanup(thd));
+ DBUG_RETURN(tmp_join->cleanup());
}
lock=0; // It's faster to unlock later
@@ -1396,7 +1406,7 @@ err:
thd->limit_found_rows= curr_join->send_records;
thd->examined_row_count= curr_join->examined_rows;
thd->proc_info="end";
- err= join->cleanup(thd);
+ err= join->cleanup();
if (thd->net.report_error)
err= -1;
delete join;
@@ -2916,7 +2926,6 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join->tmp_table_param.func_count=0;
join->tmp_table_param.copy_field=join->tmp_table_param.copy_field_end=0;
join->first_record=join->sort_and_group=0;
- join->sum_funcs=0;
join->send_records=(ha_rows) 0;
join->group=0;
join->row_limit=join->unit->select_limit_cnt;
@@ -5715,8 +5724,12 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
if (join->having && join->having->val_int() == 0)
error= -1; // Didn't satisfy having
- else if (join->do_send_rows)
- error=join->procedure->send_row(*join->fields) ? 1 : 0;
+ else
+ {
+ if (join->do_send_rows)
+ error=join->procedure->send_row(*join->fields) ? 1 : 0;
+ join->send_records++;
+ }
if (end_of_records && join->procedure->end_of_records())
error= 1; // Fatal error
}
@@ -5730,17 +5743,23 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
}
if (join->having && join->having->val_int() == 0)
error= -1; // Didn't satisfy having
- else if (join->do_send_rows)
- error=join->result->send_data(*join->fields) ? 1 : 0;
+ else
+ {
+ if (join->do_send_rows)
+ error=join->result->send_data(*join->fields) ? 1 : 0;
+ join->send_records++;
+ }
+ if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0)
+ {
+ if (join->rollup_send_data((uint) (idx+1)))
+ error= 1;
+ }
}
if (error > 0)
DBUG_RETURN(-1); /* purecov: inspected */
if (end_of_records)
- {
- join->send_records++;
DBUG_RETURN(0);
- }
- if (!error && ++join->send_records >= join->unit->select_limit_cnt &&
+ if (join->send_records >= join->unit->select_limit_cnt &&
join->do_send_rows)
{
if (!(join->select_options & OPTION_FOUND_ROWS))
@@ -5760,7 +5779,8 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (idx < (int) join->send_group_parts)
{
copy_fields(&join->tmp_table_param);
- init_sum_functions(join->sum_funcs);
+ if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
+ DBUG_RETURN(-1);
if (join->procedure)
join->procedure->add();
DBUG_RETURN(0);
@@ -6016,7 +6036,8 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
copy_fields(&join->tmp_table_param);
copy_funcs(join->tmp_table_param.items_to_copy);
- init_sum_functions(join->sum_funcs);
+ if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
+ DBUG_RETURN(-1);
if (join->procedure)
join->procedure->add();
DBUG_RETURN(0);
@@ -7674,7 +7695,10 @@ err2:
/*
- Copy fields and null values between two tables
+ Make a copy of all simple SELECT'ed items
+
+ This is done at the start of a new group so that we can retrieve
+ these later when the group changes.
*/
void
@@ -7694,33 +7718,76 @@ copy_fields(TMP_TABLE_PARAM *param)
}
-/*****************************************************************************
- Make an array of pointer to sum_functions to speed up sum_func calculation
-*****************************************************************************/
+/*
+ Make an array of pointers to sum_functions to speed up sum_func calculation
-static bool
-make_sum_func_list(JOIN *join,List<Item> &fields)
+ SYNOPSIS
+ alloc_func_list()
+
+ RETURN
+ 0 ok
+ 1 Error
+*/
+
+bool JOIN::alloc_func_list()
{
+ uint func_count, group_parts;
+ DBUG_ENTER("alloc_func_list");
+
+ func_count= tmp_table_param.sum_func_count;
+ /*
+ If we are using rollup, we need a copy of the summary functions for
+ each level
+ */
+ if (rollup.state != ROLLUP::STATE_NONE)
+ func_count*= (send_group_parts+1);
+
+ group_parts= send_group_parts;
+ /*
+ If distinct, reserve memory for possible
+ disctinct->group_by optimization
+ */
+ if (select_distinct)
+ group_parts+= fields_list.elements;
+
+ /* This must use calloc() as rollup_make_fields depends on this */
+ sum_funcs= (Item_sum**) thd->calloc(sizeof(Item_sum**) * (func_count+1) +
+ sizeof(Item_sum***) * (group_parts+1));
+ sum_funcs_end= (Item_sum***) (sum_funcs+func_count+1);
+ DBUG_RETURN(sum_funcs == 0);
+}
+
+
+bool JOIN::make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields,
+ bool before_group_by)
+{
+ List_iterator_fast<Item> it(all_fields);
+ Item_sum **func;
+ Item *item;
DBUG_ENTER("make_sum_func_list");
- Item_sum **func =
- (Item_sum**) sql_alloc(sizeof(Item_sum*)*
- (join->tmp_table_param.sum_func_count+1));
- if (!func)
- DBUG_RETURN(TRUE);
- List_iterator<Item> it(fields);
- join->sum_funcs=func;
- Item *field;
- while ((field=it++))
+ func= sum_funcs;
+ while ((item=it++))
{
- if (field->type() == Item::SUM_FUNC_ITEM && !field->const_item())
+ if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
{
- *func++=(Item_sum*) field;
+ *func++= (Item_sum*) item;
/* let COUNT(DISTINCT) create the temporary table */
- if (((Item_sum*) field)->setup(join->thd))
+ if (((Item_sum*) item)->setup(thd))
DBUG_RETURN(TRUE);
}
}
+ if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
+ {
+ rollup.state= ROLLUP::STATE_READY;
+ if (rollup_make_fields(all_fields, send_fields, &func))
+ DBUG_RETURN(TRUE); // Should never happen
+ }
+ else if (rollup.state == ROLLUP::STATE_NONE)
+ {
+ for (uint i=0 ; i <= send_group_parts ;i++)
+ sum_funcs_end[i]= func;
+ }
*func=0; // End marker
DBUG_RETURN(FALSE);
}
@@ -7816,8 +7883,8 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
all_fields - all fields list
RETURN
- 0 - ok
- !=0 - error
+ 0 ok
+ 1 error
*/
static bool
@@ -7886,12 +7953,21 @@ copy_sum_funcs(Item_sum **func_ptr)
}
-static void
-init_sum_functions(Item_sum **func_ptr)
+static bool
+init_sum_functions(Item_sum **func_ptr, Item_sum **end_ptr)
{
- Item_sum *func;
- for (; (func= (Item_sum*) *func_ptr) ; func_ptr++)
- func->reset();
+ for (; func_ptr != end_ptr ;func_ptr++)
+ {
+ if ((*func_ptr)->reset())
+ return 1;
+ }
+ /* If rollup, calculate the upper sum levels */
+ for ( ; *func_ptr ; func_ptr++)
+ {
+ if ((*func_ptr)->add())
+ return 1;
+ }
+ return 0;
}
@@ -7916,10 +7992,10 @@ copy_funcs(Item **func_ptr)
}
-/*****************************************************************************
+/*
Create a condition for a const reference and add this to the
currenct select for the table
-*****************************************************************************/
+*/
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
{
@@ -7935,7 +8011,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
for (uint i=0 ; i < join_tab->ref.key_parts ; i++)
{
- Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i].fieldnr-1];
+ Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i].
+ fieldnr-1];
Item *value=join_tab->ref.items[i];
cond->add(new Item_func_equal(new Item_field(field),value));
}
@@ -7958,7 +8035,241 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
DBUG_RETURN(error ? TRUE : FALSE);
}
+
+/*
+ Free joins of subselect of this select.
+
+ free_underlaid_joins()
+ thd - THD pointer
+ select - pointer to st_select_lex which subselects joins we will free
+*/
+
+void free_underlaid_joins(THD *thd, SELECT_LEX *select)
+{
+ for (SELECT_LEX_UNIT *unit= select->first_inner_unit();
+ unit;
+ unit= unit->next_unit())
+ unit->cleanup();
+}
+
+/****************************************************************************
+ ROLLUP handling
+****************************************************************************/
+
+/* Allocate memory needed for other rollup functions */
+
+bool JOIN::rollup_init()
+{
+ uint i,j;
+ ORDER *group;
+ Item **ref_array;
+
+ tmp_table_param.quick_group= 0; // Can't create groups in tmp table
+ rollup.state= ROLLUP::STATE_INITED;
+
+ /*
+ Create pointers to the different sum function groups
+ These are updated by rollup_make_fields()
+ */
+ tmp_table_param.group_parts= send_group_parts;
+
+ if (!(rollup.fields= (List<Item>*) thd->alloc((sizeof(Item*) +
+ sizeof(List<Item>) +
+ ref_pointer_array_size)
+ * send_group_parts)))
+ return 1;
+ rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts);
+ ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts);
+ rollup.item_null= new (&thd->mem_root) Item_null();
+
+ /*
+ Prepare space for field list for the different levels
+ These will be filled up in rollup_make_fields()
+ */
+ for (i= 0 ; i < send_group_parts ; i++)
+ {
+ List<Item> *fields= &rollup.fields[i];
+ fields->empty();
+ rollup.ref_pointer_arrays[i]= ref_array;
+ ref_array+= all_fields.elements;
+ for (j=0 ; j < fields_list.elements ; j++)
+ fields->push_back(rollup.item_null);
+ }
+ return 0;
+}
+
+
+/*
+ Fill up rollup structures with pointers to fields to use
+
+ SYNOPSIS
+ rollup_make_fields()
+ all_fields List of all fields (hidden and real ones)
+ fields Pointer to selected fields
+ func Store here a pointer to all fields
+
+ IMPLEMENTATION:
+ Creates copies of item_sum items for each sum level
+
+ RETURN
+ 0 if ok
+ In this case func is pointing to next not used element.
+ 1 on error
+*/
+
+bool JOIN::rollup_make_fields(List<Item> &all_fields, List<Item> &fields,
+ Item_sum ***func)
+{
+ List_iterator_fast<Item> it(all_fields);
+ Item *first_field= fields.head();
+ uint level;
+
+ /*
+ Create field lists for the different levels
+
+ The idea here is to have a separate field list for each rollup level to
+ avoid all runtime checks of which columns should be NULL.
+
+ The list is stored in reverse order to get sum function in such an order
+ in func that it makes it easy to reset them with init_sum_functions()
+
+ Assuming: SELECT a, b, c SUM(b) FROM t1 GROUP BY a,b WITH ROLLUP
+
+ rollup.fields[0] will contain list where a,b,c is NULL
+ rollup.fields[1] will contain list where b,c is NULL
+ ...
+ rollup.ref_pointer_array[#] points to fields for rollup.fields[#]
+ ...
+ sum_funcs_end[0] points to all sum functions
+ sum_funcs_end[1] points to all sum functions, except grand totals
+ ...
+ */
+
+ for (level=0 ; level < send_group_parts > 0 ; level++)
+ {
+ uint i;
+ uint pos= send_group_parts - level -1;
+ bool real_fields= 0;
+ Item *item;
+ List_iterator<Item> new_it(rollup.fields[pos]);
+ Item **ref_array_start= rollup.ref_pointer_arrays[pos];
+ ORDER *start_group;
+
+ /* Point to first hidden field */
+ Item **ref_array= ref_array_start + all_fields.elements-1;
+
+ /* Remember where the sum functions ends for the previous level */
+ sum_funcs_end[pos+1]= *func;
+
+ /* Find the start of the group for this level */
+ for (i= 0, start_group= group_list ;
+ i++ < pos ;
+ start_group= start_group->next)
+ ;
+
+ it.rewind();
+ while ((item= it++))
+ {
+ if (item == first_field)
+ {
+ real_fields= 1; // End of hidden fields
+ ref_array= ref_array_start;
+ }
+
+ if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
+ {
+ /*
+ This is a top level summary function that must be replaced with
+ a sum function that is reset for this level.
+
+ NOTE: This code creates an object which is not that nice in a
+ sub select. Fortunately it's not common to have rollup in
+ sub selects.
+ */
+ item= item->copy_or_same(thd);
+ ((Item_sum*) item)->make_unique();
+ if (((Item_sum*) item)->setup(thd))
+ return 1;
+ *(*func)= (Item_sum*) item;
+ (*func)++;
+ }
+ else if (real_fields)
+ {
+ /* Check if this is something that is part of this group by */
+ ORDER *group;
+ for (group= start_group ; group ; group= group->next)
+ {
+ if (*group->item == item)
+ {
+ /*
+ This is an element that is used by the GROUP BY and should be
+ set to NULL in this level
+ */
+ item->maybe_null= 1; // Value will be null sometimes
+ item= rollup.item_null;
+ break;
+ }
+ }
+ }
+ *ref_array= item;
+ if (real_fields)
+ {
+ (void) new_it++; // Point to next item
+ new_it.replace(item); // Replace previous
+ ref_array++;
+ }
+ else
+ ref_array--;
+ }
+ }
+ sum_funcs_end[0]= *func; // Point to last function
+ return 0;
+}
+
+/*
+ Send all rollup levels higher than the current one to the client
+
+ SYNOPSIS:
+ rollup_send_data()
+ idx Level we are on:
+ 0 = Total sum level
+ 1 = First group changed (a)
+ 2 = Second group changed (a,b)
+
+ SAMPLE
+ SELECT a, b, c SUM(b) FROM t1 GROUP BY a,b WITH ROLLUP
+
+ RETURN
+ 0 ok
+ 1 If send_data_failed()
+*/
+
+int JOIN::rollup_send_data(uint idx)
+{
+ uint i;
+ for (i= send_group_parts ; i-- > idx ; )
+ {
+ /* Get reference pointers to sum functions in place */
+ memcpy((char*) ref_pointer_array,
+ (char*) rollup.ref_pointer_arrays[i],
+ ref_pointer_array_size);
+ if ((!having || having->val_int()))
+ {
+ if (send_records < unit->select_limit_cnt &&
+ result->send_data(rollup.fields[i]))
+ return 1;
+ send_records++;
+ }
+ }
+ /* Restore ref_pointer_array */
+ set_items_ref_array(current_ref_pointer_array);
+ return 0;
+}
+
+
/****************************************************************************
+ EXPLAIN handling
+
Send a description about what how the select will be done to stdout
****************************************************************************/
@@ -8198,19 +8509,3 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
result, unit, select_lex, 0);
DBUG_RETURN(res);
}
-
-/*
- Free joins of subselect of this select.
-
- free_underlaid_joins()
- thd - THD pointer
- select - pointer to st_select_lex which subselects joins we will free
-*/
-
-void free_underlaid_joins(THD *thd, SELECT_LEX *select)
-{
- for (SELECT_LEX_UNIT *unit= select->first_inner_unit();
- unit;
- unit= unit->next_unit())
- unit->cleanup();
-}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 7f3669f7478..df21d337b54 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -106,12 +106,22 @@ typedef struct st_join_table {
} JOIN_TAB;
-typedef struct st_position { /* Used in find_best */
+typedef struct st_position /* Used in find_best */
+{
double records_read;
JOIN_TAB *table;
KEYUSE *key;
} POSITION;
+typedef struct st_rollup
+{
+ enum State { STATE_NONE, STATE_INITED, STATE_READY };
+ State state;
+ Item *item_null;
+ Item ***ref_pointer_arrays;
+ List<Item> *fields;
+} ROLLUP;
+
class JOIN :public Sql_alloc
{
@@ -132,7 +142,7 @@ class JOIN :public Sql_alloc
// used to store 2 possible tmp table of SELECT
TABLE *exec_tmp_table1, *exec_tmp_table2;
THD *thd;
- Item_sum **sum_funcs;
+ Item_sum **sum_funcs, ***sum_funcs_end;
Procedure *procedure;
Item *having;
Item *tmp_having; // To store Having when processed temporary table
@@ -146,6 +156,7 @@ class JOIN :public Sql_alloc
SELECT_LEX *select_lex;
JOIN *tmp_join; // copy of this JOIN to be used with temporary tables
+ ROLLUP rollup; // Used with rollup
bool select_distinct, //Is select distinct?
no_order, simple_order, simple_group,
@@ -159,7 +170,7 @@ class JOIN :public Sql_alloc
List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
//Part, shared with list above, emulate following list
List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3;
- List<Item> & fields_list; // hold field list passed to mysql_select
+ List<Item> &fields_list; // hold field list passed to mysql_select
int error;
ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select
@@ -168,15 +179,15 @@ class JOIN :public Sql_alloc
SQL_SELECT *select; //created in optimisation phase
Item **ref_pointer_array; //used pointer reference for this select
// Copy of above to be used with different lists
- Item **items0, **items1, **items2, **items3;
+ Item **items0, **items1, **items2, **items3, **current_ref_pointer_array;
uint ref_pointer_array_size; // size of above in bytes
const char *zero_result_cause; // not 0 if exec must return zero result
bool union_part; // this subselect is part of union
bool optimized; // flag to avoid double optimization in EXPLAIN
- JOIN(THD *thd, List<Item> &fields,
- ulong select_options, select_result *result):
+ JOIN(THD *thd_arg, List<Item> &fields, ulong select_options_arg,
+ select_result *result_arg):
join_tab(0),
table(0),
tables(0), const_tables(0),
@@ -184,13 +195,13 @@ class JOIN :public Sql_alloc
do_send_rows(1),
send_records(0), found_records(0), examined_rows(0),
exec_tmp_table1(0), exec_tmp_table2(0),
- thd(thd),
+ thd(thd_arg),
sum_funcs(0),
procedure(0),
having(0), tmp_having(0),
- select_options(select_options),
- result(result),
- lock(thd->lock),
+ select_options(select_options_arg),
+ result(result_arg),
+ lock(thd_arg->lock),
select_lex(0), //for safety
tmp_join(0),
select_distinct(test(select_options & SELECT_DISTINCT)),
@@ -212,6 +223,7 @@ class JOIN :public Sql_alloc
bzero((char*) &keyuse,sizeof(keyuse));
tmp_table_param.copy_field=0;
tmp_table_param.end_write_records= HA_POS_ERROR;
+ rollup.state= ROLLUP::STATE_NONE;
}
int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
@@ -221,15 +233,28 @@ class JOIN :public Sql_alloc
int optimize();
int reinit();
void exec();
- int cleanup(THD *thd);
+ int cleanup();
void restore_tmp();
+ bool alloc_func_list();
+ bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields,
+ bool before_group_by);
+ inline void set_items_ref_array(Item **ptr)
+ {
+ memcpy((char*) ref_pointer_array, (char*) ptr, ref_pointer_array_size);
+ current_ref_pointer_array= ptr;
+ }
inline void init_items_ref_array()
{
items0= ref_pointer_array + all_fields.elements;
- ref_pointer_array_size= all_fields.elements*sizeof(Item*);
memcpy(items0, ref_pointer_array, ref_pointer_array_size);
+ current_ref_pointer_array= items0;
}
+
+ bool rollup_init();
+ bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields,
+ Item_sum ***func);
+ int JOIN::rollup_send_data(uint idx);
};
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 277bc5d8337..1c4954e0276 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1006,12 +1006,7 @@ static void
append_identifier(THD *thd, String *packet, const char *name)
{
char qtype;
- if ((thd->variables.sql_mode & MODE_ANSI_QUOTES) ||
- (thd->variables.sql_mode & MODE_POSTGRESQL) ||
- (thd->variables.sql_mode & MODE_ORACLE) ||
- (thd->variables.sql_mode & MODE_MSSQL) ||
- (thd->variables.sql_mode & MODE_DB2) ||
- (thd->variables.sql_mode & MODE_SAPDB))
+ if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
qtype= '\"';
else
qtype= '`';
@@ -1033,16 +1028,16 @@ append_identifier(THD *thd, String *packet, const char *name)
static int
store_create_info(THD *thd, TABLE *table, String *packet)
{
- my_bool foreign_db_mode= ((thd->variables.sql_mode & MODE_POSTGRESQL) ||
- (thd->variables.sql_mode & MODE_ORACLE) ||
- (thd->variables.sql_mode & MODE_MSSQL) ||
- (thd->variables.sql_mode & MODE_DB2) ||
- (thd->variables.sql_mode & MODE_SAPDB));
- my_bool limited_mysql_mode= ((thd->variables.sql_mode &
- MODE_NO_FIELD_OPTIONS) ||
- (thd->variables.sql_mode & MODE_MYSQL323) ||
- (thd->variables.sql_mode & MODE_MYSQL40));
-
+ my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
+ MODE_ORACLE |
+ MODE_MSSQL |
+ MODE_DB2 |
+ MODE_SAPDB |
+ MODE_ANSI)) != 0;
+ my_bool limited_mysql_mode= (thd->variables.sql_mode &
+ (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
+ MODE_MYSQL40)) != 0;
+
DBUG_ENTER("store_create_info");
DBUG_PRINT("enter",("table: %s",table->real_name));
diff --git a/sql/sql_state.c b/sql/sql_state.c
new file mode 100644
index 00000000000..355b847f239
--- /dev/null
+++ b/sql/sql_state.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* Functions to map mysqld errno to sql_state */
+
+#include <my_global.h>
+#include <mysqld_error.h>
+
+struct st_map_errno_to_sqlstate
+{
+ uint mysql_errno;
+ const char *odbc_state;
+ const char *jdbc_state;
+};
+
+struct st_map_errno_to_sqlstate sqlstate_map[]=
+{
+#include <sql_state.h>
+};
+
+const char *mysql_errno_to_sqlstate(uint mysql_errno)
+{
+ uint first=0, end= array_elements(sqlstate_map)-1;
+ struct st_map_errno_to_sqlstate *map;
+
+ /* Do binary search in the sorted array */
+ while (first != end)
+ {
+ uint mid= (first+end)/2;
+ map= sqlstate_map+mid;
+ if (map->mysql_errno < mysql_errno)
+ first= mid+1;
+ else
+ end= mid;
+ }
+ map= sqlstate_map+first;
+ if (map->mysql_errno == mysql_errno)
+ return map->odbc_state;
+ return "HY000"; /* General error */
+}
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index cf6645fa23e..0a3e8d0db9f 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -28,10 +28,6 @@
#include <floatingpoint.h>
#endif
-CHARSET_INFO *system_charset_info= &my_charset_utf8_general_ci;
-CHARSET_INFO *files_charset_info= &my_charset_utf8_general_ci;
-CHARSET_INFO *national_charset_info= &my_charset_utf8_general_ci;
-
extern gptr sql_alloc(unsigned size);
extern void sql_element_free(void *ptr);
diff --git a/sql/sql_string.h b/sql/sql_string.h
index ee38853a2d3..e88c9389589 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -69,7 +69,10 @@ public:
Alloced_length=str.Alloced_length; alloced=0;
str_charset=str.str_charset;
}
- static void *operator new(size_t size) { return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size)
+ { return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size, MEM_ROOT *mem_root)
+ { return (void*) alloc_root(mem_root, (uint) size); }
static void operator delete(void *ptr_arg,size_t size) /*lint -e715 */
{ sql_element_free(ptr_arg); }
~String() { free(); }
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index c53ca0b68a8..2b329aac305 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1082,58 +1082,76 @@ mysql_rename_table(enum db_type base,
}
/*
- close table in this thread and force close + reopen in other threads
- This assumes that the calling thread has lock on LOCK_open
- Win32 clients must also have a WRITE LOCK on the table !
+ Force all other threads to stop using the table
+
+ SYNOPSIS
+ wait_while_table_is_used()
+ thd Thread handler
+ table Table to remove from cache
+
+ NOTES
+ When returning, the table will be unusable for other threads until
+ the table is closed.
+
+ PREREQUISITES
+ Lock on LOCK_open
+ Win32 clients must also have a WRITE LOCK on the table !
*/
-static void safe_remove_from_cache(THD *thd,TABLE *table)
+static void wait_while_table_is_used(THD *thd,TABLE *table)
{
- DBUG_ENTER("safe_remove_from_cache");
- if (table)
- {
- DBUG_PRINT("enter",("table: %s", table->real_name));
- VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files
- /* Mark all tables that are in use as 'old' */
- mysql_lock_abort(thd,table); // end threads waiting on lock
+ DBUG_PRINT("enter",("table: %s", table->real_name));
+ DBUG_ENTER("wait_while_table_is_used");
+ safe_mutex_assert_owner(&LOCK_open);
-#if defined(USING_TRANSACTIONS) || defined( __WIN__) || defined( __EMX__) || !defined(OS2)
- /* Wait until all there are no other threads that has this table open */
- while (remove_table_from_cache(thd,table->table_cache_key,
- table->real_name))
- {
- dropping_tables++;
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- dropping_tables--;
- }
-#else
- (void) remove_table_from_cache(thd,table->table_cache_key,
- table->real_name);
-#endif
- /* When lock on LOCK_open is freed other threads can continue */
- pthread_cond_broadcast(&COND_refresh);
+ VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files
+ /* Mark all tables that are in use as 'old' */
+ mysql_lock_abort(thd, table); // end threads waiting on lock
+
+ /* Wait until all there are no other threads that has this table open */
+ while (remove_table_from_cache(thd,table->table_cache_key,
+ table->real_name))
+ {
+ dropping_tables++;
+ (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+ dropping_tables--;
}
DBUG_VOID_RETURN;
}
+/*
+ Close a cached table
-bool close_cached_table(THD *thd,TABLE *table)
+ SYNOPSIS
+ clsoe_cached_table()
+ thd Thread handler
+ table Table to remove from cache
+
+ NOTES
+ Function ends by signaling threads waiting for the table to try to
+ reopen the table.
+
+ PREREQUISITES
+ Lock on LOCK_open
+ Win32 clients must also have a WRITE LOCK on the table !
+*/
+
+static bool close_cached_table(THD *thd, TABLE *table)
{
DBUG_ENTER("close_cached_table");
- safe_mutex_assert_owner(&LOCK_open);
-
- if (table)
+
+ wait_while_table_is_used(thd,table);
+ /* Close lock if this is not got with LOCK TABLES */
+ if (thd->lock)
{
- safe_remove_from_cache(thd,table);
- /* Close lock if this is not got with LOCK TABLES */
- if (thd->lock)
- {
- mysql_unlock_tables(thd, thd->lock);
- thd->lock=0; // Start locked threads
- }
- /* Close all copies of 'table'. This also frees all LOCK TABLES lock */
- thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock=0; // Start locked threads
}
+ /* Close all copies of 'table'. This also frees all LOCK TABLES lock */
+ thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
+
+ /* When lock on LOCK_open is freed other threads can continue */
+ pthread_cond_broadcast(&COND_refresh);
DBUG_RETURN(0);
}
@@ -1262,10 +1280,13 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
- pthread_mutex_lock(&LOCK_open);
- close_cached_table(thd,table_list->table);
- pthread_mutex_unlock(&LOCK_open);
-
+ /* If we could open the table, close it */
+ if (table_list->table)
+ {
+ pthread_mutex_lock(&LOCK_open);
+ close_cached_table(thd, table);
+ pthread_mutex_unlock(&LOCK_open);
+ }
if (lock_and_wait_for_table_name(thd,table_list))
{
error= -1;
@@ -1732,10 +1753,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
fn_same(new_name_buff,table_name,3);
if (lower_case_table_names)
my_casedn_str(system_charset_info,new_name);
- if ((lower_case_table_names &&
- !my_strcasecmp(system_charset_info, new_name_buff,table_name)) ||
- (!lower_case_table_names &&
- !strcmp(new_name_buff,table_name)))
+ if (!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
new_name=table_name; // No. Make later check easier
else
{
@@ -1798,11 +1816,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
else
{
*fn_ext(new_name)=0;
- close_cached_table(thd,table);
+ close_cached_table(thd, table);
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name))
error= -1;
}
- VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open));
}
if (!error)
@@ -1811,12 +1828,18 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
case LEAVE_AS_IS:
break;
case ENABLE:
- safe_remove_from_cache(thd,table);
- error= table->file->activate_all_index(thd);
+ VOID(pthread_mutex_lock(&LOCK_open));
+ wait_while_table_is_used(thd, table);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ error= table->file->activate_all_index(thd);
+ /* COND_refresh will be signaled in close_thread_tables() */
break;
case DISABLE:
- safe_remove_from_cache(thd,table);
+ VOID(pthread_mutex_lock(&LOCK_open));
+ wait_while_table_is_used(thd, table);
+ VOID(pthread_mutex_unlock(&LOCK_open));
table->file->deactivate_non_unique_index(HA_POS_ERROR);
+ /* COND_refresh will be signaled in close_thread_tables() */
break;
}
}
@@ -2251,7 +2274,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
close the original table at before doing the rename
*/
table_name=thd->strdup(table_name); // must be saved
- if (close_cached_table(thd,table))
+ if (close_cached_table(thd, table))
{ // Aborted
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -2285,7 +2308,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
This shouldn't happen. We solve this the safe way by
closing the locked table.
*/
- close_cached_table(thd,table);
+ if (table)
+ close_cached_table(thd,table);
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
@@ -2295,7 +2319,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
Not table locking or alter table with rename
free locks and remove old table
*/
- close_cached_table(thd,table);
+ if (table)
+ close_cached_table(thd,table);
VOID(quick_rm_table(old_db_type,db,old_name));
}
else
@@ -2315,7 +2340,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (close_data_tables(thd,db,table_name) ||
reopen_tables(thd,1,0))
{ // This shouldn't happen
- close_cached_table(thd,table); // Remove lock for table
+ if (table)
+ close_cached_table(thd,table); // Remove lock for table
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 1d0f37f0042..f47900d8276 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -389,7 +389,7 @@ int st_select_lex_unit::cleanup()
JOIN *join;
if ((join= sl->join))
{
- error|= sl->join->cleanup(thd);
+ error|= sl->join->cleanup();
delete join;
}
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 1f6364ec427..989d17b006b 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -200,7 +200,6 @@ int mysql_update(THD *thd,
*/
uint length;
SORT_FIELD *sortorder;
- List<Item> fields;
ha_rows examined_rows;
table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 9b2808f93a8..91bd5a77d27 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -804,6 +804,18 @@ master_def:
MASTER_LOG_POS_SYM EQ ulonglong_num
{
Lex->mi.pos = $3;
+ /*
+ If the user specified a value < BIN_LOG_HEADER_SIZE, adjust it
+ instead of causing subsequent errors.
+ We need to do it in this file, because only there we know that
+ MASTER_LOG_POS has been explicitely specified. On the contrary
+ in change_master() (sql_repl.cc) we cannot distinguish between 0
+ (MASTER_LOG_POS explicitely specified as 0) and 0 (unspecified),
+ whereas we want to distinguish (specified 0 means "read the binlog
+ from 0" (4 in fact), unspecified means "don't change the position
+ (keep the preceding value)").
+ */
+ Lex->mi.pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.pos);
}
|
MASTER_CONNECT_RETRY_SYM EQ ULONG_NUM
@@ -819,6 +831,8 @@ master_def:
RELAY_LOG_POS_SYM EQ ULONG_NUM
{
Lex->mi.relay_log_pos = $3;
+ /* Adjust if < BIN_LOG_HEADER_SIZE (same comment as Lex->mi.pos) */
+ Lex->mi.relay_log_pos = max(BIN_LOG_HEADER_SIZE, Lex->mi.relay_log_pos);
}
;
@@ -2975,7 +2989,7 @@ olap_opt:
}
lex->current_select->select_lex()->olap= CUBE_TYPE;
net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "CUBE");
- YYABORT; /* To be deleted in 4.1 */
+ YYABORT; /* To be deleted in 5.1 */
}
| WITH ROLLUP_SYM
{
@@ -2987,8 +3001,6 @@ olap_opt:
YYABORT;
}
lex->current_select->select_lex()->olap= ROLLUP_TYPE;
- net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "ROLLUP");
- YYABORT; /* To be deleted in 4.1 */
}
;
@@ -3043,20 +3055,7 @@ opt_limit_clause:
;
limit_clause:
- LIMIT
- {
- LEX *lex= Lex;
- if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
- lex->current_select->select_lex()->olap !=
- UNSPECIFIED_OLAP_TYPE)
- {
- net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP",
- "LIMIT");
- YYABORT;
- }
- }
- limit_options
- {}
+ LIMIT limit_options {}
;
limit_options:
@@ -3217,7 +3216,7 @@ do: DO_SYM
;
/*
- Drop : delete tables or index
+ Drop : delete tables or index or user
*/
drop:
@@ -3251,7 +3250,16 @@ drop:
LEX *lex=Lex;
lex->sql_command = SQLCOM_DROP_FUNCTION;
lex->udf.name = $3;
- };
+ }
+ | DROP USER
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_DROP_USER;
+ lex->users_list.empty();
+ }
+ user_list
+ {}
+ ;
table_list:
@@ -4179,8 +4187,10 @@ user:
THD *thd= YYTHD;
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
YYABORT;
- $$->user = $1; $$->host.str=NullS;
- }
+ $$->user = $1;
+ $$->host.str= (char *) "%";
+ $$->host.length= 1;
+ }
| ident_or_text '@' ident_or_text
{
THD *thd= YYTHD;
@@ -4343,6 +4353,7 @@ keyword:
| SHARE_SYM {}
| SHUTDOWN {}
| SLAVE {}
+ | SOUNDS_SYM {}
| SQL_CACHE_SYM {}
| SQL_BUFFER_RESULT {}
| SQL_NO_CACHE_SYM {}
@@ -4363,12 +4374,13 @@ keyword:
| UDF_SYM {}
| UNCOMMITTED_SYM {}
| UNICODE_SYM {}
+ | USER {}
| USE_FRM {}
| VARIABLES {}
| VALUE_SYM {}
| WORK_SYM {}
+ | X509_SYM {}
| YEAR_SYM {}
- | SOUNDS_SYM {}
;
/* Option functions */
@@ -4634,8 +4646,18 @@ revoke:
lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
bzero((char*) &lex->mqh, sizeof(lex->mqh));
}
+ revoke_command
+ {}
+ ;
+
+revoke_command:
grant_privileges ON opt_table FROM user_list
{}
+ |
+ ALL PRIVILEGES ',' GRANT FROM user_list
+ {
+ Lex->sql_command = SQLCOM_REVOKE_ALL;
+ }
;
grant:
diff --git a/sql/time.cc b/sql/time.cc
index eba664a690d..b6ca306e523 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -28,7 +28,6 @@ uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037
/* Currently only my_time_zone is inited */
static long my_time_zone=0;
-pthread_mutex_t LOCK_timezone;
void init_time(void)
{
@@ -39,14 +38,14 @@ void init_time(void)
seconds= (time_t) time((time_t*) 0);
localtime_r(&seconds,&tm_tmp);
l_time= &tm_tmp;
- my_time_zone=0;
+ my_time_zone= 3600; /* Comp. for -3600 in my_gmt_sec */
my_time.year= (uint) l_time->tm_year+1900;
my_time.month= (uint) l_time->tm_mon+1;
my_time.day= (uint) l_time->tm_mday;
my_time.hour= (uint) l_time->tm_hour;
my_time.minute= (uint) l_time->tm_min;
- my_time.second= (uint) l_time->tm_sec;
- VOID(my_gmt_sec(&my_time)); /* Init my_time_zone */
+ my_time.second= (uint) l_time->tm_sec;
+ my_gmt_sec(&my_time, &my_time_zone); /* Init my_time_zone */
}
/*
@@ -57,26 +56,39 @@ void init_time(void)
*/
-long my_gmt_sec(TIME *t)
+long my_gmt_sec(TIME *t, long *my_timezone)
{
uint loop;
time_t tmp;
struct tm *l_time,tm_tmp;
- long diff;
+ long diff, current_timezone;
if (t->hour >= 24)
{ /* Fix for time-loop */
t->day+=t->hour/24;
t->hour%=24;
}
- pthread_mutex_lock(&LOCK_timezone);
- tmp=(time_t) ((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) -
- (long) days_at_timestart)*86400L + (long) t->hour*3600L +
- (long) (t->minute*60 + t->second)) + (time_t) my_time_zone;
+
+ /*
+ Calculate the gmt time based on current time and timezone
+ The -1 on the end is to ensure that if have a date that exists twice
+ (like 2002-10-27 02:00:0 MET), we will find the initial date.
+
+ By doing -3600 we will have to call localtime_r() several times, but
+ I couldn't come up with a better way to get a repeatable result :(
+
+ We can't use mktime() as it's buggy on many platforms and not thread safe.
+ */
+ tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) -
+ (long) days_at_timestart)*86400L + (long) t->hour*3600L +
+ (long) (t->minute*60 + t->second)) + (time_t) my_time_zone -
+ 3600);
+ current_timezone= my_time_zone;
+
localtime_r(&tmp,&tm_tmp);
l_time=&tm_tmp;
for (loop=0;
- loop < 3 &&
+ loop < 2 &&
(t->hour != (uint) l_time->tm_hour ||
t->minute != (uint) l_time->tm_min);
loop++)
@@ -89,14 +101,16 @@ long my_gmt_sec(TIME *t)
days= -1;
diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) +
(long) (60*((int) t->minute - (int) l_time->tm_min)));
- my_time_zone+=diff;
- tmp+=(time_t) diff;
+ current_timezone+= diff+3600; // Compensate for -3600 above
+ tmp+= (time_t) diff;
localtime_r(&tmp,&tm_tmp);
l_time=&tm_tmp;
}
- /* Fix that if we are in the not existing daylight saving time hour
- we move the start of the next real hour */
- if (loop == 3 && t->hour != (uint) l_time->tm_hour)
+ /*
+ Fix that if we are in the not existing daylight saving time hour
+ we move the start of the next real hour
+ */
+ if (loop == 2 && t->hour != (uint) l_time->tm_hour)
{
int days= t->day - l_time->tm_mday;
if (days < -1)
@@ -108,11 +122,9 @@ long my_gmt_sec(TIME *t)
if (diff == 3600)
tmp+=3600 - t->minute*60 - t->second; // Move to next hour
else if (diff == -3600)
- tmp-=t->minute*60 + t->second; // Move to next hour
+ tmp-=t->minute*60 + t->second; // Move to previous hour
}
- if ((my_time_zone >=0 ? my_time_zone: -my_time_zone) > 3600L*12)
- my_time_zone=0; /* Wrong date */
- pthread_mutex_unlock(&LOCK_timezone);
+ *my_timezone= current_timezone;
return (long) tmp;
} /* my_gmt_sec */
@@ -428,6 +440,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
time_t str_to_timestamp(const char *str,uint length)
{
TIME l_time;
+ long not_used;
+
if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE)
return(0);
if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR)
@@ -435,7 +449,7 @@ time_t str_to_timestamp(const char *str,uint length)
current_thd->cuted_fields++;
return(0);
}
- return(my_gmt_sec(&l_time));
+ return(my_gmt_sec(&l_time, &not_used));
}
diff --git a/sql/unireg.h b/sql/unireg.h
index 6ddd9856724..4bbfa8b0fae 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -106,8 +106,8 @@
#define SPECIAL_SAFE_MODE 2048
/* Extern defines */
-#define store_record(A,B) bmove_allign((A)->B,(A)->record[0],(size_t) (A)->reclength)
-#define restore_record(A,B) bmove_allign((A)->record[0],(A)->B,(size_t) (A)->reclength)
+#define store_record(A,B) bmove_align((A)->B,(A)->record[0],(size_t) (A)->reclength)
+#define restore_record(A,B) bmove_align((A)->record[0],(A)->B,(size_t) (A)->reclength)
#define cmp_record(A,B) memcmp((A)->record[0],(A)->B,(size_t) (A)->reclength)
#define empty_record(A) { \
restore_record((A),default_values); \
@@ -141,10 +141,13 @@
*/
#define MIN_TURBOBM_PATTERN_LEN 3
-/* Defines for binary logging */
-
-#define BIN_LOG_HEADER_SIZE 4
+/*
+ Defines for binary logging.
+ Do not decrease the value of BIN_LOG_HEADER_SIZE.
+ Do not even increase it before checking code.
+*/
+#define BIN_LOG_HEADER_SIZE 4
#define FLOATING_POINT_BUFFER 331
/* Include prototypes for unireg */
diff --git a/strings/Makefile.am b/strings/Makefile.am
index 4a57ed73d20..7b2fdcccc55 100644
--- a/strings/Makefile.am
+++ b/strings/Makefile.am
@@ -73,7 +73,7 @@ if ASSEMBLER
endif
str_test: str_test.c $(LIBRARIES)
- $(LINK) $(FLAGS) -DMAIN $(srcdir)/str_test.c $(LDADD) $(LIBS)
+ $(LINK) $(FLAGS) -DMAIN $INCLUDES $(srcdir)/str_test.c $(LDADD) $(LIBS) $(pkglib_LIBRARIES)
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/strings/ctype.c b/strings/ctype.c
index ce7bb9ca4a4..cbd13111b70 100644
--- a/strings/ctype.c
+++ b/strings/ctype.c
@@ -31,7 +31,6 @@ static char *mstr(char *str,const char *src,uint l1,uint l2)
return str;
}
-
struct my_cs_file_section_st
{
int state;
@@ -265,4 +264,3 @@ my_bool my_parse_charset_xml(const char *buf, uint len,
my_xml_parser_free(&p);
return rc;
}
-
diff --git a/strings/str_test.c b/strings/str_test.c
index 0c3ff471ad7..369fa7251d8 100644
--- a/strings/str_test.c
+++ b/strings/str_test.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -94,6 +94,8 @@ int main(void)
test_strarg("bmove_upp(to+6,from+6,3)",(bmove_upp(to+6,from+6,3),0L),INT_MAX32,
3,T_CHAR,3,F_CHAR,0,0);
test_strarg("bmove_upp(to,from,0)",(bmove_upp(to,from,0),0L),INT_MAX32,0,0);
+ test_strarg("bmove_align(to,from,8)",(bmove_align(to,from,8),0L),INT_MAX32,
+ 8,F_CHAR,0,0);
test_strarg("strappend(to,3,' ')",(strappend(to,3,' '),0L),INT_MAX32,
3,T_CHAR,1,0,T_LEN-4,T_CHAR,1,0,0,0);
test_strarg("strappend(to,T_LEN+5,' ')",(strappend(to,T_LEN+5,' '),0L),INT_MAX32,
diff --git a/strings/strings-x86.s b/strings/strings-x86.s
index 8b29a2db7f1..9409657e06c 100644
--- a/strings/strings-x86.s
+++ b/strings/strings-x86.s
@@ -23,44 +23,53 @@
# Move a alligned, not overlapped, by (long) divided memory area
# Args: to,from,length
-.globl bmove_allign
- .type bmove_allign,@function
-bmove_allign:
+.globl bmove_align
+ .type bmove_align,@function
+bmove_align:
movl %edi,%edx
- movl %esi,%eax
+ push %esi
movl 4(%esp),%edi # to
movl 8(%esp),%esi # from
movl 12(%esp),%ecx # length
addw $3,%cx # fix if not divisible with long
shrw $2,%cx
- rep
- movsl
- movl %eax,%esi
+ jz .ba_20
+ .p2align 4,,7
+.ba_10:
+ movl -4(%esi,%ecx),%eax
+ movl %eax,-4(%edi,%ecx)
+ decl %ecx
+ jnz .ba_10
+.ba_20: pop %esi
movl %edx,%edi
ret
-.end:
- .size bmove_allign,.end-bmove_allign
+ .size bmove_align,.end-bmove_align
# Move a string from higher to lower
- # Arg from+1,to+1,length
+ # Arg from_end+1,to_end+1,length
.globl bmove_upp
.type bmove_upp,@function
bmove_upp:
- std # Work downward
- movl %edi,%edx
- movl %esi,%eax
- movl 4(%esp),%edi # p1
- movl 8(%esp),%esi # p2
- movl 12(%esp),%ecx # length
- decl %edi # Don't move last arg
- decl %esi
- rep
- movsb # One byte a time because overlap
- cld # C library wants cld
- movl %eax,%esi
+ movl %edi,%edx # Remember %edi
+ push %esi
+ movl 8(%esp),%edi # dst
+ movl 16(%esp),%ecx # length
+ movl 12(%esp),%esi # source
+ test %ecx,%ecx
+ jz .bu_20
+ subl %ecx,%esi # To start of strings
+ subl %ecx,%edi
+
+ .p2align 4,,7
+.bu_10: movb -1(%esi,%ecx),%al
+ movb %al,-1(%edi,%ecx)
+ decl %ecx
+ jnz .bu_10
+.bu_20: pop %esi
movl %edx,%edi
ret
+
.bmove_upp_end:
.size bmove_upp,.bmove_upp_end-bmove_upp
@@ -304,22 +313,23 @@ si_99: popl %ebp
strmake:
pushl %edi
pushl %esi
- movl 12(%esp),%edi # dst
- movl 16(%esp),%esi # src
- movl 20(%esp),%ecx # Length of memory-area
- clrb %al # For test of end-null
- jecxz sm_90 # Nothing to move, put zero at end.
-
-sm_10: cmpb (%esi),%al # Next char to move
- movsb # move arg
- jz sm_99 # last char, we are ready
- loop sm_10 # Continue moving
-sm_90: movb %al,(%edi) # Set end pos
- incl %edi # Fix that di points at end null
-sm_99: decl %edi # di points now at end null
- movl %edi,%eax # Ret value.p $
- popl %esi
- popl %edi
+ mov 12(%esp),%edi # dst
+ movl $0,%edx
+ movl 20(%esp),%ecx # length
+ movl 16(%esp),%esi # src
+ cmpl %edx,%ecx
+ jz sm_90
+sm_00: movb (%esi,%edx),%al
+ cmpb $0,%al
+ jz sm_90
+ movb %al,(%edi,%edx)
+ incl %edx
+ cmpl %edx,%ecx
+ jnz sm_00
+sm_90: movb $0,(%edi,%edx)
+sm_99: lea (%edi,%edx),%eax # Return pointer to end null
+ pop %esi
+ pop %edi
ret
.strmake_end:
.size strmake,.strmake_end-strmake
diff --git a/strings/strings.asm b/strings/strings.asm
index 43bc23fa965..fe39c8bb3e6 100644
--- a/strings/strings.asm
+++ b/strings/strings.asm
@@ -219,8 +219,8 @@ _bmove ENDP
; Args: to,from,length
;
- PUBLIC _bmove_allign
-_bmove_allign PROC
+ PUBLIC _bmove_align
+_bmove_align PROC
mov bx,bp
mov dx,di
mov ax,si
@@ -238,7 +238,7 @@ _bmove_allign PROC
mov di,dx
mov bp,bx
ret
-_bmove_allign ENDP
+_bmove_align ENDP
;
; Move a string from higher to lower
@@ -656,9 +656,9 @@ _bmove ENDP
; Args: to,from,length
;
- begcode bmove_allign
- public _bmove_allign
-_bmove_allign proc near
+ begcode bmove_align
+ public _bmove_align
+_bmove_align proc near
fix_es 1
mov edx,edi
mov eax,esi
@@ -671,8 +671,8 @@ _bmove_allign proc near
mov esi,eax
mov edi,edx
ret
-_bmove_allign ENDP
- endcode bmove_allign
+_bmove_align ENDP
+ endcode bmove_align
;
; Move a string from higher to lower
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index de01142beac..694e6fa8ebb 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -19,7 +19,7 @@
# Required-Start: $local_fs $network $remote_fs
# Required-Stop: $local_fs $network $remote_fs
# Default-Start: 2 3 4 5
-# Default-Stop: 2 3 4 5
+# Default-Stop: 0 1 6
# Short-Description: start and stop MySQL
# Description: MySQL is a very fast and reliable SQL database engine.
### END INIT INFO
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 11e850206c3..81c05f9cc89 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -254,6 +254,13 @@ export PATH
# Build the 4.0 Max binary (includes BDB and UDFs and therefore
# cannot be linked statically against the patched glibc)
+# If we want to compile with RAID using gcc 3, we need to use
+# gcc instead of g++ to avoid linking problems (RAID code is written in C++)
+if gcc -v 2>&1 | grep 'version 3' > /dev/null 2>&1
+then
+ export CXX="gcc"
+fi
+
BuildMySQL "--enable-shared \
--with-openssl \
--with-berkeley-db \
@@ -319,6 +326,10 @@ install -m644 $MBD/sql/mysqld.sym $RBR/usr/lib/mysql/mysqld.sym
install -m644 $MBD/support-files/mysql-log-rotate $RBR/etc/logrotate.d/mysql
install -m755 $MBD/support-files/mysql.server $RBR/etc/init.d/mysql
+# Create a symlink "rcmysql", pointing to the init.script. SuSE users
+# will appreciate that, as all services usually offer this.
+ln -s ../../sbin/init.d/mysql $RPM_BUILD_ROOT/usr/sbin/rcmysql
+
# Create symbolic compatibility link safe_mysqld -> mysqld_safe
# (safe_mysqld will be gone in MySQL 4.1)
ln -sf ./mysqld_safe $RBR/usr/bin/safe_mysqld
@@ -463,6 +474,7 @@ fi
%attr(755, root, root) /usr/bin/safe_mysqld
%attr(755, root, root) /usr/sbin/mysqld
+%attr(755, root, root) /usr/sbin/rcmysql
%attr(644, root, root) /usr/lib/mysql/mysqld.sym
%attr(644, root, root) /etc/logrotate.d/mysql
diff --git a/tests/client_test.c b/tests/client_test.c
index eebf65ce45f..d22aa900a4e 100644
--- a/tests/client_test.c
+++ b/tests/client_test.c
@@ -180,7 +180,7 @@ static void client_connect()
if (!(mysql = mysql_init(NULL)))
{
- myerror("mysql_init() failed");
+ myerror("mysql_init() failed");
exit(0);
}
@@ -535,7 +535,7 @@ static void verify_prepare_field(MYSQL_RES *result,
unsigned int no,const char *name, const char *org_name,
enum enum_field_types type, const char *table,
const char *org_table, const char *db,
- unsigned long length)
+ unsigned long length, const char *def)
{
MYSQL_FIELD *field;
@@ -554,6 +554,7 @@ static void verify_prepare_field(MYSQL_RES *result,
fprintf(stdout,"\n length :`%ld`\t(expected: `%ld`)", field->length, length);
fprintf(stdout,"\n maxlength:`%ld`", field->max_length);
fprintf(stdout,"\n charsetnr:`%d`", field->charsetnr);
+ fprintf(stdout,"\n default :`%s`\t(expected: `%s`)", field->def ? field->def : "(null)", def ? def: "(null)");
fprintf(stdout,"\n");
myassert(strcmp(field->name,name) == 0);
myassert(strcmp(field->org_name,org_name) == 0);
@@ -562,6 +563,8 @@ static void verify_prepare_field(MYSQL_RES *result,
myassert(strcmp(field->org_table,org_table) == 0);
myassert(strcmp(field->db,db) == 0);
myassert(field->length == length);
+ if (def)
+ myassert(strcmp(field->def,def) == 0);
}
/*
@@ -1021,15 +1024,15 @@ static void test_prepare_field_result()
fprintf(stdout,"\n\n field attributes:\n");
verify_prepare_field(result,0,"int_c","int_c",MYSQL_TYPE_LONG,
- "t1","test_prepare_field_result",current_db,11);
+ "t1","test_prepare_field_result",current_db,11,0);
verify_prepare_field(result,1,"var_c","var_c",MYSQL_TYPE_VAR_STRING,
- "t1","test_prepare_field_result",current_db,50);
+ "t1","test_prepare_field_result",current_db,50,0);
verify_prepare_field(result,2,"date","date_c",MYSQL_TYPE_DATE,
- "t1","test_prepare_field_result",current_db,10);
+ "t1","test_prepare_field_result",current_db,10,0);
verify_prepare_field(result,3,"ts_c","ts_c",MYSQL_TYPE_TIMESTAMP,
- "t1","test_prepare_field_result",current_db,19);
+ "t1","test_prepare_field_result",current_db,19,0);
verify_prepare_field(result,4,"char_c","char_c",MYSQL_TYPE_STRING,
- "t1","test_prepare_field_result",current_db,3);
+ "t1","test_prepare_field_result",current_db,3,0);
verify_field_count(result, 5);
mysql_free_result(result);
@@ -5830,7 +5833,7 @@ static void test_field_misc()
"@@autocommit","", /* field and its org name */
MYSQL_TYPE_LONGLONG, /* field type */
"", "", /* table and its org name */
- "",1); /* db name, length(its bool flag)*/
+ "",1,0); /* db name, length(its bool flag)*/
mysql_free_result(result);
@@ -5849,7 +5852,7 @@ static void test_field_misc()
"@@autocommit","", /* field and its org name */
MYSQL_TYPE_LONGLONG, /* field type */
"", "", /* table and its org name */
- "",1); /* db name, length(its bool flag)*/
+ "",1,0); /* db name, length(its bool flag)*/
mysql_free_result(result);
mysql_stmt_close(stmt);
@@ -5893,7 +5896,7 @@ static void test_field_misc()
"@@table_type","", /* field and its org name */
MYSQL_TYPE_STRING, /* field type */
"", "", /* table and its org name */
- "",type_length); /* db name, length */
+ "",type_length,0); /* db name, length */
mysql_free_result(result);
mysql_stmt_close(stmt);
@@ -5913,7 +5916,7 @@ static void test_field_misc()
"@@max_error_count","", /* field and its org name */
MYSQL_TYPE_LONGLONG, /* field type */
"", "", /* table and its org name */
- "",10); /* db name, length */
+ "",10,0); /* db name, length */
mysql_free_result(result);
mysql_stmt_close(stmt);
@@ -5933,7 +5936,7 @@ static void test_field_misc()
"@@max_allowed_packet","", /* field and its org name */
MYSQL_TYPE_LONGLONG, /* field type */
"", "", /* table and its org name */
- "",10); /* db name, length */
+ "",10,0); /* db name, length */
mysql_free_result(result);
mysql_stmt_close(stmt);
@@ -5953,7 +5956,7 @@ static void test_field_misc()
"@@sql_warnings","", /* field and its org name */
MYSQL_TYPE_LONGLONG, /* field type */
"", "", /* table and its org name */
- "",1); /* db name, length */
+ "",1,0); /* db name, length */
mysql_free_result(result);
mysql_stmt_close(stmt);
@@ -6340,39 +6343,22 @@ static void test_explain_bug()
myassert(6 == mysql_num_fields(result));
verify_prepare_field(result,0,"Field","",MYSQL_TYPE_STRING,
- "","","",NAME_LEN);
+ "","","",NAME_LEN,0);
verify_prepare_field(result,1,"Type","",MYSQL_TYPE_STRING,
- "","","",40);
-#if 0
-
- verify_prepare_field(result,2,"Collation","",MYSQL_TYPE_STRING,
- "","","",40);
-
- verify_prepare_field(result,3,"Null","",MYSQL_TYPE_STRING,
- "","","",1);
+ "","","",40,0);
- verify_prepare_field(result,4,"Key","",MYSQL_TYPE_STRING,
- "","","",3);
-
- verify_prepare_field(result,5,"Default","",MYSQL_TYPE_STRING,
- "","","",NAME_LEN);
-
- verify_prepare_field(result,6,"Extra","",MYSQL_TYPE_STRING,
- "","","",20);
-#else
verify_prepare_field(result,2,"Null","",MYSQL_TYPE_STRING,
- "","","",1);
+ "","","",1,0);
verify_prepare_field(result,3,"Key","",MYSQL_TYPE_STRING,
- "","","",3);
+ "","","",3,0);
verify_prepare_field(result,4,"Default","",MYSQL_TYPE_STRING,
- "","","",NAME_LEN);
+ "","","",NAME_LEN,0);
verify_prepare_field(result,5,"Extra","",MYSQL_TYPE_STRING,
- "","","",20);
-#endif
+ "","","",20,0);
mysql_free_result(result);
mysql_stmt_close(stmt);
@@ -6393,34 +6379,34 @@ static void test_explain_bug()
myassert(10 == mysql_num_fields(result));
verify_prepare_field(result,0,"id","",MYSQL_TYPE_LONGLONG,
- "","","",3);
+ "","","",3,0);
verify_prepare_field(result,1,"select_type","",MYSQL_TYPE_STRING,
- "","","",19);
+ "","","",19,0);
verify_prepare_field(result,2,"table","",MYSQL_TYPE_STRING,
- "","","",NAME_LEN);
+ "","","",NAME_LEN,0);
verify_prepare_field(result,3,"type","",MYSQL_TYPE_STRING,
- "","","",10);
+ "","","",10,0);
verify_prepare_field(result,4,"possible_keys","",MYSQL_TYPE_STRING,
- "","","",NAME_LEN*32);
+ "","","",NAME_LEN*32,0);
verify_prepare_field(result,5,"key","",MYSQL_TYPE_STRING,
- "","","",NAME_LEN);
+ "","","",NAME_LEN,0);
verify_prepare_field(result,6,"key_len","",MYSQL_TYPE_LONGLONG,
- "","","",3);
+ "","","",3,0);
verify_prepare_field(result,7,"ref","",MYSQL_TYPE_STRING,
- "","","",NAME_LEN*16);
+ "","","",NAME_LEN*16,0);
verify_prepare_field(result,8,"rows","",MYSQL_TYPE_LONGLONG,
- "","","",10);
+ "","","",10,0);
verify_prepare_field(result,9,"Extra","",MYSQL_TYPE_STRING,
- "","","",255);
+ "","","",255,0);
mysql_free_result(result);
mysql_stmt_close(stmt);
@@ -7053,6 +7039,9 @@ static void test_fetch_column()
fprintf(stdout, "\n col 0: %d(%ld)", c1, l1);
myassert(c1 == 1 && l1 == 4);
+ rc = mysql_fetch_column(stmt,bind,10,0);
+ mystmt_r(stmt,rc);
+
rc = mysql_fetch(stmt);
mystmt(stmt,rc);
@@ -7110,13 +7099,20 @@ static void test_list_fields()
rc= mysql_query(mysql,"drop table if exists test_list_fields");
myquery(rc);
- rc = mysql_query(mysql, "create table test_list_fields(c1 int primary key auto_increment, c2 char(10))");
+ rc = mysql_query(mysql, "create table test_list_fields(c1 int primary key auto_increment, c2 char(10) default 'mysql')");
myquery(rc);
result = mysql_list_fields(mysql, "test_list_fields",NULL);
mytest(result);
myassert( 0 == my_process_result_set(result));
+
+ verify_prepare_field(result,0,"c1","c1",MYSQL_TYPE_LONG,
+ "test_list_fields","test_list_fields",current_db,11,"0");
+
+ verify_prepare_field(result,1,"c2","c2",MYSQL_TYPE_STRING,
+ "test_list_fields","test_list_fields",current_db,10,"mysql");
+
mysql_free_result(result);
}
@@ -7188,6 +7184,149 @@ static void test_mem_overun()
mysql_stmt_close(stmt);
}
+
+/*
+ To test mysql_stmt_free_result()
+*/
+static void test_free_result()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ char c2[5];
+ ulong length;
+ int rc, c1;
+
+ myheader("test_free_result");
+
+ rc= mysql_query(mysql,"drop table if exists test_free_result");
+ myquery(rc);
+
+ rc = mysql_query(mysql, "create table test_free_result(c1 int primary key auto_increment)");
+ myquery(rc);
+
+ rc = mysql_query(mysql, "insert into test_free_result values(),(),()");
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql,"select * from test_free_result",50);
+ mystmt_init(stmt);
+
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (char *)c2;
+ bind[0].buffer_length= 7;
+ bind[0].is_null= 0;
+ bind[0].length= &length;
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ c2[0]= '\0'; length= 0;
+ rc = mysql_fetch_column(stmt,bind,0,0);
+ mystmt(stmt,rc);
+ fprintf(stdout, "\n col 1: %s(%ld)", c2, length);
+ myassert(strncmp(c2,"1",1)==0 && length == 1);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ c1= 0, length= 0;
+
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (char *)&c1;
+ bind[0].buffer_length= 0;
+ bind[0].is_null= 0;
+ bind[0].length= &length;
+
+ rc = mysql_fetch_column(stmt,bind,0,0);
+ mystmt(stmt,rc);
+ fprintf(stdout, "\n col 0: %d(%ld)", c1, length);
+ myassert(c1 == 2 && length == 4);
+
+ rc = mysql_query(mysql,"drop table test_free_result");
+ myquery_r(rc); /* error should be, COMMANDS OUT OF SYNC */
+
+ rc = mysql_stmt_free_result(stmt);
+ mystmt(stmt,rc);
+
+ rc = mysql_query(mysql,"drop table test_free_result");
+ myquery(rc); /* should be successful */
+
+ mysql_stmt_close(stmt);
+}
+
+/*
+ To test mysql_stmt_free_result()
+*/
+static void test_free_store_result()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ char c2[5];
+ ulong length;
+ int rc, c1;
+
+ myheader("test_free_store_result");
+
+ rc= mysql_query(mysql,"drop table if exists test_free_result");
+ myquery(rc);
+
+ rc = mysql_query(mysql, "create table test_free_result(c1 int primary key auto_increment)");
+ myquery(rc);
+
+ rc = mysql_query(mysql, "insert into test_free_result values(),(),()");
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql,"select * from test_free_result",50);
+ mystmt_init(stmt);
+
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= (char *)c2;
+ bind[0].buffer_length= 7;
+ bind[0].is_null= 0;
+ bind[0].length= &length;
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ rc = mysql_stmt_store_result(stmt);
+ mystmt(stmt,rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ c2[0]= '\0'; length= 0;
+ rc = mysql_fetch_column(stmt,bind,0,0);
+ mystmt(stmt,rc);
+ fprintf(stdout, "\n col 1: %s(%ld)", c2, length);
+ myassert(strncmp(c2,"1",1)==0 && length == 1);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ c1= 0, length= 0;
+
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer= (char *)&c1;
+ bind[0].buffer_length= 0;
+ bind[0].is_null= 0;
+ bind[0].length= &length;
+
+ rc = mysql_fetch_column(stmt,bind,0,0);
+ mystmt(stmt,rc);
+ fprintf(stdout, "\n col 0: %d(%ld)", c1, length);
+ myassert(c1 == 2 && length == 4);
+
+ rc = mysql_stmt_free_result(stmt);
+ mystmt(stmt,rc);
+
+ rc = mysql_query(mysql,"drop table test_free_result");
+ myquery(rc);
+
+ mysql_stmt_close(stmt);
+}
+
/*
Read and parse arguments and MySQL options from my.cnf
*/
@@ -7428,6 +7567,11 @@ int main(int argc, char **argv)
test_open_direct(); /* direct execution in the middle of open stmts */
test_fetch_offset(); /* to test mysql_fetch_column with offset */
test_fetch_column(); /* to test mysql_fetch_column */
+ test_mem_overun(); /* test DBD ovverun bug */
+ test_list_fields(); /* test COM_LIST_FIELDS for DEFAULT */
+ test_free_result(); /* test mysql_stmt_free_result() */
+ test_free_store_result(); /* test to make sure stmt results are cleared
+ during stmt_free_result() */
end_time= time((time_t *)0);
total_time+= difftime(end_time, start_time);