mirror of
https://github.com/MariaDB/server.git
synced 2025-02-01 11:31:51 +01:00
Merge kboortz@bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/Users/kent/mysql/bk/mysql-5.0
This commit is contained in:
commit
8ea4fc68bd
104 changed files with 2698 additions and 637 deletions
|
@ -1268,3 +1268,4 @@ vio/viotest-sslconnect.cpp
|
|||
vio/viotest.cpp
|
||||
zlib/*.ds?
|
||||
zlib/*.vcproj
|
||||
libmysqld/ha_blackhole.cc
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -16,7 +16,6 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [
|
|||
AC_MSG_RESULT([using bundled yaSSL])
|
||||
yassl_dir="extra/yassl"
|
||||
yassl_libs="-L\$(top_srcdir)/extra/yassl/src -lyassl -L\$(top_srcdir)/extra/yassl/taocrypt/src -ltaocrypt"
|
||||
yassl_libs_with_path="\$(top_srcdir)/extra/yassl/src/libyassl.a \$(top_srcdir)/extra/yassl/taocrypt/src/libtaocrypt.a"
|
||||
yassl_includes="-I\$(top_srcdir)/extra/yassl/include"
|
||||
AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.])
|
||||
AC_DEFINE([HAVE_YASSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.])
|
||||
|
@ -24,12 +23,12 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [
|
|||
yassl_integer_extra_cxxflags=""
|
||||
case $host_cpu--$CXX_VERSION in
|
||||
sparc*--*Sun*C++*5.6*)
|
||||
# Disable inlining when compiling taocrypt/src/integer.cpp
|
||||
yassl_integer_extra_cxxflags="+d"
|
||||
AC_MSG_NOTICE([disabling inlining for yassl/taocrypt/src/integer.cpp])
|
||||
# Disable inlining when compiling taocrypt/src/
|
||||
yassl_taocrypt_extra_cxxflags="+d"
|
||||
AC_MSG_NOTICE([disabling inlining for yassl/taocrypt/src/])
|
||||
;;
|
||||
esac
|
||||
AC_SUBST([yassl_integer_extra_cxxflags])
|
||||
AC_SUBST([yassl_taocrypt_extra_cxxflags])
|
||||
|
||||
else
|
||||
yassl_dir=""
|
||||
|
@ -38,6 +37,5 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [
|
|||
AC_SUBST(yassl_libs)
|
||||
AC_SUBST(yassl_includes)
|
||||
AC_SUBST(yassl_dir)
|
||||
AC_SUBST(yassl_libs_with_path)
|
||||
AM_CONDITIONAL([HAVE_YASSL], [ test "with_yassl" = "yes" ])
|
||||
])
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#define _LARGEFILE_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
|
||||
#define _XOPEN_SOURCE /* needed to include getopt.h on some platforms. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
INCLUDES = -I../include -I../taocrypt/include -I../mySTL
|
||||
|
||||
noinst_LIBRARIES = libyassl.a
|
||||
libyassl_a_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \
|
||||
noinst_LTLIBRARIES = libyassl.la
|
||||
libyassl_la_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 = $(wildcard ../include/*.hpp) $(wildcard ../include/openssl/*.h)
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
INCLUDES = -I../include -I../../mySTL
|
||||
|
||||
noinst_LIBRARIES = libtaoint.a libtaocrypt.a
|
||||
noinst_LTLIBRARIES = libtaocrypt.la
|
||||
|
||||
libtaoint_a_SOURCES = integer.cpp
|
||||
libtaoint_a_CXXFLAGS = @yassl_integer_extra_cxxflags@
|
||||
|
||||
libtaocrypt_a_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp asn.cpp \
|
||||
libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp asn.cpp \
|
||||
coding.cpp dh.cpp des.cpp dsa.cpp file.cpp hash.cpp \
|
||||
md2.cpp md5.cpp misc.cpp random.cpp ripemd.cpp rsa.cpp sha.cpp \
|
||||
template_instnt.cpp
|
||||
libtaocrypt_a_LIBADD = libtaoint_a-integer.o
|
||||
template_instnt.cpp integer.cpp
|
||||
libtaocrypt_la_CXXFLAGS = @yassl_taocrypt_extra_cxxflags@ -DYASSL_PURE_C
|
||||
|
||||
EXTRA_DIST = $(wildcard ../include/*.hpp)
|
||||
AM_CXXFLAGS = -DYASSL_PURE_C
|
||||
|
|
|
@ -248,7 +248,7 @@ enum ha_base_keytype {
|
|||
#define HA_OPTION_CHECKSUM 32
|
||||
#define HA_OPTION_DELAY_KEY_WRITE 64
|
||||
#define HA_OPTION_NO_PACK_KEYS 128 /* Reserved for MySQL */
|
||||
#define HA_OPTION_CREATE_FROM_ENGINE 256
|
||||
#define HA_OPTION_CREATE_FROM_ENGINE 256
|
||||
#define HA_OPTION_TEMP_COMPRESS_RECORD ((uint) 16384) /* set by isamchk */
|
||||
#define HA_OPTION_READ_ONLY_DATA ((uint) 32768) /* Set by isamchk */
|
||||
|
||||
|
@ -260,15 +260,48 @@ enum ha_base_keytype {
|
|||
#define HA_CREATE_CHECKSUM 8
|
||||
#define HA_CREATE_DELAY_KEY_WRITE 64
|
||||
|
||||
/* Bits in flag to _status */
|
||||
/*
|
||||
The following flags (OR-ed) are passed to handler::info() method.
|
||||
The method copies misc handler information out of the storage engine
|
||||
to data structures accessible from MySQL
|
||||
|
||||
#define HA_STATUS_POS 1 /* Return position */
|
||||
#define HA_STATUS_NO_LOCK 2 /* Don't use external lock */
|
||||
#define HA_STATUS_TIME 4 /* Return update time */
|
||||
#define HA_STATUS_CONST 8 /* Return constants values */
|
||||
#define HA_STATUS_VARIABLE 16
|
||||
#define HA_STATUS_ERRKEY 32
|
||||
#define HA_STATUS_AUTO 64
|
||||
Same flags are also passed down to mi_status, myrg_status, etc.
|
||||
*/
|
||||
|
||||
/* this one is not used */
|
||||
#define HA_STATUS_POS 1
|
||||
/*
|
||||
assuming the table keeps shared actual copy of the 'info' and
|
||||
local, possibly outdated copy, the following flag means that
|
||||
it should not try to get the actual data (locking the shared structure)
|
||||
slightly outdated version will suffice
|
||||
*/
|
||||
#define HA_STATUS_NO_LOCK 2
|
||||
/* update the time of the last modification (in handler::update_time) */
|
||||
#define HA_STATUS_TIME 4
|
||||
/*
|
||||
update the 'constant' part of the info:
|
||||
handler::max_data_file_length, max_index_file_length, create_time
|
||||
sortkey, ref_length, block_size, data_file_name, index_file_name.
|
||||
handler::table->s->keys_in_use, keys_for_keyread, rec_per_key
|
||||
*/
|
||||
#define HA_STATUS_CONST 8
|
||||
/*
|
||||
update the 'variable' part of the info:
|
||||
handler::records, deleted, data_file_length, index_file_length,
|
||||
delete_length, check_time, mean_rec_length
|
||||
*/
|
||||
#define HA_STATUS_VARIABLE 16
|
||||
/*
|
||||
get the information about the key that caused last duplicate value error
|
||||
update handler::errkey and handler::dupp_ref
|
||||
see handler::get_dup_key()
|
||||
*/
|
||||
#define HA_STATUS_ERRKEY 32
|
||||
/*
|
||||
update handler::auto_increment_value
|
||||
*/
|
||||
#define HA_STATUS_AUTO 64
|
||||
|
||||
/* Errorcodes given by functions */
|
||||
|
||||
|
|
|
@ -574,11 +574,7 @@ typedef SOCKET_SIZE_TYPE size_socket;
|
|||
#define FN_LEN 256 /* Max file name len */
|
||||
#define FN_HEADLEN 253 /* Max length of filepart of file name */
|
||||
#define FN_EXTLEN 20 /* Max length of extension (part of FN_LEN) */
|
||||
#ifdef PATH_MAX
|
||||
#define FN_REFLEN PATH_MAX/* Max length of full path-name */
|
||||
#else
|
||||
#define FN_REFLEN 512 /* Max length of full path-name */
|
||||
#endif
|
||||
#define FN_EXTCHAR '.'
|
||||
#define FN_HOMELIB '~' /* ~/ is used as abbrev for home dir */
|
||||
#define FN_CURLIB '.' /* ./ is used as abbrev for current dir */
|
||||
|
|
|
@ -80,8 +80,7 @@ INC_LIB= $(top_builddir)/regex/libregex.a \
|
|||
$(top_builddir)/mysys/libmysys.a \
|
||||
$(top_builddir)/strings/libmystrings.a \
|
||||
$(top_builddir)/dbug/libdbug.a \
|
||||
$(top_builddir)/vio/libvio.a \
|
||||
@yassl_libs_with_path@
|
||||
$(top_builddir)/vio/libvio.a
|
||||
|
||||
|
||||
#
|
||||
|
|
|
@ -34,8 +34,8 @@ link_sources:
|
|||
DEFS = -DEMBEDDED_LIBRARY
|
||||
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir) \
|
||||
-I$(top_srcdir) -I$(top_srcdir)/client -I$(top_srcdir)/regex \
|
||||
$(openssl_includes)
|
||||
LIBS = @LIBS@ @WRAPLIBS@ @CLIENT_LIBS@
|
||||
$(openssl_includes) $(yassl_includes)
|
||||
LIBS = @LIBS@ @WRAPLIBS@ @CLIENT_LIBS@ $(yassl_libs)
|
||||
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysqld.a @innodb_system_libs@ @LIBDL@ $(CXXLDFLAGS)
|
||||
|
||||
mysqltest_embedded_LINK = $(CXXLINK)
|
||||
|
|
|
@ -149,8 +149,10 @@ byte ft_get_word(CHARSET_INFO *cs, byte **start, byte *end,
|
|||
for (word->pos=doc; doc<end; length++, mbl=my_mbcharlen(cs, *(uchar *)doc), doc+=(mbl ? mbl : 1))
|
||||
if (true_word_char(cs,*doc))
|
||||
mwc=0;
|
||||
else if (!misc_word_char(*doc) || mwc++)
|
||||
else if (!misc_word_char(*doc) || mwc)
|
||||
break;
|
||||
else
|
||||
mwc++;
|
||||
|
||||
param->prev='A'; /* be sure *prev is true_word_char */
|
||||
word->len= (uint)(doc-word->pos) - mwc;
|
||||
|
|
4
mysql-test/include/is_debug_build.inc
Normal file
4
mysql-test/include/is_debug_build.inc
Normal file
|
@ -0,0 +1,4 @@
|
|||
-- require r/is_debug_build.require
|
||||
--disable_query_log
|
||||
select instr(version(), "debug") > 0;
|
||||
--enable_query_log
|
|
@ -9,7 +9,7 @@ use strict;
|
|||
sub mtr_full_hostname ();
|
||||
sub mtr_short_hostname ();
|
||||
sub mtr_init_args ($);
|
||||
sub mtr_add_arg ($$);
|
||||
sub mtr_add_arg ($$@);
|
||||
sub mtr_path_exists(@);
|
||||
sub mtr_script_exists(@);
|
||||
sub mtr_exe_exists(@);
|
||||
|
@ -51,7 +51,7 @@ sub mtr_init_args ($) {
|
|||
$$args = []; # Empty list
|
||||
}
|
||||
|
||||
sub mtr_add_arg ($$) {
|
||||
sub mtr_add_arg ($$@) {
|
||||
my $args= shift;
|
||||
my $format= shift;
|
||||
my @fargs = @_;
|
||||
|
|
172
mysql-test/lib/mtr_stress.pl
Normal file
172
mysql-test/lib/mtr_stress.pl
Normal file
|
@ -0,0 +1,172 @@
|
|||
# -*- cperl -*-
|
||||
|
||||
# This is a library file used by the Perl version of mysql-test-run,
|
||||
# and is part of the translation of the Bourne shell script with the
|
||||
# same name.
|
||||
|
||||
use strict;
|
||||
use File::Spec;
|
||||
|
||||
# These are not to be prefixed with "mtr_"
|
||||
|
||||
sub run_stress_test ();
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Run tests in the stress mode
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
sub run_stress_test ()
|
||||
{
|
||||
|
||||
my $args;
|
||||
my $stress_basedir;
|
||||
my $stress_suitedir;
|
||||
|
||||
mtr_report("Starting stress testing\n");
|
||||
|
||||
if ( ! $::glob_use_embedded_server and ! $::opt_local_master )
|
||||
{
|
||||
$::master->[0]->{'pid'}= mysqld_start('master',0,[],[]);
|
||||
if ( ! $::master->[0]->{'pid'} )
|
||||
{
|
||||
mtr_error("Can't start the mysqld server");
|
||||
}
|
||||
}
|
||||
|
||||
my $stress_basedir=File::Spec->catdir($::opt_vardir, "stress");
|
||||
|
||||
#Clean up stress dir
|
||||
if ( -d $stress_basedir )
|
||||
{
|
||||
rmtree($stress_basedir);
|
||||
}
|
||||
mkpath($stress_basedir);
|
||||
|
||||
if ($::opt_stress_suite ne 'main' && $::opt_stress_suite ne 'default' )
|
||||
{
|
||||
$stress_suitedir=File::Spec->catdir($::glob_mysql_test_dir, "suite",
|
||||
$::opt_stress_suite);
|
||||
}
|
||||
else
|
||||
{
|
||||
$stress_suitedir=$::glob_mysql_test_dir;
|
||||
}
|
||||
|
||||
if ( -d $stress_suitedir )
|
||||
{
|
||||
#$stress_suite_t_dir=File::Spec->catdir($stress_suitedir, "t");
|
||||
#$stress_suite_r_dir=File::Spec->catdir($stress_suitedir, "r");
|
||||
#FIXME: check dirs above for existence to ensure that test suite
|
||||
# contains tests and results dirs
|
||||
}
|
||||
else
|
||||
{
|
||||
mtr_error("Specified test suite $::opt_stress_suite doesn't exist");
|
||||
}
|
||||
|
||||
if ( @::opt_cases )
|
||||
{
|
||||
$::opt_stress_test_file=File::Spec->catfile($stress_basedir, "stress_tests.txt");
|
||||
open(STRESS_FILE, ">$::opt_stress_test_file");
|
||||
print STRESS_FILE join("\n",@::opt_cases),"\n";
|
||||
close(STRESS_FILE);
|
||||
}
|
||||
elsif ( $::opt_stress_test_file )
|
||||
{
|
||||
$::opt_stress_test_file=File::Spec->catfile($stress_suitedir,
|
||||
$::opt_stress_test_file);
|
||||
if ( ! -f $::opt_stress_test_file )
|
||||
{
|
||||
mtr_error("Specified file $::opt_stress_test_file with list of tests does not exist\n",
|
||||
"Please ensure that file exists and has proper permissions");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$::opt_stress_test_file=File::Spec->catfile($stress_suitedir,
|
||||
"stress_tests.txt");
|
||||
if ( ! -f $::opt_stress_test_file )
|
||||
{
|
||||
mtr_error("Default file $::opt_stress_test_file with list of tests does not exist\n",
|
||||
"Please use --stress-test-file option to specify custom one or you can\n",
|
||||
"just specify name of test for testing as last argument in command line");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ( $::opt_stress_init_file )
|
||||
{
|
||||
$::opt_stress_init_file=File::Spec->catfile($stress_suitedir,
|
||||
$::opt_stress_init_file);
|
||||
if ( ! -f $::opt_stress_init_file )
|
||||
{
|
||||
mtr_error("Specified file $::opt_stress_init_file with list of tests does not exist\n",
|
||||
"Please ensure that file exists and has proper permissions");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$::opt_stress_init_file=File::Spec->catfile($stress_suitedir,
|
||||
"stress_init.txt");
|
||||
if ( ! -f $::opt_stress_init_file )
|
||||
{
|
||||
$::opt_stress_init_file='';
|
||||
}
|
||||
}
|
||||
|
||||
if ( $::opt_stress_mode ne 'random' && $::opt_stress_mode ne 'seq' )
|
||||
{
|
||||
mtr_error("You specified wrong mode $::opt_stress_mode for stress test\n",
|
||||
"Correct values are 'random' or 'seq'");
|
||||
}
|
||||
|
||||
mtr_init_args(\$args);
|
||||
|
||||
mtr_add_arg($args, "--server-socket=%s", $::master->[0]->{'path_mysock'});
|
||||
mtr_add_arg($args, "--server-user=%s", $::opt_user);
|
||||
mtr_add_arg($args, "--server-database=%s", "test");
|
||||
mtr_add_arg($args, "--stress-suite-basedir=%s", $::glob_mysql_test_dir);
|
||||
mtr_add_arg($args, "--suite=%s", $::opt_stress_suite);
|
||||
mtr_add_arg($args, "--stress-tests-file=%s", $::opt_stress_test_file);
|
||||
mtr_add_arg($args, "--stress-basedir=%s", $stress_basedir);
|
||||
mtr_add_arg($args, "--server-logs-dir=%s", $stress_basedir);
|
||||
mtr_add_arg($args, "--stress-mode=%s", $::opt_stress_mode);
|
||||
mtr_add_arg($args, "--mysqltest=%s", $::exe_mysqltest);
|
||||
mtr_add_arg($args, "--threads=%s", $::opt_stress_threads);
|
||||
mtr_add_arg($args, "--verbose");
|
||||
mtr_add_arg($args, "--cleanup");
|
||||
mtr_add_arg($args, "--log-error-details");
|
||||
mtr_add_arg($args, "--abort-on-error");
|
||||
|
||||
if ( $::opt_stress_init_file )
|
||||
{
|
||||
mtr_add_arg($args, "--stress-init-file=%", $::opt_stress_init_file);
|
||||
}
|
||||
|
||||
if ( $::opt_stress_loop_count )
|
||||
{
|
||||
mtr_add_arg($args, "--loop-count=%s", $::opt_stress_loop_count);
|
||||
}
|
||||
|
||||
if ( $::opt_stress_test_count )
|
||||
{
|
||||
mtr_add_arg($args, "--test-count=%s", $::opt_stress_test_count);
|
||||
}
|
||||
|
||||
if ( $::opt_stress_test_duration )
|
||||
{
|
||||
mtr_add_arg($args, "--test-duration=%s", $::opt_stress_test_duration);
|
||||
}
|
||||
|
||||
#Run stress test
|
||||
mtr_run("$::glob_mysql_test_dir/mysql-stress-test.pl", $args, "", "", "", "");
|
||||
|
||||
if ( ! $::glob_use_embedded_server )
|
||||
{
|
||||
stop_masters();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
|
@ -96,6 +96,7 @@ require "lib/mtr_report.pl";
|
|||
require "lib/mtr_diff.pl";
|
||||
require "lib/mtr_match.pl";
|
||||
require "lib/mtr_misc.pl";
|
||||
require "lib/mtr_stress.pl";
|
||||
|
||||
$Devel::Trace::TRACE= 1;
|
||||
|
||||
|
@ -271,6 +272,16 @@ our $opt_valgrind_mysqltest;
|
|||
our $opt_valgrind_all;
|
||||
our $opt_valgrind_options;
|
||||
|
||||
our $opt_stress= "";
|
||||
our $opt_stress_suite= "main";
|
||||
our $opt_stress_mode= "random";
|
||||
our $opt_stress_threads= 5;
|
||||
our $opt_stress_test_count= 20;
|
||||
our $opt_stress_loop_count= "";
|
||||
our $opt_stress_test_duration= "";
|
||||
our $opt_stress_init_file= "";
|
||||
our $opt_stress_test_file= "";
|
||||
|
||||
our $opt_verbose;
|
||||
|
||||
our $opt_wait_for_master;
|
||||
|
@ -391,6 +402,10 @@ sub main () {
|
|||
{
|
||||
run_benchmarks(shift); # Shift what? Extra arguments?!
|
||||
}
|
||||
elsif ( $opt_stress )
|
||||
{
|
||||
run_stress_test()
|
||||
}
|
||||
else
|
||||
{
|
||||
run_tests();
|
||||
|
@ -547,6 +562,17 @@ sub command_line_setup () {
|
|||
'valgrind-all:s' => \$opt_valgrind_all,
|
||||
'valgrind-options=s' => \$opt_valgrind_options,
|
||||
|
||||
# Stress testing
|
||||
'stress' => \$opt_stress,
|
||||
'stress-suite=s' => \$opt_stress_suite,
|
||||
'stress-threads=i' => \$opt_stress_threads,
|
||||
'stress-test-file=s' => \$opt_stress_test_file,
|
||||
'stress-init-file=s' => \$opt_stress_init_file,
|
||||
'stress-mode=s' => \$opt_stress_mode,
|
||||
'stress-loop-count=i' => \$opt_stress_loop_count,
|
||||
'stress-test-count=i' => \$opt_stress_test_count,
|
||||
'stress-test-duration=i' => \$opt_stress_test_duration,
|
||||
|
||||
# Misc
|
||||
'big-test' => \$opt_big_test,
|
||||
'debug' => \$opt_debug,
|
||||
|
|
|
@ -4976,3 +4976,27 @@ c1
|
|||
4
|
||||
5
|
||||
DROP TABLE bug14672;
|
||||
create table t1 (a int) engine=csv;
|
||||
insert t1 values (1);
|
||||
delete from t1;
|
||||
affected rows: 1
|
||||
delete from t1;
|
||||
affected rows: 0
|
||||
insert t1 values (1),(2);
|
||||
delete from t1;
|
||||
affected rows: 2
|
||||
insert t1 values (1),(2),(3);
|
||||
flush tables;
|
||||
delete from t1;
|
||||
affected rows: 3
|
||||
insert t1 values (1),(2),(3),(4);
|
||||
flush tables;
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
4
|
||||
delete from t1;
|
||||
affected rows: 4
|
||||
insert t1 values (1),(2),(3),(4),(5);
|
||||
truncate table t1;
|
||||
affected rows: 0
|
||||
drop table t1;
|
||||
|
|
|
@ -1095,6 +1095,11 @@ char(0xff,0x8f using utf8)
|
|||
ÿ<EFBFBD>
|
||||
Warnings:
|
||||
Warning 1300 Invalid utf8 character string: 'FF8F'
|
||||
select convert(char(0xff,0x8f) using utf8);
|
||||
convert(char(0xff,0x8f) using utf8)
|
||||
ÿ<EFBFBD>
|
||||
Warnings:
|
||||
Warning 1300 Invalid utf8 character string: 'FF8F'
|
||||
set sql_mode=traditional;
|
||||
select char(0xff,0x8f using utf8);
|
||||
char(0xff,0x8f using utf8)
|
||||
|
@ -1116,6 +1121,11 @@ char(2557 using utf8)
|
|||
NULL
|
||||
Warnings:
|
||||
Error 1300 Invalid utf8 character string: 'FD'
|
||||
select convert(char(0xff,0x8f) using utf8);
|
||||
convert(char(0xff,0x8f) using utf8)
|
||||
NULL
|
||||
Warnings:
|
||||
Error 1300 Invalid utf8 character string: 'FF8F'
|
||||
select hex(convert(char(2557 using latin1) using utf8));
|
||||
hex(convert(char(2557 using latin1) using utf8))
|
||||
09C3BD
|
||||
|
|
|
@ -40,14 +40,14 @@ CREATE TABLE federated.t1 (
|
|||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t3';
|
||||
ERROR HY000: Can't create federated table. Foreign data src error : ': 1146 : Table 'federated.t3' doesn't exist'
|
||||
ERROR HY000: Can't create federated table. Foreign data src error: error: 1146 'Table 'federated.t3' doesn't exist'
|
||||
CREATE TABLE federated.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(32) NOT NULL default ''
|
||||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://user:pass@127.0.0.1:SLAVE_PORT/federated/t1';
|
||||
ERROR HY000: Unable to connect to foreign data source - database ' database federated username user hostname 127.0.0.1'!
|
||||
ERROR HY000: Unable to connect to foreign data source: database: 'federated' username: 'user' hostname: '127.0.0.1'
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
|
|
|
@ -433,4 +433,7 @@ INSERT INTO t1 VALUES('testword\'\'');
|
|||
SELECT a FROM t1 WHERE MATCH a AGAINST('testword' IN BOOLEAN MODE);
|
||||
a
|
||||
testword''
|
||||
SELECT a FROM t1 WHERE MATCH a AGAINST('testword\'\'' IN BOOLEAN MODE);
|
||||
a
|
||||
testword''
|
||||
DROP TABLE t1;
|
||||
|
|
|
@ -238,7 +238,7 @@ Grants for drop_user@localhost
|
|||
GRANT USAGE ON *.* TO 'drop_user'@'localhost'
|
||||
drop user drop_user@localhost;
|
||||
revoke all privileges, grant option from drop_user@localhost;
|
||||
ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users
|
||||
ERROR HY000: Can't revoke all privileges for one or more of the requested users
|
||||
grant select(a) on test.t1 to drop_user1@localhost;
|
||||
grant select on test.t1 to drop_user2@localhost;
|
||||
grant select on test.* to drop_user3@localhost;
|
||||
|
@ -247,7 +247,7 @@ drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
|
|||
drop_user4@localhost;
|
||||
revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost,
|
||||
drop_user3@localhost, drop_user4@localhost;
|
||||
ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users
|
||||
ERROR HY000: Can't revoke all privileges for one or more of the requested users
|
||||
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
|
||||
drop_user4@localhost;
|
||||
ERROR HY000: Operation DROP USER failed for 'drop_user1'@'localhost','drop_user2'@'localhost','drop_user3'@'localhost','drop_user4'@'localhost'
|
||||
|
|
|
@ -191,7 +191,7 @@ flush privileges;
|
|||
show grants for 'mysqltest_1';
|
||||
ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%'
|
||||
revoke all privileges, grant option from 'mysqltest_1';
|
||||
ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users
|
||||
ERROR HY000: Can't revoke all privileges for one or more of the requested users
|
||||
drop user 'mysqltest_1';
|
||||
select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user;
|
||||
host db user
|
||||
|
|
|
@ -2002,3 +2002,13 @@ a count(a)
|
|||
1 1
|
||||
NULL 1
|
||||
drop table t1;
|
||||
create table t1 (f1 int, f2 char(1), primary key(f1,f2)) engine=innodb;
|
||||
insert into t1 values ( 1,"e"),(2,"a"),( 3,"c"),(4,"d");
|
||||
alter table t1 drop primary key, add primary key (f2, f1);
|
||||
explain select distinct f1 a, f1 b from t1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index NULL PRIMARY 5 NULL 4 Using index; Using temporary
|
||||
explain select distinct f1, f2 from t1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range NULL PRIMARY 5 NULL 3 Using index for group-by; Using temporary
|
||||
drop table t1;
|
||||
|
|
2
mysql-test/r/is_debug_build.require
Normal file
2
mysql-test/r/is_debug_build.require
Normal file
|
@ -0,0 +1,2 @@
|
|||
instr(version(), "debug") > 0
|
||||
1
|
|
@ -1466,4 +1466,4 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||
1 SIMPLE t4 ref a a 5 test.t3.b X
|
||||
1 SIMPLE t6 ref a a 5 test.t4.b X
|
||||
1 SIMPLE t5 ref a a 5 test.t3.b X
|
||||
drop table t0, t1, t2, t4, t5, t6;
|
||||
drop table t0, t1, t2, t3, t4, t5, t6, t7;
|
||||
|
|
|
@ -179,7 +179,7 @@ a b c
|
|||
2 two two
|
||||
alter table t1 drop index c;
|
||||
select * from t1 where b = 'two';
|
||||
ERROR HY000: Table definition has changed, please retry transaction
|
||||
ERROR HY000: Can't lock file (errno: 241)
|
||||
select * from t1 where b = 'two';
|
||||
a b c
|
||||
2 two two
|
||||
|
|
|
@ -667,13 +667,13 @@ counter datavalue
|
|||
57 newval
|
||||
58 newval
|
||||
drop table t1;
|
||||
CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb;
|
||||
select * from t1;
|
||||
b
|
||||
drop table t1;
|
||||
create table atablewithareallylongandirritatingname (a int);
|
||||
insert into atablewithareallylongandirritatingname values (2);
|
||||
select * from atablewithareallylongandirritatingname;
|
||||
a
|
||||
2
|
||||
drop table atablewithareallylongandirritatingname;
|
||||
CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb;
|
||||
select * from t1;
|
||||
b
|
||||
drop table t1;
|
||||
|
|
|
@ -806,3 +806,22 @@ execute stmt;
|
|||
@@tx_isolation
|
||||
REPEATABLE-READ
|
||||
deallocate prepare stmt;
|
||||
prepare stmt from "create temporary table t1 (letter enum('','a','b','c')
|
||||
not null)";
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
set names latin1;
|
||||
prepare stmt from "create table t1 (a enum('test') default 'test')
|
||||
character set utf8";
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
set names default;
|
||||
deallocate prepare stmt;
|
||||
|
|
|
@ -2708,6 +2708,14 @@ select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1;
|
|||
count(f2) >0
|
||||
1
|
||||
drop table t1,t2;
|
||||
create table t1 (f1 int,f2 int);
|
||||
insert into t1 values(1,1);
|
||||
create table t2 (f3 int, f4 int, primary key(f3,f4));
|
||||
insert into t2 values(1,1);
|
||||
select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 from t2));
|
||||
f1 f2
|
||||
1 1
|
||||
drop table t1,t2;
|
||||
CREATE TABLE t1 ( city char(30) );
|
||||
INSERT INTO t1 VALUES ('London');
|
||||
INSERT INTO t1 VALUES ('Paris');
|
||||
|
@ -3283,3 +3291,49 @@ f1 f2 x1
|
|||
30 1 30
|
||||
drop table t1;
|
||||
drop view v1, v2, v3;
|
||||
CREATE TABLE t1(key_a int4 NOT NULL, optimus varchar(32), PRIMARY KEY(key_a));
|
||||
CREATE TABLE t2(key_a int4 NOT NULL, prime varchar(32), PRIMARY KEY(key_a));
|
||||
CREATE table t3(key_a int4 NOT NULL, key_b int4 NOT NULL, foo varchar(32),
|
||||
PRIMARY KEY(key_a,key_b));
|
||||
INSERT INTO t1 VALUES (0,'');
|
||||
INSERT INTO t1 VALUES (1,'i');
|
||||
INSERT INTO t1 VALUES (2,'j');
|
||||
INSERT INTO t1 VALUES (3,'k');
|
||||
INSERT INTO t2 VALUES (1,'r');
|
||||
INSERT INTO t2 VALUES (2,'s');
|
||||
INSERT INTO t2 VALUES (3,'t');
|
||||
INSERT INTO t3 VALUES (1,5,'x');
|
||||
INSERT INTO t3 VALUES (1,6,'y');
|
||||
INSERT INTO t3 VALUES (2,5,'xx');
|
||||
INSERT INTO t3 VALUES (2,6,'yy');
|
||||
INSERT INTO t3 VALUES (2,7,'zz');
|
||||
INSERT INTO t3 VALUES (3,5,'xxx');
|
||||
SELECT t2.key_a,foo
|
||||
FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a
|
||||
INNER JOIN t3 ON t1.key_a = t3.key_a
|
||||
WHERE t2.key_a=2 and key_b=5;
|
||||
key_a foo
|
||||
2 xx
|
||||
EXPLAIN SELECT t2.key_a,foo
|
||||
FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a
|
||||
INNER JOIN t3 ON t1.key_a = t3.key_a
|
||||
WHERE t2.key_a=2 and key_b=5;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
|
||||
1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 Using index
|
||||
1 SIMPLE t3 const PRIMARY PRIMARY 8 const,const 1
|
||||
SELECT t2.key_a,foo
|
||||
FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a
|
||||
INNER JOIN t3 ON t1.key_a = t3.key_a
|
||||
WHERE t2.key_a=2 and key_b=5;
|
||||
key_a foo
|
||||
2 xx
|
||||
EXPLAIN SELECT t2.key_a,foo
|
||||
FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a
|
||||
INNER JOIN t3 ON t1.key_a = t3.key_a
|
||||
WHERE t2.key_a=2 and key_b=5;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
|
||||
1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 Using index
|
||||
1 SIMPLE t3 const PRIMARY PRIMARY 8 const,const 1
|
||||
DROP TABLE t1,t2,t3;
|
||||
|
|
62
mysql-test/r/sp-code.result
Normal file
62
mysql-test/r/sp-code.result
Normal file
|
@ -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;
|
|
@ -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: 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: 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
|
||||
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 limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine p1
|
||||
call p1()|
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -988,6 +988,10 @@ end|
|
|||
select f5(1)|
|
||||
f5(1)
|
||||
1
|
||||
select f5(2)|
|
||||
ERROR HY000: Recursive stored functions and triggers are not allowed.
|
||||
select f5(3)|
|
||||
ERROR HY000: Recursive stored functions and triggers are not allowed.
|
||||
create function f6() returns int
|
||||
begin
|
||||
declare n int;
|
||||
|
@ -1035,6 +1039,12 @@ select * from v1|
|
|||
ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
|
||||
create function f1() returns int
|
||||
return (select sum(data) from t1) + (select sum(data) from v1)|
|
||||
select f1()|
|
||||
ERROR HY000: Recursive stored functions and triggers are not allowed.
|
||||
select * from v1|
|
||||
ERROR HY000: Recursive stored functions and triggers are not allowed.
|
||||
select * from v2|
|
||||
ERROR HY000: Recursive stored functions and triggers are not allowed.
|
||||
drop function f1|
|
||||
create function f1() returns int
|
||||
return (select sum(data) from t1)|
|
||||
|
@ -1053,7 +1063,7 @@ f0()
|
|||
select *, f0() from v0|
|
||||
f0() f0()
|
||||
100 100
|
||||
lock tables t1 read, t1 as t11 read, mysql.proc read|
|
||||
lock tables t1 read, t1 as t11 read|
|
||||
select f3()|
|
||||
f3()
|
||||
1
|
||||
|
@ -1251,6 +1261,62 @@ drop procedure opp|
|
|||
drop procedure ip|
|
||||
show procedure status like '%p%'|
|
||||
Db Name Type Definer Modified Created Security_type Comment
|
||||
drop table if exists fib|
|
||||
create table fib ( f bigint unsigned not null )|
|
||||
drop procedure if exists fib|
|
||||
create procedure fib(n int unsigned)
|
||||
begin
|
||||
if n > 1 then
|
||||
begin
|
||||
declare x, y bigint unsigned;
|
||||
declare c cursor for select f from fib order by f desc limit 2;
|
||||
open c;
|
||||
fetch c into y;
|
||||
fetch c into x;
|
||||
close c;
|
||||
insert into fib values (x+y);
|
||||
call fib(n-1);
|
||||
end;
|
||||
end if;
|
||||
end|
|
||||
set @@max_sp_recursion_depth= 20|
|
||||
insert into fib values (0), (1)|
|
||||
call fib(3)|
|
||||
select * from fib order by f asc|
|
||||
f
|
||||
0
|
||||
1
|
||||
1
|
||||
2
|
||||
delete from fib|
|
||||
insert into fib values (0), (1)|
|
||||
call fib(20)|
|
||||
select * from fib order by f asc|
|
||||
f
|
||||
0
|
||||
1
|
||||
1
|
||||
2
|
||||
3
|
||||
5
|
||||
8
|
||||
13
|
||||
21
|
||||
34
|
||||
55
|
||||
89
|
||||
144
|
||||
233
|
||||
377
|
||||
610
|
||||
987
|
||||
1597
|
||||
2584
|
||||
4181
|
||||
6765
|
||||
drop table fib|
|
||||
drop procedure fib|
|
||||
set @@max_sp_recursion_depth= 0|
|
||||
drop procedure if exists bar|
|
||||
create procedure bar(x char(16), y int)
|
||||
comment "111111111111" sql security invoker
|
||||
|
@ -1479,6 +1545,52 @@ select @x2|
|
|||
@x2
|
||||
2
|
||||
drop procedure bug2260|
|
||||
drop procedure if exists bug2267_1|
|
||||
create procedure bug2267_1()
|
||||
begin
|
||||
show procedure status;
|
||||
end|
|
||||
drop procedure if exists bug2267_2|
|
||||
create procedure bug2267_2()
|
||||
begin
|
||||
show function status;
|
||||
end|
|
||||
drop procedure if exists bug2267_3|
|
||||
create procedure bug2267_3()
|
||||
begin
|
||||
show create procedure bug2267_1;
|
||||
end|
|
||||
drop procedure if exists bug2267_4|
|
||||
drop function if exists bug2267_4|
|
||||
create procedure bug2267_4()
|
||||
begin
|
||||
show create function bug2267_4;
|
||||
end|
|
||||
create function bug2267_4() returns int return 100|
|
||||
call bug2267_1()|
|
||||
Db Name Type Definer Modified Created Security_type Comment
|
||||
test bug2267_1 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||
test bug2267_2 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||
test bug2267_3 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||
test bug2267_4 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||
call bug2267_2()|
|
||||
Db Name Type Definer Modified Created Security_type Comment
|
||||
test bug2267_4 FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
|
||||
call bug2267_3()|
|
||||
Procedure sql_mode Create Procedure
|
||||
bug2267_1 CREATE PROCEDURE `bug2267_1`()
|
||||
begin
|
||||
show procedure status;
|
||||
end
|
||||
call bug2267_4()|
|
||||
Function sql_mode Create Function
|
||||
bug2267_4 CREATE FUNCTION `bug2267_4`() RETURNS int(11)
|
||||
return 100
|
||||
drop procedure bug2267_1|
|
||||
drop procedure bug2267_2|
|
||||
drop procedure bug2267_3|
|
||||
drop procedure bug2267_4|
|
||||
drop function bug2267_4|
|
||||
drop procedure if exists bug2227|
|
||||
create procedure bug2227(x int)
|
||||
begin
|
||||
|
@ -1490,6 +1602,18 @@ call bug2227(9)|
|
|||
1.3 x y 42 z
|
||||
1.3 9 2.6 42 zzz
|
||||
drop procedure bug2227|
|
||||
drop procedure if exists bug2614|
|
||||
create procedure bug2614()
|
||||
begin
|
||||
drop table if exists t3;
|
||||
create table t3 (id int default '0' not null);
|
||||
insert into t3 select 12;
|
||||
insert into t3 select * from t3;
|
||||
end|
|
||||
call bug2614()|
|
||||
call bug2614()|
|
||||
drop table t3|
|
||||
drop procedure bug2614|
|
||||
drop function if exists bug2674|
|
||||
create function bug2674() returns int
|
||||
return @@sort_buffer_size|
|
||||
|
@ -3417,6 +3541,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 +3794,220 @@ 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 procedure if exists bug13729|
|
||||
drop table if exists t3|
|
||||
create table t3 (s1 int, primary key (s1))|
|
||||
insert into t3 values (1),(2)|
|
||||
create procedure bug13729()
|
||||
begin
|
||||
declare continue handler for sqlexception select 55;
|
||||
update t3 set s1 = 1;
|
||||
end|
|
||||
call bug13729()|
|
||||
55
|
||||
55
|
||||
select * from t3|
|
||||
s1
|
||||
1
|
||||
2
|
||||
drop procedure bug13729|
|
||||
drop table t3|
|
||||
drop table t1,t2;
|
||||
|
|
|
@ -369,3 +369,59 @@ drop procedure bug13825_0|
|
|||
drop procedure bug13825_1|
|
||||
drop procedure bug13825_2|
|
||||
drop table t1, t2|
|
||||
drop table if exists t3|
|
||||
drop procedure if exists bug14840_1|
|
||||
drop procedure if exists bug14840_2|
|
||||
create table t3
|
||||
(
|
||||
x int,
|
||||
y int,
|
||||
primary key (x)
|
||||
) engine=InnoDB|
|
||||
create procedure bug14840_1()
|
||||
begin
|
||||
declare err int default 0;
|
||||
declare continue handler for sqlexception
|
||||
set err = err + 1;
|
||||
start transaction;
|
||||
update t3 set x = 1, y = 42 where x = 2;
|
||||
insert into t3 values (3, 4711);
|
||||
if err > 0 then
|
||||
rollback;
|
||||
else
|
||||
commit;
|
||||
end if;
|
||||
select * from t3;
|
||||
end|
|
||||
create procedure bug14840_2()
|
||||
begin
|
||||
declare err int default 0;
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
set err = err + 1;
|
||||
select err as 'Ping';
|
||||
end;
|
||||
update t3 set x = 1, y = 42 where x = 2;
|
||||
update t3 set x = 1, y = 42 where x = 2;
|
||||
insert into t3 values (3, 4711);
|
||||
select * from t3;
|
||||
end|
|
||||
insert into t3 values (1, 3), (2, 5)|
|
||||
call bug14840_1()|
|
||||
x y
|
||||
1 3
|
||||
2 5
|
||||
delete from t3|
|
||||
insert into t3 values (1, 3), (2, 5)|
|
||||
call bug14840_2()|
|
||||
Ping
|
||||
1
|
||||
Ping
|
||||
2
|
||||
x y
|
||||
1 3
|
||||
2 5
|
||||
3 4711
|
||||
drop procedure bug14840_1|
|
||||
drop procedure bug14840_2|
|
||||
drop table t3|
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1352,3 +1352,35 @@ SELECT * FROM bug14672;
|
|||
DROP TABLE bug14672;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
# BUG#13406 - incorrect amount of "records deleted"
|
||||
#
|
||||
|
||||
create table t1 (a int) engine=csv;
|
||||
insert t1 values (1);
|
||||
--enable_info
|
||||
delete from t1; -- delete_row
|
||||
delete from t1; -- delete_all_rows
|
||||
--disable_info
|
||||
insert t1 values (1),(2);
|
||||
--enable_info
|
||||
delete from t1; -- delete_all_rows
|
||||
--disable_info
|
||||
insert t1 values (1),(2),(3);
|
||||
flush tables;
|
||||
--enable_info
|
||||
delete from t1; -- delete_row
|
||||
--disable_info
|
||||
insert t1 values (1),(2),(3),(4);
|
||||
flush tables;
|
||||
select count(*) from t1;
|
||||
--enable_info
|
||||
delete from t1; -- delete_all_rows
|
||||
--disable_info
|
||||
insert t1 values (1),(2),(3),(4),(5);
|
||||
--enable_info
|
||||
truncate table t1; -- truncate
|
||||
--disable_info
|
||||
drop table t1;
|
||||
|
||||
|
|
|
@ -884,7 +884,9 @@ SELECT DISTINCT id FROM t1 ORDER BY id;
|
|||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bugs#10504: Character set does not support traditional mode
|
||||
# Bug#10504: Character set does not support traditional mode
|
||||
# Bug#14146: CHAR(...USING ...) and CONVERT(CHAR(...) USING...)
|
||||
# produce different results
|
||||
#
|
||||
set names utf8;
|
||||
# correct value
|
||||
|
@ -894,12 +896,14 @@ select char(0xd18f using utf8);
|
|||
select char(53647 using utf8);
|
||||
# incorrect value: return with warning
|
||||
select char(0xff,0x8f using utf8);
|
||||
select convert(char(0xff,0x8f) using utf8);
|
||||
# incorrect value in strict mode: return NULL with "Error" level warning
|
||||
set sql_mode=traditional;
|
||||
select char(0xff,0x8f using utf8);
|
||||
select char(195 using utf8);
|
||||
select char(196 using utf8);
|
||||
select char(2557 using utf8);
|
||||
select convert(char(0xff,0x8f) using utf8);
|
||||
|
||||
#
|
||||
# Check convert + char + using
|
||||
|
|
|
@ -354,6 +354,7 @@ SET myisam_repair_threads=@@global.myisam_repair_threads;
|
|||
#
|
||||
INSERT INTO t1 VALUES('testword\'\'');
|
||||
SELECT a FROM t1 WHERE MATCH a AGAINST('testword' IN BOOLEAN MODE);
|
||||
SELECT a FROM t1 WHERE MATCH a AGAINST('testword\'\'' IN BOOLEAN MODE);
|
||||
DROP TABLE t1;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
|
|
@ -693,3 +693,13 @@ create table t1(a int, key(a)) engine=innodb;
|
|||
insert into t1 values(1);
|
||||
select a, count(a) from t1 group by a with rollup;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug #13293 Wrongly used index results in endless loop.
|
||||
#
|
||||
create table t1 (f1 int, f2 char(1), primary key(f1,f2)) engine=innodb;
|
||||
insert into t1 values ( 1,"e"),(2,"a"),( 3,"c"),(4,"d");
|
||||
alter table t1 drop primary key, add primary key (f2, f1);
|
||||
explain select distinct f1 a, f1 b from t1;
|
||||
explain select distinct f1, f2 from t1;
|
||||
drop table t1;
|
||||
|
|
|
@ -899,4 +899,4 @@ explain select * from t2 left join
|
|||
(t3 left join (t4 join t6 on t6.a=t4.b) on t4.a=t3.b
|
||||
join t5 on t5.a=t3.b) on t3.a=t2.b;
|
||||
|
||||
drop table t0, t1, t2, t4, t5, t6;
|
||||
drop table t0, t1, t2, t3, t4, t5, t6, t7;
|
||||
|
|
|
@ -153,7 +153,7 @@ connection server1;
|
|||
alter table t1 drop index c;
|
||||
connection server2;
|
||||
# This should fail since index information is not automatically refreshed
|
||||
--error 1412
|
||||
--error 1015
|
||||
select * from t1 where b = 'two';
|
||||
select * from t1 where b = 'two';
|
||||
connection server1;
|
||||
|
|
|
@ -606,6 +606,14 @@ select * from t1 order by counter;
|
|||
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# BUG#14514 Creating table with packed key fails silently
|
||||
#
|
||||
|
||||
CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb;
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
|
@ -615,12 +623,3 @@ create table atablewithareallylongandirritatingname (a int);
|
|||
insert into atablewithareallylongandirritatingname values (2);
|
||||
select * from atablewithareallylongandirritatingname;
|
||||
drop table atablewithareallylongandirritatingname;
|
||||
|
||||
|
||||
#
|
||||
# BUG#14514
|
||||
#
|
||||
|
||||
CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb;
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
|
|
@ -842,4 +842,32 @@ set @@tx_isolation=default;
|
|||
execute stmt;
|
||||
deallocate prepare stmt;
|
||||
|
||||
#
|
||||
# Bug#14410 "Crash in Enum or Set type in CREATE TABLE and PS/SP"
|
||||
#
|
||||
# Part I. Make sure the typelib for ENUM is created in the statement memory
|
||||
# root.
|
||||
prepare stmt from "create temporary table t1 (letter enum('','a','b','c')
|
||||
not null)";
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
# Part II. Make sure that when the default value is converted to UTF-8,
|
||||
# the new item is # created in the statement memory root.
|
||||
set names latin1;
|
||||
prepare stmt from "create table t1 (a enum('test') default 'test')
|
||||
character set utf8";
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
# Cleanup
|
||||
set names default;
|
||||
deallocate prepare stmt;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
|
|
@ -2253,6 +2253,17 @@ insert into t1 values (1,1);
|
|||
insert into t2 values (1,1),(1,2);
|
||||
select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1;
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
# Bug #14482 Server crash when subselecting from the same table
|
||||
#
|
||||
create table t1 (f1 int,f2 int);
|
||||
insert into t1 values(1,1);
|
||||
create table t2 (f3 int, f4 int, primary key(f3,f4));
|
||||
insert into t2 values(1,1);
|
||||
select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 from t2));
|
||||
drop table t1,t2;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
|
@ -2749,3 +2760,48 @@ select f1, f2, v2.f1 as x1 from v2 order by v2.f1;
|
|||
select f1, f2, v3.f1 as x1 from v3 order by v3.f1;
|
||||
drop table t1;
|
||||
drop view v1, v2, v3;
|
||||
|
||||
#
|
||||
# Bug #15106: lost equality predicate of the form field=const in a join query
|
||||
#
|
||||
|
||||
CREATE TABLE t1(key_a int4 NOT NULL, optimus varchar(32), PRIMARY KEY(key_a));
|
||||
CREATE TABLE t2(key_a int4 NOT NULL, prime varchar(32), PRIMARY KEY(key_a));
|
||||
CREATE table t3(key_a int4 NOT NULL, key_b int4 NOT NULL, foo varchar(32),
|
||||
PRIMARY KEY(key_a,key_b));
|
||||
|
||||
INSERT INTO t1 VALUES (0,'');
|
||||
INSERT INTO t1 VALUES (1,'i');
|
||||
INSERT INTO t1 VALUES (2,'j');
|
||||
INSERT INTO t1 VALUES (3,'k');
|
||||
|
||||
INSERT INTO t2 VALUES (1,'r');
|
||||
INSERT INTO t2 VALUES (2,'s');
|
||||
INSERT INTO t2 VALUES (3,'t');
|
||||
|
||||
INSERT INTO t3 VALUES (1,5,'x');
|
||||
INSERT INTO t3 VALUES (1,6,'y');
|
||||
INSERT INTO t3 VALUES (2,5,'xx');
|
||||
INSERT INTO t3 VALUES (2,6,'yy');
|
||||
INSERT INTO t3 VALUES (2,7,'zz');
|
||||
INSERT INTO t3 VALUES (3,5,'xxx');
|
||||
|
||||
SELECT t2.key_a,foo
|
||||
FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a
|
||||
INNER JOIN t3 ON t1.key_a = t3.key_a
|
||||
WHERE t2.key_a=2 and key_b=5;
|
||||
EXPLAIN SELECT t2.key_a,foo
|
||||
FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a
|
||||
INNER JOIN t3 ON t1.key_a = t3.key_a
|
||||
WHERE t2.key_a=2 and key_b=5;
|
||||
|
||||
SELECT t2.key_a,foo
|
||||
FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a
|
||||
INNER JOIN t3 ON t1.key_a = t3.key_a
|
||||
WHERE t2.key_a=2 and key_b=5;
|
||||
EXPLAIN SELECT t2.key_a,foo
|
||||
FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a
|
||||
INNER JOIN t3 ON t1.key_a = t3.key_a
|
||||
WHERE t2.key_a=2 and key_b=5;
|
||||
|
||||
DROP TABLE t1,t2,t3;
|
||||
|
|
49
mysql-test/t/sp-code.test
Normal file
49
mysql-test/t/sp-code.test
Normal file
|
@ -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;
|
|
@ -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_SP_NO_RECURSION
|
||||
--error ER_PS_NO_RECURSION
|
||||
call p1()|
|
||||
--error ER_SP_NO_RECURSION
|
||||
--error ER_PS_NO_RECURSION
|
||||
call p1()|
|
||||
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.
|
||||
|
|
|
@ -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 ;|
|
||||
|
||||
|
|
|
@ -1211,15 +1211,13 @@ begin
|
|||
end if;
|
||||
end|
|
||||
select f5(1)|
|
||||
# This should generate an error about insuficient number of tables locked
|
||||
# Now this crash server
|
||||
--disable_parsing # until bug#11394 fix
|
||||
--error 1100
|
||||
# Since currently recursive functions are disallowed ER_SP_NO_RECURSION
|
||||
# error will be returned, once we will allow them error about
|
||||
# insufficient number of locked tables will be returned instead.
|
||||
--error ER_SP_NO_RECURSION
|
||||
select f5(2)|
|
||||
# But now it simply miserably fails because we are trying to use the same
|
||||
# lex on the next iteration :/ It should generate some error too...
|
||||
--error ER_SP_NO_RECURSION
|
||||
select f5(3)|
|
||||
--enable_parsing
|
||||
|
||||
# OTOH this should work
|
||||
create function f6() returns int
|
||||
|
@ -1265,13 +1263,12 @@ select * from v1|
|
|||
# views and functions ?
|
||||
create function f1() returns int
|
||||
return (select sum(data) from t1) + (select sum(data) from v1)|
|
||||
# This queries will crash server because we can't use LEX in
|
||||
# reenterable fashion yet. Patch disabling recursion will heal this.
|
||||
--disable_parsing
|
||||
--error ER_SP_NO_RECURSION
|
||||
select f1()|
|
||||
--error ER_SP_NO_RECURSION
|
||||
select * from v1|
|
||||
--error ER_SP_NO_RECURSION
|
||||
select * from v2|
|
||||
--enable_parsing
|
||||
# Back to the normal cases
|
||||
drop function f1|
|
||||
create function f1() returns int
|
||||
|
@ -1289,9 +1286,7 @@ select *, f0() from v0|
|
|||
#
|
||||
# Let us test how well prelocking works with explicit LOCK TABLES.
|
||||
#
|
||||
# Nowdays we have to lock mysql.proc to be able to read SP definitions.
|
||||
# But Monty was going to fix this.
|
||||
lock tables t1 read, t1 as t11 read, mysql.proc read|
|
||||
lock tables t1 read, t1 as t11 read|
|
||||
# These should work well
|
||||
select f3()|
|
||||
select id, f3() from t1 as t11|
|
||||
|
@ -1481,9 +1476,6 @@ show procedure status like '%p%'|
|
|||
|
||||
# Fibonacci, for recursion test. (Yet Another Numerical series :)
|
||||
#
|
||||
# This part of test is disabled until we implement support for
|
||||
# recursive stored procedures.
|
||||
--disable_parsing
|
||||
--disable_warnings
|
||||
drop table if exists fib|
|
||||
--enable_warnings
|
||||
|
@ -1512,6 +1504,9 @@ begin
|
|||
end if;
|
||||
end|
|
||||
|
||||
# Enable recursion
|
||||
set @@max_sp_recursion_depth= 20|
|
||||
|
||||
# Minimum test: recursion of 3 levels
|
||||
|
||||
insert into fib values (0), (1)|
|
||||
|
@ -1531,7 +1526,7 @@ call fib(20)|
|
|||
select * from fib order by f asc|
|
||||
drop table fib|
|
||||
drop procedure fib|
|
||||
--enable_parsing
|
||||
set @@max_sp_recursion_depth= 0|
|
||||
|
||||
#
|
||||
# Comment & suid
|
||||
|
@ -1800,16 +1795,8 @@ select @x2|
|
|||
drop procedure bug2260|
|
||||
|
||||
#
|
||||
# BUG#2267
|
||||
# BUG#2267 "Lost connect if stored procedure has SHOW FUNCTION STATUS"
|
||||
#
|
||||
# NOTE: This test case will be fixed as soon as Monty
|
||||
# will allow to open mysql.proc table under LOCK TABLES
|
||||
# without mentioning in lock list.
|
||||
#
|
||||
# FIXME: Other solution would be to use preopened proc table
|
||||
# instead of opening it anew.
|
||||
#
|
||||
--disable_parsing
|
||||
--disable_warnings
|
||||
drop procedure if exists bug2267_1|
|
||||
--enable_warnings
|
||||
|
@ -1836,11 +1823,13 @@ end|
|
|||
|
||||
--disable_warnings
|
||||
drop procedure if exists bug2267_4|
|
||||
drop function if exists bug2267_4|
|
||||
--enable_warnings
|
||||
create procedure bug2267_4()
|
||||
begin
|
||||
show create function fac;
|
||||
show create function bug2267_4;
|
||||
end|
|
||||
create function bug2267_4() returns int return 100|
|
||||
|
||||
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
|
||||
call bug2267_1()|
|
||||
|
@ -1853,7 +1842,7 @@ drop procedure bug2267_1|
|
|||
drop procedure bug2267_2|
|
||||
drop procedure bug2267_3|
|
||||
drop procedure bug2267_4|
|
||||
--enable_parsing
|
||||
drop function bug2267_4|
|
||||
|
||||
#
|
||||
# BUG#2227
|
||||
|
@ -1873,23 +1862,16 @@ call bug2227(9)|
|
|||
drop procedure bug2227|
|
||||
|
||||
#
|
||||
# BUG#2614
|
||||
# BUG#2614 "Stored procedure with INSERT ... SELECT that does not
|
||||
# contain any tables crashes server"
|
||||
#
|
||||
# QQ The second insert doesn't work with temporary tables (it was an
|
||||
# QQ ordinary table before we changed the locking scheme). It results
|
||||
# QQ in an error: 1137: Can't reopen table: 't3'
|
||||
# QQ which is a known limit with temporary tables.
|
||||
# QQ For this reason we can't run this test any more (i.e., if we modify
|
||||
# QQ it, it's no longer a test case for the bug), but we keep it here
|
||||
# QQ anyway, for tracability.
|
||||
--disable_parsing
|
||||
--disable_warnings
|
||||
drop procedure if exists bug2614|
|
||||
--enable_warnings
|
||||
create procedure bug2614()
|
||||
begin
|
||||
drop temporary table if exists t3;
|
||||
create temporary table t3 (id int default '0' not null);
|
||||
drop table if exists t3;
|
||||
create table t3 (id int default '0' not null);
|
||||
insert into t3 select 12;
|
||||
insert into t3 select * from t3;
|
||||
end|
|
||||
|
@ -1898,9 +1880,8 @@ end|
|
|||
call bug2614()|
|
||||
--enable_warnings
|
||||
call bug2614()|
|
||||
drop temporary table t3|
|
||||
drop table t3|
|
||||
drop procedure bug2614|
|
||||
--enable_parsing
|
||||
|
||||
#
|
||||
# BUG#2674
|
||||
|
@ -4291,6 +4272,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
|
||||
|
@ -4594,6 +4578,210 @@ end|
|
|||
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|
|
||||
|
||||
#
|
||||
# BUG#13729: Stored procedures: packet error after exception handled
|
||||
#
|
||||
--disable_warnings
|
||||
drop procedure if exists bug13729|
|
||||
drop table if exists t3|
|
||||
--enable_warnings
|
||||
|
||||
create table t3 (s1 int, primary key (s1))|
|
||||
|
||||
insert into t3 values (1),(2)|
|
||||
|
||||
create procedure bug13729()
|
||||
begin
|
||||
declare continue handler for sqlexception select 55;
|
||||
|
||||
update t3 set s1 = 1;
|
||||
end|
|
||||
|
||||
call bug13729()|
|
||||
# Used to cause Packets out of order
|
||||
select * from t3|
|
||||
|
||||
drop procedure bug13729|
|
||||
drop table t3|
|
||||
|
||||
|
||||
#
|
||||
# BUG#NNNN: New bug synopsis
|
||||
#
|
||||
|
|
|
@ -355,6 +355,70 @@ drop procedure bug13825_2|
|
|||
drop table t1, t2|
|
||||
|
||||
|
||||
#
|
||||
# BUG#14840: CONTINUE handler problem
|
||||
#
|
||||
--disable_warnings
|
||||
drop table if exists t3|
|
||||
drop procedure if exists bug14840_1|
|
||||
drop procedure if exists bug14840_2|
|
||||
--enable_warnings
|
||||
|
||||
create table t3
|
||||
(
|
||||
x int,
|
||||
y int,
|
||||
primary key (x)
|
||||
) engine=InnoDB|
|
||||
|
||||
# This used to hang the client since the insert returned with an
|
||||
# error status (left over from the update) even though it succeeded,
|
||||
# which caused the execution to end at that point.
|
||||
create procedure bug14840_1()
|
||||
begin
|
||||
declare err int default 0;
|
||||
declare continue handler for sqlexception
|
||||
set err = err + 1;
|
||||
|
||||
start transaction;
|
||||
update t3 set x = 1, y = 42 where x = 2;
|
||||
insert into t3 values (3, 4711);
|
||||
if err > 0 then
|
||||
rollback;
|
||||
else
|
||||
commit;
|
||||
end if;
|
||||
select * from t3;
|
||||
end|
|
||||
|
||||
# A simpler (non-transactional) case: insert at select should be done
|
||||
create procedure bug14840_2()
|
||||
begin
|
||||
declare err int default 0;
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
set err = err + 1;
|
||||
select err as 'Ping';
|
||||
end;
|
||||
|
||||
update t3 set x = 1, y = 42 where x = 2;
|
||||
update t3 set x = 1, y = 42 where x = 2;
|
||||
insert into t3 values (3, 4711);
|
||||
select * from t3;
|
||||
end|
|
||||
|
||||
insert into t3 values (1, 3), (2, 5)|
|
||||
call bug14840_1()|
|
||||
|
||||
delete from t3|
|
||||
insert into t3 values (1, 3), (2, 5)|
|
||||
call bug14840_2()|
|
||||
|
||||
drop procedure bug14840_1|
|
||||
drop procedure bug14840_2|
|
||||
drop table t3|
|
||||
|
||||
|
||||
#
|
||||
# BUG#NNNN: New bug synopsis
|
||||
#
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -267,7 +267,7 @@ File my_sopen(const char *path, int oflag, int shflag, int pmode)
|
|||
*/
|
||||
switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
|
||||
case 0:
|
||||
case _O_EXCL: // ignore EXCL w/o CREAT
|
||||
case _O_EXCL: /* ignore EXCL w/o CREAT */
|
||||
filecreate= OPEN_EXISTING;
|
||||
break;
|
||||
|
||||
|
@ -281,7 +281,7 @@ File my_sopen(const char *path, int oflag, int shflag, int pmode)
|
|||
break;
|
||||
|
||||
case _O_TRUNC:
|
||||
case _O_TRUNC | _O_EXCL: // ignore EXCL w/o CREAT
|
||||
case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */
|
||||
filecreate= TRUNCATE_EXISTING;
|
||||
break;
|
||||
|
||||
|
@ -290,7 +290,7 @@ File my_sopen(const char *path, int oflag, int shflag, int pmode)
|
|||
break;
|
||||
|
||||
default:
|
||||
// this can't happen ... all cases are covered
|
||||
/* this can't happen ... all cases are covered */
|
||||
errno= EINVAL;
|
||||
_doserrno= 0L;
|
||||
return -1;
|
||||
|
|
|
@ -336,14 +336,21 @@ ConfigRetriever::setNodeId(Uint32 nodeid)
|
|||
Uint32
|
||||
ConfigRetriever::allocNodeId(int no_retries, int retry_delay_in_seconds)
|
||||
{
|
||||
int res;
|
||||
_ownNodeId= 0;
|
||||
if(m_handle != 0)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
int res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type);
|
||||
if(!ndb_mgm_is_connected(m_handle))
|
||||
if(!ndb_mgm_connect(m_handle, 0, 0, 0))
|
||||
goto next;
|
||||
|
||||
res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type);
|
||||
if(res >= 0)
|
||||
return _ownNodeId= (Uint32)res;
|
||||
|
||||
next:
|
||||
if (no_retries == 0)
|
||||
break;
|
||||
no_retries--;
|
||||
|
|
|
@ -336,10 +336,16 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
|
|||
const Properties* p = parser.parse(ctx, session);
|
||||
if (p == NULL){
|
||||
if(!ndb_mgm_is_connected(handle)) {
|
||||
return NULL;
|
||||
DBUG_RETURN(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ctx.m_status==Parser_t::Eof
|
||||
|| ctx.m_status==Parser_t::NoLine)
|
||||
{
|
||||
ndb_mgm_disconnect(handle);
|
||||
DBUG_RETURN(NULL);
|
||||
}
|
||||
/**
|
||||
* Print some info about why the parser returns NULL
|
||||
*/
|
||||
|
|
|
@ -1495,12 +1495,17 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
|
|||
static void
|
||||
mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
|
||||
{
|
||||
struct st_VioSSLConnectorFd *st=
|
||||
(struct st_VioSSLConnectorFd*) mysql->connector_fd;
|
||||
DBUG_ENTER("mysql_ssl_free");
|
||||
|
||||
my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
|
||||
if (st)
|
||||
SSL_CTX_free(st->ssl_context);
|
||||
my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR));
|
||||
mysql->options.ssl_key = 0;
|
||||
mysql->options.ssl_cert = 0;
|
||||
|
|
|
@ -480,6 +480,8 @@ int ha_example::rnd_pos(byte * buf, byte *pos)
|
|||
|
||||
/*
|
||||
::info() is used to return information to the optimizer.
|
||||
see my_base.h for the complete description
|
||||
|
||||
Currently this table handler doesn't implement most of the fields
|
||||
really needed. SHOW also makes use of this data
|
||||
Another note, you will probably want to have the following in your
|
||||
|
|
|
@ -274,7 +274,8 @@ ha_tina::ha_tina(TABLE *table_arg)
|
|||
These definitions are found in hanler.h
|
||||
These are not probably completely right.
|
||||
*/
|
||||
current_position(0), next_position(0), chain_alloced(0), chain_size(DEFAULT_CHAIN_LENGTH)
|
||||
current_position(0), next_position(0), chain_alloced(0),
|
||||
chain_size(DEFAULT_CHAIN_LENGTH), records_is_known(0)
|
||||
{
|
||||
/* Set our original buffers from pre-allocated memory */
|
||||
buffer.set(byte_buffer, IO_SIZE, system_charset_info);
|
||||
|
@ -504,6 +505,7 @@ int ha_tina::write_row(byte * buf)
|
|||
*/
|
||||
if (get_mmap(share, 0) > 0)
|
||||
DBUG_RETURN(-1);
|
||||
records++;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -668,6 +670,7 @@ int ha_tina::rnd_init(bool scan)
|
|||
|
||||
current_position= next_position= 0;
|
||||
records= 0;
|
||||
records_is_known= 0;
|
||||
chain_ptr= chain;
|
||||
#ifdef HAVE_MADVISE
|
||||
if (scan)
|
||||
|
@ -745,7 +748,7 @@ void ha_tina::info(uint flag)
|
|||
{
|
||||
DBUG_ENTER("ha_tina::info");
|
||||
/* This is a lie, but you don't want the optimizer to see zero or 1 */
|
||||
if (records < 2)
|
||||
if (!records_is_known && records < 2)
|
||||
records= 2;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
@ -780,6 +783,8 @@ int ha_tina::rnd_end()
|
|||
{
|
||||
DBUG_ENTER("ha_tina::rnd_end");
|
||||
|
||||
records_is_known= 1;
|
||||
|
||||
/* First position will be truncate position, second will be increment */
|
||||
if ((chain_ptr - chain) > 0)
|
||||
{
|
||||
|
@ -824,17 +829,21 @@ int ha_tina::rnd_end()
|
|||
}
|
||||
|
||||
/*
|
||||
Truncate table and others of its ilk call this.
|
||||
DELETE without WHERE calls it
|
||||
*/
|
||||
int ha_tina::delete_all_rows()
|
||||
{
|
||||
DBUG_ENTER("ha_tina::delete_all_rows");
|
||||
|
||||
if (!records_is_known)
|
||||
return (my_errno=HA_ERR_WRONG_COMMAND);
|
||||
|
||||
int rc= my_chsize(share->data_file, 0, 0, MYF(MY_WME));
|
||||
|
||||
if (get_mmap(share, 0) > 0)
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
records=0;
|
||||
DBUG_RETURN(rc);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ class ha_tina: public handler
|
|||
tina_set *chain_ptr;
|
||||
byte chain_alloced;
|
||||
uint32 chain_size;
|
||||
bool records_is_known;
|
||||
|
||||
public:
|
||||
ha_tina(TABLE *table_arg);
|
||||
|
|
|
@ -469,8 +469,7 @@ bool federated_db_end()
|
|||
table, and if so, does the foreign table exist.
|
||||
*/
|
||||
|
||||
static int check_foreign_data_source(
|
||||
FEDERATED_SHARE *share,
|
||||
static int check_foreign_data_source(FEDERATED_SHARE *share,
|
||||
bool table_create_flag)
|
||||
{
|
||||
char escaped_table_name[NAME_LEN*2];
|
||||
|
@ -496,15 +495,17 @@ static int check_foreign_data_source(
|
|||
share->port,
|
||||
share->socket, 0))
|
||||
{
|
||||
/*
|
||||
we want the correct error message, but it to return
|
||||
ER_CANT_CREATE_FEDERATED_TABLE if called by ::create
|
||||
*/
|
||||
error_code= table_create_flag?
|
||||
ER_CANT_CREATE_FEDERATED_TABLE : ER_CONNECT_TO_FOREIGN_DATA_SOURCE;
|
||||
/*
|
||||
we want the correct error message, but it to return
|
||||
ER_CANT_CREATE_FEDERATED_TABLE if called by ::create
|
||||
*/
|
||||
error_code= (table_create_flag ?
|
||||
ER_CANT_CREATE_FEDERATED_TABLE :
|
||||
ER_CONNECT_TO_FOREIGN_DATA_SOURCE);
|
||||
|
||||
my_sprintf(error_buffer,
|
||||
(error_buffer, " database %s username %s hostname %s",
|
||||
(error_buffer,
|
||||
"database: '%s' username: '%s' hostname: '%s'",
|
||||
share->database, share->username, share->hostname));
|
||||
|
||||
my_error(ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), error_buffer);
|
||||
|
@ -545,8 +546,8 @@ static int check_foreign_data_source(
|
|||
{
|
||||
error_code= table_create_flag ?
|
||||
ER_CANT_CREATE_FEDERATED_TABLE : ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST;
|
||||
my_sprintf(error_buffer, (error_buffer, ": %d : %s",
|
||||
mysql_errno(mysql), mysql_error(mysql)));
|
||||
my_sprintf(error_buffer, (error_buffer, "error: %d '%s'",
|
||||
mysql_errno(mysql), mysql_error(mysql)));
|
||||
|
||||
my_error(error_code, MYF(0), error_buffer);
|
||||
goto error;
|
||||
|
@ -2035,7 +2036,7 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key,
|
|||
}
|
||||
if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length()))
|
||||
{
|
||||
my_sprintf(error_buffer, (error_buffer, ": %d : %s",
|
||||
my_sprintf(error_buffer, (error_buffer, "error: %d '%s'",
|
||||
mysql_errno(mysql), mysql_error(mysql)));
|
||||
retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
|
||||
goto error;
|
||||
|
|
|
@ -3332,17 +3332,20 @@ 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= (void *)tab;
|
||||
m_table_version = tab->getObjectVersion();
|
||||
}
|
||||
else if (m_table_version < tab->getObjectVersion())
|
||||
if (m_table_version < tab->getObjectVersion())
|
||||
{
|
||||
/*
|
||||
The table has been altered, caller has to retry
|
||||
*/
|
||||
DBUG_RETURN(my_errno= HA_ERR_TABLE_DEF_CHANGED);
|
||||
NdbError err= ndb->getNdbError(NDB_INVALID_SCHEMA_OBJECT);
|
||||
DBUG_RETURN(ndb_to_mysql_error(&err));
|
||||
}
|
||||
if (m_table != (void *)tab)
|
||||
{
|
||||
m_table= (void *)tab;
|
||||
m_table_version = tab->getObjectVersion();
|
||||
if (!(my_errno= build_index_list(ndb, table, ILBP_OPEN)))
|
||||
DBUG_RETURN(my_errno);
|
||||
}
|
||||
m_table_info= tab_info;
|
||||
}
|
||||
|
@ -3880,9 +3883,8 @@ int ha_ndbcluster::create(const char *name,
|
|||
uint pack_length, length, i, pk_length= 0;
|
||||
const void *data, *pack_data;
|
||||
char name2[FN_HEADLEN];
|
||||
bool create_from_engine= test(info->table_options &
|
||||
HA_OPTION_CREATE_FROM_ENGINE);
|
||||
|
||||
bool create_from_engine= (info->table_options & HA_OPTION_CREATE_FROM_ENGINE);
|
||||
|
||||
DBUG_ENTER("ha_ndbcluster::create");
|
||||
DBUG_PRINT("enter", ("name: %s", name));
|
||||
fn_format(name2, name, "", "",2); // Remove the .frm extension
|
||||
|
|
|
@ -672,7 +672,7 @@ public:
|
|||
key_range *max_key)
|
||||
{ return (ha_rows) 10; }
|
||||
virtual void position(const byte *record)=0;
|
||||
virtual void info(uint)=0;
|
||||
virtual void info(uint)=0; // see my_base.h for full description
|
||||
virtual int extra(enum ha_extra_function operation)
|
||||
{ return 0; }
|
||||
virtual int extra_opt(enum ha_extra_function operation, ulong cache_size)
|
||||
|
|
18
sql/item.cc
18
sql/item.cc
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -5254,7 +5260,7 @@ Item_result item_cmp_type(Item_result a,Item_result b)
|
|||
void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
|
||||
{
|
||||
Item *item= *ref;
|
||||
Item *new_item;
|
||||
Item *new_item= NULL;
|
||||
if (item->basic_const_item())
|
||||
return; // Can't be better
|
||||
Item_result res_type=item_cmp_type(comp_item->result_type(),
|
||||
|
@ -5287,7 +5293,16 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
|
|||
break;
|
||||
}
|
||||
case ROW_RESULT:
|
||||
if (item->type() == Item::ROW_ITEM && comp_item->type() == Item::ROW_ITEM)
|
||||
{
|
||||
/*
|
||||
Substitute constants only in Item_rows. Don't affect other Items
|
||||
with ROW_RESULT (eg Item_singlerow_subselect).
|
||||
|
||||
For such Items more optimal is to detect if it is constant and replace
|
||||
it with Item_row. This would optimize queries like this:
|
||||
SELECT * FROM t1 WHERE (a,b) = (SELECT a,b FROM t2 LIMIT 1);
|
||||
*/
|
||||
Item_row *item_row= (Item_row*) item;
|
||||
Item_row *comp_item_row= (Item_row*) comp_item;
|
||||
uint col;
|
||||
|
@ -5305,6 +5320,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
|
|||
resolve_const_item(thd, item_row->addr(col), comp_item_row->el(col));
|
||||
break;
|
||||
}
|
||||
/* Fallthrough */
|
||||
case REAL_RESULT:
|
||||
{ // It must REAL_RESULT
|
||||
double result= item->val_real();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -3662,7 +3662,7 @@ void Item_equal::merge(Item_equal *item)
|
|||
the multiple equality already contains a constant and its
|
||||
value is not equal to the value of c.
|
||||
*/
|
||||
add(const_item);
|
||||
add(c);
|
||||
}
|
||||
cond_false|= item->cond_false;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -48,6 +48,38 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
|
|||
}
|
||||
|
||||
|
||||
String *Item_str_func::check_well_formed_result(String *str)
|
||||
{
|
||||
/* Check whether we got a well-formed string */
|
||||
CHARSET_INFO *cs= str->charset();
|
||||
int well_formed_error;
|
||||
uint wlen= cs->cset->well_formed_len(cs,
|
||||
str->ptr(), str->ptr() + str->length(),
|
||||
str->length(), &well_formed_error);
|
||||
if (wlen < str->length())
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
char hexbuf[7];
|
||||
enum MYSQL_ERROR::enum_warning_level level;
|
||||
uint diff= str->length() - wlen;
|
||||
set_if_smaller(diff, 3);
|
||||
octet2hex(hexbuf, str->ptr() + wlen, diff);
|
||||
if (thd->variables.sql_mode &
|
||||
(MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))
|
||||
{
|
||||
level= MYSQL_ERROR::WARN_LEVEL_ERROR;
|
||||
null_value= 1;
|
||||
str= 0;
|
||||
}
|
||||
else
|
||||
level= MYSQL_ERROR::WARN_LEVEL_WARN;
|
||||
push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING,
|
||||
ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
double Item_str_func::val_real()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
|
@ -1984,34 +2016,7 @@ String *Item_func_char::val_str(String *str)
|
|||
}
|
||||
str->set_charset(collation.collation);
|
||||
str->realloc(str->length()); // Add end 0 (for Purify)
|
||||
|
||||
/* Check whether we got a well-formed string */
|
||||
CHARSET_INFO *cs= collation.collation;
|
||||
int well_formed_error;
|
||||
uint wlen= cs->cset->well_formed_len(cs,
|
||||
str->ptr(), str->ptr() + str->length(),
|
||||
str->length(), &well_formed_error);
|
||||
if (wlen < str->length())
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
char hexbuf[7];
|
||||
enum MYSQL_ERROR::enum_warning_level level;
|
||||
uint diff= str->length() - wlen;
|
||||
set_if_smaller(diff, 3);
|
||||
octet2hex(hexbuf, str->ptr() + wlen, diff);
|
||||
if (thd->variables.sql_mode &
|
||||
(MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))
|
||||
{
|
||||
level= MYSQL_ERROR::WARN_LEVEL_ERROR;
|
||||
null_value= 1;
|
||||
str= 0;
|
||||
}
|
||||
else
|
||||
level= MYSQL_ERROR::WARN_LEVEL_WARN;
|
||||
push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING,
|
||||
ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf);
|
||||
}
|
||||
return str;
|
||||
return check_well_formed_result(str);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2320,7 +2325,7 @@ String *Item_func_conv_charset::val_str(String *str)
|
|||
}
|
||||
null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(),
|
||||
conv_charset, &dummy_errors);
|
||||
return null_value ? 0 : &str_value;
|
||||
return null_value ? 0 : check_well_formed_result(&str_value);
|
||||
}
|
||||
|
||||
void Item_func_conv_charset::fix_length_and_dec()
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
double val_real();
|
||||
enum Item_result result_type () const { return STRING_RESULT; }
|
||||
void left_right_max_length();
|
||||
String *check_well_formed_result(String *str);
|
||||
};
|
||||
|
||||
class Item_func_md5 :public Item_str_func
|
||||
|
|
|
@ -110,6 +110,7 @@ static SYMBOL symbols[] = {
|
|||
{ "CIPHER", SYM(CIPHER_SYM)},
|
||||
{ "CLIENT", SYM(CLIENT_SYM)},
|
||||
{ "CLOSE", SYM(CLOSE_SYM)},
|
||||
{ "CODE", SYM(CODE_SYM)},
|
||||
{ "COLLATE", SYM(COLLATE_SYM)},
|
||||
{ "COLLATION", SYM(COLLATION_SYM)},
|
||||
{ "COLUMN", SYM(COLUMN_SYM)},
|
||||
|
|
|
@ -101,6 +101,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
|
|||
#define MAX_FIELDS_BEFORE_HASH 32
|
||||
#define USER_VARS_HASH_SIZE 16
|
||||
#define STACK_MIN_SIZE 8192 // Abort if less stack during eval.
|
||||
#define STACK_MIN_SIZE_FOR_OPEN 1024*80
|
||||
#define STACK_BUFF_ALLOC 256 // For stack overrun checks
|
||||
#ifndef MYSQLD_NET_RETRY_COUNT
|
||||
#define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int.
|
||||
|
@ -1361,7 +1362,7 @@ int calc_weekday(long daynr,bool sunday_first_day_of_week);
|
|||
uint calc_week(TIME *l_time, uint week_behaviour, uint *year);
|
||||
void find_date(char *pos,uint *vek,uint flag);
|
||||
TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
|
||||
TYPELIB *typelib(List<String> &strings);
|
||||
TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings);
|
||||
ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
|
||||
ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
|
||||
const char *newname);
|
||||
|
|
|
@ -1589,6 +1589,7 @@ void end_thread(THD *thd, bool put_in_cache)
|
|||
wake_thread--;
|
||||
thd=thread_cache.get();
|
||||
thd->real_id=pthread_self();
|
||||
thd->thread_stack= (char *) &thd;
|
||||
(void) thd->store_globals();
|
||||
thd->thr_create_time= time(NULL);
|
||||
threads.append(thd);
|
||||
|
@ -4545,6 +4546,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,
|
||||
|
@ -5760,6 +5762,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.",
|
||||
|
@ -6906,8 +6913,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
|||
case OPT_MYISAM_STATS_METHOD:
|
||||
{
|
||||
ulong method_conv;
|
||||
myisam_stats_method_str= argument;
|
||||
int method;
|
||||
LINT_INIT(method_conv);
|
||||
|
||||
myisam_stats_method_str= argument;
|
||||
if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0)
|
||||
{
|
||||
fprintf(stderr, "Invalid value of myisam_stats_method: %s.\n", argument);
|
||||
|
|
|
@ -3136,10 +3136,10 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
|
|||
/* F=F-covered by first(I) */
|
||||
bitmap_union(&covered_fields, &(*ror_scan_mark)->covered_fields);
|
||||
all_covered= bitmap_is_subset(¶m->needed_fields, &covered_fields);
|
||||
} while (!all_covered && (++ror_scan_mark < ror_scans_end));
|
||||
|
||||
if (!all_covered)
|
||||
DBUG_RETURN(NULL); /* should not happen actually */
|
||||
} while ((++ror_scan_mark < ror_scans_end) && !all_covered);
|
||||
|
||||
if (!all_covered || (ror_scan_mark - tree->ror_scans) == 1)
|
||||
DBUG_RETURN(NULL);
|
||||
|
||||
/*
|
||||
Ok, [tree->ror_scans .. ror_scan) holds covering index_intersection with
|
||||
|
@ -7197,6 +7197,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
|
|||
{
|
||||
select_items_it.rewind();
|
||||
cur_used_key_parts.clear_all();
|
||||
uint max_key_part= 0;
|
||||
while ((item= select_items_it++))
|
||||
{
|
||||
item_field= (Item_field*) item; /* (SA5) already checked above. */
|
||||
|
@ -7214,7 +7215,19 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
|
|||
cur_group_prefix_len+= cur_part->store_length;
|
||||
cur_used_key_parts.set_bit(key_part_nr);
|
||||
++cur_group_key_parts;
|
||||
max_key_part= max(max_key_part,key_part_nr);
|
||||
}
|
||||
/*
|
||||
Check that used key parts forms a prefix of the index.
|
||||
To check this we compare bits in all_parts and cur_parts.
|
||||
all_parts have all bits set from 0 to (max_key_part-1).
|
||||
cur_parts have bits set for only used keyparts.
|
||||
*/
|
||||
ulonglong all_parts, cur_parts;
|
||||
all_parts= (1<<max_key_part) - 1;
|
||||
cur_parts= cur_used_key_parts.to_ulonglong() >> 1;
|
||||
if (all_parts != cur_parts)
|
||||
goto next_index;
|
||||
}
|
||||
else
|
||||
DBUG_ASSERT(FALSE);
|
||||
|
|
|
@ -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;
|
||||
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -261,6 +261,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);
|
||||
|
@ -631,6 +633,7 @@ sys_var *sys_variables[]=
|
|||
&sys_max_relay_log_size,
|
||||
&sys_max_seeks_for_key,
|
||||
&sys_max_sort_length,
|
||||
&sys_max_sp_recursion_depth,
|
||||
&sys_max_tmp_tables,
|
||||
&sys_max_user_connections,
|
||||
&sys_max_write_lock_count,
|
||||
|
@ -896,6 +899,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},
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3446,6 +3446,7 @@ slave_begin:
|
|||
THD_CHECK_SENTRY(thd);
|
||||
|
||||
pthread_detach_this_thread();
|
||||
thd->thread_stack= (char*) &thd; // remember where our stack is
|
||||
if (init_slave_thread(thd, SLAVE_THD_IO))
|
||||
{
|
||||
pthread_cond_broadcast(&mi->start_cond);
|
||||
|
@ -3454,7 +3455,6 @@ slave_begin:
|
|||
goto err;
|
||||
}
|
||||
mi->io_thd = thd;
|
||||
thd->thread_stack = (char*)&thd; // remember where our stack is
|
||||
pthread_mutex_lock(&LOCK_thread_count);
|
||||
threads.append(thd);
|
||||
pthread_mutex_unlock(&LOCK_thread_count);
|
||||
|
|
295
sql/sp.cc
295
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,79 +382,10 @@ 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL)
|
||||
{
|
||||
LEX *newlex= thd->lex;
|
||||
sp_head *sp= newlex->sphead;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -457,6 +393,72 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
|
|||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
dbchanged= FALSE;
|
||||
if ((ret= sp_use_new_db(thd, name->m_db.str, olddb, sizeof(olddb),
|
||||
1, &dbchanged)))
|
||||
goto end;
|
||||
|
||||
lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sp_returns_type(THD *thd, String &result, sp_head *sp)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
if (!(sp= sp_cache_lookup(&thd->sp_proc_cache, name)) && !cache_only)
|
||||
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(cp, name)))
|
||||
{
|
||||
if (db_find_routine(thd, TYPE_ENUM_PROCEDURE, name, &sp) == SP_OK)
|
||||
sp_cache_insert(&thd->sp_proc_cache, sp);
|
||||
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, 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)
|
||||
{
|
||||
|
|
6
sql/sp.h
6
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);
|
||||
|
||||
|
|
389
sql/sp_head.cc
389
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);
|
||||
}
|
||||
|
@ -882,6 +886,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;
|
||||
|
||||
/* Use some extra margin for possible SP recursion and functions */
|
||||
if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (char*)&old_packet))
|
||||
{
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
/* 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))
|
||||
{
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
@ -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(STRING_WITH_LEN("stmt "));
|
||||
str->qs_append((uint)m_lex_keeper.sql_command());
|
||||
}
|
||||
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(STRING_WITH_LEN("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,7 +2265,7 @@ sp_instr_set_trigger_field::exec_core(THD *thd, uint *nextp)
|
|||
void
|
||||
sp_instr_set_trigger_field::print(String *str)
|
||||
{
|
||||
str->append(STRING_WITH_LEN("set "));
|
||||
str->append(STRING_WITH_LEN("set_trigger_field "));
|
||||
trigger_field->print(str);
|
||||
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(STRING_WITH_LEN("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(STRING_WITH_LEN("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(STRING_WITH_LEN("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(STRING_WITH_LEN("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(STRING_WITH_LEN("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(STRING_WITH_LEN(" t="));
|
||||
str->qs_append(m_type);
|
||||
str->append(STRING_WITH_LEN(" f="));
|
||||
str->qs_append(' ');
|
||||
str->qs_append(m_frame);
|
||||
str->append(STRING_WITH_LEN(" 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(STRING_WITH_LEN("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(STRING_WITH_LEN("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(STRING_WITH_LEN("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(STRING_WITH_LEN("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(STRING_WITH_LEN("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(STRING_WITH_LEN("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;
|
||||
LEX_STRING n;
|
||||
my_bool found= m_ctx->find_cursor(m_cursor, &n);
|
||||
/* cfetch name@offset vars... */
|
||||
uint rsrv= SP_INSTR_UINT_MAXLEN+8;
|
||||
|
||||
str->reserve(12);
|
||||
str->append(STRING_WITH_LEN("cfetch "));
|
||||
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(STRING_WITH_LEN("error "));
|
||||
/* error code */
|
||||
if (str->reserve(SP_INSTR_UINT_MAXLEN+6))
|
||||
return;
|
||||
str->qs_append(STRING_WITH_LEN("error "));
|
||||
str->qs_append(m_errcode);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -158,6 +158,7 @@ my_bool acl_init(bool dont_read_acl_tables)
|
|||
*/
|
||||
if (!(thd=new THD))
|
||||
DBUG_RETURN(1); /* purecov: inspected */
|
||||
thd->thread_stack= (char*) &thd;
|
||||
thd->store_globals();
|
||||
/*
|
||||
It is safe to call acl_reload() since acl_* arrays and hashes which
|
||||
|
@ -3263,6 +3264,7 @@ my_bool grant_init()
|
|||
|
||||
if (!(thd= new THD))
|
||||
DBUG_RETURN(1); /* purecov: deadcode */
|
||||
thd->thread_stack= (char*) &thd;
|
||||
thd->store_globals();
|
||||
return_val= grant_reload(thd);
|
||||
delete thd;
|
||||
|
|
|
@ -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, STACK_MIN_SIZE_FOR_OPEN, (char *)&alias))
|
||||
return 0;
|
||||
|
||||
if (thd->killed)
|
||||
DBUG_RETURN(0);
|
||||
key_length= (uint) (strmov(strmov(key, table_list->db)+1,
|
||||
|
|
|
@ -410,7 +410,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);
|
||||
|
|
|
@ -183,6 +183,7 @@ THD::THD()
|
|||
spcont(NULL)
|
||||
{
|
||||
stmt_arena= this;
|
||||
thread_stack= 0;
|
||||
db= 0;
|
||||
catalog= (char*)"std"; // the only catalog we have for now
|
||||
main_security_ctx.init();
|
||||
|
@ -517,6 +518,12 @@ void THD::awake(THD::killed_state state_to_set)
|
|||
|
||||
bool THD::store_globals()
|
||||
{
|
||||
/*
|
||||
Assert that thread_stack is initialized: it's necessary to be able
|
||||
to track stack overrun.
|
||||
*/
|
||||
DBUG_ASSERT(this->thread_stack);
|
||||
|
||||
if (my_pthread_setspecific_ptr(THR_THD, this) ||
|
||||
my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
|
||||
return 1;
|
||||
|
@ -1495,7 +1502,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);
|
||||
|
|
|
@ -530,6 +530,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;
|
||||
|
@ -1229,14 +1230,16 @@ public:
|
|||
free_root(&mem_root,MYF(MY_KEEP_PREALLOC));
|
||||
#endif
|
||||
}
|
||||
#ifdef USING_TRANSACTIONS
|
||||
st_transactions()
|
||||
{
|
||||
#ifdef USING_TRANSACTIONS
|
||||
bzero((char*)this, sizeof(*this));
|
||||
xid_state.xid.null();
|
||||
init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
|
||||
}
|
||||
#else
|
||||
xid_state.xa_state= XA_NOTR;
|
||||
#endif
|
||||
}
|
||||
} transaction;
|
||||
Field *dupp_field;
|
||||
#ifndef __WIN__
|
||||
|
@ -2085,6 +2088,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;
|
||||
|
|
|
@ -1723,6 +1723,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
|
|||
#endif
|
||||
|
||||
DBUG_ENTER("handle_delayed_insert");
|
||||
thd->thread_stack= (char*) &thd;
|
||||
if (init_thr_lock() || thd->store_globals())
|
||||
{
|
||||
thd->fatal_error();
|
||||
|
|
|
@ -90,6 +90,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,
|
||||
/* This should be the last !!! */
|
||||
|
||||
SQLCOM_END
|
||||
|
|
|
@ -1097,6 +1097,7 @@ pthread_handler_t handle_one_connection(void *arg)
|
|||
VOID(sigemptyset(&set)); // Get mask in use
|
||||
VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
|
||||
#endif
|
||||
thd->thread_stack= (char*) &thd;
|
||||
if (thd->store_globals())
|
||||
{
|
||||
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
|
||||
|
@ -1110,7 +1111,6 @@ pthread_handler_t handle_one_connection(void *arg)
|
|||
int error;
|
||||
NET *net= &thd->net;
|
||||
Security_context *sctx= thd->security_ctx;
|
||||
thd->thread_stack= (char*) &thd;
|
||||
net->no_send_error= 0;
|
||||
|
||||
if ((error=check_connection(thd)))
|
||||
|
@ -1201,6 +1201,7 @@ pthread_handler_t handle_bootstrap(void *arg)
|
|||
char *buff;
|
||||
|
||||
/* The following must be called before DBUG_ENTER */
|
||||
thd->thread_stack= (char*) &thd;
|
||||
if (my_thread_init() || thd->store_globals())
|
||||
{
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
|
@ -3682,7 +3683,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;
|
||||
|
@ -4216,7 +4218,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);
|
||||
|
@ -4340,9 +4343,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)
|
||||
{
|
||||
|
@ -4418,9 +4423,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)
|
||||
{
|
||||
|
@ -4548,6 +4555,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))
|
||||
|
@ -5255,6 +5289,7 @@ bool check_stack_overrun(THD *thd, long margin,
|
|||
char *buf __attribute__((unused)))
|
||||
{
|
||||
long stack_used;
|
||||
DBUG_ASSERT(thd == current_thd);
|
||||
if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >=
|
||||
(long) (thread_stack - margin))
|
||||
{
|
||||
|
@ -6704,7 +6739,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
|
|||
allocate temporary THD for execution of acl_reload()/grant_reload().
|
||||
*/
|
||||
if (!thd && (thd= (tmp_thd= new THD)))
|
||||
{
|
||||
thd->thread_stack= (char*) &tmp_thd;
|
||||
thd->store_globals();
|
||||
}
|
||||
if (thd)
|
||||
{
|
||||
(void)acl_reload(thd);
|
||||
|
|
|
@ -898,7 +898,6 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
|
|||
}
|
||||
|
||||
key_info= table->key_info;
|
||||
file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
|
||||
bzero((char*) &create_info, sizeof(create_info));
|
||||
file->update_create_info(&create_info);
|
||||
primary_key= share->primary_key;
|
||||
|
|
|
@ -725,7 +725,14 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||
*/
|
||||
if (!interval)
|
||||
{
|
||||
interval= sql_field->interval= typelib(sql_field->interval_list);
|
||||
/*
|
||||
Create the typelib in prepared statement memory if we're
|
||||
executing one.
|
||||
*/
|
||||
MEM_ROOT *stmt_root= thd->stmt_arena->mem_root;
|
||||
|
||||
interval= sql_field->interval= typelib(stmt_root,
|
||||
sql_field->interval_list);
|
||||
List_iterator<String> it(sql_field->interval_list);
|
||||
String conv, *tmp;
|
||||
for (uint i= 0; (tmp= it++); i++)
|
||||
|
@ -736,7 +743,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||
{
|
||||
uint cnv_errs;
|
||||
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
|
||||
interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
|
||||
interval->type_names[i]= strmake_root(stmt_root, conv.ptr(),
|
||||
conv.length());
|
||||
interval->type_lengths[i]= conv.length();
|
||||
}
|
||||
|
@ -756,8 +763,22 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||
*/
|
||||
if (sql_field->def && cs != sql_field->def->collation.collation)
|
||||
{
|
||||
if (!(sql_field->def=
|
||||
sql_field->def->safe_charset_converter(cs)))
|
||||
Query_arena backup_arena;
|
||||
bool need_to_change_arena= !thd->stmt_arena->is_conventional();
|
||||
if (need_to_change_arena)
|
||||
{
|
||||
/* Asser that we don't do that at every PS execute */
|
||||
DBUG_ASSERT(thd->stmt_arena->is_first_stmt_execute() ||
|
||||
thd->stmt_arena->is_first_sp_execute());
|
||||
thd->set_n_backup_active_arena(thd->stmt_arena, &backup_arena);
|
||||
}
|
||||
|
||||
sql_field->def= sql_field->def->safe_charset_converter(cs);
|
||||
|
||||
if (need_to_change_arena)
|
||||
thd->restore_active_arena(thd->stmt_arena, &backup_arena);
|
||||
|
||||
if (! sql_field->def)
|
||||
{
|
||||
/* Could not convert */
|
||||
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
|
||||
|
|
|
@ -816,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;
|
||||
|
@ -831,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)
|
||||
{
|
||||
/*
|
||||
|
@ -911,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);
|
||||
|
@ -919,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;
|
||||
|
|
|
@ -159,6 +159,7 @@ void udf_init()
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
initialized = 1;
|
||||
new_thd->thread_stack= (char*) &new_thd;
|
||||
new_thd->store_globals();
|
||||
new_thd->db= my_strdup("mysql", MYF(0));
|
||||
new_thd->db_length=5;
|
||||
|
|
|
@ -465,7 +465,12 @@ int mysql_update(THD *thd,
|
|||
}
|
||||
else if (!ignore || error != HA_ERR_FOUND_DUPP_KEY)
|
||||
{
|
||||
thd->fatal_error(); // Force error message
|
||||
/*
|
||||
If (ignore && error == HA_ERR_FOUND_DUPP_KEY) we don't have to
|
||||
do anything; otherwise...
|
||||
*/
|
||||
if (error != HA_ERR_FOUND_DUPP_KEY)
|
||||
thd->fatal_error(); /* Other handler errors are fatal */
|
||||
table->file->print_error(error,MYF(0));
|
||||
error= 1;
|
||||
break;
|
||||
|
@ -1259,7 +1264,12 @@ bool multi_update::send_data(List<Item> ¬_used_values)
|
|||
updated--;
|
||||
if (!ignore || error != HA_ERR_FOUND_DUPP_KEY)
|
||||
{
|
||||
thd->fatal_error(); // Force error message
|
||||
/*
|
||||
If (ignore && error == HA_ERR_FOUND_DUPP_KEY) we don't have to
|
||||
do anything; otherwise...
|
||||
*/
|
||||
if (error != HA_ERR_FOUND_DUPP_KEY)
|
||||
thd->fatal_error(); /* Other handler errors are fatal */
|
||||
table->file->print_error(error,MYF(0));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
|
|
@ -175,6 +175,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
|
||||
|
@ -1604,13 +1605,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));
|
||||
|
||||
|
@ -1619,7 +1621,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;
|
||||
|
@ -1693,7 +1695,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;
|
||||
|
@ -2283,8 +2286,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);
|
||||
|
@ -5865,7 +5872,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
|
||||
}
|
||||
}
|
||||
;
|
||||
|
@ -6587,7 +6600,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
|
||||
|
@ -7147,6 +7181,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;
|
||||
|
@ -7496,6 +7534,7 @@ keyword_sp:
|
|||
| CHANGED {}
|
||||
| CIPHER_SYM {}
|
||||
| CLIENT_SYM {}
|
||||
| CODE_SYM {}
|
||||
| COLLATION_SYM {}
|
||||
| COLUMNS {}
|
||||
| COMMITTED_SYM {}
|
||||
|
|
|
@ -1247,15 +1247,15 @@ fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types,
|
|||
} /* fix_type_pointers */
|
||||
|
||||
|
||||
TYPELIB *typelib(List<String> &strings)
|
||||
TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings)
|
||||
{
|
||||
TYPELIB *result=(TYPELIB*) sql_alloc(sizeof(TYPELIB));
|
||||
TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
|
||||
if (!result)
|
||||
return 0;
|
||||
result->count=strings.elements;
|
||||
result->name="";
|
||||
uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1);
|
||||
if (!(result->type_names= (const char**) sql_alloc(nbytes)))
|
||||
if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes)))
|
||||
return 0;
|
||||
result->type_lengths= (uint*) (result->type_names + result->count + 1);
|
||||
List_iterator<String> it(strings);
|
||||
|
|
|
@ -1532,6 +1532,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
|
|||
*/
|
||||
if (!(thd= new THD))
|
||||
DBUG_RETURN(1);
|
||||
thd->thread_stack= (char*) &thd;
|
||||
thd->store_globals();
|
||||
|
||||
/* Init all memory structures that require explicit destruction */
|
||||
|
|
|
@ -43,8 +43,8 @@
|
|||
|
||||
#define ERRMAPP 1 /* Errormap f|r my_error */
|
||||
#define LIBLEN FN_REFLEN-FN_LEN /* Max l{ngd p} dev */
|
||||
#define MAX_DBKEY_LENGTH (FN_LEN*2+1+1+4+4) /* extra 4+4 bytes for slave tmp
|
||||
* tables */
|
||||
/* extra 4+4 bytes for slave tmp tables */
|
||||
#define MAX_DBKEY_LENGTH (NAME_LEN*2+1+1+4+4)
|
||||
#define MAX_ALIAS_NAME 256
|
||||
#define MAX_FIELD_NAME 34 /* Max colum name length +2 */
|
||||
#define MAX_SYS_VAR_LENGTH 32
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue