summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Docs/Makefile.am29
-rw-r--r--Makefile.am31
-rw-r--r--client/Makefile.am6
-rw-r--r--client/mysql.cc2
-rw-r--r--client/mysqladmin.cc2
-rw-r--r--client/mysqlbinlog.cc2
-rw-r--r--client/mysqlcheck.c2
-rw-r--r--client/mysqldump.c5
-rw-r--r--client/mysqlimport.c2
-rw-r--r--client/mysqlshow.c2
-rw-r--r--client/mysqltest.c40
-rw-r--r--cmd-line-utils/libedit/Makefile.am16
-rw-r--r--config/ac-macros/zlib.m42
-rw-r--r--configure.in14
-rw-r--r--extra/Makefile.am3
-rw-r--r--extra/yassl/Makefile.am2
-rw-r--r--extra/yassl/src/Makefile.am2
-rw-r--r--extra/yassl/taocrypt/src/Makefile.am2
-rw-r--r--include/Makefile.am8
-rw-r--r--libmysql/Makefile.am32
-rw-r--r--libmysql_r/Makefile.am4
-rw-r--r--libmysqld/Makefile.am16
-rw-r--r--libmysqld/examples/Makefile.am13
-rw-r--r--mysql-test/Makefile.am3
-rw-r--r--mysql-test/include/is_debug_build.inc4
-rw-r--r--mysql-test/r/cast.result36
-rw-r--r--mysql-test/r/is_debug_build.require2
-rw-r--r--mysql-test/r/mysqldump.result56
-rw-r--r--mysql-test/r/ndb_alter_table.result3
-rw-r--r--mysql-test/r/sp-code.result62
-rw-r--r--mysql-test/r/sp-dynamic.result15
-rw-r--r--mysql-test/r/sp-error.result9
-rw-r--r--mysql-test/r/sp.result202
-rw-r--r--mysql-test/r/sp_trans.result195
-rw-r--r--mysql-test/r/trigger.result17
-rw-r--r--mysql-test/r/type_binary.result3
-rw-r--r--mysql-test/r/variables.result8
-rw-r--r--mysql-test/r/view_grant.result17
-rw-r--r--mysql-test/t/cast.test4
-rw-r--r--mysql-test/t/mysqldump.test24
-rw-r--r--mysql-test/t/ndb_alter_table.test4
-rw-r--r--mysql-test/t/sp-code.test49
-rw-r--r--mysql-test/t/sp-dynamic.test17
-rw-r--r--mysql-test/t/sp-error.test7
-rw-r--r--mysql-test/t/sp.test182
-rw-r--r--mysql-test/t/sp_trans.test180
-rw-r--r--mysql-test/t/trigger.test32
-rw-r--r--mysql-test/t/type_binary.test3
-rw-r--r--mysql-test/t/variables.test4
-rw-r--r--mysql-test/t/view_grant.test36
-rw-r--r--netware/Makefile.am6
-rw-r--r--netware/mysql_test_run.c3
-rw-r--r--pstack/Makefile.am2
-rw-r--r--scripts/Makefile.am3
-rw-r--r--server-tools/instance-manager/Makefile.am8
-rw-r--r--sql-bench/Makefile.am2
-rw-r--r--sql/Makefile.am10
-rw-r--r--sql/field.cc73
-rw-r--r--sql/ha_federated.cc8
-rw-r--r--sql/ha_innodb.cc12
-rw-r--r--sql/ha_myisammrg.cc4
-rw-r--r--sql/ha_ndbcluster.cc43
-rw-r--r--sql/handler.cc17
-rw-r--r--sql/item.cc22
-rw-r--r--sql/item.h11
-rw-r--r--sql/item_cmpfunc.cc24
-rw-r--r--sql/item_func.cc47
-rw-r--r--sql/item_strfunc.cc19
-rw-r--r--sql/item_subselect.cc26
-rw-r--r--sql/item_sum.cc14
-rw-r--r--sql/item_timefunc.cc101
-rw-r--r--sql/item_uniq.h4
-rw-r--r--sql/key.cc4
-rw-r--r--sql/lex.h1
-rw-r--r--sql/log.cc6
-rw-r--r--sql/log_event.cc36
-rw-r--r--sql/mysqld.cc8
-rw-r--r--sql/opt_range.cc10
-rw-r--r--sql/parse_file.cc181
-rw-r--r--sql/parse_file.h32
-rw-r--r--sql/protocol.cc40
-rw-r--r--sql/protocol.h2
-rw-r--r--sql/repl_failsafe.cc13
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/share/Makefile.am10
-rw-r--r--sql/share/errmsg.txt6
-rw-r--r--sql/slave.cc10
-rw-r--r--sql/sp.cc313
-rw-r--r--sql/sp.h6
-rw-r--r--sql/sp_head.cc393
-rw-r--r--sql/sp_head.h39
-rw-r--r--sql/sp_pcontext.cc40
-rw-r--r--sql/sp_pcontext.h17
-rw-r--r--sql/sp_rcontext.h8
-rw-r--r--sql/spatial.cc2
-rw-r--r--sql/sql_acl.cc104
-rw-r--r--sql/sql_analyse.cc58
-rw-r--r--sql/sql_base.cc22
-rw-r--r--sql/sql_cache.h2
-rw-r--r--sql/sql_class.cc26
-rw-r--r--sql/sql_class.h9
-rw-r--r--sql/sql_lex.cc10
-rw-r--r--sql/sql_lex.h1
-rw-r--r--sql/sql_load.cc3
-rw-r--r--sql/sql_parse.cc53
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--sql/sql_select.cc73
-rw-r--r--sql/sql_show.cc168
-rw-r--r--sql/sql_string.cc12
-rw-r--r--sql/sql_string.h2
-rw-r--r--sql/sql_table.cc52
-rw-r--r--sql/sql_trigger.cc109
-rw-r--r--sql/sql_view.cc8
-rw-r--r--sql/sql_yacc.yy55
-rw-r--r--sql/structs.h2
-rw-r--r--sql/table.cc2
-rw-r--r--sql/tztime.cc2
-rw-r--r--storage/myisam/myisamchk.c2
-rw-r--r--storage/myisam/myisampack.c2
-rw-r--r--storage/ndb/docs/Makefile.am2
-rw-r--r--support-files/Makefile.am2
121 files changed, 2852 insertions, 982 deletions
diff --git a/Docs/Makefile.am b/Docs/Makefile.am
index b1f69381774..542c82d8f58 100644
--- a/Docs/Makefile.am
+++ b/Docs/Makefile.am
@@ -18,11 +18,11 @@ noinst_SCRIPTS = Support/generate-text-files.pl
EXTRA_DIST = $(noinst_SCRIPTS) mysql.info INSTALL-BINARY
-all: txt_files
-
-txt_files: ../INSTALL-SOURCE ../INSTALL-WIN-SOURCE ../EXCEPTIONS-CLIENT \
+TXT_FILES= ../INSTALL-SOURCE ../INSTALL-WIN-SOURCE ../EXCEPTIONS-CLIENT \
INSTALL-BINARY ../support-files/MacOSX/ReadMe.txt
+all-local: $(TXT_FILES)
+
# make sure that "make install" installs the info page, too
# automake only seems to take care of this automatically,
# if we're building the info page from texi directly.
@@ -30,28 +30,37 @@ install-data-hook: mysql.info
$(mkinstalldirs) $(DESTDIR)$(infodir)
$(INSTALL_DATA) $(srcdir)/mysql.info $(DESTDIR)$(infodir)
-CLEAN_FILES: $(txt_files)
- touch $(txt_files)
+uninstall-local:
+ @RM@ -f $(DESTDIR)$(infodir)/mysql.info
+
+# Problems with "make distclean", works differently for make files
+# generated by different versions of the automake. Some require the
+# generated files explicitly in DISTCLEANFILES.
+DISTCLEANFILES = $(TXT_FILES)
+
+# This target is not used in builds, just for convinience
+CLEAN_FILES: $(TXT_FILES)
+ touch $(TXT_FILES)
GT = $(srcdir)/Support/generate-text-files.pl
../INSTALL-SOURCE: mysql.info $(GT)
- perl -w $(GT) mysql.info "installing-source" "windows-source-build" > $@
+ perl -w $(GT) $< "installing-source" "windows-source-build" > $@
../INSTALL-WIN-SOURCE: mysql.info $(GT)
- perl -w $(GT) mysql.info "windows-source-build" "post-installation" > $@
+ perl -w $(GT) $< "windows-source-build" "post-installation" > $@
# We put the description for the binary installation here so that
# people who download source wont have to see it. It is moved up to
# the toplevel by the script that makes the binary tar files.
INSTALL-BINARY: mysql.info $(GT)
- perl -w $(GT) mysql.info "installing-binary" "installing-source" > $@
+ perl -w $(GT) $< "installing-binary" "installing-source" > $@
../EXCEPTIONS-CLIENT: mysql.info $(GT)
- perl -w $(GT) mysql.info "mysql-floss-license-exception" "function-index" > $@
+ perl -w $(GT) $< "mysql-floss-license-exception" "function-index" > $@
../support-files/MacOSX/ReadMe.txt: mysql.info $(GT)
- perl -w $(GT) mysql.info "mac-os-x-installation" "netware-installation" > $@
+ perl -w $(GT) $< "mac-os-x-installation" "netware-installation" > $@
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/Makefile.am b/Makefile.am
index 16cd8fcffd1..e78a762af53 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,7 +19,8 @@
AUTOMAKE_OPTIONS = foreign
# These are built from source in the Docs directory
-EXTRA_DIST = INSTALL-SOURCE README COPYING EXCEPTIONS-CLIENT
+EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \
+ README COPYING EXCEPTIONS-CLIENT
SUBDIRS = . include @docs_dirs@ @zlib_dir@ @yassl_dir@ \
@readline_topdir@ sql-common \
@thread_dirs@ pstack \
@@ -37,16 +38,19 @@ DIST_SUBDIRS = . include @docs_dirs@ zlib \
BUILD netware os2 @libmysqld_dirs@\
@bench_dirs@ support-files server-tools tools
-# Relink after clean
-linked_sources = linked_client_sources linked_server_sources \
- linked_libmysql_sources linked_libmysql_r_sources \
- linked_libmysqld_sources linked_libmysqldex_sources \
+# Run these targets before any others, also make part of clean target,
+# to make sure we create new links after a clean.
+BUILT_SOURCES = linked_client_sources linked_server_sources \
+ @linked_client_targets@ \
+ @linked_libmysqld_targets@ \
linked_include_sources @linked_netware_sources@
-CLEANFILES = $(linked_sources)
-
-# This is just so that the linking is done early.
-all-local: $(linked_sources)
+# The db.h file is a bit special, see note in "configure.in".
+# In the case we didn't compile with bdb, a dummy file is put
+# there, but will not be removed by the bdb make file becuase
+# it will never be called.
+CLEANFILES = $(BUILT_SOURCES) bdb/build_unix/db.h
+DISTCLEANFILES = ac_available_languages_fragment
linked_include_sources:
cd include; $(MAKE) link_sources
@@ -76,13 +80,8 @@ linked_netware_sources:
cd @netware_dir@; $(MAKE) link_sources
echo timestamp > linked_netware_sources
-#avoid recursive make calls in sql directory
linked_server_sources:
- cd sql; rm -f mini_client_errors.c;\
- @LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c;\
- rm -f pack.c;@LN_CP_F@ ../sql-common/pack.c pack.c;\
- rm -f client.c;@LN_CP_F@ ../sql-common/client.c client.c;\
- rm -f my_time.c;@LN_CP_F@ ../sql-common/my_time.c my_time.c
+ cd sql; $(MAKE) link_sources
echo timestamp > linked_server_sources
# Create permission databases
@@ -94,7 +93,7 @@ bin-dist: all
# Remove BK's "SCCS" subdirectories from source distribution
dist-hook:
- rm -rf `find $(distdir) -type d -name SCCS`
+ rm -rf `find $(distdir) -type d -name SCCS -print`
tags:
support-files/build-tags
diff --git a/client/Makefile.am b/client/Makefile.am
index cf9d2884ded..804f194085f 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -56,12 +56,12 @@ DEFS = -DUNDEF_THREADS_HACK
link_sources:
for f in $(sql_src) ; do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ $(top_srcdir)/sql/$$f $(srcdir)/$$f; \
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \
done; \
for f in $(strings_src) ; do \
rm -f $(srcdir)/$$f; \
- @LN_CP_F@ $(top_srcdir)/strings/$$f $(srcdir)/$$f; \
+ @LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \
done;
# Don't update the files from bitkeeper
diff --git a/client/mysql.cc b/client/mysql.cc
index b2c9666f8b0..c5f0b6cd09a 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -527,7 +527,7 @@ static struct my_option my_long_options[] =
{"help", 'I', "Synonym for -?", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
#ifdef __NETWARE__
- {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
+ {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"auto-rehash", OPT_AUTO_REHASH,
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index ec136402bd8..53bf59af67a 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -127,7 +127,7 @@ static TYPELIB command_typelib=
static struct my_option my_long_options[] =
{
#ifdef __NETWARE__
- {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
+ {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"count", 'c',
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 6cba3c0cb44..7eb26d30cf9 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -647,7 +647,7 @@ static struct my_option my_long_options[] =
{
#ifdef __NETWARE__
- {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
+ {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
/*
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 2eb3e55c2e9..1324060eb55 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -63,7 +63,7 @@ static struct my_option my_long_options[] =
(gptr*) &opt_all_in_1, (gptr*) &opt_all_in_1, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
#ifdef __NETWARE__
- {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
+ {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"auto-repair", OPT_AUTO_REPAIR,
diff --git a/client/mysqldump.c b/client/mysqldump.c
index b92b971ea4f..47ec9a72108 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -173,7 +173,7 @@ static struct my_option my_long_options[] =
"Allow creation of column names that are keywords.", (gptr*) &opt_keywords,
(gptr*) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifdef __NETWARE__
- {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
+ {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"character-sets-dir", OPT_CHARSETS_DIR,
@@ -1841,12 +1841,13 @@ DELIMITER ;;\n");
while ((row= mysql_fetch_row(result)))
{
fprintf(sql_file, "/*!50003 SET SESSION SQL_MODE=\"%s\" */;;\n\
-/*!50003 CREATE TRIGGER %s %s %s ON %s FOR EACH ROW%s */;;\n\n",
+/*!50003 CREATE TRIGGER %s %s %s ON %s FOR EACH ROW%s%s */;;\n\n",
row[6], /* sql_mode */
quote_name(row[0], name_buff, 0), /* Trigger */
row[4], /* Timing */
row[1], /* Event */
result_table,
+ (strchr(" \t\n\r", *(row[3]))) ? "" : " ",
row[3] /* Statement */);
}
if (mysql_num_rows(result))
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index 19d4ef16ef9..958f987d16b 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -59,7 +59,7 @@ static char *shared_memory_base_name=0;
static struct my_option my_long_options[] =
{
#ifdef __NETWARE__
- {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
+ {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"character-sets-dir", OPT_CHARSETS_DIR,
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index 8f6be6cf70b..8369d918d6f 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -157,7 +157,7 @@ int main(int argc, char **argv)
static struct my_option my_long_options[] =
{
#ifdef __NETWARE__
- {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
+ {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"character-sets-dir", 'c', "Directory where character sets are.",
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 58c0928c36d..f6d28101fa0 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -3314,20 +3314,23 @@ static int handle_error(const char *query, struct st_query *q,
((q->expected_errno[i].type == ERR_SQLSTATE) &&
(strcmp(q->expected_errno[i].code.sqlstate, err_sqlstate) == 0)))
{
- if (q->expected_errors == 1)
+ if (!disable_result_log)
{
- /* Only log error if there is one possible error */
- dynstr_append_mem(ds, "ERROR ", 6);
- replace_dynstr_append(ds, err_sqlstate);
- dynstr_append_mem(ds, ": ", 2);
- replace_dynstr_append(ds, err_error);
- dynstr_append_mem(ds,"\n",1);
+ if (q->expected_errors == 1)
+ {
+ /* Only log error if there is one possible error */
+ dynstr_append_mem(ds, "ERROR ", 6);
+ replace_dynstr_append(ds, err_sqlstate);
+ dynstr_append_mem(ds, ": ", 2);
+ replace_dynstr_append(ds, err_error);
+ dynstr_append_mem(ds,"\n",1);
+ }
+ /* Don't log error if we may not get an error */
+ else if (q->expected_errno[0].type == ERR_SQLSTATE ||
+ (q->expected_errno[0].type == ERR_ERRNO &&
+ q->expected_errno[0].code.errnum != 0))
+ dynstr_append(ds,"Got one of the listed errors\n");
}
- /* Don't log error if we may not get an error */
- else if (q->expected_errno[0].type == ERR_SQLSTATE ||
- (q->expected_errno[0].type == ERR_ERRNO &&
- q->expected_errno[0].code.errnum != 0))
- dynstr_append(ds,"Got one of the listed errors\n");
/* OK */
DBUG_RETURN(0);
}
@@ -3335,11 +3338,14 @@ static int handle_error(const char *query, struct st_query *q,
DBUG_PRINT("info",("i: %d expected_errors: %d", i, q->expected_errors));
- dynstr_append_mem(ds, "ERROR ",6);
- replace_dynstr_append(ds, err_sqlstate);
- dynstr_append_mem(ds, ": ", 2);
- replace_dynstr_append(ds, err_error);
- dynstr_append_mem(ds, "\n", 1);
+ if (!disable_result_log)
+ {
+ dynstr_append_mem(ds, "ERROR ",6);
+ replace_dynstr_append(ds, err_sqlstate);
+ dynstr_append_mem(ds, ": ", 2);
+ replace_dynstr_append(ds, err_error);
+ dynstr_append_mem(ds, "\n", 1);
+ }
if (i)
{
diff --git a/cmd-line-utils/libedit/Makefile.am b/cmd-line-utils/libedit/Makefile.am
index af1bf8b2c97..ae6755f1c5c 100644
--- a/cmd-line-utils/libedit/Makefile.am
+++ b/cmd-line-utils/libedit/Makefile.am
@@ -2,8 +2,8 @@
# Makefile for the GNU readline library.
# Copyright (C) 1994,1996,1997 Free Software Foundation, Inc.
-ASRC=vi.c emacs.c common.c
-AHDR=vi.h emacs.h common.h
+ASRC = $(srcdir)/vi.c $(srcdir)/emacs.c $(srcdir)/common.c
+AHDR = vi.h emacs.h common.h
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
-I$(srcdir)/../.. -I..
@@ -42,16 +42,16 @@ SUFFIXES = .sh
$< > $@-t
@MV@ $@-t $@
-vi.h: vi.c makelist
- sh ./makelist -h ./vi.c > $@.tmp && \
+vi.h: $(srcdir)/vi.c makelist
+ sh ./makelist -h $(srcdir)/vi.c > $@.tmp && \
mv $@.tmp $@
-emacs.h: emacs.c makelist
- sh ./makelist -h ./emacs.c > $@.tmp && \
+emacs.h: $(srcdir)/emacs.c makelist
+ sh ./makelist -h $(srcdir)/emacs.c > $@.tmp && \
mv $@.tmp $@
-common.h: common.c makelist
- sh ./makelist -h ./common.c > $@.tmp && \
+common.h: $(srcdir)/common.c makelist
+ sh ./makelist -h $(srcdir)/common.c > $@.tmp && \
mv $@.tmp $@
help.c: ${ASRC} makelist
diff --git a/config/ac-macros/zlib.m4 b/config/ac-macros/zlib.m4
index 22cf9542cf0..ec55f19b98f 100644
--- a/config/ac-macros/zlib.m4
+++ b/config/ac-macros/zlib.m4
@@ -19,7 +19,7 @@ INCLUDES="$INCLUDES $ZLIB_INCLUDES"
LIBS="$LIBS $ZLIB_LIBS"
AC_CACHE_VAL([mysql_cv_compress],
[AC_TRY_LINK([#include <zlib.h>],
- [return compress(0, (unsigned long*) 0, "", 0);],
+ [return zlibCompileFlags();],
[mysql_cv_compress="yes"
AC_MSG_RESULT([ok])],
[mysql_cv_compress="no"])
diff --git a/configure.in b/configure.in
index 1504fb2ba80..efcaf82934d 100644
--- a/configure.in
+++ b/configure.in
@@ -60,7 +60,6 @@ AC_DEFINE_UNQUOTED([DOT_FRM_VERSION], [$DOT_FRM_VERSION],
[Version of .frm files])
AC_SUBST(SHARED_LIB_VERSION)
AC_SUBST(AVAILABLE_LANGUAGES)
-AC_SUBST(AVAILABLE_LANGUAGES_ERRORS)
# Canonicalize the configuration name.
@@ -2181,6 +2180,7 @@ then
AC_MSG_WARN([extra-tools disabled because --enable-thread-safe-client wasn't used])
else
tools_dirs="tools"
+ AC_CONFIG_FILES(tools/Makefile)
fi
fi
@@ -2202,9 +2202,12 @@ MYSQL_CHECK_OPENSSL
MYSQL_CHECK_YASSL
libmysqld_dirs=
+linked_libmysqld_targets=
if test "$with_embedded_server" = "yes"
then
libmysqld_dirs=libmysqld
+ linked_libmysqld_targets="linked_libmysqld_sources linked_libmysqldex_sources"
+ AC_CONFIG_FILES(libmysqld/Makefile libmysqld/examples/Makefile)
# We can't build embedded library without building the server, because
# we depend on libmysys, libmystrings, libmyisam, etc.
with_server=yes
@@ -2213,6 +2216,7 @@ fi
# mysql_config --libmysqld-libs will print out something like
# -L/path/to/lib/mysql -lmysqld -lmyisam -lmysys -lmystrings -ldbug ...
AC_SUBST([libmysqld_dirs])
+AC_SUBST([linked_libmysqld_targets])
# Shall we build the docs?
AC_ARG_WITH(docs,
@@ -2317,7 +2321,7 @@ then
readline_basedir="libedit"
readline_dir="$readline_topdir/$readline_basedir"
readline_link="\$(top_builddir)/cmd-line-utils/libedit/libedit.a"
- readline_h_ln_cmd="\$(LN) -s \$(top_builddir)/cmd-line-utils/libedit/readline readline"
+ readline_h_ln_cmd="\$(LN) -s \$(top_srcdir)/cmd-line-utils/libedit/readline readline"
compile_libedit=yes
AC_DEFINE_UNQUOTED(HAVE_HIST_ENTRY, 1)
AC_DEFINE_UNQUOTED(USE_LIBEDIT_INTERFACE, 1)
@@ -2327,7 +2331,7 @@ then
readline_basedir="readline"
readline_dir="$readline_topdir/$readline_basedir"
readline_link="\$(top_builddir)/cmd-line-utils/readline/libreadline.a"
- readline_h_ln_cmd="\$(LN) -s \$(top_builddir)/cmd-line-utils/readline readline"
+ readline_h_ln_cmd="\$(LN) -s \$(top_srcdir)/cmd-line-utils/readline readline"
compile_readline=yes
AC_DEFINE_UNQUOTED(USE_NEW_READLINE_INTERFACE, 1)
else
@@ -2432,6 +2436,7 @@ if test "$THREAD_SAFE_CLIENT" != "no"
then
sql_client_dirs="libmysql_r $sql_client_dirs"
linked_client_targets="$linked_client_targets linked_libmysql_r_sources"
+ AC_CONFIG_FILES(libmysql_r/Makefile)
AC_DEFINE([THREAD_SAFE_CLIENT], [1], [Should be client be thread safe])
fi
@@ -2531,12 +2536,11 @@ AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
storage/myisam/Makefile storage/myisammrg/Makefile dnl
os2/Makefile os2/include/Makefile os2/include/sys/Makefile dnl
man/Makefile BUILD/Makefile vio/Makefile dnl
- libmysql_r/Makefile libmysqld/Makefile libmysqld/examples/Makefile dnl
libmysql/Makefile client/Makefile dnl
pstack/Makefile pstack/aout/Makefile sql/Makefile sql/share/Makefile dnl
sql/handlerton.cc sql-common/Makefile SSL/Makefile dnl
dbug/Makefile scripts/Makefile dnl
- include/Makefile sql-bench/Makefile tools/Makefile dnl
+ include/Makefile sql-bench/Makefile dnl
server-tools/Makefile server-tools/instance-manager/Makefile dnl
tests/Makefile Docs/Makefile support-files/Makefile dnl
support-files/MacOSX/Makefile mysql-test/Makefile dnl
diff --git a/extra/Makefile.am b/extra/Makefile.am
index feb96cdaf24..a2b4dce374a 100644
--- a/extra/Makefile.am
+++ b/extra/Makefile.am
@@ -23,6 +23,9 @@ BUILT_SOURCES= $(top_builddir)/include/mysqld_error.h \
$(top_builddir)/include/mysqld_ername.h
pkginclude_HEADERS= $(BUILT_SOURCES)
CLEANFILES = $(BUILT_SOURCES)
+# We never use SUBDIRS here, but needed for automake 1.6.3
+# to generate code to handle DIST_SUBDIRS
+SUBDIRS=
DIST_SUBDIRS= yassl
# This will build mysqld_error.h and sql_state.h
diff --git a/extra/yassl/Makefile.am b/extra/yassl/Makefile.am
index 7c1f2ea5acb..41c4d84f24f 100644
--- a/extra/yassl/Makefile.am
+++ b/extra/yassl/Makefile.am
@@ -1,2 +1,2 @@
SUBDIRS = taocrypt src
-EXTRA_DIST = yassl.dsp yassl.dsw mySTL/*.hpp
+EXTRA_DIST = yassl.dsp yassl.dsw $(wildcard mySTL/*.hpp)
diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am
index 4ebb9a2d862..df96018e1cf 100644
--- a/extra/yassl/src/Makefile.am
+++ b/extra/yassl/src/Makefile.am
@@ -4,5 +4,5 @@ noinst_LIBRARIES = libyassl.a
libyassl_a_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \
handshake.cpp lock.cpp log.cpp socket_wrapper.cpp ssl.cpp \
template_instnt.cpp timer.cpp yassl_imp.cpp yassl_error.cpp yassl_int.cpp
-EXTRA_DIST = ../include/*.hpp ../include/openssl/*.h
+EXTRA_DIST = $(wildcard ../include/*.hpp) $(wildcard ../include/openssl/*.h)
AM_CXXFLAGS = -DYASSL_PURE_C
diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am
index 9ce083e9e56..0319fc6057b 100644
--- a/extra/yassl/taocrypt/src/Makefile.am
+++ b/extra/yassl/taocrypt/src/Makefile.am
@@ -11,5 +11,5 @@ libtaocrypt_a_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp asn.cpp \
template_instnt.cpp
libtaocrypt_a_LIBADD = libtaoint_a-integer.o
-EXTRA_DIST = ../include/*.hpp
+EXTRA_DIST = $(wildcard ../include/*.hpp)
AM_CXXFLAGS = -DYASSL_PURE_C
diff --git a/include/Makefile.am b/include/Makefile.am
index 8c3a575453d..d2605628a7d 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -38,20 +38,12 @@ CLEANFILES = mysql_version.h my_config.h readline
# Some include files that may be moved and patched by configure
DISTCLEANFILES = sched.h $(CLEANFILES)
-all-local: my_config.h
-
-# Since we include my_config.h it better exist from the beginning
link_sources:
- $(CP) ../config.h my_config.h
-$(RM) -fr readline
@readline_h_ln_cmd@
-# Keep automake happy
-
my_config.h: ../config.h
$(CP) ../config.h my_config.h
- -$(RM) -fr readline
- @readline_h_ln_cmd@
# These files should not be included in distributions since they are
# generated by configure from the .h.in files
diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am
index 403ff415378..319a9913255 100644
--- a/libmysql/Makefile.am
+++ b/libmysql/Makefile.am
@@ -43,33 +43,33 @@ link_sources:
vs=`echo $(vio_objects) | sed "s;\.lo;.c;g"`; \
scs=`echo $(sql_cmn_objects) | sed "s;\.lo;.c;g"`; \
for f in $$ss; do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \
done; \
for f in $$vs $(vioheaders); do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ $(srcdir)/../vio/$$f $(srcdir)/$$f; \
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/vio/$$f $$f; \
done; \
for f in $$scs; do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ $(srcdir)/../sql-common/$$f $(srcdir)/$$f; \
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/sql-common/$$f $$f; \
done; \
for f in $(mystringsextra); do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \
done; \
for f in $$ds; do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ $(srcdir)/../dbug/$$f $(srcdir)/$$f; \
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/dbug/$$f $$f; \
done; \
for f in $$ms $(mysysheaders); do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ $(srcdir)/../mysys/$$f $(srcdir)/$$f; \
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/mysys/$$f $$f; \
done; \
- rm -f $(srcdir)/net.c; \
- @LN_CP_F@ $(srcdir)/../sql/net_serv.cc $(srcdir)/net.c ; \
- rm -f $(srcdir)/password.c; \
- @LN_CP_F@ $(srcdir)/../sql/password.c $(srcdir)/password.c
+ rm -f net.c; \
+ @LN_CP_F@ $(top_srcdir)/sql/net_serv.cc net.c ; \
+ rm -f password.c; \
+ @LN_CP_F@ $(top_srcdir)/sql/password.c password.c
# This part requires GNUmake
#
diff --git a/libmysql_r/Makefile.am b/libmysql_r/Makefile.am
index 6ab09368cc5..ee6dd4cfded 100644
--- a/libmysql_r/Makefile.am
+++ b/libmysql_r/Makefile.am
@@ -39,6 +39,6 @@ libmysqlclient_r_la_LDFLAGS = $(target_ldflags)
link_sources:
set -x; \
for f in `cd $(libmysql_dir) && echo *.[ch]`; do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ $(libmysql_dir)/$$f $(srcdir)/$$f; \
+ rm -f $$f; \
+ @LN_CP_F@ $(libmysql_dir)/$$f $$f; \
done
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index 14125c79e10..da0418eaf9c 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -143,19 +143,19 @@ endif
link_sources:
set -x; \
for f in $(sqlsources); do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ $(srcdir)/../sql/$$f $(srcdir)/$$f; \
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \
done; \
for f in $(libmysqlsources); do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ $(srcdir)/../libmysql/$$f $(srcdir)/$$f; \
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/libmysql/$$f $$f; \
done; \
for f in $(sqlstoragesources); do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ `find $(srcdir)/../sql -name $$f` $(srcdir)/$$f; \
+ rm -f $$f; \
+ @LN_CP_F@ `find $(srcdir)/../sql -name $$f` $$f; \
done; \
- rm -f $(srcdir)/client_settings.h; \
- @LN_CP_F@ $(srcdir)/../libmysql/client_settings.h $(srcdir)/client_settings.h;
+ rm -f client_settings.h; \
+ @LN_CP_F@ $(top_srcdir)/libmysql/client_settings.h client_settings.h
clean-local:
diff --git a/libmysqld/examples/Makefile.am b/libmysqld/examples/Makefile.am
index 0bd3f06a9f3..bbfa4d87181 100644
--- a/libmysqld/examples/Makefile.am
+++ b/libmysqld/examples/Makefile.am
@@ -21,14 +21,15 @@ tests_sources = $(mysql_client_test_embedded_SOURCES)
CLEANFILES = $(client_sources) $(tests_sources)
link_sources:
+ set -x; \
for f in $(client_sources); do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ $(srcdir)/../../client/$$f $(srcdir)/$$f; \
- done;
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/client/$$f $$f; \
+ done; \
for f in $(tests_sources); do \
- rm -f $(srcdir)/$$f; \
- @LN_CP_F@ $(srcdir)/../../tests/$$f $(srcdir)/$$f; \
- done;
+ rm -f $$f; \
+ @LN_CP_F@ $(top_srcdir)/tests/$$f $$f; \
+ done
DEFS = -DEMBEDDED_LIBRARY
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir) \
diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am
index 2142a84419e..a63b4cbf178 100644
--- a/mysql-test/Makefile.am
+++ b/mysql-test/Makefile.am
@@ -85,6 +85,9 @@ install-data-local:
$(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(DESTDIR)$(testdir)/lib
$(INSTALL_DATA) $(srcdir)/lib/*.pl $(DESTDIR)$(testdir)/lib
+uninstall-local:
+ @RM@ -f -r $(DESTDIR)$(testdir)
+
std_data/client-key.pem:
@CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data
std_data/client-cert.pem:
diff --git a/mysql-test/include/is_debug_build.inc b/mysql-test/include/is_debug_build.inc
new file mode 100644
index 00000000000..23a2814e2bb
--- /dev/null
+++ b/mysql-test/include/is_debug_build.inc
@@ -0,0 +1,4 @@
+-- require r/is_debug_build.require
+--disable_query_log
+select instr(version(), "debug") > 0;
+--enable_query_log
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index 817be3a2e7c..8da18df1954 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -68,12 +68,12 @@ select CONVERT(DATE "2004-01-22 21:45:33",BINARY(4));
CONVERT(DATE "2004-01-22 21:45:33",BINARY(4))
2004
Warnings:
-Warning 1292 Truncated incorrect CHAR(4) value: '2004-01-22 21:45:33'
+Warning 1292 Truncated incorrect BINARY(4) value: '2004-01-22 21:45:33'
select CAST(DATE "2004-01-22 21:45:33" AS BINARY(4));
CAST(DATE "2004-01-22 21:45:33" AS BINARY(4))
2004
Warnings:
-Warning 1292 Truncated incorrect CHAR(4) value: '2004-01-22 21:45:33'
+Warning 1292 Truncated incorrect BINARY(4) value: '2004-01-22 21:45:33'
select CAST(0xb3 as signed);
CAST(0xb3 as signed)
179
@@ -165,17 +165,17 @@ cast(_latin1'ab' AS char) as c1,
cast(_latin1'a ' AS char) as c2,
cast(_latin1'abc' AS char(2)) as c3,
cast(_latin1'a ' AS char(2)) as c4,
-cast(_latin1'a' AS char(2)) as c5;
+hex(cast(_latin1'a' AS char(2))) as c5;
c1 c2 c3 c4 c5
-ab a ab a a
+ab a ab a 6100
Warnings:
-Warning 1292 Truncated incorrect CHAR(2) value: 'abc'
-Warning 1292 Truncated incorrect CHAR(2) value: 'a '
+Warning 1292 Truncated incorrect BINARY(2) value: 'abc'
+Warning 1292 Truncated incorrect BINARY(2) value: 'a '
select cast(1000 as CHAR(3));
cast(1000 as CHAR(3))
100
Warnings:
-Warning 1292 Truncated incorrect CHAR(3) value: '1000'
+Warning 1292 Truncated incorrect BINARY(3) value: '1000'
create table t1 select
cast(_latin1'ab' AS char) as c1,
cast(_latin1'a ' AS char) as c2,
@@ -183,11 +183,11 @@ cast(_latin1'abc' AS char(2)) as c3,
cast(_latin1'a ' AS char(2)) as c4,
cast(_latin1'a' AS char(2)) as c5;
Warnings:
-Warning 1292 Truncated incorrect CHAR(2) value: 'abc'
-Warning 1292 Truncated incorrect CHAR(2) value: 'a '
-select * from t1;
-c1 c2 c3 c4 c5
-ab a ab a a
+Warning 1292 Truncated incorrect BINARY(2) value: 'abc'
+Warning 1292 Truncated incorrect BINARY(2) value: 'a '
+select c1,c2,c3,c4,hex(c5) from t1;
+c1 c2 c3 c4 hex(c5)
+ab a ab a 6100
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -274,9 +274,9 @@ aac aac
aab aab
aaa aaa
Warnings:
-Warning 1292 Truncated incorrect CHAR(2) value: 'aaa'
-Warning 1292 Truncated incorrect CHAR(2) value: 'aab'
-Warning 1292 Truncated incorrect CHAR(2) value: 'aac'
+Warning 1292 Truncated incorrect BINARY(2) value: 'aaa'
+Warning 1292 Truncated incorrect BINARY(2) value: 'aab'
+Warning 1292 Truncated incorrect BINARY(2) value: 'aac'
SELECT a, CAST(a AS UNSIGNED) FROM t1 ORDER BY CAST(a AS CHAR) ;
a CAST(a AS UNSIGNED)
aaa 3
@@ -288,9 +288,9 @@ aaa aa
aab aa
aac aa
Warnings:
-Warning 1292 Truncated incorrect CHAR(2) value: 'aaa'
-Warning 1292 Truncated incorrect CHAR(2) value: 'aab'
-Warning 1292 Truncated incorrect CHAR(2) value: 'aac'
+Warning 1292 Truncated incorrect BINARY(2) value: 'aaa'
+Warning 1292 Truncated incorrect BINARY(2) value: 'aab'
+Warning 1292 Truncated incorrect BINARY(2) value: 'aac'
DROP TABLE t1;
select date_add(cast('2004-12-30 12:00:00' as date), interval 0 hour);
date_add(cast('2004-12-30 12:00:00' as date), interval 0 hour)
diff --git a/mysql-test/r/is_debug_build.require b/mysql-test/r/is_debug_build.require
new file mode 100644
index 00000000000..4d77bcdc1ed
--- /dev/null
+++ b/mysql-test/r/is_debug_build.require
@@ -0,0 +1,2 @@
+instr(version(), "debug") > 0
+1
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index 3b3db08303a..bb89ff29b8a 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -2494,3 +2494,59 @@ drop view v2;
drop view v0;
drop view v1;
drop table t1;
+SET @old_sql_mode = @@SQL_MODE;
+SET SQL_MODE = IGNORE_SPACE;
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER tr1 BEFORE INSERT ON t1
+FOR EACH ROW
+BEGIN
+SET new.a = 0;
+END|
+SET SQL_MODE = @old_sql_mode;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET latin1 */;
+
+USE `test`;
+DROP TABLE IF EXISTS `t1`;
+CREATE TABLE `t1` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
+LOCK TABLES `t1` WRITE;
+UNLOCK TABLES;
+/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
+
+/*!50003 SET @OLD_SQL_MODE=@@SQL_MODE*/;
+DELIMITER ;;
+/*!50003 SET SESSION SQL_MODE="IGNORE_SPACE" */;;
+/*!50003 CREATE TRIGGER `tr1` BEFORE INSERT ON `t1` FOR EACH ROW BEGIN
+SET new.a = 0;
+END */;;
+
+DELIMITER ;
+/*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE */;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+DROP TRIGGER tr1;
+DROP TABLE t1;
diff --git a/mysql-test/r/ndb_alter_table.result b/mysql-test/r/ndb_alter_table.result
index 84dbe975a59..ee88b7c8007 100644
--- a/mysql-test/r/ndb_alter_table.result
+++ b/mysql-test/r/ndb_alter_table.result
@@ -179,8 +179,7 @@ a b c
2 two two
alter table t1 drop index c;
select * from t1 where b = 'two';
-a b c
-2 two two
+ERROR HY000: Table definition has changed, please retry transaction
select * from t1 where b = 'two';
a b c
2 two two
diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result
new file mode 100644
index 00000000000..e6c4ffe1731
--- /dev/null
+++ b/mysql-test/r/sp-code.result
@@ -0,0 +1,62 @@
+create procedure empty()
+begin
+end;
+show procedure code empty;
+Pos Instruction
+drop procedure empty;
+create function almost_empty()
+returns int
+return 0;
+show function code almost_empty;
+Pos Instruction
+0 freturn 3 0
+drop function almost_empty;
+create procedure code_sample(x int, out err int, out nulls int)
+begin
+declare count int default 0;
+set nulls = 0;
+begin
+declare c cursor for select name from t1;
+declare exit handler for not found close c;
+open c;
+loop
+begin
+declare n varchar(20);
+declare continue handler for sqlexception set err=1;
+fetch c into n;
+if isnull(n) then
+set nulls = nulls + 1;
+else
+set count = count + 1;
+update t2 set idx = count where name=n;
+end if;
+end;
+end loop;
+end;
+select t.name, t.idx from t2 t order by idx asc;
+end//
+show procedure code code_sample;
+Pos Instruction
+0 set count@3 0
+1 set nulls@2 0
+2 cpush c@0
+3 hpush_jump 6 4 EXIT
+4 cclose c@0
+5 hreturn 0 19
+6 copen c@0
+7 set n@4 NULL
+8 hpush_jump 11 5 CONTINUE
+9 set err@1 1
+10 hreturn 5
+11 cfetch c@0 n@4
+12 jump_if_not 15 isnull(n@4)
+13 set nulls@2 (nulls@2 + 1)
+14 jump 17
+15 set count@3 (count@3 + 1)
+16 stmt 4 "update t2 set idx = count where name=n"
+17 hpop 1
+18 jump 7
+19 hpop 1
+20 cpop 1
+21 stmt 0 "select t.name, t.idx from t2 t order ..."
+drop procedure code_sample;
diff --git a/mysql-test/r/sp-dynamic.result b/mysql-test/r/sp-dynamic.result
index 8fe469431cc..cf07f540608 100644
--- a/mysql-test/r/sp-dynamic.result
+++ b/mysql-test/r/sp-dynamic.result
@@ -33,6 +33,8 @@ begin
execute stmt;
end|
prepare stmt from "call p1()"|
+set @SAVE_SP_RECURSION_LEVELS=@@max_sp_recursion_depth|
+set @@max_sp_recursion_depth=100|
execute stmt|
ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
execute stmt|
@@ -40,11 +42,18 @@ ERROR HY000: The prepared statement contains a stored routine call that refers t
execute stmt|
ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
call p1()|
-ERROR HY000: Recursive stored routines are not allowed.
+ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
+call p1()|
+ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
+call p1()|
+ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
+set @@max_sp_recursion_depth=@SAVE_SP_RECURSION_LEVELS|
+call p1()|
+ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine p1
call p1()|
-ERROR HY000: Recursive stored routines are not allowed.
+ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine p1
call p1()|
-ERROR HY000: Recursive stored routines are not allowed.
+ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine p1
drop procedure p1|
create procedure p1()
begin
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index 858f7d0bb16..963f14820be 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -708,7 +708,7 @@ return (i in (100, 200, bug11394(i-1), 400));
end if;
end|
select bug11394(2)|
-ERROR HY000: Recursive stored routines are not allowed.
+ERROR HY000: Recursive stored functions and triggers are not allowed.
drop function bug11394|
create function bug11394_1(i int) returns int
begin
@@ -719,7 +719,7 @@ return (select bug11394_1(i-1));
end if;
end|
select bug11394_1(2)|
-ERROR HY000: Recursive stored routines are not allowed.
+ERROR HY000: Recursive stored functions and triggers are not allowed.
drop function bug11394_1|
create function bug11394_2(i int) returns int return i|
select bug11394_2(bug11394_2(10))|
@@ -733,7 +733,10 @@ call bug11394(i - 1,(select 1));
end if;
end|
call bug11394(2, 1)|
-ERROR HY000: Recursive stored routines are not allowed.
+ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine bug11394
+set @@max_sp_recursion_depth=10|
+call bug11394(2, 1)|
+set @@max_sp_recursion_depth=default|
drop procedure bug11394|
CREATE PROCEDURE BUG_12490() HELP CONTENTS;
ERROR 0A000: HELP is not allowed in stored procedures
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 93332af21a9..c3b4039d12d 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -3417,6 +3417,9 @@ Table Create Table
tm1 CREATE TEMPORARY TABLE `tm1` (
`spv1` decimal(6,3) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop procedure bug12589_1|
+drop procedure bug12589_2|
+drop procedure bug12589_3|
drop table if exists t3|
drop procedure if exists bug7049_1|
drop procedure if exists bug7049_2|
@@ -3667,4 +3670,203 @@ call bug14845()|
a
0
drop procedure bug14845|
+drop procedure if exists bug13549_1|
+drop procedure if exists bug13549_2|
+CREATE PROCEDURE `bug13549_2`()
+begin
+call bug13549_1();
+end|
+CREATE PROCEDURE `bug13549_1`()
+begin
+declare done int default 0;
+set done= not done;
+end|
+CALL bug13549_2()|
+drop procedure bug13549_2|
+drop procedure bug13549_1|
+drop function if exists bug10100f|
+drop procedure if exists bug10100p|
+drop procedure if exists bug10100t|
+drop procedure if exists bug10100pt|
+drop procedure if exists bug10100pv|
+drop procedure if exists bug10100pd|
+drop procedure if exists bug10100pc|
+create function bug10100f(prm int) returns int
+begin
+if prm > 1 then
+return prm * bug10100f(prm - 1);
+end if;
+return 1;
+end|
+create procedure bug10100p(prm int, inout res int)
+begin
+set res = res * prm;
+if prm > 1 then
+call bug10100p(prm - 1, res);
+end if;
+end|
+create procedure bug10100t(prm int)
+begin
+declare res int;
+set res = 1;
+call bug10100p(prm, res);
+select res;
+end|
+create table t3 (a int)|
+insert into t3 values (0)|
+create view v1 as select a from t3;
+create procedure bug10100pt(level int, lim int)
+begin
+if level < lim then
+update t3 set a=level;
+FLUSH TABLES;
+call bug10100pt(level+1, lim);
+else
+select * from t3;
+end if;
+end|
+create procedure bug10100pv(level int, lim int)
+begin
+if level < lim then
+update v1 set a=level;
+FLUSH TABLES;
+call bug10100pv(level+1, lim);
+else
+select * from v1;
+end if;
+end|
+prepare stmt2 from "select * from t3;";
+create procedure bug10100pd(level int, lim int)
+begin
+if level < lim then
+select level;
+prepare stmt1 from "update t3 set a=a+2";
+execute stmt1;
+FLUSH TABLES;
+execute stmt1;
+FLUSH TABLES;
+execute stmt1;
+FLUSH TABLES;
+deallocate prepare stmt1;
+execute stmt2;
+select * from t3;
+call bug10100pd(level+1, lim);
+else
+execute stmt2;
+end if;
+end|
+create procedure bug10100pc(level int, lim int)
+begin
+declare lv int;
+declare c cursor for select a from t3;
+open c;
+if level < lim then
+select level;
+fetch c into lv;
+select lv;
+update t3 set a=level+lv;
+FLUSH TABLES;
+call bug10100pc(level+1, lim);
+else
+select * from t3;
+end if;
+close c;
+end|
+set @@max_sp_recursion_depth=4|
+select @@max_sp_recursion_depth|
+@@max_sp_recursion_depth
+4
+select bug10100f(3)|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+select bug10100f(6)|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+call bug10100t(5)|
+res
+120
+call bug10100pt(1,5)|
+a
+4
+call bug10100pv(1,5)|
+a
+4
+update t3 set a=1|
+call bug10100pd(1,5)|
+level
+1
+a
+7
+a
+7
+level
+2
+a
+13
+a
+13
+level
+3
+a
+19
+a
+19
+level
+4
+a
+25
+a
+25
+a
+25
+select * from t3|
+a
+25
+update t3 set a=1|
+call bug10100pc(1,5)|
+level
+1
+lv
+1
+level
+2
+lv
+2
+level
+3
+lv
+4
+level
+4
+lv
+7
+a
+11
+select * from t3|
+a
+11
+set @@max_sp_recursion_depth=0|
+select @@max_sp_recursion_depth|
+@@max_sp_recursion_depth
+0
+select bug10100f(5)|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+call bug10100t(5)|
+ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine bug10100p
+set @@max_sp_recursion_depth=255|
+set @var=1|
+call bug10100p(255, @var)|
+call bug10100pt(1,255)|
+call bug10100pv(1,255)|
+call bug10100pd(1,255)|
+call bug10100pc(1,255)|
+set @@max_sp_recursion_depth=0|
+deallocate prepare stmt2|
+drop function bug10100f|
+drop procedure bug10100p|
+drop procedure bug10100t|
+drop procedure bug10100pt|
+drop procedure bug10100pv|
+drop procedure bug10100pd|
+drop procedure bug10100pc|
+drop view v1|
+drop table t3|
drop table t1,t2;
diff --git a/mysql-test/r/sp_trans.result b/mysql-test/r/sp_trans.result
index 6077087ab87..bb742d0d3d7 100644
--- a/mysql-test/r/sp_trans.result
+++ b/mysql-test/r/sp_trans.result
@@ -174,3 +174,198 @@ ERROR HY000: Explicit or implicit commit is not allowed in stored function or tr
drop procedure bug10015_8|
drop function bug10015_7|
drop table t1, t2|
+drop function if exists bug13825_0|
+drop function if exists bug13825_1|
+drop function if exists bug13825_2|
+drop function if exists bug13825_3|
+drop function if exists bug13825_4|
+drop function if exists bug13825_5|
+drop procedure if exists bug13825_0|
+drop procedure if exists bug13825_1|
+drop procedure if exists bug13825_2|
+drop table if exists t1|
+create table t1 (i int) engine=innodb|
+create table t2 (i int) engine=innodb|
+create function bug13825_0() returns int
+begin
+rollback to savepoint x;
+return 1;
+end|
+create function bug13825_1() returns int
+begin
+release savepoint x;
+return 1;
+end|
+create function bug13825_2() returns int
+begin
+insert into t1 values (2);
+savepoint x;
+insert into t1 values (3);
+rollback to savepoint x;
+insert into t1 values (4);
+return 1;
+end|
+create procedure bug13825_0()
+begin
+rollback to savepoint x;
+end|
+create procedure bug13825_1()
+begin
+release savepoint x;
+end|
+create procedure bug13825_2()
+begin
+savepoint x;
+end|
+insert into t2 values (1)|
+create trigger t2_bi before insert on t2 for each row
+rollback to savepoint x|
+create trigger t2_bu before update on t2 for each row
+release savepoint x|
+create trigger t2_bd before delete on t2 for each row
+begin
+insert into t1 values (2);
+savepoint x;
+insert into t1 values (3);
+rollback to savepoint x;
+insert into t1 values (4);
+end|
+create function bug13825_3(rb int) returns int
+begin
+insert into t1 values(1);
+savepoint x;
+insert into t1 values(2);
+if rb then
+rollback to savepoint x;
+end if;
+insert into t1 values(3);
+return rb;
+end|
+create function bug13825_4() returns int
+begin
+savepoint x;
+insert into t1 values(2);
+rollback to savepoint x;
+return 0;
+end|
+create function bug13825_5(p int) returns int
+begin
+savepoint x;
+insert into t2 values(p);
+rollback to savepoint x;
+insert into t2 values(p+1);
+return p;
+end|
+set autocommit= 0|
+begin |
+insert into t1 values (1)|
+savepoint x|
+set @a:= bug13825_0()|
+ERROR 42000: SAVEPOINT x does not exist
+insert into t2 values (2)|
+ERROR 42000: SAVEPOINT x does not exist
+set @a:= bug13825_1()|
+ERROR 42000: SAVEPOINT x does not exist
+update t2 set i = 2|
+ERROR 42000: SAVEPOINT x does not exist
+set @a:= bug13825_2()|
+select * from t1|
+i
+1
+2
+4
+rollback to savepoint x|
+select * from t1|
+i
+1
+delete from t2|
+select * from t1|
+i
+1
+2
+4
+rollback to savepoint x|
+select * from t1|
+i
+1
+release savepoint x|
+set @a:= bug13825_2()|
+select * from t1|
+i
+1
+2
+4
+rollback to savepoint x|
+ERROR 42000: SAVEPOINT x does not exist
+delete from t1|
+commit|
+begin|
+insert into t1 values (5)|
+savepoint x|
+insert into t1 values (6)|
+call bug13825_0()|
+select * from t1|
+i
+5
+call bug13825_1()|
+rollback to savepoint x|
+ERROR 42000: SAVEPOINT x does not exist
+savepoint x|
+insert into t1 values (7)|
+call bug13825_2()|
+rollback to savepoint x|
+select * from t1|
+i
+5
+7
+delete from t1|
+commit|
+set autocommit= 1|
+select bug13825_3(0)|
+bug13825_3(0)
+0
+select * from t1|
+i
+1
+2
+3
+delete from t1|
+select bug13825_3(1)|
+bug13825_3(1)
+1
+select * from t1|
+i
+1
+3
+delete from t1|
+set autocommit= 0|
+begin|
+insert into t1 values (1)|
+set @a:= bug13825_4()|
+select * from t1|
+i
+1
+delete from t1|
+commit|
+set autocommit= 1|
+drop table t2|
+create table t2 (i int) engine=innodb|
+insert into t1 values (1), (bug13825_5(2)), (3)|
+select * from t1|
+i
+1
+2
+3
+select * from t2|
+i
+3
+drop function bug13825_0|
+drop function bug13825_1|
+drop function bug13825_2|
+drop function bug13825_3|
+drop function bug13825_4|
+drop function bug13825_5|
+drop procedure bug13825_0|
+drop procedure bug13825_1|
+drop procedure bug13825_2|
+drop table t1, t2|
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index af99dea58b9..ff92fc543d4 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -703,8 +703,11 @@ create trigger t1_ai after insert on t1
for each row insert into t2 values (new.f1+1);
create trigger t2_ai after insert on t2
for each row insert into t1 values (new.f2+1);
+set @SAVE_SP_RECURSION_LEVELS=@@max_sp_recursion_depth;
+set @@max_sp_recursion_depth=100;
insert into t1 values (1);
ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+set @@max_sp_recursion_depth=@SAVE_SP_RECURSION_LEVELS;
select * from t1;
f1
1
@@ -763,3 +766,17 @@ ERROR HY000: Table 't3' was not locked with LOCK TABLES
deallocate prepare stmt1;
drop procedure p1;
drop table t1, t2, t3;
+create table t1 (a int);
+drop procedure if exists p2;
+CREATE PROCEDURE `p2`()
+begin
+insert into t1 values (1);
+end//
+create trigger trg before insert on t1 for each row
+begin
+declare done int default 0;
+set done= not done;
+end//
+CALL p2();
+drop procedure p2;
+drop table t1;
diff --git a/mysql-test/r/type_binary.result b/mysql-test/r/type_binary.result
index 49fd7ba5633..1c60bf46608 100644
--- a/mysql-test/r/type_binary.result
+++ b/mysql-test/r/type_binary.result
@@ -111,3 +111,6 @@ select count(distinct s1) from t1;
count(distinct s1)
3
drop table t1;
+select hex(cast(0x10 as binary(2)));
+hex(cast(0x10 as binary(2)))
+1000
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index 3ecc48620b1..df180218a09 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -351,6 +351,14 @@ set global rpl_recovery_rank=100;
set global server_id=100;
set global slow_launch_time=100;
set sort_buffer_size=100;
+set @@max_sp_recursion_depth=10;
+select @@max_sp_recursion_depth;
+@@max_sp_recursion_depth
+10
+set @@max_sp_recursion_depth=0;
+select @@max_sp_recursion_depth;
+@@max_sp_recursion_depth
+0
set sql_auto_is_null=1;
select @@sql_auto_is_null;
@@sql_auto_is_null
diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result
index 89067ec23a2..e2ee02351d7 100644
--- a/mysql-test/r/view_grant.result
+++ b/mysql-test/r/view_grant.result
@@ -501,3 +501,20 @@ drop user test14256;
insert into mysql.user select * from t1;
flush privileges;
drop table t1;
+create database mysqltest;
+use mysqltest;
+CREATE TABLE t1 (i INT);
+CREATE VIEW v1 AS SELECT * FROM t1;
+SHOW CREATE VIEW v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1`
+GRANT SELECT, LOCK TABLES ON mysqltest.* TO mysqltest_1@localhost;
+use mysqltest;
+LOCK TABLES v1 READ;
+SHOW CREATE TABLE v1;
+ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1'
+UNLOCK TABLES;
+use test;
+use test;
+drop user mysqltest_1@localhost;
+drop database mysqltest;
diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test
index 70eb87131df..dc7f695e38e 100644
--- a/mysql-test/t/cast.test
+++ b/mysql-test/t/cast.test
@@ -64,7 +64,7 @@ select
cast(_latin1'a ' AS char) as c2,
cast(_latin1'abc' AS char(2)) as c3,
cast(_latin1'a ' AS char(2)) as c4,
- cast(_latin1'a' AS char(2)) as c5;
+ hex(cast(_latin1'a' AS char(2))) as c5;
select cast(1000 as CHAR(3));
create table t1 select
@@ -73,7 +73,7 @@ create table t1 select
cast(_latin1'abc' AS char(2)) as c3,
cast(_latin1'a ' AS char(2)) as c4,
cast(_latin1'a' AS char(2)) as c5;
-select * from t1;
+select c1,c2,c3,c4,hex(c5) from t1;
show create table t1;
drop table t1;
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 83085823729..5666f23f5aa 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -999,3 +999,27 @@ drop view v2;
drop view v0;
drop view v1;
drop table t1;
+
+#
+# BUG#14554 - mysqldump does not separate words "ROW" and "BEGIN"
+# for tables with trigger created in the IGNORE_SPACE sql mode.
+#
+
+SET @old_sql_mode = @@SQL_MODE;
+SET SQL_MODE = IGNORE_SPACE;
+
+CREATE TABLE t1 (a INT);
+DELIMITER |;
+CREATE TRIGGER tr1 BEFORE INSERT ON t1
+ FOR EACH ROW
+ BEGIN
+ SET new.a = 0;
+ END|
+DELIMITER ;|
+
+SET SQL_MODE = @old_sql_mode;
+
+--exec $MYSQL_DUMP --skip-comments --databases test
+
+DROP TRIGGER tr1;
+DROP TABLE t1;
diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test
index 75ab245a352..58e3e002b2a 100644
--- a/mysql-test/t/ndb_alter_table.test
+++ b/mysql-test/t/ndb_alter_table.test
@@ -142,6 +142,7 @@ INSERT INTO t1 VALUES (1,2,0),(18,19,4),(20,21,0);
select c from t1 order by c;
drop table t1;
+--disable_ps_protocol
create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) )
engine=ndb;
insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three');
@@ -151,10 +152,13 @@ select * from t1 where b = 'two';
connection server1;
alter table t1 drop index c;
connection server2;
+# This should fail since index information is not automatically refreshed
+--error 1412
select * from t1 where b = 'two';
select * from t1 where b = 'two';
connection server1;
drop table t1;
+--enable_ps_protocol
#--disable_warnings
#DROP TABLE IF EXISTS t2;
diff --git a/mysql-test/t/sp-code.test b/mysql-test/t/sp-code.test
new file mode 100644
index 00000000000..6644bc3ab43
--- /dev/null
+++ b/mysql-test/t/sp-code.test
@@ -0,0 +1,49 @@
+#
+# Test the debugging feature "show procedure/function code <name>"
+#
+
+-- source include/is_debug_build.inc
+
+create procedure empty()
+begin
+end;
+show procedure code empty;
+drop procedure empty;
+
+create function almost_empty()
+ returns int
+ return 0;
+show function code almost_empty;
+drop function almost_empty;
+
+delimiter //;
+create procedure code_sample(x int, out err int, out nulls int)
+begin
+ declare count int default 0;
+
+ set nulls = 0;
+ begin
+ declare c cursor for select name from t1;
+ declare exit handler for not found close c;
+
+ open c;
+ loop
+ begin
+ declare n varchar(20);
+ declare continue handler for sqlexception set err=1;
+
+ fetch c into n;
+ if isnull(n) then
+ set nulls = nulls + 1;
+ else
+ set count = count + 1;
+ update t2 set idx = count where name=n;
+ end if;
+ end;
+ end loop;
+ end;
+ select t.name, t.idx from t2 t order by idx asc;
+end//
+delimiter ;//
+show procedure code code_sample;
+drop procedure code_sample;
diff --git a/mysql-test/t/sp-dynamic.test b/mysql-test/t/sp-dynamic.test
index e9816ee3ef0..5416f5931ff 100644
--- a/mysql-test/t/sp-dynamic.test
+++ b/mysql-test/t/sp-dynamic.test
@@ -26,18 +26,29 @@ begin
execute stmt;
end|
prepare stmt from "call p1()"|
+# Allow SP resursion to be show that it has not influence here
+set @SAVE_SP_RECURSION_LEVELS=@@max_sp_recursion_depth|
+set @@max_sp_recursion_depth=100|
--error ER_PS_NO_RECURSION
execute stmt|
--error ER_PS_NO_RECURSION
execute stmt|
--error ER_PS_NO_RECURSION
execute stmt|
---error ER_SP_NO_RECURSION
+--error ER_PS_NO_RECURSION
+call p1()|
+--error ER_PS_NO_RECURSION
call p1()|
---error ER_SP_NO_RECURSION
+--error ER_PS_NO_RECURSION
call p1()|
---error ER_SP_NO_RECURSION
+set @@max_sp_recursion_depth=@SAVE_SP_RECURSION_LEVELS|
+--error ER_SP_RECURSION_LIMIT
call p1()|
+--error ER_SP_RECURSION_LIMIT
+call p1()|
+--error ER_SP_RECURSION_LIMIT
+call p1()|
+
drop procedure p1|
#
# C. Create/drop a stored procedure in Dynamic SQL.
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index 5057dd0d9f8..69e5f73817b 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -1044,10 +1044,11 @@ begin
call bug11394(i - 1,(select 1));
end if;
end|
-# Again if we allow recursion for stored procedures (without
-# additional efforts) the following statement will crash the server.
---error 1424
+--error ER_SP_RECURSION_LIMIT
+call bug11394(2, 1)|
+set @@max_sp_recursion_depth=10|
call bug11394(2, 1)|
+set @@max_sp_recursion_depth=default|
drop procedure bug11394|
delimiter ;|
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 5ad2b9287aa..def6afc000e 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -4291,6 +4291,9 @@ call bug12589_1()|
# No warnings here
call bug12589_2()|
call bug12589_3()|
+drop procedure bug12589_1|
+drop procedure bug12589_2|
+drop procedure bug12589_3|
#
# BUG#7049: Stored procedure CALL errors are ignored
@@ -4595,6 +4598,185 @@ call bug14845()|
drop procedure bug14845|
#
+# BUG#13549 "Server crash with nested stored procedures".
+# Server should not crash when during execution of stored procedure
+# we have to parse trigger/function definition and this new trigger/
+# function has more local variables declared than invoking stored
+# procedure and last of these variables is used in argument of NOT
+# operator.
+#
+--disable_warnings
+drop procedure if exists bug13549_1|
+drop procedure if exists bug13549_2|
+--enable_warnings
+CREATE PROCEDURE `bug13549_2`()
+begin
+ call bug13549_1();
+end|
+CREATE PROCEDURE `bug13549_1`()
+begin
+ declare done int default 0;
+ set done= not done;
+end|
+CALL bug13549_2()|
+drop procedure bug13549_2|
+drop procedure bug13549_1|
+
+#
+# BUG#10100: function (and stored procedure?) recursivity problem
+#
+--disable_warnings
+drop function if exists bug10100f|
+drop procedure if exists bug10100p|
+drop procedure if exists bug10100t|
+drop procedure if exists bug10100pt|
+drop procedure if exists bug10100pv|
+drop procedure if exists bug10100pd|
+drop procedure if exists bug10100pc|
+--enable_warnings
+# routines with simple recursion
+create function bug10100f(prm int) returns int
+begin
+ if prm > 1 then
+ return prm * bug10100f(prm - 1);
+ end if;
+ return 1;
+end|
+create procedure bug10100p(prm int, inout res int)
+begin
+ set res = res * prm;
+ if prm > 1 then
+ call bug10100p(prm - 1, res);
+ end if;
+end|
+create procedure bug10100t(prm int)
+begin
+ declare res int;
+ set res = 1;
+ call bug10100p(prm, res);
+ select res;
+end|
+
+# a procedure which use tables and recursion
+create table t3 (a int)|
+insert into t3 values (0)|
+create view v1 as select a from t3;
+create procedure bug10100pt(level int, lim int)
+begin
+ if level < lim then
+ update t3 set a=level;
+ FLUSH TABLES;
+ call bug10100pt(level+1, lim);
+ else
+ select * from t3;
+ end if;
+end|
+# view & recursion
+create procedure bug10100pv(level int, lim int)
+begin
+ if level < lim then
+ update v1 set a=level;
+ FLUSH TABLES;
+ call bug10100pv(level+1, lim);
+ else
+ select * from v1;
+ end if;
+end|
+# dynamic sql & recursion
+prepare stmt2 from "select * from t3;";
+create procedure bug10100pd(level int, lim int)
+begin
+ if level < lim then
+ select level;
+ prepare stmt1 from "update t3 set a=a+2";
+ execute stmt1;
+ FLUSH TABLES;
+ execute stmt1;
+ FLUSH TABLES;
+ execute stmt1;
+ FLUSH TABLES;
+ deallocate prepare stmt1;
+ execute stmt2;
+ select * from t3;
+ call bug10100pd(level+1, lim);
+ else
+ execute stmt2;
+ end if;
+end|
+# cursor & recursion
+create procedure bug10100pc(level int, lim int)
+begin
+ declare lv int;
+ declare c cursor for select a from t3;
+ open c;
+ if level < lim then
+ select level;
+ fetch c into lv;
+ select lv;
+ update t3 set a=level+lv;
+ FLUSH TABLES;
+ call bug10100pc(level+1, lim);
+ else
+ select * from t3;
+ end if;
+ close c;
+end|
+
+set @@max_sp_recursion_depth=4|
+select @@max_sp_recursion_depth|
+-- error ER_SP_NO_RECURSION
+select bug10100f(3)|
+-- error ER_SP_NO_RECURSION
+select bug10100f(6)|
+call bug10100t(5)|
+call bug10100pt(1,5)|
+call bug10100pv(1,5)|
+update t3 set a=1|
+call bug10100pd(1,5)|
+select * from t3|
+update t3 set a=1|
+call bug10100pc(1,5)|
+select * from t3|
+set @@max_sp_recursion_depth=0|
+select @@max_sp_recursion_depth|
+-- error ER_SP_NO_RECURSION
+select bug10100f(5)|
+-- error ER_SP_RECURSION_LIMIT
+call bug10100t(5)|
+
+#end of the stack checking
+set @@max_sp_recursion_depth=255|
+set @var=1|
+#disable log because error about stack overrun contains numbers which
+#depend on a system
+-- disable_result_log
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100p(255, @var)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pt(1,255)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pv(1,255)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pd(1,255)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pc(1,255)|
+-- enable_result_log
+set @@max_sp_recursion_depth=0|
+
+deallocate prepare stmt2|
+
+drop function bug10100f|
+drop procedure bug10100p|
+drop procedure bug10100t|
+drop procedure bug10100pt|
+drop procedure bug10100pv|
+drop procedure bug10100pd|
+drop procedure bug10100pc|
+drop view v1|
+drop table t3|
+
+
+#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
diff --git a/mysql-test/t/sp_trans.test b/mysql-test/t/sp_trans.test
index 82e1cd2f1c9..d72eaf5dca0 100644
--- a/mysql-test/t/sp_trans.test
+++ b/mysql-test/t/sp_trans.test
@@ -176,6 +176,186 @@ drop table t1, t2|
#
+# BUG#13825 "Triggers: crash if release savepoint".
+# Also general test for handling of savepoints in stored routines.
+#
+# According to SQL standard we should establish new savepoint
+# level before executing stored function/trigger and destroy
+# this savepoint level after execution. Stored procedures by
+# default should be executed using the same savepoint level
+# as their caller (to execute stored procedure using new
+# savepoint level one should explicitly specify NEW SAVEPOINT
+# LEVEL clause in procedure creation statement which MySQL
+# does not support yet).
+--disable_warnings
+drop function if exists bug13825_0|
+drop function if exists bug13825_1|
+drop function if exists bug13825_2|
+drop function if exists bug13825_3|
+drop function if exists bug13825_4|
+drop function if exists bug13825_5|
+drop procedure if exists bug13825_0|
+drop procedure if exists bug13825_1|
+drop procedure if exists bug13825_2|
+drop table if exists t1|
+--enable_warnings
+create table t1 (i int) engine=innodb|
+create table t2 (i int) engine=innodb|
+create function bug13825_0() returns int
+begin
+ rollback to savepoint x;
+ return 1;
+end|
+create function bug13825_1() returns int
+begin
+ release savepoint x;
+ return 1;
+end|
+create function bug13825_2() returns int
+begin
+ insert into t1 values (2);
+ savepoint x;
+ insert into t1 values (3);
+ rollback to savepoint x;
+ insert into t1 values (4);
+ return 1;
+end|
+create procedure bug13825_0()
+begin
+ rollback to savepoint x;
+end|
+create procedure bug13825_1()
+begin
+ release savepoint x;
+end|
+create procedure bug13825_2()
+begin
+ savepoint x;
+end|
+insert into t2 values (1)|
+create trigger t2_bi before insert on t2 for each row
+ rollback to savepoint x|
+create trigger t2_bu before update on t2 for each row
+ release savepoint x|
+create trigger t2_bd before delete on t2 for each row
+begin
+ insert into t1 values (2);
+ savepoint x;
+ insert into t1 values (3);
+ rollback to savepoint x;
+ insert into t1 values (4);
+end|
+create function bug13825_3(rb int) returns int
+begin
+ insert into t1 values(1);
+ savepoint x;
+ insert into t1 values(2);
+ if rb then
+ rollback to savepoint x;
+ end if;
+ insert into t1 values(3);
+ return rb;
+end|
+create function bug13825_4() returns int
+begin
+ savepoint x;
+ insert into t1 values(2);
+ rollback to savepoint x;
+ return 0;
+end|
+create function bug13825_5(p int) returns int
+begin
+ savepoint x;
+ insert into t2 values(p);
+ rollback to savepoint x;
+ insert into t2 values(p+1);
+ return p;
+end|
+set autocommit= 0|
+# Test of savepoint level handling for stored functions and triggers
+begin |
+insert into t1 values (1)|
+savepoint x|
+--error ER_SP_DOES_NOT_EXIST
+set @a:= bug13825_0()|
+--error ER_SP_DOES_NOT_EXIST
+insert into t2 values (2)|
+--error ER_SP_DOES_NOT_EXIST
+set @a:= bug13825_1()|
+--error ER_SP_DOES_NOT_EXIST
+update t2 set i = 2|
+set @a:= bug13825_2()|
+select * from t1|
+rollback to savepoint x|
+select * from t1|
+delete from t2|
+select * from t1|
+rollback to savepoint x|
+select * from t1|
+# Of course savepoints set in function should not be visible from its caller
+release savepoint x|
+set @a:= bug13825_2()|
+select * from t1|
+--error ER_SP_DOES_NOT_EXIST
+rollback to savepoint x|
+delete from t1|
+commit|
+# Test of savepoint level handling for stored procedures
+begin|
+insert into t1 values (5)|
+savepoint x|
+insert into t1 values (6)|
+call bug13825_0()|
+select * from t1|
+call bug13825_1()|
+--error ER_SP_DOES_NOT_EXIST
+rollback to savepoint x|
+savepoint x|
+insert into t1 values (7)|
+call bug13825_2()|
+rollback to savepoint x|
+select * from t1|
+delete from t1|
+commit|
+set autocommit= 1|
+# Let us test that savepoints work inside of functions
+# even in auto-commit mode
+select bug13825_3(0)|
+select * from t1|
+delete from t1|
+select bug13825_3(1)|
+select * from t1|
+delete from t1|
+# Curious case: rolling back to savepoint which is set by first
+# statement in function should not rollback whole transaction.
+set autocommit= 0|
+begin|
+insert into t1 values (1)|
+set @a:= bug13825_4()|
+select * from t1|
+delete from t1|
+commit|
+set autocommit= 1|
+# Other curious case: savepoint in the middle of statement
+drop table t2|
+create table t2 (i int) engine=innodb|
+insert into t1 values (1), (bug13825_5(2)), (3)|
+select * from t1|
+select * from t2|
+# Cleanup
+drop function bug13825_0|
+drop function bug13825_1|
+drop function bug13825_2|
+drop function bug13825_3|
+drop function bug13825_4|
+drop function bug13825_5|
+drop procedure bug13825_0|
+drop procedure bug13825_1|
+drop procedure bug13825_2|
+drop table t1, t2|
+
+
+#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index 02d994128e2..d4fa5268762 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -743,8 +743,12 @@ create trigger t1_ai after insert on t1
for each row insert into t2 values (new.f1+1);
create trigger t2_ai after insert on t2
for each row insert into t1 values (new.f2+1);
+# Allow SP resursion to be show that it has not influence here
+set @SAVE_SP_RECURSION_LEVELS=@@max_sp_recursion_depth;
+set @@max_sp_recursion_depth=100;
--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
insert into t1 values (1);
+set @@max_sp_recursion_depth=@SAVE_SP_RECURSION_LEVELS;
select * from t1;
select * from t2;
drop trigger t1_ai;
@@ -914,3 +918,31 @@ call p1();
deallocate prepare stmt1;
drop procedure p1;
drop table t1, t2, t3;
+
+#
+# BUG#13549 "Server crash with nested stored procedures".
+# Server should not crash when during execution of stored procedure
+# we have to parse trigger/function definition and this new trigger/
+# function has more local variables declared than invoking stored
+# procedure and last of these variables is used in argument of NOT
+# operator.
+#
+create table t1 (a int);
+--disable_warnings
+drop procedure if exists p2;
+--enable_warnings
+DELIMITER //;
+CREATE PROCEDURE `p2`()
+begin
+ insert into t1 values (1);
+end//
+create trigger trg before insert on t1 for each row
+begin
+ declare done int default 0;
+ set done= not done;
+end//
+DELIMITER ;//
+CALL p2();
+drop procedure p2;
+drop table t1;
+
diff --git a/mysql-test/t/type_binary.test b/mysql-test/t/type_binary.test
index b5928cb14c4..451363c1ae4 100644
--- a/mysql-test/t/type_binary.test
+++ b/mysql-test/t/type_binary.test
@@ -65,3 +65,6 @@ select hex(s1) from t1 where s1=0x0120;
select hex(s1) from t1 where s1=0x0100;
select count(distinct s1) from t1;
drop table t1;
+
+# check that cast appends trailing zeros
+select hex(cast(0x10 as binary(2)));
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index f23cc0152c1..2d0e2dbc9c9 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -237,6 +237,10 @@ set global rpl_recovery_rank=100;
set global server_id=100;
set global slow_launch_time=100;
set sort_buffer_size=100;
+set @@max_sp_recursion_depth=10;
+select @@max_sp_recursion_depth;
+set @@max_sp_recursion_depth=0;
+select @@max_sp_recursion_depth;
set sql_auto_is_null=1;
select @@sql_auto_is_null;
set @@sql_auto_is_null=0;
diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test
index b4f367c2065..04d6d2f323b 100644
--- a/mysql-test/t/view_grant.test
+++ b/mysql-test/t/view_grant.test
@@ -664,3 +664,39 @@ insert into mysql.user select * from t1;
flush privileges;
drop table t1;
+
+#
+# BUG#14726: freeing stack variable in case of an error of opening
+# a view when we have locked tables with LOCK TABLES statement.
+#
+connection root;
+--disable_warnings
+create database mysqltest;
+--enable_warnings
+
+use mysqltest;
+CREATE TABLE t1 (i INT);
+CREATE VIEW v1 AS SELECT * FROM t1;
+SHOW CREATE VIEW v1;
+GRANT SELECT, LOCK TABLES ON mysqltest.* TO mysqltest_1@localhost;
+
+connection user1;
+
+use mysqltest;
+LOCK TABLES v1 READ;
+-- error ER_TABLEACCESS_DENIED_ERROR
+SHOW CREATE TABLE v1;
+UNLOCK TABLES;
+use test;
+
+connection root;
+use test;
+drop user mysqltest_1@localhost;
+drop database mysqltest;
+
+#
+# switch to default connaction
+#
+disconnect user1;
+disconnect root;
+connection default;
diff --git a/netware/Makefile.am b/netware/Makefile.am
index be59efd1deb..ab88d97f9bc 100644
--- a/netware/Makefile.am
+++ b/netware/Makefile.am
@@ -40,10 +40,10 @@ netware_build_files = client/mysql.def client/mysqladmin.def \
link_sources:
set -x; \
for f in $(netware_build_files); do \
- rm -f $(srcdir)/../$$f; \
+ rm -f ../$$f; \
org=`echo $$f | sed -e 's/.*\/\(.*\)/\1/g'`; \
- @LN_CP_F@ $(srcdir)/$$org $(srcdir)/../$$f; \
- done;
+ @LN_CP_F@ $(srcdir)/$$org ../$$f; \
+ done
else
EXTRA_DIST= comp_err.def init_db.sql install_test_db.ncf \
libmysql.def libmysql.imp \
diff --git a/netware/mysql_test_run.c b/netware/mysql_test_run.c
index 92ed89b4770..98b7ab7fd8c 100644
--- a/netware/mysql_test_run.c
+++ b/netware/mysql_test_run.c
@@ -1173,6 +1173,9 @@ void setup(char *file)
setenv("MYSQL",file_path,1);
snprintf(file_path, PATH_MAX*2, "%s/mysqlshow --no-defaults --user=root --port=%u", bin_dir, master_port);
setenv("MYSQL_SHOW",file_path,1);
+ snprintf(file_path, PATH_MAX*2, "%s/mysqlcheck --no-defaults -uroot --port=%u", bin_dir, master_port);
+ setenv("MYSQL_CHECK",file_path,1);
+
}
/******************************************************************************
diff --git a/pstack/Makefile.am b/pstack/Makefile.am
index 77f84d212cd..20d5d8314ce 100644
--- a/pstack/Makefile.am
+++ b/pstack/Makefile.am
@@ -20,7 +20,7 @@
#
SUBDIRS = aout
-INCLUDES = -I$(top_srcdir)/include
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
noinst_HEADERS = bucomm.h debug.h ieee.h budbg.h demangle.h \
linuxthreads.h pstack.h pstacktrace.h
SRC= bucomm.c filemode.c linuxthreads.c rddbg.c \
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 2d7f18b676b..56a2d4a7bc6 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -83,9 +83,10 @@ CLEANFILES = @server_scripts@ \
mysql_find_rows \
mysqlhotcopy \
mysqldumpslow \
+ mysql_explain_log \
+ mysql_tableinfo \
mysqld_multi \
make_win_src_distribution \
- make_win_binary_distribution \
mysql_create_system_tables
DISTCLEANFILES = mysqlbug
diff --git a/server-tools/instance-manager/Makefile.am b/server-tools/instance-manager/Makefile.am
index 4fa2a0da405..7449735f0bf 100644
--- a/server-tools/instance-manager/Makefile.am
+++ b/server-tools/instance-manager/Makefile.am
@@ -53,12 +53,12 @@ libnet_a_LIBADD= $(top_builddir)/sql/password.$(OBJEXT) \
CLEANFILES= net_serv.cc client_settings.h
net_serv.cc:
- rm -f $(srcdir)/net_serv.cc
- @LN_CP_F@ $(top_srcdir)/sql/net_serv.cc $(srcdir)/net_serv.cc
+ rm -f net_serv.cc
+ @LN_CP_F@ $(top_srcdir)/sql/net_serv.cc net_serv.cc
client_settings.h:
- rm -f $(srcdir)/client_settings.h
- @LN_CP_F@ $(top_srcdir)/sql/client_settings.h $(srcdir)/client_settings.h
+ rm -f client_settings.h
+ @LN_CP_F@ $(top_srcdir)/sql/client_settings.h client_settings.h
libexec_PROGRAMS= mysqlmanager
diff --git a/sql-bench/Makefile.am b/sql-bench/Makefile.am
index 579a2a9f7fe..12f3d5550b3 100644
--- a/sql-bench/Makefile.am
+++ b/sql-bench/Makefile.am
@@ -60,6 +60,8 @@ install-data-local:
for i in $(srcdir)/limits/*.* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/limits; done
for i in $(srcdir)/Comments/*.* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/Comments; done
+uninstall-local:
+ @RM@ -f -r $(DESTDIR)$(benchdir)
SUFFIXES = .sh
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 0155d53dad2..78d5e262fde 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -124,17 +124,17 @@ AM_YFLAGS = -d
mysql_tzinfo_to_sql.cc:
rm -f mysql_tzinfo_to_sql.cc
- @LN_CP_F@ tztime.cc mysql_tzinfo_to_sql.cc
+ @LN_CP_F@ $(srcdir)/tztime.cc mysql_tzinfo_to_sql.cc
link_sources: mysql_tzinfo_to_sql.cc
rm -f mini_client_errors.c
- @LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c
+ @LN_CP_F@ $(top_srcdir)/libmysql/errmsg.c mini_client_errors.c
rm -f pack.c
- @LN_CP_F@ ../sql-common/pack.c pack.c
+ @LN_CP_F@ $(top_srcdir)/sql-common/pack.c pack.c
rm -f client.c
- @LN_CP_F@ ../sql-common/client.c client.c
+ @LN_CP_F@ $(top_srcdir)/sql-common/client.c client.c
rm -f my_time.c
- @LN_CP_F@ ../sql-common/my_time.c my_time.c
+ @LN_CP_F@ $(top_srcdir)/sql-common/my_time.c my_time.c
mysql_tzinfo_to_sql.o: $(mysql_tzinfo_to_sql_SOURCES)
$(CXXCOMPILE) -c $(INCLUDES) -DTZINFO2SQL $<
diff --git a/sql/field.cc b/sql/field.cc
index 8ba6b65ae73..55d6bf7e3a2 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1274,9 +1274,9 @@ my_decimal *Field::val_decimal(my_decimal *decimal)
void Field_num::add_zerofill_and_unsigned(String &res) const
{
if (unsigned_flag)
- res.append(" unsigned");
+ res.append(STRING_WITH_LEN(" unsigned"));
if (zerofill)
- res.append(" zerofill");
+ res.append(STRING_WITH_LEN(" zerofill"));
}
@@ -1657,7 +1657,7 @@ bool Field::needs_quotes(void)
void Field_null::sql_type(String &res) const
{
- res.set_ascii("null", 4);
+ res.set_ascii(STRING_WITH_LEN("null"));
}
@@ -1669,7 +1669,7 @@ void Field_null::sql_type(String &res) const
void
Field_decimal::reset(void)
{
- Field_decimal::store("0",1,&my_charset_bin);
+ Field_decimal::store(STRING_WITH_LEN("0"),&my_charset_bin);
}
void Field_decimal::overflow(bool negative)
@@ -4115,7 +4115,7 @@ void Field_float::sql_type(String &res) const
{
if (dec == NOT_FIXED_DEC)
{
- res.set_ascii("float", 5);
+ res.set_ascii(STRING_WITH_LEN("float"));
}
else
{
@@ -4386,7 +4386,7 @@ void Field_double::sql_type(String &res) const
CHARSET_INFO *cs=res.charset();
if (dec == NOT_FIXED_DEC)
{
- res.set_ascii("double",6);
+ res.set_ascii(STRING_WITH_LEN("double"));
}
else
{
@@ -4675,7 +4675,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
if (temp == 0L)
{ /* Zero time is "000000" */
- val_ptr->set("0000-00-00 00:00:00", 19, &my_charset_bin);
+ val_ptr->set(STRING_WITH_LEN("0000-00-00 00:00:00"), &my_charset_bin);
return val_ptr;
}
val_buffer->set_charset(&my_charset_bin); // Safety
@@ -4807,7 +4807,7 @@ void Field_timestamp::sort_string(char *to,uint length __attribute__((unused)))
void Field_timestamp::sql_type(String &res) const
{
- res.set_ascii("timestamp", 9);
+ res.set_ascii(STRING_WITH_LEN("timestamp"));
}
@@ -5076,7 +5076,7 @@ void Field_time::sort_string(char *to,uint length __attribute__((unused)))
void Field_time::sql_type(String &res) const
{
- res.set_ascii("time", 4);
+ res.set_ascii(STRING_WITH_LEN("time"));
}
/****************************************************************************
@@ -5383,7 +5383,7 @@ void Field_date::sort_string(char *to,uint length __attribute__((unused)))
void Field_date::sql_type(String &res) const
{
- res.set_ascii("date", 4);
+ res.set_ascii(STRING_WITH_LEN("date"));
}
@@ -5566,7 +5566,7 @@ void Field_newdate::sort_string(char *to,uint length __attribute__((unused)))
void Field_newdate::sql_type(String &res) const
{
- res.set_ascii("date", 4);
+ res.set_ascii(STRING_WITH_LEN("date"));
}
@@ -5840,7 +5840,7 @@ void Field_datetime::sort_string(char *to,uint length __attribute__((unused)))
void Field_datetime::sql_type(String &res) const
{
- res.set_ascii("datetime", 8);
+ res.set_ascii(STRING_WITH_LEN("datetime"));
}
/****************************************************************************
@@ -6083,7 +6083,7 @@ void Field_string::sql_type(String &res) const
res.length(length);
if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
has_charset() && (charset()->state & MY_CS_BINSORT))
- res.append(" binary");
+ res.append(STRING_WITH_LEN(" binary"));
}
@@ -6216,6 +6216,8 @@ uint Field_string::max_packed_col_length(uint max_length)
Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table)
{
+ Field *new_field;
+
if (type() != MYSQL_TYPE_VAR_STRING || table == new_table)
return Field::new_field(root, new_table);
@@ -6224,15 +6226,16 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table)
This is done to ensure that ALTER TABLE will convert old VARCHAR fields
to now VARCHAR fields.
*/
- Field *new_field= new Field_varstring(field_length, maybe_null(),
- field_name, new_table,
- charset());
- /*
- delayed_insert::get_local_table() needs a ptr copied from old table.
- This is what other new_field() methods do too. The above method of
- Field_varstring sets ptr to NULL.
- */
- new_field->ptr= ptr;
+ if (new_field= new Field_varstring(field_length, maybe_null(),
+ field_name, new_table, charset()))
+ {
+ /*
+ delayed_insert::get_local_table() needs a ptr copied from old table.
+ This is what other new_field() methods do too. The above method of
+ Field_varstring sets ptr to NULL.
+ */
+ new_field->ptr= ptr;
+ }
return new_field;
}
@@ -6479,7 +6482,7 @@ void Field_varstring::sql_type(String &res) const
res.length(length);
if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
has_charset() && (charset()->state & MY_CS_BINSORT))
- res.append(" binary");
+ res.append(STRING_WITH_LEN(" binary"));
}
@@ -7218,10 +7221,10 @@ void Field_blob::sql_type(String &res) const
}
res.set_ascii(str,length);
if (charset() == &my_charset_bin)
- res.append("blob");
+ res.append(STRING_WITH_LEN("blob"));
else
{
- res.append("text");
+ res.append(STRING_WITH_LEN("text"));
}
}
@@ -7441,28 +7444,28 @@ void Field_geom::sql_type(String &res) const
switch (geom_type)
{
case GEOM_POINT:
- res.set("point", 5, cs);
+ res.set(STRING_WITH_LEN("point"), cs);
break;
case GEOM_LINESTRING:
- res.set("linestring", 10, cs);
+ res.set(STRING_WITH_LEN("linestring"), cs);
break;
case GEOM_POLYGON:
- res.set("polygon", 7, cs);
+ res.set(STRING_WITH_LEN("polygon"), cs);
break;
case GEOM_MULTIPOINT:
- res.set("multipoint", 10, cs);
+ res.set(STRING_WITH_LEN("multipoint"), cs);
break;
case GEOM_MULTILINESTRING:
- res.set("multilinestring", 15, cs);
+ res.set(STRING_WITH_LEN("multilinestring"), cs);
break;
case GEOM_MULTIPOLYGON:
- res.set("multipolygon", 12, cs);
+ res.set(STRING_WITH_LEN("multipolygon"), cs);
break;
case GEOM_GEOMETRYCOLLECTION:
- res.set("geometrycollection", 18, cs);
+ res.set(STRING_WITH_LEN("geometrycollection"), cs);
break;
default:
- res.set("geometry", 8, cs);
+ res.set(STRING_WITH_LEN("geometry"), cs);
}
}
@@ -7739,7 +7742,7 @@ void Field_enum::sql_type(String &res) const
String enum_item(buffer, sizeof(buffer), res.charset());
res.length(0);
- res.append("enum(");
+ res.append(STRING_WITH_LEN("enum("));
bool flag=0;
uint *len= typelib->type_lengths;
@@ -7853,7 +7856,7 @@ void Field_set::sql_type(String &res) const
String set_item(buffer, sizeof(buffer), res.charset());
res.length(0);
- res.append("set(");
+ res.append(STRING_WITH_LEN("set("));
bool flag=0;
uint *len= typelib->type_lengths;
diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc
index 57dc51edb90..badfe3cdf62 100644
--- a/sql/ha_federated.cc
+++ b/sql/ha_federated.cc
@@ -2612,7 +2612,7 @@ int ha_federated::stash_remote_error()
{
DBUG_ENTER("ha_federated::stash_remote_error()");
remote_error_number= mysql_errno(mysql);
- my_snprintf(remote_error_buf, FEDERATED_QUERY_BUFFER_SIZE,
+ my_snprintf(remote_error_buf, sizeof(remote_error_buf), "%s",
mysql_error(mysql));
DBUG_RETURN(HA_FEDERATED_ERROR_WITH_REMOTE_SYSTEM);
}
@@ -2624,10 +2624,10 @@ bool ha_federated::get_error_message(int error, String* buf)
DBUG_PRINT("enter", ("error: %d", error));
if (error == HA_FEDERATED_ERROR_WITH_REMOTE_SYSTEM)
{
- buf->append("Error on remote system: ");
+ buf->append(STRING_WITH_LEN("Error on remote system: "));
buf->qs_append(remote_error_number);
- buf->append(": ");
- buf->append(remote_error_buf, FEDERATED_QUERY_BUFFER_SIZE);
+ buf->append(STRING_WITH_LEN(": "));
+ buf->append(remote_error_buf);
remote_error_number= 0;
remote_error_buf[0]= '\0';
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 7dcb0b677e5..dae018e71f1 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -2219,11 +2219,13 @@ innobase_savepoint(
DBUG_ENTER("innobase_savepoint");
- if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
- /* In the autocommit state there is no sense to set a
- savepoint: we return immediate success */
- DBUG_RETURN(0);
- }
+ /*
+ In the autocommit mode there is no sense to set a savepoint
+ (unless we are in sub-statement), so SQL layer ensures that
+ this method is never called in such situation.
+ */
+ DBUG_ASSERT(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
+ thd->in_sub_stmt);
trx = check_trx_exists(thd);
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 61dbc315185..abf0f1d2ed5 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -506,10 +506,10 @@ void ha_myisammrg::append_create_info(String *packet)
if (file->merge_insert_method != MERGE_INSERT_DISABLED)
{
- packet->append(" INSERT_METHOD=",15);
+ packet->append(STRING_WITH_LEN(" INSERT_METHOD="));
packet->append(get_type(&merge_insert_method,file->merge_insert_method-1));
}
- packet->append(" UNION=(",8);
+ packet->append(STRING_WITH_LEN(" UNION=("));
MYRG_TABLE *open_table,*first;
current_db= table->s->db;
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 89cf020262d..abb12163f1c 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -101,6 +101,8 @@ static handler *ndbcluster_create_handler(TABLE *table)
#define NDB_FAILED_AUTO_INCREMENT ~(Uint64)0
#define NDB_AUTO_INCREMENT_RETRIES 10
+#define NDB_INVALID_SCHEMA_OBJECT 241
+
#define ERR_PRINT(err) \
DBUG_PRINT("error", ("%d message: %s", err.code, err.message))
@@ -368,7 +370,21 @@ Thd_ndb::Thd_ndb()
Thd_ndb::~Thd_ndb()
{
if (ndb)
+ {
+#ifndef DBUG_OFF
+ Ndb::Free_list_usage tmp; tmp.m_name= 0;
+ while (ndb->get_free_list_usage(&tmp))
+ {
+ uint leaked= (uint) tmp.m_created - tmp.m_free;
+ if (leaked)
+ fprintf(stderr, "NDB: Found %u %s%s that %s not been released\n",
+ leaked, tmp.m_name,
+ (leaked == 1)?"":"'s",
+ (leaked == 1)?"has":"have");
+ }
+#endif
delete ndb;
+ }
ndb= NULL;
changed_tables.empty();
}
@@ -3415,15 +3431,18 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
DBUG_PRINT("info", ("Table schema version: %d",
tab->getObjectVersion()));
}
- if (m_table != (void *)tab || m_table_version < tab->getObjectVersion())
+ if (m_table != (void *)tab)
{
- /*
- The table has been altered, refresh the index list
- */
- build_index_list(ndb, table, ILBP_OPEN);
m_table= (void *)tab;
m_table_version = tab->getObjectVersion();
}
+ else if (m_table_version < tab->getObjectVersion())
+ {
+ /*
+ The table has been altered, caller has to retry
+ */
+ DBUG_RETURN(my_errno= HA_ERR_TABLE_DEF_CHANGED);
+ }
m_table_info= tab_info;
}
no_uncommitted_rows_init(thd);
@@ -5118,7 +5137,21 @@ int ndbcluster_end(ha_panic_function type)
(void) pthread_mutex_unlock(&LOCK_ndb_util_thread);
if (g_ndb)
+ {
+#ifndef DBUG_OFF
+ Ndb::Free_list_usage tmp; tmp.m_name= 0;
+ while (g_ndb->get_free_list_usage(&tmp))
+ {
+ uint leaked= (uint) tmp.m_created - tmp.m_free;
+ if (leaked)
+ fprintf(stderr, "NDB: Found %u %s%s that %s not been released\n",
+ leaked, tmp.m_name,
+ (leaked == 1)?"":"'s",
+ (leaked == 1)?"has":"have");
+ }
+#endif
delete g_ndb;
+ }
g_ndb= NULL;
if (g_ndb_cluster_connection)
delete g_ndb_cluster_connection;
diff --git a/sql/handler.cc b/sql/handler.cc
index 3db2f76aef8..0977fb311d3 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1026,10 +1026,10 @@ int ha_update_statistics()
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
{
int error=0;
- THD_TRANS *trans=&thd->transaction.all;
+ THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
+ &thd->transaction.all);
handlerton **ht=trans->ht, **end_ht;
DBUG_ENTER("ha_rollback_to_savepoint");
- DBUG_ASSERT(thd->transaction.stmt.ht[0] == 0);
trans->nht=sv->nht;
trans->no_2pc=0;
@@ -1057,7 +1057,7 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
for (; *ht ; ht++)
{
int err;
- if ((err= (*(*ht)->rollback)(thd, 1)))
+ if ((err= (*(*ht)->rollback)(thd, !thd->in_sub_stmt)))
{ // cannot happen
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
error=1;
@@ -1077,10 +1077,10 @@ int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
int ha_savepoint(THD *thd, SAVEPOINT *sv)
{
int error=0;
- THD_TRANS *trans=&thd->transaction.all;
+ THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
+ &thd->transaction.all);
handlerton **ht=trans->ht;
DBUG_ENTER("ha_savepoint");
- DBUG_ASSERT(thd->transaction.stmt.ht[0] == 0);
#ifdef USING_TRANSACTIONS
for (; *ht; ht++)
{
@@ -1106,9 +1106,10 @@ int ha_savepoint(THD *thd, SAVEPOINT *sv)
int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
{
int error=0;
- handlerton **ht=thd->transaction.all.ht, **end_ht;
+ THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
+ &thd->transaction.all);
+ handlerton **ht=trans->ht, **end_ht;
DBUG_ENTER("ha_release_savepoint");
- DBUG_ASSERT(thd->transaction.stmt.ht[0] == 0);
end_ht=ht+sv->nht;
for (; ht < end_ht; ht++)
@@ -1680,7 +1681,7 @@ void handler::print_error(int error, myf errflag)
if (str.length() >= max_length)
{
str.length(max_length-4);
- str.append("...");
+ str.append(STRING_WITH_LEN("..."));
}
my_error(ER_DUP_ENTRY, MYF(0), str.c_ptr(), key_nr+1);
DBUG_VOID_RETURN;
diff --git a/sql/item.cc b/sql/item.cc
index e3627ec22bf..a1213d60aa8 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -383,7 +383,7 @@ void Item::print_item_w_name(String *str)
if (name)
{
THD *thd= current_thd;
- str->append(" AS ", 4);
+ str->append(STRING_WITH_LEN(" AS "));
append_identifier(thd, str, name, (uint) strlen(name));
}
}
@@ -894,6 +894,7 @@ bool Item_splocal::is_null()
Item *
Item_splocal::this_item()
{
+ DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item(m_offset);
}
@@ -901,12 +902,14 @@ Item_splocal::this_item()
Item **
Item_splocal::this_item_addr(THD *thd, Item **addr)
{
+ DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item_addr(m_offset);
}
Item *
Item_splocal::this_const_item() const
{
+ DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item(m_offset);
}
@@ -914,7 +917,10 @@ Item::Type
Item_splocal::type() const
{
if (thd && thd->spcont)
+ {
+ DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item(m_offset)->type();
+ }
return NULL_ITEM; // Anything but SUBSELECT_ITEM
}
@@ -1031,7 +1037,7 @@ void Item_name_const::cleanup()
void Item_name_const::print(String *str)
{
- str->append("NAME_CONST(");
+ str->append(STRING_WITH_LEN("NAME_CONST("));
name_item->print(str);
str->append(',');
value_item->print(str);
@@ -4857,7 +4863,7 @@ void Item_ref::make_field(Send_field *field)
void Item_ref_null_helper::print(String *str)
{
- str->append("<ref_null_helper>(", 18);
+ str->append(STRING_WITH_LEN("<ref_null_helper>("));
if (ref)
(*ref)->print(str);
else
@@ -4983,7 +4989,7 @@ bool Item_direct_view_ref::eq(const Item *item, bool binary_cmp) const
void Item_null_helper::print(String *str)
{
- str->append("<null_helper>(", 14);
+ str->append(STRING_WITH_LEN("<null_helper>("));
store->print(str);
str->append(')');
}
@@ -5043,10 +5049,10 @@ void Item_default_value::print(String *str)
{
if (!arg)
{
- str->append("default", 7);
+ str->append(STRING_WITH_LEN("default"));
return;
}
- str->append("default(", 8);
+ str->append(STRING_WITH_LEN("default("));
arg->print(str);
str->append(')');
}
@@ -5140,7 +5146,7 @@ bool Item_insert_value::fix_fields(THD *thd, Item **items)
void Item_insert_value::print(String *str)
{
- str->append("values(", 7);
+ str->append(STRING_WITH_LEN("values("));
arg->print(str);
str->append(')');
}
@@ -5401,7 +5407,7 @@ Item_cache* Item_cache::get_cache(Item_result type)
void Item_cache::print(String *str)
{
- str->append("<cache>(", 8);
+ str->append(STRING_WITH_LEN("<cache>("));
if (example)
example->print(str);
else
diff --git a/sql/item.h b/sql/item.h
index 332eac70145..4201790e907 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -704,6 +704,8 @@ public:
};
+class sp_head;
+
/*
A reference to local SP variable (incl. reference to SP parameter), used in
runtime.
@@ -721,6 +723,13 @@ class Item_splocal : public Item
uint m_offset;
public:
+#ifndef DBUG_OFF
+ /*
+ Routine to which this Item_splocal belongs. Used for checking if correct
+ runtime context is used for variable handling.
+ */
+ sp_head *owner;
+#endif
LEX_STRING m_name;
THD *thd;
@@ -1055,7 +1064,7 @@ public:
bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_null(name); }
bool is_null() { return 1; }
- void print(String *str) { str->append("NULL", 4); }
+ void print(String *str) { str->append(STRING_WITH_LEN("NULL")); }
Item *safe_charset_converter(CHARSET_INFO *tocs);
};
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 06cb83a7101..2a7754c0217 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1175,10 +1175,10 @@ void Item_func_between::print(String *str)
str->append('(');
args[0]->print(str);
if (negated)
- str->append(" not", 4);
- str->append(" between ", 9);
+ str->append(STRING_WITH_LEN(" not"));
+ str->append(STRING_WITH_LEN(" between "));
args[1]->print(str);
- str->append(" and ", 5);
+ str->append(STRING_WITH_LEN(" and "));
args[2]->print(str);
str->append(')');
}
@@ -1793,7 +1793,7 @@ uint Item_func_case::decimal_precision() const
void Item_func_case::print(String *str)
{
- str->append("(case ", 6);
+ str->append(STRING_WITH_LEN("(case "));
if (first_expr_num != -1)
{
args[first_expr_num]->print(str);
@@ -1801,19 +1801,19 @@ void Item_func_case::print(String *str)
}
for (uint i=0 ; i < ncases ; i+=2)
{
- str->append("when ", 5);
+ str->append(STRING_WITH_LEN("when "));
args[i]->print(str);
- str->append(" then ", 6);
+ str->append(STRING_WITH_LEN(" then "));
args[i+1]->print(str);
str->append(' ');
}
if (else_expr_num != -1)
{
- str->append("else ", 5);
+ str->append(STRING_WITH_LEN("else "));
args[else_expr_num]->print(str);
str->append(' ');
}
- str->append("end)", 4);
+ str->append(STRING_WITH_LEN("end)"));
}
/*
@@ -2419,10 +2419,10 @@ void Item_func_in::print(String *str)
str->append('(');
args[0]->print(str);
if (negated)
- str->append(" not", 4);
- str->append(" in (", 5);
+ str->append(STRING_WITH_LEN(" not"));
+ str->append(STRING_WITH_LEN(" in ("));
print_args(str, 1);
- str->append("))", 2);
+ str->append(STRING_WITH_LEN("))"));
}
@@ -2894,7 +2894,7 @@ void Item_func_isnotnull::print(String *str)
{
str->append('(');
args[0]->print(str);
- str->append(" is not null)", 13);
+ str->append(STRING_WITH_LEN(" is not null)"));
}
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 7598865fbb7..ef3ebde74e5 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -794,9 +794,9 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
void Item_func_signed::print(String *str)
{
- str->append("cast(", 5);
+ str->append(STRING_WITH_LEN("cast("));
args[0]->print(str);
- str->append(" as signed)", 11);
+ str->append(STRING_WITH_LEN(" as signed)"));
}
@@ -855,9 +855,9 @@ longlong Item_func_signed::val_int()
void Item_func_unsigned::print(String *str)
{
- str->append("cast(", 5);
+ str->append(STRING_WITH_LEN("cast("));
args[0]->print(str);
- str->append(" as unsigned)", 13);
+ str->append(STRING_WITH_LEN(" as unsigned)"));
}
@@ -927,9 +927,9 @@ my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec)
void Item_decimal_typecast::print(String *str)
{
- str->append("cast(", 5);
+ str->append(STRING_WITH_LEN("cast("));
args[0]->print(str);
- str->append(" as decimal)", 12);
+ str->append(STRING_WITH_LEN(" as decimal)"));
}
@@ -2234,7 +2234,7 @@ longlong Item_func_locate::val_int()
void Item_func_locate::print(String *str)
{
- str->append("locate(", 7);
+ str->append(STRING_WITH_LEN("locate("));
args[1]->print(str);
str->append(',');
args[0]->print(str);
@@ -3297,7 +3297,7 @@ longlong Item_func_benchmark::val_int()
void Item_func_benchmark::print(String *str)
{
- str->append("benchmark(", 10);
+ str->append(STRING_WITH_LEN("benchmark("));
char buffer[20];
// my_charset_bin is good enough for numbers
String st(buffer, sizeof(buffer), &my_charset_bin);
@@ -3811,9 +3811,9 @@ my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
void Item_func_set_user_var::print(String *str)
{
- str->append("(@", 2);
+ str->append(STRING_WITH_LEN("(@"));
str->append(name.str, name.length);
- str->append(":=", 2);
+ str->append(STRING_WITH_LEN(":="));
args[0]->print(str);
str->append(')');
}
@@ -3821,9 +3821,9 @@ void Item_func_set_user_var::print(String *str)
void Item_func_set_user_var::print_as_stmt(String *str)
{
- str->append("set @", 5);
+ str->append(STRING_WITH_LEN("set @"));
str->append(name.str, name.length);
- str->append(":=", 2);
+ str->append(STRING_WITH_LEN(":="));
args[0]->print(str);
str->append(')');
}
@@ -4054,7 +4054,7 @@ enum Item_result Item_func_get_user_var::result_type() const
void Item_func_get_user_var::print(String *str)
{
- str->append("(@", 2);
+ str->append(STRING_WITH_LEN("(@"));
str->append(name.str,name.length);
str->append(')');
}
@@ -4479,15 +4479,15 @@ double Item_func_match::val_real()
void Item_func_match::print(String *str)
{
- str->append("(match ", 7);
+ str->append(STRING_WITH_LEN("(match "));
print_args(str, 1);
- str->append(" against (", 10);
+ str->append(STRING_WITH_LEN(" against ("));
args[0]->print(str);
if (flags & FT_BOOL)
- str->append(" in boolean mode", 16);
+ str->append(STRING_WITH_LEN(" in boolean mode"));
else if (flags & FT_EXPAND)
- str->append(" with query expansion", 21);
- str->append("))", 2);
+ str->append(STRING_WITH_LEN(" with query expansion"));
+ str->append(STRING_WITH_LEN("))"));
}
longlong Item_func_bit_xor::val_int()
@@ -4690,10 +4690,16 @@ Item_func_sp::sp_result_field(void) const
{
Field *field;
DBUG_ENTER("Item_func_sp::sp_result_field");
+ DBUG_PRINT("info", ("sp: %s, flags: %x, level: %lu",
+ (m_sp ? "YES" : "NO"),
+ (m_sp ? m_sp->m_flags : (uint)0),
+ (m_sp ? m_sp->m_recursion_level : (ulong)0)));
if (!m_sp)
{
- if (!(m_sp= sp_find_function(current_thd, m_name, TRUE)))
+ THD *thd= current_thd;
+ if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
+ &thd->sp_func_cache, TRUE)))
{
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
DBUG_RETURN(0);
@@ -4919,7 +4925,8 @@ Item_func_sp::find_and_check_access(THD *thd, ulong want_access,
bool res= TRUE;
*save= 0; // Safety if error
- if (! m_sp && ! (m_sp= sp_find_function(thd, m_name, TRUE)))
+ if (! m_sp && ! (m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
+ &thd->sp_func_cache, TRUE)))
{
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
goto error;
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 1e8fe2e695f..a8c51bb6662 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1790,7 +1790,7 @@ String *Item_func_format::val_str(String *str)
void Item_func_format::print(String *str)
{
- str->append("format(", 7);
+ str->append(STRING_WITH_LEN("format("));
args[0]->print(str);
str->append(',');
// my_charset_bin is good enough for numbers
@@ -1950,7 +1950,7 @@ String *Item_func_make_set::val_str(String *str)
void Item_func_make_set::print(String *str)
{
- str->append("make_set(", 9);
+ str->append(STRING_WITH_LEN("make_set("));
item->print(str);
if (arg_count)
{
@@ -2331,9 +2331,9 @@ void Item_func_conv_charset::fix_length_and_dec()
void Item_func_conv_charset::print(String *str)
{
- str->append("convert(", 8);
+ str->append(STRING_WITH_LEN("convert("));
args[0]->print(str);
- str->append(" using ", 7);
+ str->append(STRING_WITH_LEN(" using "));
str->append(conv_charset->csname);
str->append(')');
}
@@ -2403,7 +2403,7 @@ void Item_func_set_collation::print(String *str)
{
str->append('(');
args[0]->print(str);
- str->append(" collate ", 9);
+ str->append(STRING_WITH_LEN(" collate "));
DBUG_ASSERT(args[1]->basic_const_item() &&
args[1]->type() == Item::STRING_ITEM);
args[1]->str_value.print(str);
@@ -2523,9 +2523,9 @@ String *Item_func_unhex::val_str(String *str)
void Item_func_binary::print(String *str)
{
- str->append("cast(", 5);
+ str->append(STRING_WITH_LEN("cast("));
args[0]->print(str);
- str->append(" as binary)", 11);
+ str->append(STRING_WITH_LEN(" as binary)"));
}
@@ -2630,7 +2630,7 @@ String* Item_func_export_set::val_str(String* str)
}
break;
case 3:
- sep_buf.set(",", 1, default_charset());
+ sep_buf.set(STRING_WITH_LEN(","), default_charset());
sep = &sep_buf;
break;
default:
@@ -2745,7 +2745,8 @@ String *Item_func_quote::val_str(String *str)
uint arg_length, new_length;
if (!arg) // Null argument
{
- str->copy("NULL", 4, collation.collation); // Return the string 'NULL'
+ /* Return the string 'NULL' */
+ str->copy(STRING_WITH_LEN("NULL"), collation.collation);
null_value= 0;
return str;
}
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index a32b0d1dbbf..8c4bc996100 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -533,7 +533,7 @@ Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex):
void Item_exists_subselect::print(String *str)
{
- str->append("exists", 6);
+ str->append(STRING_WITH_LEN("exists"));
Item_subselect::print(str);
}
@@ -1339,11 +1339,11 @@ err:
void Item_in_subselect::print(String *str)
{
if (transformed)
- str->append("<exists>", 8);
+ str->append(STRING_WITH_LEN("<exists>"));
else
{
left_expr->print(str);
- str->append(" in ", 4);
+ str->append(STRING_WITH_LEN(" in "));
}
Item_subselect::print(str);
}
@@ -1362,7 +1362,7 @@ Item_allany_subselect::select_transformer(JOIN *join)
void Item_allany_subselect::print(String *str)
{
if (transformed)
- str->append("<exists>", 8);
+ str->append(STRING_WITH_LEN("<exists>"));
else
{
left_expr->print(str);
@@ -1794,16 +1794,16 @@ void subselect_union_engine::print(String *str)
void subselect_uniquesubquery_engine::print(String *str)
{
- str->append("<primary_index_lookup>(", 23);
+ str->append(STRING_WITH_LEN("<primary_index_lookup>("));
tab->ref.items[0]->print(str);
- str->append(" in ", 4);
+ str->append(STRING_WITH_LEN(" in "));
str->append(tab->table->s->table_name);
KEY *key_info= tab->table->key_info+ tab->ref.key;
- str->append(" on ", 4);
+ str->append(STRING_WITH_LEN(" on "));
str->append(key_info->name);
if (cond)
{
- str->append(" where ", 7);
+ str->append(STRING_WITH_LEN(" where "));
cond->print(str);
}
str->append(')');
@@ -1812,18 +1812,18 @@ void subselect_uniquesubquery_engine::print(String *str)
void subselect_indexsubquery_engine::print(String *str)
{
- str->append("<index_lookup>(", 15);
+ str->append(STRING_WITH_LEN("<index_lookup>("));
tab->ref.items[0]->print(str);
- str->append(" in ", 4);
+ str->append(STRING_WITH_LEN(" in "));
str->append(tab->table->s->table_name);
KEY *key_info= tab->table->key_info+ tab->ref.key;
- str->append(" on ", 4);
+ str->append(STRING_WITH_LEN(" on "));
str->append(key_info->name);
if (check_null)
- str->append(" checking NULL", 14);
+ str->append(STRING_WITH_LEN(" checking NULL"));
if (cond)
{
- str->append(" where ", 7);
+ str->append(STRING_WITH_LEN(" where "));
cond->print(str);
}
str->append(')');
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index b2eaf39d624..506d2a16108 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -3156,9 +3156,9 @@ String* Item_func_group_concat::val_str(String* str)
void Item_func_group_concat::print(String *str)
{
- str->append("group_concat(", 13);
+ str->append(STRING_WITH_LEN("group_concat("));
if (distinct)
- str->append("distinct ", 9);
+ str->append(STRING_WITH_LEN("distinct "));
for (uint i= 0; i < arg_count_field; i++)
{
if (i)
@@ -3167,19 +3167,19 @@ void Item_func_group_concat::print(String *str)
}
if (arg_count_order)
{
- str->append(" order by ", 10);
+ str->append(STRING_WITH_LEN(" order by "));
for (uint i= 0 ; i < arg_count_order ; i++)
{
if (i)
str->append(',');
(*order[i]->item)->print(str);
if (order[i]->asc)
- str->append(" ASC");
+ str->append(STRING_WITH_LEN(" ASC"));
else
- str->append(" DESC");
+ str->append(STRING_WITH_LEN(" DESC"));
}
}
- str->append(" separator \'", 12);
+ str->append(STRING_WITH_LEN(" separator \'"));
str->append(*separator);
- str->append("\')", 2);
+ str->append(STRING_WITH_LEN("\')"));
}
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 2b0314bb287..61449d3c671 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -506,7 +506,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
str->set_charset(&my_charset_bin);
if (l_time->neg)
- str->append("-", 1);
+ str->append('-');
end= (ptr= format->format.str) + format->format.length;
for (; ptr != end ; ptr++)
@@ -546,21 +546,21 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
length= int10_to_str(l_time->day, intbuff, 10) - intbuff;
str->append_with_prefill(intbuff, length, 1, '0');
if (l_time->day >= 10 && l_time->day <= 19)
- str->append("th", 2);
+ str->append(STRING_WITH_LEN("th"));
else
{
switch (l_time->day %10) {
case 1:
- str->append("st",2);
+ str->append(STRING_WITH_LEN("st"));
break;
case 2:
- str->append("nd",2);
+ str->append(STRING_WITH_LEN("nd"));
break;
case 3:
- str->append("rd",2);
+ str->append(STRING_WITH_LEN("rd"));
break;
default:
- str->append("th",2);
+ str->append(STRING_WITH_LEN("th"));
break;
}
}
@@ -2142,9 +2142,9 @@ void Item_date_add_interval::print(String *str)
void Item_extract::print(String *str)
{
- str->append("extract(", 8);
+ str->append(STRING_WITH_LEN("extract("));
str->append(interval_names[int_type]);
- str->append(" from ", 6);
+ str->append(STRING_WITH_LEN(" from "));
args[0]->print(str);
str->append(')');
}
@@ -2286,9 +2286,9 @@ bool Item_char_typecast::eq(const Item *item, bool binary_cmp) const
void Item_typecast::print(String *str)
{
- str->append("cast(", 5);
+ str->append(STRING_WITH_LEN("cast("));
args[0]->print(str);
- str->append(" as ", 4);
+ str->append(STRING_WITH_LEN(" as "));
str->append(cast_type());
str->append(')');
}
@@ -2296,9 +2296,9 @@ void Item_typecast::print(String *str)
void Item_char_typecast::print(String *str)
{
- str->append("cast(", 5);
+ str->append(STRING_WITH_LEN("cast("));
args[0]->print(str);
- str->append(" as char", 8);
+ str->append(STRING_WITH_LEN(" as char"));
if (cast_length >= 0)
{
str->append('(');
@@ -2311,7 +2311,7 @@ void Item_char_typecast::print(String *str)
}
if (cast_cs)
{
- str->append(" charset ", 9);
+ str->append(STRING_WITH_LEN(" charset "));
str->append(cast_cs->csname);
}
str->append(')');
@@ -2352,22 +2352,37 @@ String *Item_char_typecast::val_str(String *str)
and the result is longer than cast length, e.g.
CAST('string' AS CHAR(1))
*/
- if (cast_length >= 0 &&
- (res->length() > (length= (uint32) res->charpos(cast_length))))
- { // Safe even if const arg
- char char_type[40];
- my_snprintf(char_type, sizeof(char_type), "CHAR(%lu)", length);
-
- if (!res->alloced_length())
- { // Don't change const str
- str_value= *res; // Not malloced string
- res= &str_value;
+ if (cast_length >= 0)
+ {
+ if (res->length() > (length= (uint32) res->charpos(cast_length)))
+ { // Safe even if const arg
+ char char_type[40];
+ my_snprintf(char_type, sizeof(char_type), "%s(%lu)",
+ cast_cs == &my_charset_bin ? "BINARY" : "CHAR", length);
+
+ if (!res->alloced_length())
+ { // Don't change const str
+ str_value= *res; // Not malloced string
+ res= &str_value;
+ }
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE), char_type,
+ res->c_ptr_safe());
+ res->length((uint) length);
+ }
+ else if (cast_cs == &my_charset_bin && res->length() < (uint) cast_length)
+ {
+ if (res->alloced_length() < (uint) cast_length)
+ {
+ str->alloc(cast_length);
+ str->copy(*res);
+ res= str;
+ }
+ bzero((char*) res->ptr() + res->length(),
+ (uint) cast_length - res->length());
+ res->length(cast_length);
}
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE,
- ER(ER_TRUNCATED_WRONG_VALUE), char_type,
- res->c_ptr_safe());
- res->length((uint) length);
}
null_value= 0;
return res;
@@ -2609,14 +2624,14 @@ void Item_func_add_time::print(String *str)
if (is_date)
{
DBUG_ASSERT(sign > 0);
- str->append("timestamp(", 10);
+ str->append(STRING_WITH_LEN("timestamp("));
}
else
{
if (sign > 0)
- str->append("addtime(", 8);
+ str->append(STRING_WITH_LEN("addtime("));
else
- str->append("subtime(", 8);
+ str->append(STRING_WITH_LEN("subtime("));
}
args[0]->print(str);
str->append(',');
@@ -2825,31 +2840,31 @@ void Item_func_timestamp_diff::print(String *str)
switch (int_type) {
case INTERVAL_YEAR:
- str->append("YEAR");
+ str->append(STRING_WITH_LEN("YEAR"));
break;
case INTERVAL_QUARTER:
- str->append("QUARTER");
+ str->append(STRING_WITH_LEN("QUARTER"));
break;
case INTERVAL_MONTH:
- str->append("MONTH");
+ str->append(STRING_WITH_LEN("MONTH"));
break;
case INTERVAL_WEEK:
- str->append("WEEK");
+ str->append(STRING_WITH_LEN("WEEK"));
break;
case INTERVAL_DAY:
- str->append("DAY");
+ str->append(STRING_WITH_LEN("DAY"));
break;
case INTERVAL_HOUR:
- str->append("HOUR");
+ str->append(STRING_WITH_LEN("HOUR"));
break;
case INTERVAL_MINUTE:
- str->append("MINUTE");
+ str->append(STRING_WITH_LEN("MINUTE"));
break;
case INTERVAL_SECOND:
- str->append("SECOND");
+ str->append(STRING_WITH_LEN("SECOND"));
break;
case INTERVAL_MICROSECOND:
- str->append("SECOND_FRAC");
+ str->append(STRING_WITH_LEN("SECOND_FRAC"));
break;
default:
break;
@@ -2905,13 +2920,13 @@ void Item_func_get_format::print(String *str)
switch (type) {
case MYSQL_TIMESTAMP_DATE:
- str->append("DATE, ");
+ str->append(STRING_WITH_LEN("DATE, "));
break;
case MYSQL_TIMESTAMP_DATETIME:
- str->append("DATETIME, ");
+ str->append(STRING_WITH_LEN("DATETIME, "));
break;
case MYSQL_TIMESTAMP_TIME:
- str->append("TIME, ");
+ str->append(STRING_WITH_LEN("TIME, "));
break;
default:
DBUG_ASSERT(0);
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index c884c454dac..a0aa0b96cc6 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -29,7 +29,7 @@ public:
:Item_real_func(list) {}
double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
void fix_length_and_dec() { decimals=0; max_length=6; }
- void print(String *str) { str->append("0.0", 3); }
+ void print(String *str) { str->append(STRING_WITH_LEN("0.0")); }
const char *func_name() const { return "unique_users"; }
};
@@ -57,7 +57,7 @@ public:
{
return new Item_sum_unique_users(thd, this);
}
- void print(String *str) { str->append("0.0", 3); }
+ void print(String *str) { str->append(STRING_WITH_LEN("0.0")); }
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
const char *func_name() const { return "sum_unique_users"; }
};
diff --git a/sql/key.cc b/sql/key.cc
index 4af88f218ee..5d88ea0a9c3 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -322,7 +322,7 @@ void key_unpack(String *to,TABLE *table,uint idx)
{
if (table->record[0][key_part->null_offset] & key_part->null_bit)
{
- to->append("NULL", 4);
+ to->append(STRING_WITH_LEN("NULL"));
continue;
}
}
@@ -334,7 +334,7 @@ void key_unpack(String *to,TABLE *table,uint idx)
to->append(tmp);
}
else
- to->append("???", 3);
+ to->append(STRING_WITH_LEN("???"));
}
DBUG_VOID_RETURN;
}
diff --git a/sql/lex.h b/sql/lex.h
index ba290e9b646..e3cbebf4629 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -112,6 +112,7 @@ static SYMBOL symbols[] = {
{ "CLIENT", SYM(CLIENT_SYM)},
{ "CLOSE", SYM(CLOSE_SYM)},
{ "COALESCE", SYM(COALESCE)},
+ { "CODE", SYM(CODE_SYM)},
{ "COLLATE", SYM(COLLATE_SYM)},
{ "COLLATION", SYM(COLLATION_SYM)},
{ "COLUMN", SYM(COLUMN_SYM)},
diff --git a/sql/log.cc b/sql/log.cc
index 593a5ab2bdc..1fc7ba1f1fd 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -142,7 +142,7 @@ static int binlog_commit(THD *thd, bool all)
// we're here because trans_log was flushed in MYSQL_LOG::log()
DBUG_RETURN(0);
}
- Query_log_event qev(thd, "COMMIT", 6, TRUE, FALSE);
+ Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
DBUG_RETURN(binlog_end_trans(thd, trans_log, &qev));
}
@@ -166,7 +166,7 @@ static int binlog_rollback(THD *thd, bool all)
*/
if (unlikely(thd->options & OPTION_STATUS_NO_TRANS_UPDATE))
{
- Query_log_event qev(thd, "ROLLBACK", 8, TRUE, FALSE);
+ Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE);
error= binlog_end_trans(thd, trans_log, &qev);
}
else
@@ -1833,7 +1833,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event)
*/
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
{
- Query_log_event qinfo(thd, "BEGIN", 5, TRUE, FALSE);
+ Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE);
/*
Imagine this is rollback due to net timeout, after all statements of
the transaction succeeded. Then we want a zero-error code in BEGIN.
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 081b498f01e..c8f8ff40700 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -161,7 +161,7 @@ static void cleanup_load_tmpdir()
we cannot meet Start_log event in the middle of events from one
LOAD DATA.
*/
- p= strmake(prefbuf,"SQL_LOAD-",9);
+ p= strmake(prefbuf, STRING_WITH_LEN("SQL_LOAD-"));
p= int10_to_str(::server_id, p, 10);
*(p++)= '-';
*p= 0;
@@ -902,14 +902,16 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info)
/* Pretty-print event common header if header is exactly 19 bytes */
if (print_event_info->common_header_len == LOG_EVENT_MINIMAL_HEADER_LEN)
{
+ DBUG_ASSERT(hexdump_from == (unsigned long) hexdump_from);
fprintf(file, "# Position Timestamp Type Master ID "
"Size Master Pos Flags \n");
fprintf(file, "# %8.8lx %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x\n",
- hexdump_from, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4],
- ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11],
- ptr[12], ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]);
+ (unsigned long) hexdump_from,
+ ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6],
+ ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13],
+ ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]);
ptr += LOG_EVENT_MINIMAL_HEADER_LEN;
hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN;
}
@@ -926,8 +928,10 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info)
if (i % 16 == 15)
{
+ DBUG_ASSERT(hexdump_from == (unsigned long) hexdump_from);
fprintf(file, "# %8.8lx %-48.48s |%16s|\n",
- hexdump_from + (i & 0xfffffff0), hex_string, char_string);
+ (unsigned long) (hexdump_from + (i & 0xfffffff0)),
+ hex_string, char_string);
hex_string[0]= 0;
char_string[0]= 0;
c= char_string;
@@ -939,8 +943,10 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info)
/* Non-full last line */
if (hex_string[0]) {
- printf("# %8.8lx %-48.48s |%s|\n# ",
- hexdump_from + (i & 0xfffffff0), hex_string, char_string);
+ DBUG_ASSERT(hexdump_from == (unsigned long) hexdump_from);
+ fprintf(file, "# %8.8lx %-48.48s |%s|\n# ",
+ (unsigned long) (hexdump_from + (i & 0xfffffff0)),
+ hex_string, char_string);
}
}
}
@@ -2992,7 +2998,7 @@ void Rotate_log_event::pack_info(Protocol *protocol)
String tmp(buf1, sizeof(buf1), log_cs);
tmp.length(0);
tmp.append(new_log_ident, ident_len);
- tmp.append(";pos=");
+ tmp.append(STRING_WITH_LEN(";pos="));
tmp.append(llstr(pos,buf));
protocol->store(tmp.ptr(), tmp.length(), &my_charset_bin);
}
@@ -4164,7 +4170,7 @@ int Create_file_log_event::exec_event(struct st_relay_log_info* rli)
bzero((char*)&file, sizeof(file));
p = slave_load_file_stem(fname_buf, file_id, server_id);
strmov(p, ".info"); // strmov takes less code than memcpy
- strnmov(proc_info, "Making temp file ", 17); // no end 0
+ strnmov(proc_info, STRING_WITH_LEN("Making temp file ")); // no end 0
thd->proc_info= proc_info;
my_delete(fname_buf, MYF(0)); // old copy may exist already
if ((fd= my_create(fname_buf, CREATE_MODE,
@@ -4333,7 +4339,7 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
DBUG_ENTER("Append_block_log_event::exec_event");
memcpy(p, ".data", 6);
- strnmov(proc_info, "Making temp file ", 17); // no end 0
+ strnmov(proc_info, STRING_WITH_LEN("Making temp file ")); // no end 0
thd->proc_info= proc_info;
if (get_create_or_append())
{
@@ -4817,23 +4823,23 @@ Execute_load_query_log_event::exec_event(struct st_relay_log_info* rli)
p= buf;
memcpy(p, query, fn_pos_start);
p+= fn_pos_start;
- fname= (p= strmake(p, " INFILE \'", 9));
+ fname= (p= strmake(p, STRING_WITH_LEN(" INFILE \'")));
p= slave_load_file_stem(p, file_id, server_id);
- fname_end= (p= strmake(p, ".data", 5));
+ fname_end= (p= strmake(p, STRING_WITH_LEN(".data")));
*(p++)='\'';
switch (dup_handling)
{
case LOAD_DUP_IGNORE:
- p= strmake(p, " IGNORE", 7);
+ p= strmake(p, STRING_WITH_LEN(" IGNORE"));
break;
case LOAD_DUP_REPLACE:
- p= strmake(p, " REPLACE", 8);
+ p= strmake(p, STRING_WITH_LEN(" REPLACE"));
break;
default:
/* Ordinary load data */
break;
}
- p= strmake(p, " INTO", 5);
+ p= strmake(p, STRING_WITH_LEN(" INTO"));
p= strmake(p, query+fn_pos_end, q_len-fn_pos_end);
error= Query_log_event::exec_event(rli, buf, p-buf);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index dd96758455d..abcab00af3c 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -550,6 +550,8 @@ pthread_cond_t COND_server_started;
int mysqld_server_started= 0;
+File_parser_dummy_hook file_parser_dummy_hook;
+
/* replication parameters, if master_host is not NULL, we are a slave */
uint master_port= MYSQL_PORT, master_connect_retry = 60;
uint report_port= MYSQL_PORT;
@@ -4621,6 +4623,7 @@ enum options_mysqld
OPT_OPTIMIZER_PRUNE_LEVEL,
OPT_UPDATABLE_VIEWS_WITH_LIMIT,
OPT_SP_AUTOMATIC_PRIVILEGES,
+ OPT_MAX_SP_RECURSION_DEPTH,
OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET,
OPT_ENABLE_LARGE_PAGES,
OPT_TIMED_MUTEXES,
@@ -5876,6 +5879,11 @@ The minimum value for this variable is 4096.",
(gptr*) &global_system_variables.read_buff_size,
(gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG,
128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0},
+ {"max_sp_recursion_depth", OPT_MAX_SP_RECURSION_DEPTH,
+ "Maximum stored procedure recursion depth. (discussed with docs).",
+ (gptr*) &global_system_variables.max_sp_recursion_depth,
+ (gptr*) &max_system_variables.max_sp_recursion_depth, 0, GET_ULONG,
+ OPT_ARG, 0, 0, 255, 0, 1, 0 },
#ifdef HAVE_REPLICATION
{"relay_log_purge", OPT_RELAY_LOG_PURGE,
"0 = do not purge relay logs. 1 = purge them as soon as they are no more needed.",
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 9e8a39f1765..21a3f87e0fd 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -6696,7 +6696,7 @@ void QUICK_INDEX_MERGE_SELECT::add_info_string(String *str)
QUICK_RANGE_SELECT *quick;
bool first= TRUE;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
- str->append("sort_union(");
+ str->append(STRING_WITH_LEN("sort_union("));
while ((quick= it++))
{
if (!first)
@@ -6718,7 +6718,7 @@ void QUICK_ROR_INTERSECT_SELECT::add_info_string(String *str)
bool first= TRUE;
QUICK_RANGE_SELECT *quick;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
- str->append("intersect(");
+ str->append(STRING_WITH_LEN("intersect("));
while ((quick= it++))
{
KEY *key_info= head->key_info + quick->index;
@@ -6742,7 +6742,7 @@ void QUICK_ROR_UNION_SELECT::add_info_string(String *str)
bool first= TRUE;
QUICK_SELECT_I *quick;
List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
- str->append("union(");
+ str->append(STRING_WITH_LEN("union("));
while ((quick= it++))
{
if (!first)
@@ -8882,7 +8882,7 @@ static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map,
}
}
if (!tmp.length())
- tmp.append("(empty)");
+ tmp.append(STRING_WITH_LEN("(empty)"));
DBUG_PRINT("info", ("SEL_TREE %p (%s) scans:%s", tree, msg, tmp.ptr()));
@@ -8908,7 +8908,7 @@ static void print_ror_scans_arr(TABLE *table, const char *msg,
tmp.append(table->key_info[(*start)->keynr].name);
}
if (!tmp.length())
- tmp.append("(empty)");
+ tmp.append(STRING_WITH_LEN("(empty)"));
DBUG_PRINT("info", ("ROR key scans (%s): %s", msg, tmp.ptr()));
DBUG_VOID_RETURN;
}
diff --git a/sql/parse_file.cc b/sql/parse_file.cc
index d3e5645bafc..69757e0be06 100644
--- a/sql/parse_file.cc
+++ b/sql/parse_file.cc
@@ -50,23 +50,23 @@ write_escaped_string(IO_CACHE *file, LEX_STRING *val_s)
*/
switch(*ptr) {
case '\\': // escape character
- if (my_b_append(file, (const byte *)"\\\\", 2))
+ if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\\\")))
return TRUE;
break;
case '\n': // parameter value delimiter
- if (my_b_append(file, (const byte *)"\\n", 2))
+ if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\n")))
return TRUE;
break;
case '\0': // problem for some string processing utilities
- if (my_b_append(file, (const byte *)"\\0", 2))
+ if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\0")))
return TRUE;
break;
case 26: // problem for windows utilities (Ctrl-Z)
- if (my_b_append(file, (const byte *)"\\z", 2))
+ if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\z")))
return TRUE;
break;
case '\'': // list of string delimiter
- if (my_b_append(file, (const byte *)"\\\'", 2))
+ if (my_b_append(file, (const byte *)STRING_WITH_LEN("\\\'")))
return TRUE;
break;
default:
@@ -155,10 +155,10 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter,
while ((str= it++))
{
// We need ' ' after string to detect list continuation
- if ((!first && my_b_append(file, (const byte *)" ", 1)) ||
- my_b_append(file, (const byte *)"\'", 1) ||
+ if ((!first && my_b_append(file, (const byte *)STRING_WITH_LEN(" "))) ||
+ my_b_append(file, (const byte *)STRING_WITH_LEN("\'")) ||
write_escaped_string(file, str) ||
- my_b_append(file, (const byte *)"\'", 1))
+ my_b_append(file, (const byte *)STRING_WITH_LEN("\'")))
{
DBUG_RETURN(TRUE);
}
@@ -176,7 +176,7 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter,
{
num.set(*val, &my_charset_bin);
// We need ' ' after string to detect list continuation
- if ((!first && my_b_append(file, (const byte *)" ", 1)) ||
+ if ((!first && my_b_append(file, (const byte *)STRING_WITH_LEN(" "))) ||
my_b_append(file, (const byte *)num.ptr(), num.length()))
{
DBUG_RETURN(TRUE);
@@ -242,9 +242,9 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
goto err_w_file;
// write header (file signature)
- if (my_b_append(&file, (const byte *)"TYPE=", 5) ||
+ if (my_b_append(&file, (const byte *)STRING_WITH_LEN("TYPE=")) ||
my_b_append(&file, (const byte *)type->str, type->length) ||
- my_b_append(&file, (const byte *)"\n", 1))
+ my_b_append(&file, (const byte *)STRING_WITH_LEN("\n")))
goto err_w_file;
// write parameters to temporary file
@@ -252,9 +252,9 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
{
if (my_b_append(&file, (const byte *)param->name.str,
param->name.length) ||
- my_b_append(&file, (const byte *)"=", 1) ||
+ my_b_append(&file, (const byte *)STRING_WITH_LEN("=")) ||
write_parameter(&file, base, param, &old_version) ||
- my_b_append(&file, (const byte *)"\n", 1))
+ my_b_append(&file, (const byte *)STRING_WITH_LEN("\n")))
goto err_w_cache;
}
@@ -664,6 +664,61 @@ parse_quoted_escaped_string(char *ptr, char *end,
/*
+ Parser for FILE_OPTIONS_ULLLIST type value.
+
+ SYNOPSIS
+ get_file_options_ulllist()
+ ptr [in/out] pointer to parameter
+ end [in] end of the configuration
+ line [in] pointer to the line begining
+ base [in] base address for parameter writing (structure
+ like TABLE)
+ parameter [in] description
+ mem_root [in] MEM_ROOT for parameters allocation
+*/
+
+bool get_file_options_ulllist(char *&ptr, char *end, char *line,
+ gptr base, File_option *parameter,
+ MEM_ROOT *mem_root)
+{
+ List<ulonglong> *nlist= (List<ulonglong>*)(base + parameter->offset);
+ ulonglong *num;
+ nlist->empty();
+ // list parsing
+ while (ptr < end)
+ {
+ int not_used;
+ char *num_end= end;
+ if (!(num= (ulonglong*)alloc_root(mem_root, sizeof(ulonglong))) ||
+ nlist->push_back(num, mem_root))
+ goto nlist_err;
+ *num= my_strtoll10(ptr, &num_end, &not_used);
+ ptr= num_end;
+ switch (*ptr) {
+ case '\n':
+ goto end_of_nlist;
+ case ' ':
+ // we cant go over buffer bounds, because we have \0 at the end
+ ptr++;
+ break;
+ default:
+ goto nlist_err_w_message;
+ }
+ }
+
+end_of_nlist:
+ if (*(ptr++) != '\n')
+ goto nlist_err;
+ return FALSE;
+
+nlist_err_w_message:
+ my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0), parameter->name.str, line);
+nlist_err:
+ return TRUE;
+}
+
+
+/*
parse parameters
SYNOPSIS
@@ -673,6 +728,8 @@ parse_quoted_escaped_string(char *ptr, char *end,
mem_root MEM_ROOT for parameters allocation
parameters parameters description
required number of required parameters in above list
+ hook hook called for unknown keys
+ hook_data some data specific for the hook
RETURN
FALSE - OK
@@ -681,15 +738,15 @@ parse_quoted_escaped_string(char *ptr, char *end,
my_bool
File_parser::parse(gptr base, MEM_ROOT *mem_root,
- struct File_option *parameters, uint required)
+ struct File_option *parameters, uint required,
+ Unknown_key_hook *hook)
{
uint first_param= 0, found= 0;
- register char *ptr= start;
+ char *ptr= start;
char *eol;
LEX_STRING *str;
List<LEX_STRING> *list;
ulonglong *num;
- List<ulonglong> *nlist;
DBUG_ENTER("File_parser::parse");
while (ptr < end && found < required)
@@ -829,58 +886,64 @@ list_err:
DBUG_RETURN(TRUE);
}
case FILE_OPTIONS_ULLLIST:
- {
- nlist= (List<ulonglong>*)(base + parameter->offset);
- nlist->empty();
- // list parsing
- while (ptr < end)
- {
- int not_used;
- char *num_end= end;
- if (!(num= (ulonglong*)alloc_root(mem_root, sizeof(ulonglong))) ||
- nlist->push_back(num, mem_root))
- goto nlist_err;
- *num= my_strtoll10(ptr, &num_end, &not_used);
- ptr= num_end;
- switch (*ptr) {
- case '\n':
- goto end_of_nlist;
- case ' ':
- // we cant go over buffer bounds, because we have \0 at the end
- ptr++;
- break;
- default:
- goto nlist_err_w_message;
- }
- }
-
-end_of_nlist:
- if (*(ptr++) != '\n')
- goto nlist_err;
+ if (get_file_options_ulllist(ptr, end, line, base,
+ parameter, mem_root))
+ DBUG_RETURN(TRUE);
break;
-
-nlist_err_w_message:
- my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
- parameter->name.str, line);
-nlist_err:
- DBUG_RETURN(TRUE);
-
- }
default:
DBUG_ASSERT(0); // never should happened
}
}
else
{
- // skip unknown parameter
- if (!(ptr= strchr(ptr, '\n')))
- {
- my_error(ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER, MYF(0), line);
- DBUG_RETURN(TRUE);
- }
- ptr++;
+ ptr= line;
+ if (hook->process_unknown_string(ptr, base, mem_root, end))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ // skip unknown parameter
+ if (!(ptr= strchr(ptr, '\n')))
+ {
+ my_error(ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER, MYF(0), line);
+ DBUG_RETURN(TRUE);
+ }
+ ptr++;
}
}
}
DBUG_RETURN(FALSE);
}
+
+
+/*
+ Dummy unknown key hook
+
+ SYNOPSIS
+ File_parser_dummy_hook::process_unknown_string()
+ unknown_key [in/out] reference on the line with unknown
+ parameter and the parsing point
+ base [in] base address for parameter writing (structure like
+ TABLE)
+ mem_root [in] MEM_ROOT for parameters allocation
+ end [in] the end of the configuration
+
+ NOTE
+ This hook used to catch no longer supported keys and process them for
+ backward compatibility, but it will not slow down processing of modern
+ format files.
+ This hook does nothing except debug output.
+
+ RETURN
+ FALSE OK
+ TRUE Error
+*/
+
+bool
+File_parser_dummy_hook::process_unknown_string(char *&unknown_key,
+ gptr base, MEM_ROOT *mem_root,
+ char *end)
+{
+ DBUG_ENTER("file_parser_dummy_hook::process_unknown_string");
+ DBUG_PRINT("info", ("unknown key:%60s", unknown_key));
+ DBUG_RETURN(FALSE);
+}
diff --git a/sql/parse_file.h b/sql/parse_file.h
index b4199e4fbf1..afa88da2ead 100644
--- a/sql/parse_file.h
+++ b/sql/parse_file.h
@@ -40,6 +40,35 @@ struct File_option
file_opt_type type; /* Option type */
};
+
+/*
+ This hook used to catch no longer supported keys and process them for
+ backward compatibility.
+*/
+
+class Unknown_key_hook
+{
+public:
+ virtual bool process_unknown_string(char *&unknown_key, gptr base,
+ MEM_ROOT *mem_root, char *end)= 0;
+};
+
+
+/* Dummy hook for parsers which do not need hook for unknown keys */
+
+class File_parser_dummy_hook: public Unknown_key_hook
+{
+public:
+ virtual bool process_unknown_string(char *&unknown_key, gptr base,
+ MEM_ROOT *mem_root, char *end);
+};
+
+extern File_parser_dummy_hook file_parser_dummy_hook;
+
+bool get_file_options_ulllist(char *&ptr, char *end, char *line,
+ gptr base, File_option *parameter,
+ MEM_ROOT *mem_root);
+
class File_parser;
File_parser *sql_parse_prepare(const LEX_STRING *file_name,
MEM_ROOT *mem_root, bool bad_format_errors);
@@ -64,7 +93,8 @@ public:
my_bool ok() { return content_ok; }
LEX_STRING *type() { return &file_type; }
my_bool parse(gptr base, MEM_ROOT *mem_root,
- struct File_option *parameters, uint required);
+ struct File_option *parameters, uint required,
+ Unknown_key_hook *hook);
friend File_parser *sql_parse_prepare(const LEX_STRING *file_name,
MEM_ROOT *mem_root,
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 8c3e5a62820..0a1b42f5236 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -498,7 +498,7 @@ void Protocol::init(THD *thd_arg)
thd=thd_arg;
packet= &thd->packet;
convert= &thd->convert_buffer;
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
field_types= 0;
#endif
}
@@ -551,7 +551,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
(void) my_net_write(&thd->net, buff,(uint) (pos-buff));
}
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
list->elements);
uint count= 0;
@@ -572,7 +572,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
- if (prot.store("def", 3, cs, thd_charset) ||
+ if (prot.store(STRING_WITH_LEN("def"), cs, thd_charset) ||
prot.store(field.db_name, (uint) strlen(field.db_name),
cs, thd_charset) ||
prot.store(field.table_name, (uint) strlen(field.table_name),
@@ -648,7 +648,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
item->send(&prot, &tmp); // Send default value
if (prot.write())
break; /* purecov: inspected */
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
field_types[count++]= field.type;
#endif
}
@@ -732,14 +732,14 @@ bool Protocol::store(I_List<i_string>* str_list)
void Protocol_simple::prepare_for_resend()
{
packet->length(0);
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
field_pos= 0;
#endif
}
bool Protocol_simple::store_null()
{
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
field_pos++;
#endif
char buff[1];
@@ -773,7 +773,7 @@ bool Protocol::store_string_aux(const char *from, uint length,
bool Protocol_simple::store(const char *from, uint length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
{
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
@@ -790,7 +790,7 @@ bool Protocol_simple::store(const char *from, uint length,
CHARSET_INFO *fromcs)
{
CHARSET_INFO *tocs= this->thd->variables.character_set_results;
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
@@ -805,7 +805,7 @@ bool Protocol_simple::store(const char *from, uint length,
bool Protocol_simple::store_tiny(longlong from)
{
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY);
field_pos++;
#endif
@@ -817,7 +817,7 @@ bool Protocol_simple::store_tiny(longlong from)
bool Protocol_simple::store_short(longlong from)
{
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_YEAR ||
field_types[field_pos] == MYSQL_TYPE_SHORT);
@@ -831,7 +831,7 @@ bool Protocol_simple::store_short(longlong from)
bool Protocol_simple::store_long(longlong from)
{
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_INT24 ||
field_types[field_pos] == MYSQL_TYPE_LONG);
@@ -845,7 +845,7 @@ bool Protocol_simple::store_long(longlong from)
bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag)
{
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_LONGLONG);
field_pos++;
@@ -860,7 +860,7 @@ bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag)
bool Protocol_simple::store_decimal(const my_decimal *d)
{
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
field_pos++;
@@ -874,7 +874,7 @@ bool Protocol_simple::store_decimal(const my_decimal *d)
bool Protocol_simple::store(float from, uint32 decimals, String *buffer)
{
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_FLOAT);
field_pos++;
@@ -886,7 +886,7 @@ bool Protocol_simple::store(float from, uint32 decimals, String *buffer)
bool Protocol_simple::store(double from, uint32 decimals, String *buffer)
{
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DOUBLE);
field_pos++;
@@ -900,7 +900,7 @@ bool Protocol_simple::store(Field *field)
{
if (field->is_null())
return store_null();
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
field_pos++;
#endif
char buff[MAX_FIELD_WIDTH];
@@ -921,7 +921,7 @@ bool Protocol_simple::store(Field *field)
bool Protocol_simple::store(TIME *tm)
{
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DATETIME ||
field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
@@ -944,7 +944,7 @@ bool Protocol_simple::store(TIME *tm)
bool Protocol_simple::store_date(TIME *tm)
{
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DATE);
field_pos++;
@@ -963,7 +963,7 @@ bool Protocol_simple::store_date(TIME *tm)
bool Protocol_simple::store_time(TIME *tm)
{
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_TIME);
field_pos++;
@@ -1088,7 +1088,7 @@ bool Protocol_prep::store_longlong(longlong from, bool unsigned_flag)
bool Protocol_prep::store_decimal(const my_decimal *d)
{
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
field_pos++;
diff --git a/sql/protocol.h b/sql/protocol.h
index c00bbba4cc9..8d9da5774b2 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -31,7 +31,7 @@ protected:
String *packet;
String *convert;
uint field_pos;
-#ifndef DEBUG_OFF
+#ifndef DBUG_OFF
enum enum_field_types *field_types;
#endif
uint field_count;
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 823930121fe..960e0ac86cc 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -503,7 +503,7 @@ int update_slave_list(MYSQL* mysql, MASTER_INFO* mi)
int port_ind;
DBUG_ENTER("update_slave_list");
- if (mysql_real_query(mysql,"SHOW SLAVE HOSTS",16) ||
+ if (mysql_real_query(mysql, STRING_WITH_LEN("SHOW SLAVE HOSTS")) ||
!(res = mysql_store_result(mysql)))
{
error= mysql_error(mysql);
@@ -796,7 +796,7 @@ bool load_master_data(THD* thd)
MYSQL_RES *db_res, **table_res, **table_res_end, **cur_table_res;
uint num_dbs;
- if (mysql_real_query(&mysql, "SHOW DATABASES", 14) ||
+ if (mysql_real_query(&mysql, STRING_WITH_LEN("SHOW DATABASES")) ||
!(db_res = mysql_store_result(&mysql)))
{
my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
@@ -822,8 +822,9 @@ bool load_master_data(THD* thd)
we wait to issue FLUSH TABLES WITH READ LOCK for as long as we
can to minimize the lock time.
*/
- if (mysql_real_query(&mysql, "FLUSH TABLES WITH READ LOCK", 27) ||
- mysql_real_query(&mysql, "SHOW MASTER STATUS",18) ||
+ if (mysql_real_query(&mysql,
+ STRING_WITH_LEN("FLUSH TABLES WITH READ LOCK")) ||
+ mysql_real_query(&mysql, STRING_WITH_LEN("SHOW MASTER STATUS")) ||
!(master_status_res = mysql_store_result(&mysql)))
{
my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
@@ -876,7 +877,7 @@ bool load_master_data(THD* thd)
}
if (mysql_select_db(&mysql, db) ||
- mysql_real_query(&mysql, "SHOW TABLES", 11) ||
+ mysql_real_query(&mysql, STRING_WITH_LEN("SHOW TABLES")) ||
!(*cur_table_res = mysql_store_result(&mysql)))
{
my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
@@ -934,7 +935,7 @@ bool load_master_data(THD* thd)
mysql_free_result(master_status_res);
}
- if (mysql_real_query(&mysql, "UNLOCK TABLES", 13))
+ if (mysql_real_query(&mysql, STRING_WITH_LEN("UNLOCK TABLES")))
{
my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
goto err;
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 29eae82c3ae..0e57a80e52c 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -298,6 +298,8 @@ sys_var_long_ptr sys_max_relay_log_size("max_relay_log_size",
fix_max_relay_log_size);
sys_var_thd_ulong sys_max_sort_length("max_sort_length",
&SV::max_sort_length);
+sys_var_thd_ulong sys_max_sp_recursion_depth("max_sp_recursion_depth",
+ &SV::max_sp_recursion_depth);
sys_var_max_user_conn sys_max_user_connections("max_user_connections");
sys_var_thd_ulong sys_max_tmp_tables("max_tmp_tables",
&SV::max_tmp_tables);
@@ -770,6 +772,8 @@ struct show_var_st init_vars[]= {
{sys_max_relay_log_size.name, (char*) &sys_max_relay_log_size, SHOW_SYS},
{sys_max_seeks_for_key.name, (char*) &sys_max_seeks_for_key, SHOW_SYS},
{sys_max_sort_length.name, (char*) &sys_max_sort_length, SHOW_SYS},
+ {sys_max_sp_recursion_depth.name,
+ (char*) &sys_max_sp_recursion_depth, SHOW_SYS},
{sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS},
{sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS},
{sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS},
diff --git a/sql/share/Makefile.am b/sql/share/Makefile.am
index 2e23027f1f5..6d905ba35dc 100644
--- a/sql/share/Makefile.am
+++ b/sql/share/Makefile.am
@@ -49,5 +49,15 @@ install-data-local:
$(INSTALL_DATA) $(srcdir)/charsets/README $(DESTDIR)$(pkgdatadir)/charsets/README
$(INSTALL_DATA) $(srcdir)/charsets/*.xml $(DESTDIR)$(pkgdatadir)/charsets
+# FIXME maybe shouldn't remove, could be needed by other installation?
+uninstall-local:
+ @RM@ -f -r $(DESTDIR)$(pkgdatadir)
+
+distclean-local:
+ @RM@ -f */errmsg.sys
+
+# Do nothing
+link_sources:
+
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 7b2b03f9cb9..f922f7a08ba 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -5361,7 +5361,7 @@ ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
ER_NO_DEFAULT_FOR_VIEW_FIELD
eng "Field of view '%-.64s.%-.64s' underlying table doesn't have a default value"
ER_SP_NO_RECURSION
- eng "Recursive stored routines are not allowed."
+ eng "Recursive stored functions and triggers are not allowed."
ER_TOO_BIG_SCALE 42000 S1009
eng "Too big scale %d specified for column '%-.64s'. Maximum is %d."
ER_TOO_BIG_PRECISION 42000 S1009
@@ -5423,6 +5423,10 @@ ER_SP_BAD_VAR_SHADOW 42000
eng "Variable '%-.64s' must be quoted with `...`, or renamed"
ER_TRG_NO_DEFINER
eng "No definer attribute for trigger '%-.64s'.'%-.64s'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger."
+ER_OLD_FILE_FORMAT
+ eng "'%-.64s' has an old format, you should re-create the '%s' object(s)"
+ER_SP_RECURSION_LIMIT
+ eng "Recursive limit %d (as set by the max_sp_recursion_depth variable) was exceeded for routine %.64s"
ER_PARTITION_REQUIRES_VALUES_ERROR
eng "%s PARTITIONING requires definition of VALUES %s for each partition"
swe "%s PARTITIONering kräver definition av VALUES %s för varje partition"
diff --git a/sql/slave.cc b/sql/slave.cc
index 2ae51e37930..263169a8406 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1068,7 +1068,7 @@ static int get_master_version_and_clock(MYSQL* mysql, MASTER_INFO* mi)
MYSQL_RES *master_res= 0;
MYSQL_ROW master_row;
- if (!mysql_real_query(mysql, "SELECT UNIX_TIMESTAMP()", 23) &&
+ if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECT UNIX_TIMESTAMP()")) &&
(master_res= mysql_store_result(mysql)) &&
(master_row= mysql_fetch_row(master_res)))
{
@@ -1094,7 +1094,8 @@ do not trust column Seconds_Behind_Master of SHOW SLAVE STATUS");
Note: we could have put a @@SERVER_ID in the previous SELECT
UNIX_TIMESTAMP() instead, but this would not have worked on 3.23 masters.
*/
- if (!mysql_real_query(mysql, "SHOW VARIABLES LIKE 'SERVER_ID'", 31) &&
+ if (!mysql_real_query(mysql,
+ STRING_WITH_LEN("SHOW VARIABLES LIKE 'SERVER_ID'")) &&
(master_res= mysql_store_result(mysql)))
{
if ((master_row= mysql_fetch_row(master_res)) &&
@@ -1129,7 +1130,8 @@ not always make sense; please check the manual before using it).";
goto err;
if ((*mysql->server_version == '4') &&
- !mysql_real_query(mysql, "SELECT @@GLOBAL.COLLATION_SERVER", 32) &&
+ !mysql_real_query(mysql,
+ STRING_WITH_LEN("SELECT @@GLOBAL.COLLATION_SERVER")) &&
(master_res= mysql_store_result(mysql)))
{
if ((master_row= mysql_fetch_row(master_res)) &&
@@ -1156,7 +1158,7 @@ be equal for replication to work";
those were alpha).
*/
if ((*mysql->server_version == '4') &&
- !mysql_real_query(mysql, "SELECT @@GLOBAL.TIME_ZONE", 25) &&
+ !mysql_real_query(mysql, STRING_WITH_LEN("SELECT @@GLOBAL.TIME_ZONE")) &&
(master_res= mysql_store_result(mysql)))
{
if ((master_row= mysql_fetch_row(master_res)) &&
diff --git a/sql/sp.cc b/sql/sp.cc
index 1722f2b8ac1..01b16354c39 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -29,6 +29,11 @@ create_string(THD *thd, String *buf,
const char *returns, ulong returnslen,
const char *body, ulong bodylen,
st_sp_chistics *chistics);
+static int
+db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
+ ulong sql_mode, const char *params, const char *returns,
+ const char *body, st_sp_chistics &chistics,
+ const char *definer, longlong created, longlong modified);
/*
*
@@ -377,83 +382,80 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
close_proc_table(thd, &open_tables_state_backup);
table= 0;
- {
- String defstr;
- LEX *oldlex= thd->lex;
- char olddb[128];
- bool dbchanged;
- enum enum_sql_command oldcmd= thd->lex->sql_command;
- ulong old_sql_mode= thd->variables.sql_mode;
- ha_rows select_limit= thd->variables.select_limit;
-
- thd->variables.sql_mode= sql_mode;
- thd->variables.select_limit= HA_POS_ERROR;
-
- defstr.set_charset(system_charset_info);
- if (!create_string(thd, &defstr,
- type,
- name,
- params, strlen(params),
- returns, strlen(returns),
- body, strlen(body),
- &chistics))
- {
- ret= SP_INTERNAL_ERROR;
- goto done;
- }
+ ret= db_load_routine(thd, type, name, sphp,
+ sql_mode, params, returns, body, chistics,
+ definer, created, modified);
+
+ done:
+ if (table)
+ close_proc_table(thd, &open_tables_state_backup);
+ DBUG_RETURN(ret);
+}
- dbchanged= FALSE;
- if ((ret= sp_use_new_db(thd, name->m_db.str, olddb, sizeof(olddb),
- 1, &dbchanged)))
- goto done;
- {
- /* This is something of a kludge. We need to initialize some fields
- * in thd->lex (the unit and master stuff), and the easiest way to
- * do it is, is to call mysql_init_query(), but this unfortunately
- * resets teh value_list where we keep the CALL parameters. So we
- * copy the list and then restore it. (... and found_semicolon too).
- */
- List<Item> tmpvals= thd->lex->value_list;
- char *tmpfsc= thd->lex->found_semicolon;
-
- lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length());
- thd->lex->value_list= tmpvals;
- thd->lex->found_semicolon= tmpfsc;
- }
+static int
+db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
+ ulong sql_mode, const char *params, const char *returns,
+ const char *body, st_sp_chistics &chistics,
+ const char *definer, longlong created, longlong modified)
+{
+ LEX *oldlex= thd->lex, newlex;
+ sp_rcontext *save_spcont= thd->spcont;
+ String defstr;
+ char olddb[128];
+ bool dbchanged;
+ ulong old_sql_mode= thd->variables.sql_mode;
+ ha_rows select_limit= thd->variables.select_limit;
+ int ret= SP_INTERNAL_ERROR;
+
+ thd->variables.sql_mode= sql_mode;
+ thd->variables.select_limit= HA_POS_ERROR;
+
+ thd->lex= &newlex;
+ newlex.current_select= NULL;
+
+ defstr.set_charset(system_charset_info);
+ if (!create_string(thd, &defstr,
+ type,
+ name,
+ params, strlen(params),
+ returns, strlen(returns),
+ body, strlen(body),
+ &chistics))
+ goto end;
- if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL)
- {
- LEX *newlex= thd->lex;
- sp_head *sp= newlex->sphead;
+ dbchanged= FALSE;
+ if ((ret= sp_use_new_db(thd, name->m_db.str, olddb, sizeof(olddb),
+ 1, &dbchanged)))
+ goto end;
- if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
- goto done;
- if (sp)
- {
- delete sp;
- newlex->sphead= NULL;
- }
- ret= SP_PARSE_ERROR;
- }
- else
- {
- if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
- goto done;
- *sphp= thd->lex->sphead;
- (*sphp)->set_definer((char*) definer, (uint) strlen(definer));
- (*sphp)->set_info(created, modified, &chistics, sql_mode);
- (*sphp)->optimize();
- }
- thd->lex->sql_command= oldcmd;
- thd->variables.sql_mode= old_sql_mode;
- thd->variables.select_limit= select_limit;
- }
+ lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length());
- done:
- if (table)
- close_proc_table(thd, &open_tables_state_backup);
- DBUG_RETURN(ret);
+ thd->spcont= 0;
+ if (yyparse(thd) || thd->is_fatal_error || newlex.sphead == NULL)
+ {
+ sp_head *sp= newlex.sphead;
+
+ if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
+ goto end;
+ delete sp;
+ ret= SP_PARSE_ERROR;
+ }
+ else
+ {
+ if (dbchanged && (ret= mysql_change_db(thd, olddb, 1)))
+ goto end;
+ *sphp= newlex.sphead;
+ (*sphp)->set_definer((char*) definer, (uint) strlen(definer));
+ (*sphp)->set_info(created, modified, &chistics, sql_mode);
+ (*sphp)->optimize();
+ }
+end:
+ thd->spcont= save_spcont;
+ thd->variables.sql_mode= old_sql_mode;
+ thd->variables.select_limit= select_limit;
+ thd->lex= oldlex;
+ return ret;
}
@@ -899,45 +901,106 @@ err:
******************************************************************************/
/*
- Obtain object representing stored procedure by its name from
+ Obtain object representing stored procedure/function by its name from
stored procedures cache and looking into mysql.proc if needed.
SYNOPSIS
- sp_find_procedure()
+ sp_find_routine()
thd - thread context
+ type - type of object (TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE)
name - name of procedure
+ cp - hash to look routine in
cache_only - if true perform cache-only lookup
(Don't look in mysql.proc).
- TODO
- We should consider merging of sp_find_procedure() and
- sp_find_function() into one sp_find_routine() function
- (the same applies to other similarly paired functions).
-
RETURN VALUE
Non-0 pointer to sp_head object for the procedure, or
0 - in case of error.
*/
sp_head *
-sp_find_procedure(THD *thd, sp_name *name, bool cache_only)
+sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp,
+ bool cache_only)
{
sp_head *sp;
- DBUG_ENTER("sp_find_procedure");
- DBUG_PRINT("enter", ("name: %.*s.%.*s",
- name->m_db.length, name->m_db.str,
- name->m_name.length, name->m_name.str));
+ ulong depth= (type == TYPE_ENUM_PROCEDURE ?
+ thd->variables.max_sp_recursion_depth :
+ 0);
+
+ DBUG_ENTER("sp_find_routine");
+ DBUG_PRINT("enter", ("name: %.*s.%.*s, type: %d, cache only %d",
+ name->m_db.length, name->m_db.str,
+ name->m_name.length, name->m_name.str,
+ type, cache_only));
- if (!(sp= sp_cache_lookup(&thd->sp_proc_cache, name)) && !cache_only)
+ if ((sp= sp_cache_lookup(cp, name)))
+ {
+ ulong level;
+ DBUG_PRINT("info", ("found: 0x%lx", (ulong)sp));
+ if (sp->m_first_free_instance)
+ {
+ DBUG_PRINT("info", ("first free: 0x%lx, level: %lu, flags %x",
+ (ulong)sp->m_first_free_instance,
+ sp->m_first_free_instance->m_recursion_level,
+ sp->m_first_free_instance->m_flags));
+ DBUG_ASSERT(!(sp->m_first_free_instance->m_flags & sp_head::IS_INVOKED));
+ if (sp->m_first_free_instance->m_recursion_level > depth)
+ {
+ sp->recursion_level_error();
+ DBUG_RETURN(0);
+ }
+ DBUG_RETURN(sp->m_first_free_instance);
+ }
+ level= sp->m_last_cached_sp->m_recursion_level + 1;
+ if (level > depth)
+ {
+ sp->recursion_level_error();
+ DBUG_RETURN(0);
+ }
+ {
+ sp_head *new_sp;
+ const char *returns= "";
+ char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
+ String retstr(64);
+ strxmov(definer, sp->m_definer_user.str, "@",
+ sp->m_definer_host.str, NullS);
+ if (type == TYPE_ENUM_FUNCTION)
+ {
+ sp_returns_type(thd, retstr, sp);
+ returns= retstr.ptr();
+ }
+ if (db_load_routine(thd, type, name, &new_sp,
+ sp->m_sql_mode, sp->m_params.str, returns,
+ sp->m_body.str, *sp->m_chistics, definer,
+ sp->m_created, sp->m_modified) == SP_OK)
+ {
+ sp->m_last_cached_sp->m_next_cached_sp= new_sp;
+ new_sp->m_recursion_level= level;
+ new_sp->m_first_instance= sp;
+ sp->m_last_cached_sp= sp->m_first_free_instance= new_sp;
+ DBUG_PRINT("info", ("added level: 0x%lx, level: %lu, flags %x",
+ (ulong)new_sp, new_sp->m_recursion_level,
+ new_sp->m_flags));
+ DBUG_RETURN(new_sp);
+ }
+ DBUG_RETURN(0);
+ }
+ }
+ if (!cache_only)
{
- if (db_find_routine(thd, TYPE_ENUM_PROCEDURE, name, &sp) == SP_OK)
- sp_cache_insert(&thd->sp_proc_cache, sp);
+ if (db_find_routine(thd, type, name, &sp) == SP_OK)
+ {
+ sp_cache_insert(cp, sp);
+ DBUG_PRINT("info", ("added new: 0x%lx, level: %lu, flags %x",
+ (ulong)sp, sp->m_recursion_level,
+ sp->m_flags));
+ }
}
-
DBUG_RETURN(sp);
}
+
int
sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error)
{
@@ -955,8 +1018,10 @@ sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error)
lex_name.str= thd->strmake(table->table_name, lex_name.length);
name= new sp_name(lex_db, lex_name);
name->init_qname(thd);
- if (sp_find_procedure(thd, name) != NULL ||
- sp_find_function(thd, name) != NULL)
+ if (sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name,
+ &thd->sp_proc_cache, FALSE) != NULL ||
+ sp_find_routine(thd, TYPE_ENUM_FUNCTION, name,
+ &thd->sp_func_cache, FALSE) != NULL)
{
if (any)
DBUG_RETURN(1);
@@ -1024,7 +1089,8 @@ sp_show_create_procedure(THD *thd, sp_name *name)
DBUG_ENTER("sp_show_create_procedure");
DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str));
- if ((sp= sp_find_procedure(thd, name)))
+ if ((sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name,
+ &thd->sp_proc_cache, FALSE)))
{
int ret= sp->show_create_procedure(thd);
@@ -1050,42 +1116,6 @@ sp_show_status_procedure(THD *thd, const char *wild)
FUNCTION
******************************************************************************/
-/*
- Obtain object representing stored function by its name from
- stored functions cache and looking into mysql.proc if needed.
-
- SYNOPSIS
- sp_find_function()
- thd - thread context
- name - name of function
- cache_only - if true perform cache-only lookup
- (Don't look in mysql.proc).
-
- NOTE
- See TODO section for sp_find_procedure().
-
- RETURN VALUE
- Non-0 pointer to sp_head object for the function, or
- 0 - in case of error.
-*/
-
-sp_head *
-sp_find_function(THD *thd, sp_name *name, bool cache_only)
-{
- sp_head *sp;
- DBUG_ENTER("sp_find_function");
- DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str));
-
- if (!(sp= sp_cache_lookup(&thd->sp_func_cache, name)) &&
- !cache_only)
- {
- if (db_find_routine(thd, TYPE_ENUM_FUNCTION, name, &sp) == SP_OK)
- sp_cache_insert(&thd->sp_func_cache, sp);
- }
- DBUG_RETURN(sp);
-}
-
-
int
sp_create_function(THD *thd, sp_head *sp)
{
@@ -1133,7 +1163,8 @@ sp_show_create_function(THD *thd, sp_name *name)
DBUG_ENTER("sp_show_create_function");
DBUG_PRINT("enter", ("name: %.*s", name->m_name.length, name->m_name.str));
- if ((sp= sp_find_function(thd, name)))
+ if ((sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, name,
+ &thd->sp_func_cache, FALSE)))
{
int ret= sp->show_create_function(thd);
@@ -1443,10 +1474,6 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
&thd->sp_func_cache : &thd->sp_proc_cache),
&name)))
{
- LEX *oldlex= thd->lex;
- LEX *newlex= new st_lex;
- thd->lex= newlex;
- newlex->current_select= NULL;
name.m_name.str= strchr(name.m_qname.str, '.');
name.m_db.length= name.m_name.str - name.m_qname.str;
name.m_db.str= strmake_root(thd->mem_root, name.m_qname.str,
@@ -1461,8 +1488,6 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
else
sp_cache_insert(&thd->sp_proc_cache, sp);
}
- delete newlex;
- thd->lex= oldlex;
}
if (sp)
{
@@ -1585,30 +1610,30 @@ create_string(THD *thd, String *buf,
chistics->comment.length))
return FALSE;
- buf->append("CREATE ", 7);
+ buf->append(STRING_WITH_LEN("CREATE "));
if (type == TYPE_ENUM_FUNCTION)
- buf->append("FUNCTION ", 9);
+ buf->append(STRING_WITH_LEN("FUNCTION "));
else
- buf->append("PROCEDURE ", 10);
+ buf->append(STRING_WITH_LEN("PROCEDURE "));
append_identifier(thd, buf, name->m_name.str, name->m_name.length);
buf->append('(');
buf->append(params, paramslen);
buf->append(')');
if (type == TYPE_ENUM_FUNCTION)
{
- buf->append(" RETURNS ", 9);
+ buf->append(STRING_WITH_LEN(" RETURNS "));
buf->append(returns, returnslen);
}
buf->append('\n');
switch (chistics->daccess) {
case SP_NO_SQL:
- buf->append(" NO SQL\n");
+ buf->append(STRING_WITH_LEN(" NO SQL\n"));
break;
case SP_READS_SQL_DATA:
- buf->append(" READS SQL DATA\n");
+ buf->append(STRING_WITH_LEN(" READS SQL DATA\n"));
break;
case SP_MODIFIES_SQL_DATA:
- buf->append(" MODIFIES SQL DATA\n");
+ buf->append(STRING_WITH_LEN(" MODIFIES SQL DATA\n"));
break;
case SP_DEFAULT_ACCESS:
case SP_CONTAINS_SQL:
@@ -1616,12 +1641,12 @@ create_string(THD *thd, String *buf,
break;
}
if (chistics->detistic)
- buf->append(" DETERMINISTIC\n", 18);
+ buf->append(STRING_WITH_LEN(" DETERMINISTIC\n"));
if (chistics->suid == SP_IS_NOT_SUID)
- buf->append(" SQL SECURITY INVOKER\n", 25);
+ buf->append(STRING_WITH_LEN(" SQL SECURITY INVOKER\n"));
if (chistics->comment.length)
{
- buf->append(" COMMENT ");
+ buf->append(STRING_WITH_LEN(" COMMENT "));
append_unescaped(buf, chistics->comment.str, chistics->comment.length);
buf->append('\n');
}
diff --git a/sql/sp.h b/sql/sp.h
index 933e5793e4c..7f314b8903e 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -36,7 +36,8 @@ int
sp_drop_db_routines(THD *thd, char *db);
sp_head *
-sp_find_procedure(THD *thd, sp_name *name, bool cache_only = 0);
+sp_find_routine(THD *thd, int type, sp_name *name,
+ sp_cache **cp, bool cache_only);
int
sp_exists_routine(THD *thd, TABLE_LIST *procs, bool any, bool no_error);
@@ -57,9 +58,6 @@ sp_show_create_procedure(THD *thd, sp_name *name);
int
sp_show_status_procedure(THD *thd, const char *wild);
-sp_head *
-sp_find_function(THD *thd, sp_name *name, bool cache_only = 0);
-
int
sp_create_function(THD *thd, sp_head *sp);
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index c76ed813bc6..ab564cef7c1 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -105,6 +105,8 @@ sp_get_flags_for_command(LEX *lex)
case SQLCOM_SHOW_TABLES:
case SQLCOM_SHOW_VARIABLES:
case SQLCOM_SHOW_WARNS:
+ case SQLCOM_SHOW_PROC_CODE:
+ case SQLCOM_SHOW_FUNC_CODE:
flags= sp_head::MULTI_RESULTS;
break;
/*
@@ -476,7 +478,8 @@ sp_head::operator delete(void *ptr, size_t size)
sp_head::sp_head()
:Query_arena(&main_mem_root, INITIALIZED_FOR_SP),
- m_flags(0), m_returns_cs(NULL)
+ m_flags(0), m_returns_cs(NULL), m_recursion_level(0), m_next_cached_sp(0),
+ m_first_instance(this), m_first_free_instance(this), m_last_cached_sp(this)
{
extern byte *
sp_table_key(const byte *ptr, uint *plen, my_bool first);
@@ -657,6 +660,7 @@ sp_head::create(THD *thd)
sp_head::~sp_head()
{
destroy();
+ delete m_next_cached_sp;
if (m_thd)
restore_thd_mem_root(m_thd);
}
@@ -858,9 +862,9 @@ static bool subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str)
prev_pos= (*splocal)->pos_in_query + (*splocal)->m_name.length;
/* append the spvar substitute */
- res|= qbuf.append(" NAME_CONST('");
+ res|= qbuf.append(STRING_WITH_LEN(" NAME_CONST('"));
res|= qbuf.append((*splocal)->m_name.str, (*splocal)->m_name.length);
- res|= qbuf.append("',");
+ res|= qbuf.append(STRING_WITH_LEN("',"));
val= (*splocal)->this_item();
DBUG_PRINT("info", ("print %p", val));
val->print(&qbuf);
@@ -883,6 +887,31 @@ static bool subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str)
/*
+ Return appropriate error about recursion limit reaching
+
+ SYNOPSIS
+ sp_head::recursion_level_error()
+
+ NOTE
+ For functions and triggers we return error about prohibited recursion.
+ For stored procedures we return about reaching recursion limit.
+*/
+
+void sp_head::recursion_level_error()
+{
+ if (m_type == TYPE_ENUM_PROCEDURE)
+ {
+ THD *thd= current_thd;
+ my_error(ER_SP_RECURSION_LIMIT, MYF(0),
+ thd->variables.max_sp_recursion_depth,
+ m_name);
+ }
+ else
+ my_error(ER_SP_NO_RECURSION, MYF(0));
+}
+
+
+/*
Execute the routine. The main instruction jump loop is there
Assume the parameters already set.
@@ -911,37 +940,31 @@ int sp_head::execute(THD *thd)
Item_change_list old_change_list;
String old_packet;
- /* init per-instruction memroot */
- init_alloc_root(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
-
-
/* Use some extra margin for possible SP recursion and functions */
- if (check_stack_overrun(thd, 4*STACK_MIN_SIZE, olddb))
+ if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (char*)&old_packet))
{
DBUG_RETURN(-1);
}
- if (m_flags & IS_INVOKED)
- {
- /*
- We have to disable recursion for stored routines since in
- many cases LEX structure and many Item's can't be used in
- reentrant way now.
-
- TODO: We can circumvent this problem by using separate
- sp_head instances for each recursive invocation.
-
- NOTE: Theoretically arguments of procedure can be evaluated
- before its invocation so there should be no problem with
- recursion. But since we perform cleanup for CALL statement
- as for any other statement only after its execution, its LEX
- structure is not reusable for recursive calls. Thus we have
- to prohibit recursion for stored procedures too.
- */
- my_error(ER_SP_NO_RECURSION, MYF(0));
- DBUG_RETURN(-1);
- }
+ /* init per-instruction memroot */
+ init_alloc_root(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
+
+ DBUG_ASSERT(!(m_flags & IS_INVOKED));
m_flags|= IS_INVOKED;
+ m_first_instance->m_first_free_instance= m_next_cached_sp;
+ DBUG_PRINT("info", ("first free for 0x%lx ++: 0x%lx->0x%lx, level: %lu, flags %x",
+ (ulong)m_first_instance, this, m_next_cached_sp,
+ m_next_cached_sp->m_recursion_level,
+ m_next_cached_sp->m_flags));
+ /*
+ Check that if there are not any instances after this one then
+ pointer to the last instance points on this instance or if there are
+ some instances after this one then recursion level of next instance
+ greater then recursion level of current instance on 1
+ */
+ DBUG_ASSERT((m_next_cached_sp == 0 &&
+ m_first_instance->m_last_cached_sp == this) ||
+ (m_recursion_level + 1 == m_next_cached_sp->m_recursion_level));
dbchanged= FALSE;
if (m_db.length &&
@@ -1116,6 +1139,29 @@ int sp_head::execute(THD *thd)
ret= mysql_change_db(thd, olddb, 1);
}
m_flags&= ~IS_INVOKED;
+ DBUG_PRINT("info", ("first free for 0x%lx --: 0x%lx->0x%lx, level: %lu, flags %x",
+ (ulong)m_first_instance,
+ m_first_instance->m_first_free_instance, this,
+ m_recursion_level, m_flags));
+ /*
+ Check that we have one of following:
+
+ 1) there are not free instances which means that this instance is last
+ in the list of instances (pointer to the last instance point on it and
+ ther are not other instances after this one in the list)
+
+ 2) There are some free instances which mean that first free instance
+ should go just after this one and recursion level of that free instance
+ should be on 1 more then recursion leven of this instance.
+ */
+ DBUG_ASSERT((m_first_instance->m_first_free_instance == 0 &&
+ this == m_first_instance->m_last_cached_sp &&
+ m_next_cached_sp == 0) ||
+ (m_first_instance->m_first_free_instance != 0 &&
+ m_first_instance->m_first_free_instance == m_next_cached_sp &&
+ m_first_instance->m_first_free_instance->m_recursion_level ==
+ m_recursion_level + 1));
+ m_first_instance->m_first_free_instance= this;
DBUG_RETURN(ret);
}
@@ -1173,6 +1219,9 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
// QQ Should have some error checking here? (types, etc...)
if (!(nctx= new sp_rcontext(octx, csize, hmax, cmax)))
goto end;
+#ifndef DBUG_OFF
+ nctx->owner= this;
+#endif
for (i= 0 ; i < argcount ; i++)
{
sp_pvar_t *pvar = m_pcont->find_pvar(i);
@@ -1215,7 +1264,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
char buf[256];
String bufstr(buf, sizeof(buf), &my_charset_bin);
bufstr.length(0);
- bufstr.append("DO ", 3);
+ bufstr.append(STRING_WITH_LEN("DO "));
append_identifier(thd, &bufstr, m_name.str, m_name.length);
bufstr.append('(');
for (uint i=0; i < argcount; i++)
@@ -1317,6 +1366,9 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args)
{ // Create a temporary old context
if (!(octx= new sp_rcontext(octx, csize, hmax, cmax)))
DBUG_RETURN(-1);
+#ifndef DBUG_OFF
+ octx->owner= 0;
+#endif
thd->spcont= octx;
/* set callers_arena to thd, for upper-level function to work */
@@ -1328,6 +1380,9 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args)
thd->spcont= save_spcont;
DBUG_RETURN(-1);
}
+#ifndef DBUG_OFF
+ nctx->owner= this;
+#endif
if (csize > 0 || hmax > 0 || cmax > 0)
{
@@ -1740,7 +1795,7 @@ sp_head::show_create_procedure(THD *thd)
LINT_INIT(sql_mode_len);
if (check_show_routine_access(thd, this, &full_access))
- return 1;
+ DBUG_RETURN(1);
sql_mode_str=
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
@@ -1753,10 +1808,7 @@ sp_head::show_create_procedure(THD *thd)
max(buffer.length(), 1024)));
if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
Protocol::SEND_EOF))
- {
- res= 1;
- goto done;
- }
+ DBUG_RETURN(1);
protocol->prepare_for_resend();
protocol->store(m_name.str, m_name.length, system_charset_info);
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
@@ -1765,7 +1817,6 @@ sp_head::show_create_procedure(THD *thd)
res= protocol->write();
send_eof(thd);
- done:
DBUG_RETURN(res);
}
@@ -1810,7 +1861,7 @@ sp_head::show_create_function(THD *thd)
LINT_INIT(sql_mode_len);
if (check_show_routine_access(thd, this, &full_access))
- return 1;
+ DBUG_RETURN(1);
sql_mode_str=
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
@@ -1822,10 +1873,7 @@ sp_head::show_create_function(THD *thd)
max(buffer.length(),1024)));
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- {
- res= 1;
- goto done;
- }
+ DBUG_RETURN(1);
protocol->prepare_for_resend();
protocol->store(m_name.str, m_name.length, system_charset_info);
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
@@ -1834,7 +1882,6 @@ sp_head::show_create_function(THD *thd)
res= protocol->write();
send_eof(thd);
- done:
DBUG_RETURN(res);
}
@@ -1894,6 +1941,50 @@ sp_head::opt_mark(uint ip)
}
+#ifndef DBUG_OFF
+int
+sp_head::show_routine_code(THD *thd)
+{
+ Protocol *protocol= thd->protocol;
+ char buff[2048];
+ String buffer(buff, sizeof(buff), system_charset_info);
+ List<Item> field_list;
+ sp_instr *i;
+ bool full_access;
+ int res= 0;
+ uint ip;
+ DBUG_ENTER("sp_head::show_routine_code");
+ DBUG_PRINT("info", ("procedure: %s", m_name.str));
+
+ if (check_show_routine_access(thd, this, &full_access) || !full_access)
+ DBUG_RETURN(1);
+
+ field_list.push_back(new Item_uint("Pos", 9));
+ // 1024 is for not to confuse old clients
+ field_list.push_back(new Item_empty_string("Instruction",
+ max(buffer.length(), 1024)));
+ if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
+ Protocol::SEND_EOF))
+ DBUG_RETURN(1);
+
+ for (ip= 0; (i = get_instr(ip)) ; ip++)
+ {
+ protocol->prepare_for_resend();
+ protocol->store((longlong)ip);
+
+ buffer.set("", 0, system_charset_info);
+ i->print(&buffer);
+ protocol->store(buffer.ptr(), buffer.length(), system_charset_info);
+ if ((res= protocol->write()))
+ break;
+ }
+ send_eof(thd);
+
+ DBUG_RETURN(res);
+}
+#endif // ifndef DBUG_OFF
+
+
/*
Prepare LEX and thread for execution of instruction, if requested open
and lock LEX's tables, execute instruction's core function, perform
@@ -2052,14 +2143,43 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
DBUG_RETURN(res);
}
+/*
+ Sufficient max length of printed destinations and frame offsets (all uints).
+*/
+#define SP_INSTR_UINT_MAXLEN 8
+
+#define SP_STMT_PRINT_MAXLEN 40
void
sp_instr_stmt::print(String *str)
{
- str->reserve(12);
- str->append("stmt ");
+ uint i, len;
+
+ /* stmt CMD "..." */
+ if (str->reserve(SP_STMT_PRINT_MAXLEN+SP_INSTR_UINT_MAXLEN+8))
+ return;
+ str->qs_append(STRING_WITH_LEN("stmt "));
str->qs_append((uint)m_lex_keeper.sql_command());
+ str->qs_append(STRING_WITH_LEN(" \""));
+ len= m_query.length;
+ /*
+ Print the query string (but not too much of it), just to indicate which
+ statement it is.
+ */
+ if (len > SP_STMT_PRINT_MAXLEN)
+ len= SP_STMT_PRINT_MAXLEN-3;
+ /* Copy the query string and replace '\n' with ' ' in the process */
+ for (i= 0 ; i < len ; i++)
+ {
+ if (m_query.str[i] == '\n')
+ str->qs_append(' ');
+ else
+ str->qs_append(m_query.str[i]);
+ }
+ if (m_query.length > SP_STMT_PRINT_MAXLEN)
+ str->qs_append(STRING_WITH_LEN("...")); /* Indicate truncated string */
+ str->qs_append('"');
}
-
+#undef SP_STMT_PRINT_MAXLEN
int
sp_instr_stmt::exec_core(THD *thd, uint *nextp)
@@ -2096,10 +2216,23 @@ sp_instr_set::exec_core(THD *thd, uint *nextp)
void
sp_instr_set::print(String *str)
{
- str->reserve(12);
- str->append("set ");
+ /* set name@offset ... */
+ int rsrv = SP_INSTR_UINT_MAXLEN+6;
+ sp_pvar_t *var = m_ctx->find_pvar(m_offset);
+
+ /* 'var' should always be non-null, but just in case... */
+ if (var)
+ rsrv+= var->name.length;
+ if (str->reserve(rsrv))
+ return;
+ str->qs_append(STRING_WITH_LEN("set "));
+ if (var)
+ {
+ str->qs_append(var->name.str, var->name.length);
+ str->qs_append('@');
+ }
str->qs_append(m_offset);
- str->append(' ');
+ str->qs_append(' ');
m_value->print(str);
}
@@ -2132,9 +2265,9 @@ sp_instr_set_trigger_field::exec_core(THD *thd, uint *nextp)
void
sp_instr_set_trigger_field::print(String *str)
{
- str->append("set ", 4);
+ str->append(STRING_WITH_LEN("set_trigger_field "));
trigger_field->print(str);
- str->append(":=", 2);
+ str->append(STRING_WITH_LEN(":="));
value->print(str);
}
@@ -2156,8 +2289,10 @@ sp_instr_jump::execute(THD *thd, uint *nextp)
void
sp_instr_jump::print(String *str)
{
- str->reserve(12);
- str->append("jump ");
+ /* jump dest */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN+5))
+ return;
+ str->qs_append(STRING_WITH_LEN("jump "));
str->qs_append(m_dest);
}
@@ -2238,10 +2373,12 @@ sp_instr_jump_if::exec_core(THD *thd, uint *nextp)
void
sp_instr_jump_if::print(String *str)
{
- str->reserve(12);
- str->append("jump_if ");
+ /* jump_if dest ... */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN+8+32)) // Add some for the expr. too
+ return;
+ str->qs_append(STRING_WITH_LEN("jump_if "));
str->qs_append(m_dest);
- str->append(' ');
+ str->qs_append(' ');
m_expr->print(str);
}
@@ -2299,10 +2436,12 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp)
void
sp_instr_jump_if_not::print(String *str)
{
- str->reserve(16);
- str->append("jump_if_not ");
+ /* jump_if_not dest ... */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN+12+32)) // Add some for the expr. too
+ return;
+ str->qs_append(STRING_WITH_LEN("jump_if_not "));
str->qs_append(m_dest);
- str->append(' ');
+ str->qs_append(' ');
m_expr->print(str);
}
@@ -2357,10 +2496,12 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp)
void
sp_instr_freturn::print(String *str)
{
- str->reserve(12);
- str->append("freturn ");
+ /* freturn type expr... */
+ if (str->reserve(UINT_MAX+8+32)) // Add some for the expr. too
+ return;
+ str->qs_append(STRING_WITH_LEN("freturn "));
str->qs_append((uint)m_type);
- str->append(' ');
+ str->qs_append(' ');
m_value->print(str);
}
@@ -2385,15 +2526,31 @@ sp_instr_hpush_jump::execute(THD *thd, uint *nextp)
void
sp_instr_hpush_jump::print(String *str)
{
- str->reserve(32);
- str->append("hpush_jump ");
+ /* hpush_jump dest fsize type */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN*2 + 21))
+ return;
+ str->qs_append(STRING_WITH_LEN("hpush_jump "));
str->qs_append(m_dest);
- str->append(" t=");
- str->qs_append(m_type);
- str->append(" f=");
+ str->qs_append(' ');
str->qs_append(m_frame);
- str->append(" h=");
- str->qs_append(m_ip+1);
+ switch (m_type)
+ {
+ case SP_HANDLER_NONE:
+ str->qs_append(STRING_WITH_LEN(" NONE")); // This would be a bug
+ break;
+ case SP_HANDLER_EXIT:
+ str->qs_append(STRING_WITH_LEN(" EXIT"));
+ break;
+ case SP_HANDLER_CONTINUE:
+ str->qs_append(STRING_WITH_LEN(" CONTINUE"));
+ break;
+ case SP_HANDLER_UNDO:
+ str->qs_append(STRING_WITH_LEN(" UNDO"));
+ break;
+ default:
+ str->qs_append(STRING_WITH_LEN(" UNKNOWN:")); // This would be a bug as well
+ str->qs_append(m_type);
+ }
}
uint
@@ -2428,8 +2585,10 @@ sp_instr_hpop::execute(THD *thd, uint *nextp)
void
sp_instr_hpop::print(String *str)
{
- str->reserve(12);
- str->append("hpop ");
+ /* hpop count */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN+5))
+ return;
+ str->qs_append(STRING_WITH_LEN("hpop "));
str->qs_append(m_count);
}
@@ -2463,12 +2622,14 @@ sp_instr_hreturn::execute(THD *thd, uint *nextp)
void
sp_instr_hreturn::print(String *str)
{
- str->reserve(16);
- str->append("hreturn ");
+ /* hreturn framesize dest */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN*2 + 9))
+ return;
+ str->qs_append(STRING_WITH_LEN("hreturn "));
str->qs_append(m_frame);
if (m_dest)
{
- str->append(' ');
+ str->qs_append(' ');
str->qs_append(m_dest);
}
}
@@ -2516,7 +2677,22 @@ sp_instr_cpush::execute(THD *thd, uint *nextp)
void
sp_instr_cpush::print(String *str)
{
- str->append("cpush");
+ LEX_STRING n;
+ my_bool found= m_ctx->find_cursor(m_cursor, &n);
+ /* cpush name@offset */
+ uint rsrv= SP_INSTR_UINT_MAXLEN+7;
+
+ if (found)
+ rsrv+= n.length;
+ if (str->reserve(rsrv))
+ return;
+ str->qs_append(STRING_WITH_LEN("cpush "));
+ if (found)
+ {
+ str->qs_append(n.str, n.length);
+ str->qs_append('@');
+ }
+ str->qs_append(m_cursor);
}
@@ -2537,8 +2713,10 @@ sp_instr_cpop::execute(THD *thd, uint *nextp)
void
sp_instr_cpop::print(String *str)
{
- str->reserve(12);
- str->append("cpop ");
+ /* cpop count */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN+5))
+ return;
+ str->qs_append(STRING_WITH_LEN("cpop "));
str->qs_append(m_count);
}
@@ -2612,8 +2790,21 @@ sp_instr_copen::exec_core(THD *thd, uint *nextp)
void
sp_instr_copen::print(String *str)
{
- str->reserve(12);
- str->append("copen ");
+ LEX_STRING n;
+ my_bool found= m_ctx->find_cursor(m_cursor, &n);
+ /* copen name@offset */
+ uint rsrv= SP_INSTR_UINT_MAXLEN+7;
+
+ if (found)
+ rsrv+= n.length;
+ if (str->reserve(rsrv))
+ return;
+ str->qs_append(STRING_WITH_LEN("copen "));
+ if (found)
+ {
+ str->qs_append(n.str, n.length);
+ str->qs_append('@');
+ }
str->qs_append(m_cursor);
}
@@ -2641,8 +2832,21 @@ sp_instr_cclose::execute(THD *thd, uint *nextp)
void
sp_instr_cclose::print(String *str)
{
- str->reserve(12);
- str->append("cclose ");
+ LEX_STRING n;
+ my_bool found= m_ctx->find_cursor(m_cursor, &n);
+ /* cclose name@offset */
+ uint rsrv= SP_INSTR_UINT_MAXLEN+8;
+
+ if (found)
+ rsrv+= n.length;
+ if (str->reserve(rsrv))
+ return;
+ str->qs_append(STRING_WITH_LEN("cclose "));
+ if (found)
+ {
+ str->qs_append(n.str, n.length);
+ str->qs_append('@');
+ }
str->qs_append(m_cursor);
}
@@ -2671,14 +2875,29 @@ sp_instr_cfetch::print(String *str)
{
List_iterator_fast<struct sp_pvar> li(m_varlist);
sp_pvar_t *pv;
-
- str->reserve(12);
- str->append("cfetch ");
+ LEX_STRING n;
+ my_bool found= m_ctx->find_cursor(m_cursor, &n);
+ /* cfetch name@offset vars... */
+ uint rsrv= SP_INSTR_UINT_MAXLEN+8;
+
+ if (found)
+ rsrv+= n.length;
+ if (str->reserve(rsrv))
+ return;
+ str->qs_append(STRING_WITH_LEN("cfetch "));
+ if (found)
+ {
+ str->qs_append(n.str, n.length);
+ str->qs_append('@');
+ }
str->qs_append(m_cursor);
while ((pv= li++))
{
- str->reserve(8);
- str->append(' ');
+ if (str->reserve(pv->name.length+SP_INSTR_UINT_MAXLEN+2))
+ return;
+ str->qs_append(' ');
+ str->qs_append(pv->name.str, pv->name.length);
+ str->qs_append('@');
str->qs_append(pv->offset);
}
}
@@ -2702,8 +2921,10 @@ sp_instr_error::execute(THD *thd, uint *nextp)
void
sp_instr_error::print(String *str)
{
- str->reserve(12);
- str->append("error ");
+ /* error code */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN+6))
+ return;
+ str->qs_append(STRING_WITH_LEN("error "));
str->qs_append(m_errcode);
}
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 8c2d58a696e..6334bca0fc6 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -143,6 +143,32 @@ public:
LEX_STRING m_definer_host;
longlong m_created;
longlong m_modified;
+ /* Recursion level of the current SP instance. The levels are numbered from 0 */
+ ulong m_recursion_level;
+ /*
+ A list of diferent recursion level instances for the same procedure.
+ For every recursion level we have a sp_head instance. This instances
+ connected in the list. The list ordered by increasing recursion level
+ (m_recursion_level).
+ */
+ sp_head *m_next_cached_sp;
+ /*
+ Pointer to the first element of the above list
+ */
+ sp_head *m_first_instance;
+ /*
+ Pointer to the first free (non-INVOKED) routine in the list of
+ cached instances for this SP. This pointer is set only for the first
+ SP in the list of instences (see above m_first_cached_sp pointer).
+ The pointer equal to 0 if we have no free instances.
+ For non-first instance value of this pointer meanless (point to itself);
+ */
+ sp_head *m_first_free_instance;
+ /*
+ Pointer to the last element in the list of instances of the SP.
+ For non-first instance value of this pointer meanless (point to itself);
+ */
+ sp_head *m_last_cached_sp;
/*
Set containing names of stored routines used by this routine.
Note that unlike elements of similar set for statement elements of this
@@ -266,6 +292,8 @@ public:
void optimize();
void opt_mark(uint ip);
+ void recursion_level_error();
+
inline sp_instr *
get_instr(uint i)
{
@@ -304,6 +332,12 @@ public:
return test(m_flags &
(CONTAINS_DYNAMIC_SQL|MULTI_RESULTS|HAS_SET_AUTOCOMMIT_STMT));
}
+
+#ifndef DBUG_OFF
+ int show_routine_code(THD *thd);
+#endif
+
+
private:
MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root
@@ -865,8 +899,8 @@ class sp_instr_cpush : public sp_instr
public:
- sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex)
- : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE)
+ sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex, uint offset)
+ : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE), m_cursor(offset)
{}
virtual ~sp_instr_cpush()
@@ -885,6 +919,7 @@ public:
private:
sp_lex_keeper m_lex_keeper;
+ uint m_cursor; /* Frame offset (for debugging) */
}; // class sp_instr_cpush : public sp_instr
diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc
index f873b676925..147173ab4d8 100644
--- a/sql/sp_pcontext.cc
+++ b/sql/sp_pcontext.cc
@@ -169,6 +169,28 @@ sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
return NULL;
}
+/*
+ Find a variable by offset from the top.
+ This used for two things:
+ - When evaluating parameters at the beginning, and setting out parameters
+ at the end, of invokation. (Top frame only, so no recursion then.)
+ - For printing of sp_instr_set. (Debug mode only.)
+ */
+sp_pvar_t *
+sp_pcontext::find_pvar(uint offset)
+{
+ if (m_poffset <= offset && offset < m_poffset + m_pvar.elements)
+ { // This frame
+ sp_pvar_t *p;
+
+ get_dynamic(&m_pvar, (gptr)&p, offset - m_poffset);
+ return p;
+ }
+ if (m_parent)
+ return m_parent->find_pvar(offset); // Some previous frame
+ return NULL; // index out of bounds
+}
+
void
sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
sp_param_mode_t mode)
@@ -331,3 +353,21 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
return m_parent->find_cursor(name, poff, scoped);
return FALSE;
}
+
+/*
+ Find a cursor by offset from the top.
+ This is only used for debugging.
+ */
+my_bool
+sp_pcontext::find_cursor(uint offset, LEX_STRING *n)
+{
+ if (m_coffset <= offset && offset < m_coffset + m_cursor.elements)
+ { // This frame
+ get_dynamic(&m_cursor, (gptr)n, offset - m_coffset);
+ return TRUE;
+ }
+ if (m_parent)
+ return m_parent->find_cursor(offset, n); // Some previous frame
+ return FALSE; // index out of bounds
+}
+
diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h
index bd2259cb6fb..b8dd1742f7e 100644
--- a/sql/sp_pcontext.h
+++ b/sql/sp_pcontext.h
@@ -170,18 +170,9 @@ class sp_pcontext : public Sql_alloc
sp_pvar_t *
find_pvar(LEX_STRING *name, my_bool scoped=0);
- // Find by index
+ // Find by offset
sp_pvar_t *
- find_pvar(uint i)
- {
- sp_pvar_t *p;
-
- if (i < m_pvar.elements)
- get_dynamic(&m_pvar, (gptr)&p, i);
- else
- p= NULL;
- return p;
- }
+ find_pvar(uint offset);
//
// Labels
@@ -261,6 +252,10 @@ class sp_pcontext : public Sql_alloc
my_bool
find_cursor(LEX_STRING *name, uint *poff, my_bool scoped=0);
+ /* Find by offset (for debugging only) */
+ my_bool
+ find_cursor(uint offset, LEX_STRING *n);
+
inline uint
max_cursors()
{
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index cae5c5467c9..d54188aa96f 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -66,6 +66,14 @@ class sp_rcontext : public Sql_alloc
*/
Query_arena *callers_arena;
+#ifndef DBUG_OFF
+ /*
+ Routine to which this Item_splocal belongs. Used for checking if correct
+ runtime context is used for variable handling.
+ */
+ sp_head *owner;
+#endif
+
sp_rcontext(sp_rcontext *prev, uint fsize, uint hmax, uint cmax);
~sp_rcontext()
diff --git a/sql/spatial.cc b/sql/spatial.cc
index ca9615236e0..e91653f79d5 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -1793,7 +1793,7 @@ bool Gis_geometry_collection::get_data_as_wkt(String *txt,
geom->set_data_ptr(data, (uint) (m_data_end - data));
if (geom->as_wkt(txt, &data))
return 1;
- if (txt->append(",", 1, 512))
+ if (txt->append(STRING_WITH_LEN(","), 512))
return 1;
}
txt->length(txt->length() - 1);
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index a84889858db..cb46682470f 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1810,19 +1810,22 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
/* We write down SSL related ACL stuff */
switch (lex->ssl_type) {
case SSL_TYPE_ANY:
- table->field[next_field]->store("ANY", 3, &my_charset_latin1);
+ table->field[next_field]->store(STRING_WITH_LEN("ANY"),
+ &my_charset_latin1);
table->field[next_field+1]->store("", 0, &my_charset_latin1);
table->field[next_field+2]->store("", 0, &my_charset_latin1);
table->field[next_field+3]->store("", 0, &my_charset_latin1);
break;
case SSL_TYPE_X509:
- table->field[next_field]->store("X509", 4, &my_charset_latin1);
+ table->field[next_field]->store(STRING_WITH_LEN("X509"),
+ &my_charset_latin1);
table->field[next_field+1]->store("", 0, &my_charset_latin1);
table->field[next_field+2]->store("", 0, &my_charset_latin1);
table->field[next_field+3]->store("", 0, &my_charset_latin1);
break;
case SSL_TYPE_SPECIFIED:
- table->field[next_field]->store("SPECIFIED", 9, &my_charset_latin1);
+ table->field[next_field]->store(STRING_WITH_LEN("SPECIFIED"),
+ &my_charset_latin1);
table->field[next_field+1]->store("", 0, &my_charset_latin1);
table->field[next_field+2]->store("", 0, &my_charset_latin1);
table->field[next_field+3]->store("", 0, &my_charset_latin1);
@@ -4056,13 +4059,13 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
{
String global(buff,sizeof(buff),system_charset_info);
global.length(0);
- global.append("GRANT ",6);
+ global.append(STRING_WITH_LEN("GRANT "));
want_access= acl_user->access;
if (test_all_bits(want_access, (GLOBAL_ACLS & ~ GRANT_ACL)))
- global.append("ALL PRIVILEGES",14);
+ global.append(STRING_WITH_LEN("ALL PRIVILEGES"));
else if (!(want_access & ~GRANT_ACL))
- global.append("USAGE",5);
+ global.append(STRING_WITH_LEN("USAGE"));
else
{
bool found=0;
@@ -4072,16 +4075,16 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (test_access & j)
{
if (found)
- global.append(", ",2);
+ global.append(STRING_WITH_LEN(", "));
found=1;
global.append(command_array[counter],command_lengths[counter]);
}
}
}
- global.append (" ON *.* TO '",12);
+ global.append (STRING_WITH_LEN(" ON *.* TO '"));
global.append(lex_user->user.str, lex_user->user.length,
system_charset_info);
- global.append ("'@'",3);
+ global.append (STRING_WITH_LEN("'@'"));
global.append(lex_user->host.str,lex_user->host.length,
system_charset_info);
global.append ('\'');
@@ -4092,23 +4095,23 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
make_password_from_salt(passwd_buff, acl_user->salt);
else
make_password_from_salt_323(passwd_buff, (ulong *) acl_user->salt);
- global.append(" IDENTIFIED BY PASSWORD '",25);
+ global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '"));
global.append(passwd_buff);
global.append('\'');
}
/* "show grants" SSL related stuff */
if (acl_user->ssl_type == SSL_TYPE_ANY)
- global.append(" REQUIRE SSL",12);
+ global.append(STRING_WITH_LEN(" REQUIRE SSL"));
else if (acl_user->ssl_type == SSL_TYPE_X509)
- global.append(" REQUIRE X509",13);
+ global.append(STRING_WITH_LEN(" REQUIRE X509"));
else if (acl_user->ssl_type == SSL_TYPE_SPECIFIED)
{
int ssl_options = 0;
- global.append(" REQUIRE ",9);
+ global.append(STRING_WITH_LEN(" REQUIRE "));
if (acl_user->x509_issuer)
{
ssl_options++;
- global.append("ISSUER \'",8);
+ global.append(STRING_WITH_LEN("ISSUER \'"));
global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer));
global.append('\'');
}
@@ -4116,7 +4119,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
{
if (ssl_options++)
global.append(' ');
- global.append("SUBJECT \'",9);
+ global.append(STRING_WITH_LEN("SUBJECT \'"));
global.append(acl_user->x509_subject,strlen(acl_user->x509_subject),
system_charset_info);
global.append('\'');
@@ -4125,7 +4128,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
{
if (ssl_options++)
global.append(' ');
- global.append("CIPHER '",8);
+ global.append(STRING_WITH_LEN("CIPHER '"));
global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher),
system_charset_info);
global.append('\'');
@@ -4137,9 +4140,9 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
acl_user->user_resource.conn_per_hour ||
acl_user->user_resource.user_conn))
{
- global.append(" WITH",5);
+ global.append(STRING_WITH_LEN(" WITH"));
if (want_access & GRANT_ACL)
- global.append(" GRANT OPTION",13);
+ global.append(STRING_WITH_LEN(" GRANT OPTION"));
add_user_option(&global, acl_user->user_resource.questions,
"MAX_QUERIES_PER_HOUR");
add_user_option(&global, acl_user->user_resource.updates,
@@ -4177,12 +4180,12 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
{
String db(buff,sizeof(buff),system_charset_info);
db.length(0);
- db.append("GRANT ",6);
+ db.append(STRING_WITH_LEN("GRANT "));
if (test_all_bits(want_access,(DB_ACLS & ~GRANT_ACL)))
- db.append("ALL PRIVILEGES",14);
+ db.append(STRING_WITH_LEN("ALL PRIVILEGES"));
else if (!(want_access & ~GRANT_ACL))
- db.append("USAGE",5);
+ db.append(STRING_WITH_LEN("USAGE"));
else
{
int found=0, cnt;
@@ -4192,23 +4195,23 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (test_access & j)
{
if (found)
- db.append(", ",2);
+ db.append(STRING_WITH_LEN(", "));
found = 1;
db.append(command_array[cnt],command_lengths[cnt]);
}
}
}
- db.append (" ON ",4);
+ db.append (STRING_WITH_LEN(" ON "));
append_identifier(thd, &db, acl_db->db, strlen(acl_db->db));
- db.append (".* TO '",7);
+ db.append (STRING_WITH_LEN(".* TO '"));
db.append(lex_user->user.str, lex_user->user.length,
system_charset_info);
- db.append ("'@'",3);
+ db.append (STRING_WITH_LEN("'@'"));
db.append(lex_user->host.str, lex_user->host.length,
system_charset_info);
db.append ('\'');
if (want_access & GRANT_ACL)
- db.append(" WITH GRANT OPTION",18);
+ db.append(STRING_WITH_LEN(" WITH GRANT OPTION"));
protocol->prepare_for_resend();
protocol->store(db.ptr(),db.length(),db.charset());
if (protocol->write())
@@ -4241,12 +4244,12 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
ulong test_access= (table_access | grant_table->cols) & ~GRANT_ACL;
global.length(0);
- global.append("GRANT ",6);
+ global.append(STRING_WITH_LEN("GRANT "));
if (test_all_bits(table_access, (TABLE_ACLS & ~GRANT_ACL)))
- global.append("ALL PRIVILEGES",14);
+ global.append(STRING_WITH_LEN("ALL PRIVILEGES"));
else if (!test_access)
- global.append("USAGE",5);
+ global.append(STRING_WITH_LEN("USAGE"));
else
{
/* Add specific column access */
@@ -4258,7 +4261,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (test_access & j)
{
if (found)
- global.append(", ",2);
+ global.append(STRING_WITH_LEN(", "));
found= 1;
global.append(command_array[counter],command_lengths[counter]);
@@ -4282,14 +4285,14 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
*/
if (table_access & j)
{
- global.append(", ", 2);
+ global.append(STRING_WITH_LEN(", "));
global.append(command_array[counter],
command_lengths[counter]);
}
- global.append(" (",2);
+ global.append(STRING_WITH_LEN(" ("));
}
else
- global.append(", ",2);
+ global.append(STRING_WITH_LEN(", "));
global.append(grant_column->column,
grant_column->key_length,
system_charset_info);
@@ -4301,21 +4304,21 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
}
}
- global.append(" ON ",4);
+ global.append(STRING_WITH_LEN(" ON "));
append_identifier(thd, &global, grant_table->db,
strlen(grant_table->db));
global.append('.');
append_identifier(thd, &global, grant_table->tname,
strlen(grant_table->tname));
- global.append(" TO '",5);
+ global.append(STRING_WITH_LEN(" TO '"));
global.append(lex_user->user.str, lex_user->user.length,
system_charset_info);
- global.append("'@'",3);
+ global.append(STRING_WITH_LEN("'@'"));
global.append(lex_user->host.str,lex_user->host.length,
system_charset_info);
global.append('\'');
if (table_access & GRANT_ACL)
- global.append(" WITH GRANT OPTION",18);
+ global.append(STRING_WITH_LEN(" WITH GRANT OPTION"));
protocol->prepare_for_resend();
protocol->store(global.ptr(),global.length(),global.charset());
if (protocol->write())
@@ -4328,14 +4331,14 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
if (show_routine_grants(thd, lex_user, &proc_priv_hash,
- "PROCEDURE", 9, buff, sizeof(buff)))
+ STRING_WITH_LEN("PROCEDURE"), buff, sizeof(buff)))
{
error= -1;
goto end;
}
if (show_routine_grants(thd, lex_user, &func_priv_hash,
- "FUNCTION", 8, buff, sizeof(buff)))
+ STRING_WITH_LEN("FUNCTION"), buff, sizeof(buff)))
{
error= -1;
goto end;
@@ -4376,10 +4379,10 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash,
ulong test_access= proc_access & ~GRANT_ACL;
global.length(0);
- global.append("GRANT ",6);
+ global.append(STRING_WITH_LEN("GRANT "));
if (!test_access)
- global.append("USAGE",5);
+ global.append(STRING_WITH_LEN("USAGE"));
else
{
/* Add specific procedure access */
@@ -4391,13 +4394,13 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash,
if (test_access & j)
{
if (found)
- global.append(", ",2);
+ global.append(STRING_WITH_LEN(", "));
found= 1;
global.append(command_array[counter],command_lengths[counter]);
}
}
}
- global.append(" ON ",4);
+ global.append(STRING_WITH_LEN(" ON "));
global.append(type,typelen);
global.append(' ');
append_identifier(thd, &global, grant_proc->db,
@@ -4405,15 +4408,15 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash,
global.append('.');
append_identifier(thd, &global, grant_proc->tname,
strlen(grant_proc->tname));
- global.append(" TO '",5);
+ global.append(STRING_WITH_LEN(" TO '"));
global.append(lex_user->user.str, lex_user->user.length,
system_charset_info);
- global.append("'@'",3);
+ global.append(STRING_WITH_LEN("'@'"));
global.append(lex_user->host.str,lex_user->host.length,
system_charset_info);
global.append('\'');
if (proc_access & GRANT_ACL)
- global.append(" WITH GRANT OPTION",18);
+ global.append(STRING_WITH_LEN(" WITH GRANT OPTION"));
protocol->prepare_for_resend();
protocol->store(global.ptr(),global.length(),global.charset());
if (protocol->write())
@@ -5068,7 +5071,7 @@ static void append_user(String *str, LEX_USER *user)
str->append(',');
str->append('\'');
str->append(user->user.str);
- str->append("'@'");
+ str->append(STRING_WITH_LEN("'@'"));
str->append(user->host.str);
str->append('\'');
}
@@ -5650,7 +5653,8 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
strxmov(buff,"'",user,"'@'",host,"'",NullS);
if (!(want_access & ~GRANT_ACL))
- update_schema_privilege(table, buff, 0, 0, 0, 0, "USAGE", 5, is_grantable);
+ update_schema_privilege(table, buff, 0, 0, 0, 0,
+ STRING_WITH_LEN("USAGE"), is_grantable);
else
{
uint priv_id;
@@ -5708,7 +5712,7 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
strxmov(buff,"'",user,"'@'",host,"'",NullS);
if (!(want_access & ~GRANT_ACL))
update_schema_privilege(table, buff, acl_db->db, 0, 0,
- 0, "USAGE", 5, is_grantable);
+ 0, STRING_WITH_LEN("USAGE"), is_grantable);
else
{
int cnt;
@@ -5768,7 +5772,7 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
strxmov(buff,"'",user,"'@'",grant_table->host.hostname,"'",NullS);
if (!test_access)
update_schema_privilege(table, buff, grant_table->db, grant_table->tname,
- 0, 0, "USAGE", 5, is_grantable);
+ 0, 0, STRING_WITH_LEN("USAGE"), is_grantable);
else
{
ulong j;
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index e1f4b8f6076..0e4198a5114 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -733,13 +733,13 @@ bool analyse::end_of_records()
tree_info.found = 0;
tree_info.item = (*f)->item;
- tmp_str.set("ENUM(", 5,&my_charset_bin);
+ tmp_str.set(STRING_WITH_LEN("ENUM("),&my_charset_bin);
tree_walk(&(*f)->tree, (*f)->collect_enum(), (char*) &tree_info,
left_root_right);
tmp_str.append(')');
if (!(*f)->nulls)
- tmp_str.append(" NOT NULL");
+ tmp_str.append(STRING_WITH_LEN(" NOT NULL"));
output_str_length = tmp_str.length();
func_items[9]->set(tmp_str.ptr(), tmp_str.length(), tmp_str.charset());
if (result->send_data(result_fields))
@@ -749,35 +749,35 @@ bool analyse::end_of_records()
ans.length(0);
if (!(*f)->treemem && !(*f)->tree_elements)
- ans.append("CHAR(0)", 7);
+ ans.append(STRING_WITH_LEN("CHAR(0)"));
else if ((*f)->item->type() == Item::FIELD_ITEM)
{
switch (((Item_field*) (*f)->item)->field->real_type())
{
case FIELD_TYPE_TIMESTAMP:
- ans.append("TIMESTAMP", 9);
+ ans.append(STRING_WITH_LEN("TIMESTAMP"));
break;
case FIELD_TYPE_DATETIME:
- ans.append("DATETIME", 8);
+ ans.append(STRING_WITH_LEN("DATETIME"));
break;
case FIELD_TYPE_DATE:
case FIELD_TYPE_NEWDATE:
- ans.append("DATE", 4);
+ ans.append(STRING_WITH_LEN("DATE"));
break;
case FIELD_TYPE_SET:
- ans.append("SET", 3);
+ ans.append(STRING_WITH_LEN("SET"));
break;
case FIELD_TYPE_YEAR:
- ans.append("YEAR", 4);
+ ans.append(STRING_WITH_LEN("YEAR"));
break;
case FIELD_TYPE_TIME:
- ans.append("TIME", 4);
+ ans.append(STRING_WITH_LEN("TIME"));
break;
case FIELD_TYPE_DECIMAL:
- ans.append("DECIMAL", 7);
+ ans.append(STRING_WITH_LEN("DECIMAL"));
// if item is FIELD_ITEM, it _must_be_ Field_num in this case
if (((Field_num*) ((Item_field*) (*f)->item)->field)->zerofill)
- ans.append(" ZEROFILL");
+ ans.append(STRING_WITH_LEN(" ZEROFILL"));
break;
default:
(*f)->get_opt_type(&ans, rows);
@@ -785,7 +785,7 @@ bool analyse::end_of_records()
}
}
if (!(*f)->nulls)
- ans.append(" NOT NULL");
+ ans.append(STRING_WITH_LEN(" NOT NULL"));
func_items[9]->set(ans.ptr(), ans.length(), ans.charset());
if (result->send_data(result_fields))
return -1;
@@ -829,18 +829,18 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows)
sprintf(buff, "BIGINT(%d)", num_info.integers);
answer->append(buff, (uint) strlen(buff));
if (ev_num_info.llval >= 0 && ev_num_info.min_dval >= 0)
- answer->append(" UNSIGNED");
+ answer->append(STRING_WITH_LEN(" UNSIGNED"));
if (num_info.zerofill)
- answer->append(" ZEROFILL");
+ answer->append(STRING_WITH_LEN(" ZEROFILL"));
}
else if (max_length < 256)
{
if (must_be_blob)
{
if (item->collation.collation == &my_charset_bin)
- answer->append("TINYBLOB", 8);
+ answer->append(STRING_WITH_LEN("TINYBLOB"));
else
- answer->append("TINYTEXT", 8);
+ answer->append(STRING_WITH_LEN("TINYTEXT"));
}
else if ((max_length * (total_rows - nulls)) < (sum + total_rows))
{
@@ -856,23 +856,23 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows)
else if (max_length < (1L << 16))
{
if (item->collation.collation == &my_charset_bin)
- answer->append("BLOB", 4);
+ answer->append(STRING_WITH_LEN("BLOB"));
else
- answer->append("TEXT", 4);
+ answer->append(STRING_WITH_LEN("TEXT"));
}
else if (max_length < (1L << 24))
{
if (item->collation.collation == &my_charset_bin)
- answer->append("MEDIUMBLOB", 10);
+ answer->append(STRING_WITH_LEN("MEDIUMBLOB"));
else
- answer->append("MEDIUMTEXT", 10);
+ answer->append(STRING_WITH_LEN("MEDIUMTEXT"));
}
else
{
if (item->collation.collation == &my_charset_bin)
- answer->append("LONGBLOB", 8);
+ answer->append(STRING_WITH_LEN("LONGBLOB"));
else
- answer->append("LONGTEXT", 8);
+ answer->append(STRING_WITH_LEN("LONGTEXT"));
}
} // field_str::get_opt_type
@@ -902,14 +902,14 @@ void field_real::get_opt_type(String *answer,
sprintf(buff, "BIGINT(%d)", len);
answer->append(buff, (uint) strlen(buff));
if (min_arg >= 0)
- answer->append(" UNSIGNED");
+ answer->append(STRING_WITH_LEN(" UNSIGNED"));
}
else if (item->decimals == NOT_FIXED_DEC)
{
if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX)
- answer->append("FLOAT", 5);
+ answer->append(STRING_WITH_LEN("FLOAT"));
else
- answer->append("DOUBLE", 6);
+ answer->append(STRING_WITH_LEN("DOUBLE"));
}
else
{
@@ -926,7 +926,7 @@ void field_real::get_opt_type(String *answer,
// a single number shouldn't be zerofill
(max_length - (item->decimals + 1)) != 1 &&
((Field_num*) ((Item_field*) item)->field)->zerofill)
- answer->append(" ZEROFILL");
+ answer->append(STRING_WITH_LEN(" ZEROFILL"));
} // field_real::get_opt_type
@@ -950,14 +950,14 @@ void field_longlong::get_opt_type(String *answer,
sprintf(buff, "BIGINT(%d)", (int) max_length);
answer->append(buff, (uint) strlen(buff));
if (min_arg >= 0)
- answer->append(" UNSIGNED");
+ answer->append(STRING_WITH_LEN(" UNSIGNED"));
// if item is FIELD_ITEM, it _must_be_ Field_num in this class
if ((item->type() == Item::FIELD_ITEM) &&
// a single number shouldn't be zerofill
max_length != 1 &&
((Field_num*) ((Item_field*) item)->field)->zerofill)
- answer->append(" ZEROFILL");
+ answer->append(STRING_WITH_LEN(" ZEROFILL"));
} // field_longlong::get_opt_type
@@ -982,7 +982,7 @@ void field_ulonglong::get_opt_type(String *answer,
// a single number shouldn't be zerofill
max_length != 1 &&
((Field_num*) ((Item_field*) item)->field)->zerofill)
- answer->append(" ZEROFILL");
+ answer->append(STRING_WITH_LEN(" ZEROFILL"));
} //field_ulonglong::get_opt_type
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index f91a5e14835..af08d20baaf 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1088,6 +1088,11 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
/* find a unused table in the open table cache */
if (refresh)
*refresh=0;
+
+ /* an open table operation needs a lot of the stack space */
+ if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (char *)&alias))
+ return 0;
+
if (thd->killed)
DBUG_RETURN(0);
key_length= (uint) (strmov(strmov(key, table_list->db)+1,
@@ -1200,17 +1205,16 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
(void) unpack_filename(path, path);
if (mysql_frm_type(thd, path, &not_used) == FRMTYPE_VIEW)
{
- TABLE tab;// will not be used (because it's VIEW) but have to be passed
+ /*
+ Will not be used (because it's VIEW) but has to be passed.
+ Also we will not free it (because it is a stack variable).
+ */
+ TABLE tab;
table= &tab;
VOID(pthread_mutex_lock(&LOCK_open));
- if (open_unireg_entry(thd, table, table_list->db,
- table_list->table_name,
- alias, table_list, mem_root))
- {
- table->next=table->prev=table;
- free_cache_entry(table);
- }
- else
+ if (!open_unireg_entry(thd, table, table_list->db,
+ table_list->table_name,
+ alias, table_list, mem_root))
{
DBUG_ASSERT(table_list->view != 0);
VOID(pthread_mutex_unlock(&LOCK_open));
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index 880bf74e67f..b7531696150 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -412,7 +412,7 @@ protected:
/*
The following functions are only used when debugging
- We don't protect these with ifndef DEBUG_OFF to not have to recompile
+ We don't protect these with ifndef DBUG_OFF to not have to recompile
everything if we want to add checks of the cache at some places.
*/
void wreck(uint line, const char *message);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 4ca6e6486df..19bbf08353a 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1495,7 +1495,13 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
my_var *mv= gl++;
if (mv->local)
- (void)local_vars.push_back(new Item_splocal(mv->s, mv->offset));
+ {
+ Item_splocal *var;
+ (void)local_vars.push_back(var= new Item_splocal(mv->s, mv->offset));
+#ifndef DBUG_OFF
+ var->owner= mv->owner;
+#endif
+ }
else
{
Item_func_set_user_var *var= new Item_func_set_user_var(mv->s, item);
@@ -1916,6 +1922,7 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup)
- Value for found_rows() is reset and restored
- examined_row_count is added to the total
- cuted_fields is added to the total
+ - new savepoint level is created and destroyed
NOTES:
Seed for random() is saved for the first! usage of RAND()
@@ -1939,6 +1946,7 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
backup->sent_row_count= sent_row_count;
backup->cuted_fields= cuted_fields;
backup->client_capabilities= client_capabilities;
+ backup->savepoints= transaction.savepoints;
if (!lex->requires_prelocking() || is_update_query(lex->sql_command))
options&= ~OPTION_BIN_LOG;
@@ -1951,6 +1959,7 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
examined_row_count= 0;
sent_row_count= 0;
cuted_fields= 0;
+ transaction.savepoints= 0;
#ifndef EMBEDDED_LIBRARY
/* Surpress OK packets in case if we will execute statements */
@@ -1961,6 +1970,21 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
void THD::restore_sub_statement_state(Sub_statement_state *backup)
{
+ /*
+ To save resources we want to release savepoints which were created
+ during execution of function or trigger before leaving their savepoint
+ level. It is enough to release first savepoint set on this level since
+ all later savepoints will be released automatically.
+ */
+ if (transaction.savepoints)
+ {
+ SAVEPOINT *sv;
+ for (sv= transaction.savepoints; sv->prev; sv= sv->prev)
+ {}
+ /* ha_release_savepoint() never returns error. */
+ (void)ha_release_savepoint(this, sv);
+ }
+ transaction.savepoints= backup->savepoints;
options= backup->options;
in_sub_stmt= backup->in_sub_stmt;
net.no_send_ok= backup->no_send_ok;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 03838c8e337..95d4f45fcff 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -533,6 +533,7 @@ struct system_variables
ulong completion_type;
/* Determines which non-standard SQL behaviour should be enabled */
ulong sql_mode;
+ ulong max_sp_recursion_depth;
/* check of key presence in updatable view */
ulong updatable_views_with_limit;
ulong default_week_format;
@@ -1101,6 +1102,7 @@ public:
uint in_sub_stmt;
bool enable_slow_log, insert_id_used;
my_bool no_send_ok;
+ SAVEPOINT *savepoints;
};
@@ -2094,6 +2096,13 @@ public:
class my_var : public Sql_alloc {
public:
LEX_STRING s;
+#ifndef DBUG_OFF
+ /*
+ Routine to which this Item_splocal belongs. Used for checking if correct
+ runtime context is used for variable handling.
+ */
+ sp_head *owner;
+#endif
bool local;
uint offset;
enum_field_types type;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 00c095c0a4e..c19efff2d85 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1528,9 +1528,9 @@ void st_select_lex_unit::print(String *str)
{
if (sl != first_select())
{
- str->append(" union ", 7);
+ str->append(STRING_WITH_LEN(" union "));
if (union_all)
- str->append("all ", 4);
+ str->append(STRING_WITH_LEN("all "));
else if (union_distinct == sl)
union_all= TRUE;
}
@@ -1544,7 +1544,7 @@ void st_select_lex_unit::print(String *str)
{
if (fake_select_lex->order_list.elements)
{
- str->append(" order by ", 10);
+ str->append(STRING_WITH_LEN(" order by "));
fake_select_lex->print_order(str,
(ORDER *) fake_select_lex->
order_list.first);
@@ -1567,7 +1567,7 @@ void st_select_lex::print_order(String *str, ORDER *order)
else
(*order->item)->print(str);
if (!order->asc)
- str->append(" desc", 5);
+ str->append(STRING_WITH_LEN(" desc"));
if (order->next)
str->append(',');
}
@@ -1590,7 +1590,7 @@ void st_select_lex::print_limit(THD *thd, String *str)
if (explicit_limit)
{
- str->append(" limit ", 7);
+ str->append(STRING_WITH_LEN(" limit "));
if (offset_limit)
{
offset_limit->print(str);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 012b9679723..5126d0ee463 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -91,6 +91,7 @@ enum enum_sql_command {
SQLCOM_CREATE_TRIGGER, SQLCOM_DROP_TRIGGER,
SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE,
SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER,
+ SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE,
SQLCOM_INSTALL_PLUGIN, SQLCOM_UNINSTALL_PLUGIN,
SQLCOM_SHOW_AUTHORS,
/* This should be the last !!! */
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 44ddf11757a..911e0c38fc5 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -691,7 +691,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
length=(uint) (read_info.row_end-pos);
if (!read_info.enclosed &&
- (enclosed_length && length == 4 && !memcmp(pos,"NULL",4)) ||
+ (enclosed_length && length == 4 &&
+ !memcmp(pos, STRING_WITH_LEN("NULL"))) ||
(length == 1 && read_info.found_null))
{
if (item->type() == Item::FIELD_ITEM)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index cb2efe43615..74e4b094bbe 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3671,7 +3671,8 @@ end_with_restore_list:
if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
break;
#ifdef HAVE_DLOPEN
- if (sp_find_function(thd, lex->spname))
+ if (sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
+ &thd->sp_func_cache, FALSE))
{
my_error(ER_UDF_EXISTS, MYF(0), lex->spname->m_name.str);
goto error;
@@ -4022,8 +4023,8 @@ end_with_restore_list:
break;
}
case SQLCOM_SAVEPOINT:
- if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) ||
- !opt_using_transactions)
+ if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
+ thd->in_sub_stmt) || !opt_using_transactions)
send_ok(thd);
else
{
@@ -4205,7 +4206,8 @@ end_with_restore_list:
By this moment all needed SPs should be in cache so no need to look
into DB.
*/
- if (!(sp= sp_find_procedure(thd, lex->spname, TRUE)))
+ if (!(sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
+ &thd->sp_proc_cache, TRUE)))
{
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
lex->spname->m_qname.str);
@@ -4329,9 +4331,11 @@ end_with_restore_list:
memcpy(&chistics, &lex->sp_chistics, sizeof(chistics));
if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
- sp= sp_find_procedure(thd, lex->spname);
+ sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
+ &thd->sp_proc_cache, FALSE);
else
- sp= sp_find_function(thd, lex->spname);
+ sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
+ &thd->sp_func_cache, FALSE);
mysql_reset_errors(thd, 0);
if (! sp)
{
@@ -4407,9 +4411,11 @@ end_with_restore_list:
char *db, *name;
if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
- sp= sp_find_procedure(thd, lex->spname);
+ sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
+ &thd->sp_proc_cache, FALSE);
else
- sp= sp_find_function(thd, lex->spname);
+ sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
+ &thd->sp_func_cache, FALSE);
mysql_reset_errors(thd, 0);
if (sp)
{
@@ -4537,6 +4543,33 @@ end_with_restore_list:
lex->wild->ptr() : NullS));
break;
}
+#ifndef DBUG_OFF
+ case SQLCOM_SHOW_PROC_CODE:
+ case SQLCOM_SHOW_FUNC_CODE:
+ {
+ sp_head *sp;
+
+ if (lex->spname->m_name.length > NAME_LEN)
+ {
+ my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
+ goto error;
+ }
+ if (lex->sql_command == SQLCOM_SHOW_PROC_CODE)
+ sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
+ &thd->sp_proc_cache, FALSE);
+ else
+ sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
+ &thd->sp_func_cache, FALSE);
+ if (!sp || !sp->show_routine_code(thd))
+ {
+ /* We don't distinguish between errors for now */
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
+ SP_COM_STRING(lex), lex->spname->m_name.str);
+ goto error;
+ }
+ break;
+ }
+#endif // ifndef DBUG_OFF
case SQLCOM_CREATE_VIEW:
{
if (end_active_trans(thd))
@@ -4555,7 +4588,7 @@ end_with_restore_list:
buff.append(command[thd->lex->create_view_mode].str,
command[thd->lex->create_view_mode].length);
view_store_options(thd, first_table, &buff);
- buff.append("VIEW ", 5);
+ buff.append(STRING_WITH_LEN("VIEW "));
/* Test if user supplied a db (ie: we did not use thd->db) */
if (first_table->db != thd->db && first_table->db[0])
{
@@ -4565,7 +4598,7 @@ end_with_restore_list:
}
append_identifier(thd, &buff, first_table->table_name,
first_table->table_name_length);
- buff.append(" AS ", 4);
+ buff.append(STRING_WITH_LEN(" AS "));
buff.append(first_table->source.str, first_table->source.length);
Query_log_event qinfo(thd, buff.ptr(), buff.length(), 0, FALSE);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index d5282ef6b7f..2f08583d974 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1931,7 +1931,7 @@ static const char *get_dynamic_sql_string(LEX *lex, uint *query_len)
variable absent or equal to NULL, so we need to set variable to
something reasonable to get a readable error message during parsing
*/
- str.set("NULL", 4, &my_charset_latin1);
+ str.set(STRING_WITH_LEN("NULL"), &my_charset_latin1);
}
needs_conversion= String::needs_conversion(var_value->length(),
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ad520302692..6ea9231c87c 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -13699,7 +13699,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
{
SELECT_LEX *sl= join->unit->first_select();
uint len= 6, lastop= 0;
- memcpy(table_name_buffer, "<union", 6);
+ memcpy(table_name_buffer, STRING_WITH_LEN("<union"));
for (; sl && len + lastop + 5 < NAME_LEN; sl= sl->next_select())
{
len+= lastop;
@@ -13708,7 +13708,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
}
if (sl || len + lastop >= NAME_LEN)
{
- memcpy(table_name_buffer + len, "...>", 5);
+ memcpy(table_name_buffer + len, STRING_WITH_LEN("...>") + 1);
len+= 4;
}
else
@@ -13887,7 +13887,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
{
- extra.append("; Using ");
+ extra.append(STRING_WITH_LEN("; Using "));
tab->select->quick->add_info_string(&extra);
}
if (tab->select)
@@ -13895,7 +13895,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
if (tab->use_quick == 2)
{
char buf[MAX_KEY/8+1];
- extra.append("; Range checked for each record (index map: 0x");
+ extra.append(STRING_WITH_LEN("; Range checked for each "
+ "record (index map: 0x"));
extra.append(tab->keys.print(buf));
extra.append(')');
}
@@ -13905,38 +13906,39 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
if (thd->variables.engine_condition_pushdown && pushed_cond)
{
- extra.append("; Using where with pushed condition");
+ extra.append(STRING_WITH_LEN("; Using where with pushed "
+ "condition"));
if (thd->lex->describe & DESCRIBE_EXTENDED)
{
- extra.append(": ");
+ extra.append(STRING_WITH_LEN(": "));
((COND *)pushed_cond)->print(&extra);
}
}
else
- extra.append("; Using where");
+ extra.append(STRING_WITH_LEN("; Using where"));
}
}
if (key_read)
{
if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
- extra.append("; Using index for group-by");
+ extra.append(STRING_WITH_LEN("; Using index for group-by"));
else
- extra.append("; Using index");
+ extra.append(STRING_WITH_LEN("; Using index"));
}
if (table->reginfo.not_exists_optimize)
- extra.append("; Not exists");
+ extra.append(STRING_WITH_LEN("; Not exists"));
if (need_tmp_table)
{
need_tmp_table=0;
- extra.append("; Using temporary");
+ extra.append(STRING_WITH_LEN("; Using temporary"));
}
if (need_order)
{
need_order=0;
- extra.append("; Using filesort");
+ extra.append(STRING_WITH_LEN("; Using filesort"));
}
if (distinct & test_all_bits(used_tables,thd->used_tables))
- extra.append("; Distinct");
+ extra.append(STRING_WITH_LEN("; Distinct"));
/* Skip initial "; "*/
const char *str= extra.ptr();
@@ -14053,15 +14055,18 @@ static void print_join(THD *thd, String *str, List<TABLE_LIST> *tables)
{
TABLE_LIST *curr= *tbl;
if (curr->outer_join)
- str->append(" left join ", 11); // MySQL converts right to left joins
+ {
+ /* MySQL converts right to left joins */
+ str->append(STRING_WITH_LEN(" left join "));
+ }
else if (curr->straight)
- str->append(" straight_join ", 15);
+ str->append(STRING_WITH_LEN(" straight_join "));
else
- str->append(" join ", 6);
+ str->append(STRING_WITH_LEN(" join "));
curr->print(thd, str);
if (curr->on_expr)
{
- str->append(" on(", 4);
+ str->append(STRING_WITH_LEN(" on("));
curr->on_expr->print(str);
str->append(')');
}
@@ -14146,28 +14151,28 @@ void st_select_lex::print(THD *thd, String *str)
if (!thd)
thd= current_thd;
- str->append("select ", 7);
+ str->append(STRING_WITH_LEN("select "));
/* First add options */
if (options & SELECT_STRAIGHT_JOIN)
- str->append("straight_join ", 14);
+ str->append(STRING_WITH_LEN("straight_join "));
if ((thd->lex->lock_option == TL_READ_HIGH_PRIORITY) &&
(this == &thd->lex->select_lex))
- str->append("high_priority ", 14);
+ str->append(STRING_WITH_LEN("high_priority "));
if (options & SELECT_DISTINCT)
- str->append("distinct ", 9);
+ str->append(STRING_WITH_LEN("distinct "));
if (options & SELECT_SMALL_RESULT)
- str->append("sql_small_result ", 17);
+ str->append(STRING_WITH_LEN("sql_small_result "));
if (options & SELECT_BIG_RESULT)
- str->append("sql_big_result ", 15);
+ str->append(STRING_WITH_LEN("sql_big_result "));
if (options & OPTION_BUFFER_RESULT)
- str->append("sql_buffer_result ", 18);
+ str->append(STRING_WITH_LEN("sql_buffer_result "));
if (options & OPTION_FOUND_ROWS)
- str->append("sql_calc_found_rows ", 20);
+ str->append(STRING_WITH_LEN("sql_calc_found_rows "));
if (!thd->lex->safe_to_cache_query)
- str->append("sql_no_cache ", 13);
+ str->append(STRING_WITH_LEN("sql_no_cache "));
if (options & OPTION_TO_QUERY_CACHE)
- str->append("sql_cache ", 10);
+ str->append(STRING_WITH_LEN("sql_cache "));
//Item List
bool first= 1;
@@ -14188,7 +14193,7 @@ void st_select_lex::print(THD *thd, String *str)
*/
if (table_list.elements)
{
- str->append(" from ", 6);
+ str->append(STRING_WITH_LEN(" from "));
/* go through join tree */
print_join(thd, str, &top_join_list);
}
@@ -14199,22 +14204,22 @@ void st_select_lex::print(THD *thd, String *str)
cur_where= join->conds;
if (cur_where)
{
- str->append(" where ", 7);
+ str->append(STRING_WITH_LEN(" where "));
cur_where->print(str);
}
// group by & olap
if (group_list.elements)
{
- str->append(" group by ", 10);
+ str->append(STRING_WITH_LEN(" group by "));
print_order(str, (ORDER *) group_list.first);
switch (olap)
{
case CUBE_TYPE:
- str->append(" with cube", 10);
+ str->append(STRING_WITH_LEN(" with cube"));
break;
case ROLLUP_TYPE:
- str->append(" with rollup", 12);
+ str->append(STRING_WITH_LEN(" with rollup"));
break;
default:
; //satisfy compiler
@@ -14228,13 +14233,13 @@ void st_select_lex::print(THD *thd, String *str)
if (cur_having)
{
- str->append(" having ", 8);
+ str->append(STRING_WITH_LEN(" having "));
cur_having->print(str);
}
if (order_list.elements)
{
- str->append(" order by ", 10);
+ str->append(STRING_WITH_LEN(" order by "));
print_order(str, (ORDER *) order_list.first);
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 3091656d9dc..de7e1c4f8be 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -540,22 +540,22 @@ bool mysqld_show_create_db(THD *thd, char *dbname,
protocol->prepare_for_resend();
protocol->store(dbname, strlen(dbname), system_charset_info);
buffer.length(0);
- buffer.append("CREATE DATABASE ", 16);
+ buffer.append(STRING_WITH_LEN("CREATE DATABASE "));
if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
- buffer.append("/*!32312 IF NOT EXISTS*/ ", 25);
+ buffer.append(STRING_WITH_LEN("/*!32312 IF NOT EXISTS*/ "));
append_identifier(thd, &buffer, dbname, strlen(dbname));
if (create.default_table_charset)
{
- buffer.append(" /*!40100", 9);
- buffer.append(" DEFAULT CHARACTER SET ", 23);
+ buffer.append(STRING_WITH_LEN(" /*!40100"));
+ buffer.append(STRING_WITH_LEN(" DEFAULT CHARACTER SET "));
buffer.append(create.default_table_charset->csname);
if (!(create.default_table_charset->state & MY_CS_PRIMARY))
{
- buffer.append(" COLLATE ", 9);
+ buffer.append(STRING_WITH_LEN(" COLLATE "));
buffer.append(create.default_table_charset->name);
}
- buffer.append(" */", 3);
+ buffer.append(STRING_WITH_LEN(" */"));
}
protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
@@ -743,7 +743,7 @@ static void append_directory(THD *thd, String *packet, const char *dir_type,
uint length= dirname_length(filename);
packet->append(' ');
packet->append(dir_type);
- packet->append(" DIRECTORY='", 12);
+ packet->append(STRING_WITH_LEN(" DIRECTORY='"));
#ifdef __WIN__
/* Convert \ to / to be able to create table on unix */
char *winfilename= (char*) thd->memdup(filename, length);
@@ -792,16 +792,16 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
restore_record(table, s->default_values); // Get empty record
if (share->tmp_table)
- packet->append("CREATE TEMPORARY TABLE ", 23);
+ packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
else
- packet->append("CREATE TABLE ", 13);
+ packet->append(STRING_WITH_LEN("CREATE TABLE "));
if (table_list->schema_table)
alias= table_list->schema_table->table_name;
else
alias= (lower_case_table_names == 2 ? table->alias :
share->table_name);
append_identifier(thd, packet, alias, strlen(alias));
- packet->append(" (\n", 3);
+ packet->append(STRING_WITH_LEN(" (\n"));
for (ptr=table->field ; (field= *ptr); ptr++)
{
@@ -810,9 +810,9 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
uint flags = field->flags;
if (ptr != table->field)
- packet->append(",\n", 2);
+ packet->append(STRING_WITH_LEN(",\n"));
- packet->append(" ", 2);
+ packet->append(STRING_WITH_LEN(" "));
append_identifier(thd,packet,field->field_name, strlen(field->field_name));
packet->append(' ');
// check for surprises from the previous call to Field::sql_type()
@@ -829,7 +829,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
{
if (field->charset() != share->table_charset)
{
- packet->append(" character set ", 15);
+ packet->append(STRING_WITH_LEN(" character set "));
packet->append(field->charset()->csname);
}
/*
@@ -838,20 +838,20 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
*/
if (!(field->charset()->state & MY_CS_PRIMARY))
{
- packet->append(" collate ", 9);
+ packet->append(STRING_WITH_LEN(" collate "));
packet->append(field->charset()->name);
}
}
if (flags & NOT_NULL_FLAG)
- packet->append(" NOT NULL", 9);
+ packet->append(STRING_WITH_LEN(" NOT NULL"));
else if (field->type() == FIELD_TYPE_TIMESTAMP)
{
/*
TIMESTAMP field require explicit NULL flag, because unlike
all other fields they are treated as NOT NULL by default.
*/
- packet->append(" NULL", 5);
+ packet->append(STRING_WITH_LEN(" NULL"));
}
/*
@@ -869,9 +869,9 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
if (has_default)
{
- packet->append(" default ", 9);
+ packet->append(STRING_WITH_LEN(" default "));
if (has_now_default)
- packet->append("CURRENT_TIMESTAMP",17);
+ packet->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
else if (!field->is_null())
{ // Not null by default
type.set(tmp, sizeof(tmp), field->charset());
@@ -886,10 +886,10 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
append_unescaped(packet, def_val.ptr(), def_val.length());
}
else
- packet->append("''",2);
+ packet->append(STRING_WITH_LEN("''"));
}
else if (field->maybe_null())
- packet->append("NULL", 4); // Null as default
+ packet->append(STRING_WITH_LEN("NULL")); // Null as default
else
packet->append(tmp);
}
@@ -897,15 +897,15 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
if (!(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS) &&
table->timestamp_field == field &&
field->unireg_check != Field::TIMESTAMP_DN_FIELD)
- packet->append(" on update CURRENT_TIMESTAMP",28);
+ packet->append(STRING_WITH_LEN(" on update CURRENT_TIMESTAMP"));
if (field->unireg_check == Field::NEXT_NUMBER &&
!(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS))
- packet->append(" auto_increment", 15 );
+ packet->append(STRING_WITH_LEN(" auto_increment"));
if (field->comment.length)
{
- packet->append(" COMMENT ",9);
+ packet->append(STRING_WITH_LEN(" COMMENT "));
append_unescaped(packet, field->comment.str, field->comment.length);
}
}
@@ -920,20 +920,20 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
{
KEY_PART_INFO *key_part= key_info->key_part;
bool found_primary=0;
- packet->append(",\n ", 4);
+ packet->append(STRING_WITH_LEN(",\n "));
if (i == primary_key && !strcmp(key_info->name, primary_key_name))
{
found_primary=1;
- packet->append("PRIMARY ", 8);
+ packet->append(STRING_WITH_LEN("PRIMARY "));
}
else if (key_info->flags & HA_NOSAME)
- packet->append("UNIQUE ", 7);
+ packet->append(STRING_WITH_LEN("UNIQUE "));
else if (key_info->flags & HA_FULLTEXT)
- packet->append("FULLTEXT ", 9);
+ packet->append(STRING_WITH_LEN("FULLTEXT "));
else if (key_info->flags & HA_SPATIAL)
- packet->append("SPATIAL ", 8);
- packet->append("KEY ", 4);
+ packet->append(STRING_WITH_LEN("SPATIAL "));
+ packet->append(STRING_WITH_LEN("KEY "));
if (!found_primary)
append_identifier(thd, packet, key_info->name, strlen(key_info->name));
@@ -942,19 +942,19 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
!limited_mysql_mode && !foreign_db_mode)
{
if (key_info->algorithm == HA_KEY_ALG_BTREE)
- packet->append(" USING BTREE", 12);
+ packet->append(STRING_WITH_LEN(" USING BTREE"));
if (key_info->algorithm == HA_KEY_ALG_HASH)
- packet->append(" USING HASH", 11);
+ packet->append(STRING_WITH_LEN(" USING HASH"));
// +BAR: send USING only in non-default case: non-spatial rtree
if ((key_info->algorithm == HA_KEY_ALG_RTREE) &&
!(key_info->flags & HA_SPATIAL))
- packet->append(" USING RTREE", 12);
+ packet->append(STRING_WITH_LEN(" USING RTREE"));
// No need to send USING FULLTEXT, it is sent as FULLTEXT KEY
}
- packet->append(" (", 2);
+ packet->append(STRING_WITH_LEN(" ("));
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{
@@ -997,13 +997,13 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
file->free_foreign_key_create_info(for_str);
}
- packet->append("\n)", 2);
+ packet->append(STRING_WITH_LEN("\n)"));
if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
{
if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
- packet->append(" TYPE=", 6);
+ packet->append(STRING_WITH_LEN(" TYPE="));
else
- packet->append(" ENGINE=", 8);
+ packet->append(STRING_WITH_LEN(" ENGINE="));
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (table->s->part_info)
packet->append(ha_get_storage_engine(
@@ -1018,58 +1018,58 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
!(thd->variables.sql_mode & MODE_MYSQL323) &&
!(thd->variables.sql_mode & MODE_MYSQL40))
{
- packet->append(" DEFAULT CHARSET=", 17);
+ packet->append(STRING_WITH_LEN(" DEFAULT CHARSET="));
packet->append(share->table_charset->csname);
if (!(share->table_charset->state & MY_CS_PRIMARY))
{
- packet->append(" COLLATE=", 9);
+ packet->append(STRING_WITH_LEN(" COLLATE="));
packet->append(table->s->table_charset->name);
}
}
if (share->min_rows)
{
- packet->append(" MIN_ROWS=", 10);
+ packet->append(STRING_WITH_LEN(" MIN_ROWS="));
end= longlong10_to_str(share->min_rows, buff, 10);
packet->append(buff, (uint) (end- buff));
}
if (share->max_rows && !table_list->schema_table)
{
- packet->append(" MAX_ROWS=", 10);
+ packet->append(STRING_WITH_LEN(" MAX_ROWS="));
end= longlong10_to_str(share->max_rows, buff, 10);
packet->append(buff, (uint) (end - buff));
}
if (share->avg_row_length)
{
- packet->append(" AVG_ROW_LENGTH=", 16);
+ packet->append(STRING_WITH_LEN(" AVG_ROW_LENGTH="));
end= longlong10_to_str(share->avg_row_length, buff,10);
packet->append(buff, (uint) (end - buff));
}
if (share->db_create_options & HA_OPTION_PACK_KEYS)
- packet->append(" PACK_KEYS=1", 12);
+ packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
- packet->append(" PACK_KEYS=0", 12);
+ packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
if (share->db_create_options & HA_OPTION_CHECKSUM)
- packet->append(" CHECKSUM=1", 11);
+ packet->append(STRING_WITH_LEN(" CHECKSUM=1"));
if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
- packet->append(" DELAY_KEY_WRITE=1",18);
+ packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1"));
if (share->row_type != ROW_TYPE_DEFAULT)
{
- packet->append(" ROW_FORMAT=",12);
+ packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
packet->append(ha_row_type[(uint) share->row_type]);
}
table->file->append_create_info(packet);
if (share->comment && share->comment[0])
{
- packet->append(" COMMENT=", 9);
+ packet->append(STRING_WITH_LEN(" COMMENT="));
append_unescaped(packet, share->comment, strlen(share->comment));
}
if (share->connect_string.length)
{
- packet->append(" CONNECTION=", 12);
+ packet->append(STRING_WITH_LEN(" CONNECTION="));
append_unescaped(packet, share->connect_string.str, share->connect_string.length);
}
if (file->raid_type)
@@ -1107,25 +1107,25 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
void
view_store_options(THD *thd, TABLE_LIST *table, String *buff)
{
- buff->append("ALGORITHM=", 10);
+ buff->append(STRING_WITH_LEN("ALGORITHM="));
switch ((int8)table->algorithm) {
case VIEW_ALGORITHM_UNDEFINED:
- buff->append("UNDEFINED ", 10);
+ buff->append(STRING_WITH_LEN("UNDEFINED "));
break;
case VIEW_ALGORITHM_TMPTABLE:
- buff->append("TEMPTABLE ", 10);
+ buff->append(STRING_WITH_LEN("TEMPTABLE "));
break;
case VIEW_ALGORITHM_MERGE:
- buff->append("MERGE ", 6);
+ buff->append(STRING_WITH_LEN("MERGE "));
break;
default:
DBUG_ASSERT(0); // never should happen
}
append_definer(thd, buff, &table->definer.user, &table->definer.host);
if (table->view_suid)
- buff->append("SQL SECURITY DEFINER ", 21);
+ buff->append(STRING_WITH_LEN("SQL SECURITY DEFINER "));
else
- buff->append("SQL SECURITY INVOKER ", 21);
+ buff->append(STRING_WITH_LEN("SQL SECURITY INVOKER "));
}
@@ -1183,19 +1183,19 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
}
}
- buff->append("CREATE ", 7);
+ buff->append(STRING_WITH_LEN("CREATE "));
if (!foreign_db_mode)
{
view_store_options(thd, table, buff);
}
- buff->append("VIEW ", 5);
+ buff->append(STRING_WITH_LEN("VIEW "));
if (!table->compact_view_format)
{
append_identifier(thd, buff, table->view_db.str, table->view_db.length);
buff->append('.');
}
append_identifier(thd, buff, table->view_name.str, table->view_name.length);
- buff->append(" AS ", 4);
+ buff->append(STRING_WITH_LEN(" AS "));
/*
We can't just use table->query, because our SQL_MODE may trigger
@@ -1206,9 +1206,9 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
if (table->with_check != VIEW_CHECK_NONE)
{
if (table->with_check == VIEW_CHECK_LOCAL)
- buff->append(" WITH LOCAL CHECK OPTION", 24);
+ buff->append(STRING_WITH_LEN(" WITH LOCAL CHECK OPTION"));
else
- buff->append(" WITH CASCADED CHECK OPTION", 27);
+ buff->append(STRING_WITH_LEN(" WITH CASCADED CHECK OPTION"));
}
return 0;
}
@@ -2195,20 +2195,24 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
if (with_i_schema)
{
- table->field[3]->store("SYSTEM VIEW", 11, system_charset_info);
+ table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"),
+ system_charset_info);
}
else
{
my_snprintf(end, len, "/%s%s", file_name, reg_ext);
switch (mysql_frm_type(thd, path, &not_used)) {
case FRMTYPE_ERROR:
- table->field[3]->store("ERROR", 5, system_charset_info);
+ table->field[3]->store(STRING_WITH_LEN("ERROR"),
+ system_charset_info);
break;
case FRMTYPE_TABLE:
- table->field[3]->store("BASE TABLE", 10, system_charset_info);
+ table->field[3]->store(STRING_WITH_LEN("BASE TABLE"),
+ system_charset_info);
break;
case FRMTYPE_VIEW:
- table->field[3]->store("VIEW", 4, system_charset_info);
+ table->field[3]->store(STRING_WITH_LEN("VIEW"),
+ system_charset_info);
break;
default:
DBUG_ASSERT(0);
@@ -2361,8 +2365,8 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables,
}
else if (tables->view)
{
- table->field[3]->store("VIEW", 4, cs);
- table->field[20]->store("VIEW", 4, cs);
+ table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
+ table->field[20]->store(STRING_WITH_LEN("VIEW"), cs);
}
else
{
@@ -2373,11 +2377,11 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables,
file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_AUTO |
HA_STATUS_NO_LOCK);
if (share->tmp_table == SYSTEM_TMP_TABLE)
- table->field[3]->store("SYSTEM VIEW", 11, cs);
+ table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
else if (share->tmp_table)
- table->field[3]->store("LOCAL TEMPORARY", 15, cs);
+ table->field[3]->store(STRING_WITH_LEN("LOCAL TEMPORARY"), cs);
else
- table->field[3]->store("BASE TABLE", 10, cs);
+ table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs);
for (int i= 4; i < 20; i++)
{
@@ -2613,7 +2617,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
if (show_table->timestamp_field == field &&
field->unireg_check != Field::TIMESTAMP_UN_FIELD)
{
- table->field[5]->store("CURRENT_TIMESTAMP", 17, cs);
+ table->field[5]->store(STRING_WITH_LEN("CURRENT_TIMESTAMP"), cs);
table->field[5]->set_notnull();
}
else if (field->unireg_check != Field::NEXT_NUMBER &&
@@ -2875,8 +2879,8 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
get_field(thd->mem_root, proc_table->field[10], &tmp_string);
table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs);
}
- table->field[6]->store("SQL", 3, cs);
- table->field[10]->store("SQL", 3, cs);
+ table->field[6]->store(STRING_WITH_LEN("SQL"), cs);
+ table->field[10]->store(STRING_WITH_LEN("SQL"), cs);
get_field(thd->mem_root, proc_table->field[6], &tmp_string);
table->field[11]->store(tmp_string.ptr(), tmp_string.length(), cs);
table->field[12]->store(sp_data_access_name[enum_idx].str,
@@ -3031,7 +3035,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables,
pos= show_table->file->index_type(i);
table->field[13]->store(pos, strlen(pos), cs);
if (!show_table->s->keys_in_use.is_set(i))
- table->field[14]->store("disabled", 8, cs);
+ table->field[14]->store(STRING_WITH_LEN("disabled"), cs);
else
table->field[14]->store("", 0, cs);
table->field[14]->set_notnull();
@@ -3141,13 +3145,15 @@ static int get_schema_constraints_record(THD *thd, struct st_table_list *tables,
if (i == primary_key && !strcmp(key_info->name, primary_key_name))
{
if (store_constraints(thd, table, base_name, file_name, key_info->name,
- strlen(key_info->name), "PRIMARY KEY", 11))
+ strlen(key_info->name),
+ STRING_WITH_LEN("PRIMARY KEY")))
DBUG_RETURN(1);
}
else if (key_info->flags & HA_NOSAME)
{
if (store_constraints(thd, table, base_name, file_name, key_info->name,
- strlen(key_info->name), "UNIQUE", 6))
+ strlen(key_info->name),
+ STRING_WITH_LEN("UNIQUE")))
DBUG_RETURN(1);
}
}
@@ -3188,11 +3194,11 @@ static bool store_trigger(THD *thd, TABLE *table, const char *db,
table->field[5]->store(db, strlen(db), cs);
table->field[6]->store(tname, strlen(tname), cs);
table->field[9]->store(trigger_stmt->str, trigger_stmt->length, cs);
- table->field[10]->store("ROW", 3, cs);
+ table->field[10]->store(STRING_WITH_LEN("ROW"), cs);
table->field[11]->store(trg_action_time_type_names[timing].str,
trg_action_time_type_names[timing].length, cs);
- table->field[14]->store("OLD", 3, cs);
- table->field[15]->store("NEW", 3, cs);
+ table->field[14]->store(STRING_WITH_LEN("OLD"), cs);
+ table->field[15]->store(STRING_WITH_LEN("NEW"), cs);
sql_mode_str=
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
@@ -3583,9 +3589,9 @@ int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
buffer.append(field_info->old_name);
if (lex->wild && lex->wild->ptr())
{
- buffer.append(" (");
+ buffer.append(STRING_WITH_LEN(" ("));
buffer.append(lex->wild->ptr());
- buffer.append(")");
+ buffer.append(')');
}
field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
}
@@ -3606,9 +3612,9 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
buffer.append(lex->select_lex.db);
if (lex->wild && lex->wild->ptr())
{
- buffer.append(" (");
+ buffer.append(STRING_WITH_LEN(" ("));
buffer.append(lex->wild->ptr());
- buffer.append(")");
+ buffer.append(')');
}
Item_field *field= new Item_field(context,
NullS, NullS, field_info->field_name);
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 51f802e7465..fd7bca7ec21 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -848,22 +848,22 @@ void String::print(String *str)
switch (c)
{
case '\\':
- str->append("\\\\", 2);
+ str->append(STRING_WITH_LEN("\\\\"));
break;
case '\0':
- str->append("\\0", 2);
+ str->append(STRING_WITH_LEN("\\0"));
break;
case '\'':
- str->append("\\'", 2);
+ str->append(STRING_WITH_LEN("\\'"));
break;
case '\n':
- str->append("\\n", 2);
+ str->append(STRING_WITH_LEN("\\n"));
break;
case '\r':
- str->append("\\r", 2);
+ str->append(STRING_WITH_LEN("\\r"));
break;
case 26: //Ctrl-Z
- str->append("\\z", 2);
+ str->append(STRING_WITH_LEN("\\z"));
break;
default:
str->append(c);
diff --git a/sql/sql_string.h b/sql/sql_string.h
index ddae6368228..67c3e0c62f2 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -24,6 +24,8 @@
#define NOT_FIXED_DEC 31
#endif
+#define STRING_WITH_LEN(X) ((char*) X), (sizeof(X)-1)
+
class String;
int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 93315e3b9f1..32470b9be00 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -761,7 +761,8 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
MY_CS_BINSORT,MYF(0))))
{
char tmp[64];
- strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4), "_bin", 4);
+ strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
+ STRING_WITH_LEN("_bin"));
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
DBUG_RETURN(-1);
}
@@ -2093,7 +2094,7 @@ static int send_check_errmsg(THD *thd, TABLE_LIST* table,
protocol->prepare_for_resend();
protocol->store(table->alias, system_charset_info);
protocol->store((char*) operator_name, system_charset_info);
- protocol->store("error", 5, system_charset_info);
+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
protocol->store(errmsg, system_charset_info);
thd->clear_error();
if (protocol->write())
@@ -2384,7 +2385,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
- protocol->store("error",5, system_charset_info);
+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
if (!(err_msg=thd->net.last_error))
err_msg=ER(ER_CHECK_NO_SUCH_TABLE);
/* if it was a view will check md5 sum */
@@ -2421,7 +2422,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
- protocol->store("error", 5, system_charset_info);
+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
table_name);
protocol->store(buff, length, system_charset_info);
@@ -2456,8 +2457,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
- protocol->store("warning", 7, system_charset_info);
- protocol->store("Table is marked as crashed", 26, system_charset_info);
+ protocol->store(STRING_WITH_LEN("warning"), system_charset_info);
+ protocol->store(STRING_WITH_LEN("Table is marked as crashed"),
+ system_charset_info);
if (protocol->write())
goto err;
}
@@ -2481,7 +2483,7 @@ send_result_message:
char buf[ERRMSGSIZE+20];
uint length=my_snprintf(buf, ERRMSGSIZE,
ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
- protocol->store("note", 4, system_charset_info);
+ protocol->store(STRING_WITH_LEN("note"), system_charset_info);
protocol->store(buf, length, system_charset_info);
}
break;
@@ -2491,41 +2493,45 @@ send_result_message:
char buf[ERRMSGSIZE+20];
uint length= my_snprintf(buf, ERRMSGSIZE,
ER(ER_BAD_TABLE_ERROR), table_name);
- protocol->store("note", 4, system_charset_info);
+ protocol->store(STRING_WITH_LEN("note"), system_charset_info);
protocol->store(buf, length, system_charset_info);
}
break;
case HA_ADMIN_OK:
- protocol->store("status", 6, system_charset_info);
- protocol->store("OK",2, system_charset_info);
+ protocol->store(STRING_WITH_LEN("status"), system_charset_info);
+ protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
break;
case HA_ADMIN_FAILED:
- protocol->store("status", 6, system_charset_info);
- protocol->store("Operation failed",16, system_charset_info);
+ protocol->store(STRING_WITH_LEN("status"), system_charset_info);
+ protocol->store(STRING_WITH_LEN("Operation failed"),
+ system_charset_info);
break;
case HA_ADMIN_REJECT:
- protocol->store("status", 6, system_charset_info);
- protocol->store("Operation need committed state",30, system_charset_info);
+ protocol->store(STRING_WITH_LEN("status"), system_charset_info);
+ protocol->store(STRING_WITH_LEN("Operation need committed state"),
+ system_charset_info);
open_for_modify= FALSE;
break;
case HA_ADMIN_ALREADY_DONE:
- protocol->store("status", 6, system_charset_info);
- protocol->store("Table is already up to date", 27, system_charset_info);
+ protocol->store(STRING_WITH_LEN("status"), system_charset_info);
+ protocol->store(STRING_WITH_LEN("Table is already up to date"),
+ system_charset_info);
break;
case HA_ADMIN_CORRUPT:
- protocol->store("error", 5, system_charset_info);
- protocol->store("Corrupt", 7, system_charset_info);
+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
+ protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info);
fatal_error=1;
break;
case HA_ADMIN_INVALID:
- protocol->store("error", 5, system_charset_info);
- protocol->store("Invalid argument",16, system_charset_info);
+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
+ protocol->store(STRING_WITH_LEN("Invalid argument"),
+ system_charset_info);
break;
case HA_ADMIN_TRY_ALTER:
@@ -2561,7 +2567,7 @@ send_result_message:
else
{
/* Hijack the row already in-progress. */
- protocol->store("error", 5, system_charset_info);
+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
protocol->store(err_msg, system_charset_info);
(void)protocol->write();
/* Start off another row for HA_ADMIN_FAILED */
@@ -2578,7 +2584,7 @@ send_result_message:
}
case HA_ADMIN_WRONG_CHECKSUM:
{
- protocol->store("note", 4, system_charset_info);
+ protocol->store(STRING_WITH_LEN("note"), system_charset_info);
protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)),
system_charset_info);
break;
@@ -2590,7 +2596,7 @@ send_result_message:
uint length=my_snprintf(buf, ERRMSGSIZE,
"Unknown - internal error %d during operation",
result_code);
- protocol->store("error", 5, system_charset_info);
+ protocol->store(STRING_WITH_LEN("error"), system_charset_info);
protocol->store(buf, length, system_charset_info);
fatal_error=1;
break;
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 84cc79ee4dc..296b55679a3 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -20,7 +20,8 @@
#include "sql_trigger.h"
#include "parse_file.h"
-static const LEX_STRING triggers_file_type= {(char *)"TRIGGERS", 8};
+static const LEX_STRING triggers_file_type=
+ {STRING_WITH_LEN("TRIGGERS")};
const char * const triggers_file_ext= ".TRG";
@@ -33,21 +34,17 @@ const char * const triggers_file_ext= ".TRG";
static File_option triggers_file_parameters[]=
{
{
- { (char *) STRING_WITH_LEN("triggers") },
+ {STRING_WITH_LEN("triggers") },
offsetof(class Table_triggers_list, definitions_list),
FILE_OPTIONS_STRLIST
},
{
- /*
- FIXME: Length specified for "sql_modes" key is erroneous, problem caused
- by this are reported as BUG#14090 and should be fixed ASAP.
- */
- { (char *) "sql_modes", 13 },
+ {STRING_WITH_LEN("sql_modes") },
offsetof(class Table_triggers_list, definition_modes_list),
FILE_OPTIONS_ULLLIST
},
{
- { (char *) STRING_WITH_LEN("definers") },
+ {STRING_WITH_LEN("definers") },
offsetof(class Table_triggers_list, definers_list),
FILE_OPTIONS_STRLIST
},
@@ -73,7 +70,8 @@ struct st_trigname
LEX_STRING trigger_table;
};
-static const LEX_STRING trigname_file_type= {(char *)"TRIGGERNAME", 11};
+static const LEX_STRING trigname_file_type=
+ {STRING_WITH_LEN("TRIGGERNAME")};
const char * const trigname_file_ext= ".TRN";
@@ -84,7 +82,7 @@ static File_option trigname_file_parameters[]=
FIXME: Length specified for "trigger_table" key is erroneous, problem
caused by this are reported as BUG#14090 and should be fixed ASAP.
*/
- { (char *) "trigger_table", 15 },
+ {STRING_WITH_LEN("trigger_table")},
offsetof(struct st_trigname, trigger_table),
FILE_OPTIONS_ESTRING
},
@@ -108,6 +106,21 @@ const LEX_STRING trg_event_type_names[]=
static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig);
+bool handle_old_incorrect_sql_modes(char *&unknown_key, gptr base,
+ MEM_ROOT *mem_root,
+ char *end, gptr hook_data);
+
+class Handle_old_incorrect_sql_modes_hook: public Unknown_key_hook
+{
+private:
+ char *path;
+public:
+ Handle_old_incorrect_sql_modes_hook(char *file_path)
+ :path(file_path)
+ {};
+ virtual bool process_unknown_string(char *&unknown_key, gptr base,
+ MEM_ROOT *mem_root, char *end);
+};
/*
Create or drop trigger for table.
@@ -237,7 +250,7 @@ end:
{
log_query.set((char *) 0, 0, system_charset_info); /* reset log_query */
- log_query.append("CREATE ");
+ log_query.append(STRING_WITH_LEN("CREATE "));
append_definer(thd, &log_query, &definer_user, &definer_host);
log_query.append(thd->lex->trigger_definition_begin);
}
@@ -691,6 +704,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
{
Table_triggers_list *triggers=
new (&table->mem_root) Table_triggers_list(table);
+ Handle_old_incorrect_sql_modes_hook sql_modes_hook(path.str);
if (!triggers)
DBUG_RETURN(1);
@@ -705,7 +719,9 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
triggers->definers_list.empty();
if (parser->parse((gptr)triggers, &table->mem_root,
- triggers_file_parameters, TRG_NUM_REQUIRED_PARAMETERS))
+ triggers_file_parameters,
+ TRG_NUM_REQUIRED_PARAMETERS,
+ &sql_modes_hook))
DBUG_RETURN(1);
List_iterator_fast<LEX_STRING> it(triggers->definitions_list);
@@ -800,6 +816,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
List_iterator_fast<LEX_STRING> it_definer(triggers->
definers_list);
LEX *old_lex= thd->lex, lex;
+ sp_rcontext *save_spcont= thd->spcont;
ulong save_sql_mode= thd->variables.sql_mode;
thd->lex= &lex;
@@ -815,6 +832,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
thd->variables.sql_mode= (ulong)*trg_sql_mode;
lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length);
+ thd->spcont= 0;
if (yyparse((void *)thd) || thd->is_fatal_error)
{
/*
@@ -895,6 +913,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
thd->db= save_db.str;
thd->db_length= save_db.length;
thd->lex= old_lex;
+ thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
DBUG_RETURN(0);
@@ -903,6 +922,7 @@ err_with_lex_cleanup:
// QQ: anything else ?
lex_end(&lex);
thd->lex= old_lex;
+ thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
thd->db= save_db.str;
thd->db_length= save_db.length;
@@ -1020,7 +1040,8 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig)
}
if (parser->parse((gptr)&trigname, thd->mem_root,
- trigname_file_parameters, 1))
+ trigname_file_parameters, 1,
+ &file_parser_dummy_hook))
DBUG_RETURN(0);
/* We need to reset statement table list to be PS/SP friendly. */
@@ -1172,3 +1193,65 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event,
return res;
}
+
+
+/*
+ Trigger BUG#14090 compatibility hook
+
+ SYNOPSIS
+ Handle_old_incorrect_sql_modes_hook::process_unknown_string()
+ unknown_key [in/out] reference on the line with unknown
+ parameter and the parsing point
+ base [in] base address for parameter writing (structure
+ like TABLE)
+ mem_root [in] MEM_ROOT for parameters allocation
+ end [in] the end of the configuration
+
+ NOTE: this hook process back compatibility for incorrectly written
+ sql_modes parameter (see BUG#14090).
+
+ RETURN
+ FALSE OK
+ TRUE Error
+*/
+
+bool
+Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key,
+ gptr base,
+ MEM_ROOT *mem_root,
+ char *end)
+{
+#define INVALID_SQL_MODES_LENGTH 13
+ DBUG_ENTER("handle_old_incorrect_sql_modes");
+ DBUG_PRINT("info", ("unknown key:%60s", unknown_key));
+ if (unknown_key + INVALID_SQL_MODES_LENGTH + 1 < end &&
+ unknown_key[INVALID_SQL_MODES_LENGTH] == '=' &&
+ !memcmp(unknown_key, STRING_WITH_LEN("sql_modes")))
+ {
+ DBUG_PRINT("info", ("sql_modes affected by BUG#14090 detected"));
+ push_warning_printf(current_thd,
+ MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_OLD_FILE_FORMAT,
+ ER(ER_OLD_FILE_FORMAT),
+ (char *)path, "TRIGGER");
+ File_option sql_modes_parameters=
+ {
+ {STRING_WITH_LEN("sql_modes") },
+ offsetof(class Table_triggers_list, definition_modes_list),
+ FILE_OPTIONS_ULLLIST
+ };
+ char *ptr= unknown_key + INVALID_SQL_MODES_LENGTH + 1;
+ if (get_file_options_ulllist(ptr, end, unknown_key, base,
+ &sql_modes_parameters, mem_root))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ Set parsing pointer to the last symbol of string (\n)
+ 1) to avoid problem with \0 in the junk after sql_modes
+ 2) to speed up skipping this line by parser.
+ */
+ unknown_key= ptr-1;
+ }
+ DBUG_RETURN(FALSE);
+}
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 4067201bf18..e03d3b22b89 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -623,7 +623,8 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
TODO: special cascade/restrict procedure for alter?
*/
if (parser->parse((gptr)view, thd->mem_root,
- view_parameters + revision_number_position, 1))
+ view_parameters + revision_number_position, 1,
+ &file_parser_dummy_hook))
{
DBUG_RETURN(thd->net.report_error? -1 : 0);
}
@@ -792,7 +793,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
be used here
*/
if (parser->parse((gptr)table, thd->mem_root, view_parameters,
- required_view_parameters))
+ required_view_parameters, &file_parser_dummy_hook))
goto err;
/*
@@ -1502,7 +1503,8 @@ mysql_rename_view(THD *thd,
/* get view definition and source */
if (parser->parse((gptr)&view_def, thd->mem_root, view_parameters,
- array_elements(view_parameters)-1))
+ array_elements(view_parameters)-1,
+ &file_parser_dummy_hook))
goto err;
/* rename view and it's backups */
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 092d73a6ccd..c79ad97be4e 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -177,6 +177,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CLIENT_SYM
%token CLOSE_SYM
%token COALESCE
+%token CODE_SYM
%token COLLATE_SYM
%token COLLATION_SYM
%token COLUMNS
@@ -1631,13 +1632,14 @@ sp_decl:
for (uint i = max-$2 ; i < max ; i++)
{
sp_instr_set *in;
+ uint off= ctx->pvar_context2index(i);
- ctx->set_type(i, type);
+ ctx->set_type(off, type);
if (! has_default)
it= new Item_null(); /* QQ Set to the type with null_value? */
in = new sp_instr_set(lex->sphead->instructions(),
ctx,
- ctx->pvar_context2index(i),
+ off,
it, type, lex,
(i == max - 1));
@@ -1646,7 +1648,7 @@ sp_decl:
freeing LEX.
*/
lex->sphead->add_instr(in);
- ctx->set_default(i, it);
+ ctx->set_default(off, it);
}
lex->sphead->restore_lex(YYTHD);
$$.vars= $2;
@@ -1720,7 +1722,8 @@ sp_decl:
delete $5;
YYABORT;
}
- i= new sp_instr_cpush(sp->instructions(), ctx, $5);
+ i= new sp_instr_cpush(sp->instructions(), ctx, $5,
+ ctx->current_cursors());
sp->add_instr(i);
ctx->push_cursor(&$2);
$$.vars= $$.conds= $$.hndlrs= 0;
@@ -2310,8 +2313,12 @@ sp_case:
ivar.str= (char *)"_tmp_";
ivar.length= 5;
- Item *var= (Item*) new Item_splocal(ivar,
- ctx->current_pvars()-1);
+ Item_splocal *var= new Item_splocal(ivar,
+ ctx->current_pvars()-1);
+#ifndef DBUG_OFF
+ if (var)
+ var->owner= sp;
+#endif
Item *expr= new Item_func_eq(var, $2);
i= new sp_instr_jump_if_not(ip, ctx, expr, lex);
@@ -6488,7 +6495,13 @@ select_var_ident:
YYABORT;
else
{
- ((select_dumpvar *)lex->result)->var_list.push_back( new my_var($1,1,t->offset,t->type));
+ my_var *var;
+ ((select_dumpvar *)lex->result)->
+ var_list.push_back(var= new my_var($1,1,t->offset,t->type));
+#ifndef DBUG_OFF
+ if (var)
+ var->owner= lex->sphead;
+#endif
}
}
;
@@ -7238,7 +7251,28 @@ show_param:
YYABORT;
if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
YYABORT;
- };
+ }
+ | PROCEDURE CODE_SYM sp_name
+ {
+#ifdef DBUG_OFF
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+#else
+ Lex->sql_command= SQLCOM_SHOW_PROC_CODE;
+ Lex->spname= $3;
+#endif
+ }
+ | FUNCTION_SYM CODE_SYM sp_name
+ {
+#ifdef DBUG_OFF
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+#else
+ Lex->sql_command= SQLCOM_SHOW_FUNC_CODE;
+ Lex->spname= $3;
+#endif
+ }
+ ;
show_engine_param:
STATUS_SYM
@@ -7779,6 +7813,10 @@ simple_ident:
Item_splocal *splocal;
splocal= new Item_splocal($1, spv->offset, lex->tok_start_prev -
lex->sphead->m_tmp_query);
+#ifndef DBUG_OFF
+ if (splocal)
+ splocal->owner= lex->sphead;
+#endif
$$ = (Item*) splocal;
lex->variables_used= 1;
lex->safe_to_cache_query=0;
@@ -8136,6 +8174,7 @@ keyword_sp:
| CIPHER_SYM {}
| CLIENT_SYM {}
| COALESCE {}
+ | CODE_SYM {}
| COLLATION_SYM {}
| COLUMNS {}
| COMMITTED_SYM {}
diff --git a/sql/structs.h b/sql/structs.h
index 77d0d435154..12ecf68a212 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -20,8 +20,6 @@
struct st_table;
class Field;
-#define STRING_WITH_LEN(X) ((char*) X), (sizeof(X)-1)
-
typedef struct st_lex_string
{
char *str;
diff --git a/sql/table.cc b/sql/table.cc
index ab80fd1f7fb..b4548f4d90b 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -111,7 +111,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
if (my_read(file,(byte*) head,64,MYF(MY_NABP)))
goto err;
- if (memcmp(head, "TYPE=", 5) == 0)
+ if (memcmp(head, STRING_WITH_LEN("TYPE=")) == 0)
{
// new .frm
my_close(file,MYF(MY_WME));
diff --git a/sql/tztime.cc b/sql/tztime.cc
index ccef8fe8d7a..afdbebea547 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1558,7 +1558,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
sql_print_error("Fatal error: OOM while initializing time zones");
goto end_with_cleanup;
}
- tmp_tzname->name.set("SYSTEM", 6, &my_charset_latin1);
+ tmp_tzname->name.set(STRING_WITH_LEN("SYSTEM"), &my_charset_latin1);
tmp_tzname->tz= my_tz_SYSTEM;
if (my_hash_insert(&tz_names, (const byte *)tmp_tzname))
{
diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c
index b3d95d21eb7..e2c8b446322 100644
--- a/storage/myisam/myisamchk.c
+++ b/storage/myisam/myisamchk.c
@@ -165,7 +165,7 @@ static struct my_option my_long_options[] =
"Analyze distribution of keys. Will make some joins in MySQL faster. You can check the calculated distribution.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifdef __NETWARE__
- {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
+ {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"block-search", 'b',
diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c
index 114e80d8f1a..d691c24e890 100644
--- a/storage/myisam/myisampack.c
+++ b/storage/myisam/myisampack.c
@@ -254,7 +254,7 @@ enum options_mp {OPT_CHARSETS_DIR_MP=256, OPT_AUTO_CLOSE};
static struct my_option my_long_options[] =
{
#ifdef __NETWARE__
- {"auto-close", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
+ {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"backup", 'b', "Make a backup of the table as table_name.OLD.",
diff --git a/storage/ndb/docs/Makefile.am b/storage/ndb/docs/Makefile.am
index d10228d419d..d67db4a6392 100644
--- a/storage/ndb/docs/Makefile.am
+++ b/storage/ndb/docs/Makefile.am
@@ -1,7 +1,7 @@
DOXYDIR = doxygen
noinst_HEADERS = $(DOXYDIR)/predoxy.pl $(DOXYDIR)/postdoxy.pl $(DOXYDIR)/Doxyfile.ndbapi $(DOXYDIR)/Doxyfile.mgmapi $(DOXYDIR)/header.ndbapi.tex $(DOXYDIR)/header.mgmapi.tex
-all: do-check-html ndbapidoc-html mgmapidoc-html
+all-local: do-check-html ndbapidoc-html mgmapidoc-html
all-pdf: do-check-pdf ndbapidoc-pdf mgmapidoc-pdf
DOXYTMP = .doxytmp
diff --git a/support-files/Makefile.am b/support-files/Makefile.am
index 972d1dc7038..26d51438a1b 100644
--- a/support-files/Makefile.am
+++ b/support-files/Makefile.am
@@ -107,7 +107,5 @@ SUFFIXES = .sh
$< > $@-t
@MV@ $@-t $@
-all: binary-configure
-
# Don't update the files from bitkeeper
%::SCCS/s.%