From a6aa5b0fa19a1512529aa44a34875fec86e60691 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Jun 2006 01:37:29 +1000 Subject: [PATCH 01/47] WL#3310 Update ndb_size.pl for 5.1 the "If I had a hammer" patch. Had to answer the question, did it in code. Much more accurrate results for 5.1 ndb/tools/ndb_size.pl: Add experimental 5.1-dd support to ndb_size.pl Improve calculations with 5.1 and variable sized attributes. Now much more closely resembles reality. ndb/tools/ndb_size.tmpl: Comment on 5.1-dd exp support. Display: - nr varsized attributes - actual row overhead depending on version - overhead for varsized attributes --- ndb/tools/ndb_size.pl | 80 +++++++++++++++++++++++++---------------- ndb/tools/ndb_size.tmpl | 18 ++++++++-- 2 files changed, 66 insertions(+), 32 deletions(-) diff --git a/ndb/tools/ndb_size.pl b/ndb/tools/ndb_size.pl index c285a7590fd..1d616e3acc5 100644 --- a/ndb/tools/ndb_size.pl +++ b/ndb/tools/ndb_size.pl @@ -57,7 +57,7 @@ if(@ARGV < 3 || $ARGV[0] eq '--usage' || $ARGV[0] eq '--help') $template->param(dsn => $dsn); } -my @releases = ({rel=>'4.1'},{rel=>'5.0'},{rel=>'5.1'}); +my @releases = ({rel=>'4.1'},{rel=>'5.0'},{rel=>'5.1'},{rel=>'5.1-dd'}); $template->param(releases => \@releases); my $tables = $dbh->selectall_arrayref("show tables"); @@ -91,12 +91,14 @@ foreach(@{$tables}) # We now work out the DataMemory usage - # sizes for 4.1, 5.0, 5.1 - my @totalsize= (0,0,0); + # sizes for 4.1, 5.0, 5.1 and 5.1-dd + my @totalsize= (0,0,0,0); + my $nrvarsize= 0; foreach(keys %$info) { - my @realsize = (0,0,0); + my @realsize = (0,0,0,0); + my @varsize = (0,0,0,0); my $type; my $size; my $name= $_; @@ -112,53 +114,56 @@ foreach(@{$tables}) } if($type =~ /tinyint/) - {@realsize=(1,1,1)} + {@realsize=(1,1,1,1)} elsif($type =~ /smallint/) - {@realsize=(2,2,2)} + {@realsize=(2,2,2,2)} elsif($type =~ /mediumint/) - {@realsize=(3,3,3)} + {@realsize=(3,3,3,3)} elsif($type =~ /bigint/) - {@realsize=(8,8,8)} + {@realsize=(8,8,8,8)} elsif($type =~ /int/) - {@realsize=(4,4,4)} + {@realsize=(4,4,4,4)} elsif($type =~ /float/) { if($size<=24) - {@realsize=(4,4,4)} + {@realsize=(4,4,4,4)} else - {@realsize=(8,8,8)} + {@realsize=(8,8,8,8)} } elsif($type =~ /double/ || $type =~ /real/) - {@realsize=(8,8,8)} + {@realsize=(8,8,8,8)} elsif($type =~ /bit/) { my $a=($size+7)/8; - @realsize = ($a,$a,$a); + @realsize = ($a,$a,$a,$a); } elsif($type =~ /datetime/) - {@realsize=(8,8,8)} + {@realsize=(8,8,8,8)} elsif($type =~ /timestamp/) - {@realsize=(4,4,4)} + {@realsize=(4,4,4,4)} elsif($type =~ /date/ || $type =~ /time/) - {@realsize=(3,3,3)} + {@realsize=(3,3,3,3)} elsif($type =~ /year/) - {@realsize=(1,1,1)} + {@realsize=(1,1,1,1)} elsif($type =~ /varchar/ || $type =~ /varbinary/) { - my $fixed= 1+$size; + my $fixed=$size+ceil($size/256); my @dynamic=$dbh->selectrow_array("select avg(length(`" .$name ."`)) from `".$table.'`'); $dynamic[0]=0 if !$dynamic[0]; - @realsize= ($fixed,$fixed,ceil($dynamic[0])); + $dynamic[0]+=ceil($dynamic[0]/256); # size bit + $nrvarsize++; + $varsize[3]= ceil($dynamic[0]); + @realsize= ($fixed,$fixed,ceil($dynamic[0]),$fixed); } elsif($type =~ /binary/ || $type =~ /char/) - {@realsize=($size,$size,$size)} + {@realsize=($size,$size,$size,$size)} elsif($type =~ /text/ || $type =~ /blob/) { - @realsize=(256,256,1); + @realsize=(256,256,256,256); $NoOfTables[$_]{val} += 1 foreach 0..$#releases; # blob uses table - } # FIXME check if 5.1 is correct + } @realsize= align(4,@realsize); @@ -212,20 +217,20 @@ foreach(@{$tables}) type=>'bigint', size=>8, key=>'PRI', - datamemory=>[{val=>8},{val=>8},{val=>8}], + datamemory=>[{val=>8},{val=>8},{val=>8},{val=>8}], }; $columnsize{'HIDDEN_NDB_PKEY'}= [8,8,8]; } - my @IndexDataMemory= ({val=>0},{val=>0},{val=>0}); - my @RowIndexMemory= ({val=>0},{val=>0},{val=>0}); + my @IndexDataMemory= ({val=>0},{val=>0},{val=>0},{val=>0}); + my @RowIndexMemory= ({val=>0},{val=>0},{val=>0},{val=>0}); my @indexes; foreach my $index (keys %indexes) { my $im41= 25; $im41+=$columnsize{$_}[0] foreach @{$indexes{$index}{columns}}; - my @im = ({val=>$im41},{val=>25},{val=>25}); - my @dm = ({val=>10},{val=>10},{val=>10}); + my @im = ({val=>$im41},{val=>25},{val=>25},{val=>25}); + my @dm = ({val=>10},{val=>10},{val=>10},{val=>10}); push @indexes, { name=>$index, type=>$indexes{$index}{type}, @@ -233,13 +238,22 @@ foreach(@{$tables}) indexmemory=>\@im, datamemory=>\@dm, }; - $IndexDataMemory[$_]{val}+=$dm[$_]{val} foreach 0..2; - $RowIndexMemory[$_]{val}+=$im[$_]{val} foreach 0..2; + $IndexDataMemory[$_]{val}+=$dm[$_]{val} foreach 0..$#releases; + $RowIndexMemory[$_]{val}+=$im[$_]{val} foreach 0..$#releases; } # total size + 16 bytes overhead my @TotalDataMemory; - $TotalDataMemory[$_]{val}=$IndexDataMemory[$_]{val}+$totalsize[$_]+16 foreach 0..2; + my @RowOverhead = ({val=>16},{val=>16},{val=>16},{val=>24}); + # 5.1 has ptr to varsize page, and per-varsize overhead + my @nrvarsize_mem= ({val=>0},{val=>0}, + {val=>8},{val=>0}); + { + my @a= align(4,$nrvarsize*2); + $nrvarsize_mem[2]{val}+=$a[0]+$nrvarsize*4; + } + + $TotalDataMemory[$_]{val}=$IndexDataMemory[$_]{val}+$totalsize[$_]+$RowOverhead[$_]{val}+$nrvarsize_mem[$_]{val} foreach 0..$#releases; my @RowDataMemory; push @RowDataMemory,{val=>$_} foreach @totalsize; @@ -260,12 +274,18 @@ foreach(@{$tables}) my @counts; $counts[$_]{val}= $count foreach 0..$#releases; + my @nrvarsize_rel= ({val=>0},{val=>0}, + {val=>$nrvarsize},{val=>0}); + push @table_size, { table=>$table, indexes=>\@indexes, columns=>\@columns, count=>\@counts, + RowOverhead=>\@RowOverhead, RowDataMemory=>\@RowDataMemory, + nrvarsize=>\@nrvarsize_rel, + nrvarsize_mem=>\@nrvarsize_mem, releases=>\@releases, IndexDataMemory=>\@IndexDataMemory, TotalDataMemory=>\@TotalDataMemory, diff --git a/ndb/tools/ndb_size.tmpl b/ndb/tools/ndb_size.tmpl index dc02b5a5970..048b3e8ed14 100644 --- a/ndb/tools/ndb_size.tmpl +++ b/ndb/tools/ndb_size.tmpl @@ -15,6 +15,8 @@ td,th { border: 1px solid black }

This information should be valid for MySQL 4.1 and 5.0. Since 5.1 is not a final release yet, the numbers should be used as a guide only.

+

5.1-dd is for tables stored on disk. The ndb_size.pl estimates are experimental and should not be trusted. Notably we don't take into account indexed columns being in DataMemory versus non-indexed on disk.

+

Parameter Settings

NOTE the configuration parameters below do not take into account system tables and other requirements.

@@ -128,10 +130,22 @@ td,th { border: 1px solid black } + + + + + + - - + + + + + + + + From aca43bd8f97b541116e7210d9a226f07f1c15c4a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 26 Jul 2006 11:44:52 +1000 Subject: [PATCH 02/47] BUG#21204 ndb_size.pl doesn't take extended BLOB/TEXT size into account ndb/tools/ndb_size.pl: disable 5.1-dd reporting as it's not ready yet. support BLOB tables with mostly accurate space estimate (our estimates will be slightly higher due to the fact we also calculate an ORDERED index on the BLOB table, something that NDB doesn't have). now have subroutine do_table that does the calculations for a table. We call this with a "fake" blob table to get estimates for blob usage. ndb/tools/ndb_size.tmpl: Add column in columns table for if column is VARSIZED --- ndb/tools/ndb_size.pl | 109 ++++++++++++++++++++++++++++------------ ndb/tools/ndb_size.tmpl | 2 + 2 files changed, 79 insertions(+), 32 deletions(-) diff --git a/ndb/tools/ndb_size.pl b/ndb/tools/ndb_size.pl index 1d616e3acc5..3d1ea3f4231 100644 --- a/ndb/tools/ndb_size.pl +++ b/ndb/tools/ndb_size.pl @@ -57,7 +57,7 @@ if(@ARGV < 3 || $ARGV[0] eq '--usage' || $ARGV[0] eq '--help') $template->param(dsn => $dsn); } -my @releases = ({rel=>'4.1'},{rel=>'5.0'},{rel=>'5.1'},{rel=>'5.1-dd'}); +my @releases = ({rel=>'4.1'},{rel=>'5.0'},{rel=>'5.1'}); #,{rel=>'5.1-dd'}); $template->param(releases => \@releases); my $tables = $dbh->selectall_arrayref("show tables"); @@ -81,18 +81,19 @@ sub align { return @aligned; } -foreach(@{$tables}) -{ - my $table= @{$_}[0]; - my @columns; - my $info= $dbh->selectall_hashref('describe `'.$table.'`',"Field"); - my @count = $dbh->selectrow_array('select count(*) from `'.$table.'`'); - my %columnsize; # used for index calculations +sub do_table { + my $table= shift; + my $info= shift; + my %indexes= %{$_[0]}; + my @count= @{$_[1]}; + my @columns; + my %columnsize; # used for index calculations # We now work out the DataMemory usage # sizes for 4.1, 5.0, 5.1 and 5.1-dd my @totalsize= (0,0,0,0); + @totalsize= @totalsize[0..$#releases]; # limit to releases we're outputting my $nrvarsize= 0; foreach(keys %$info) @@ -102,6 +103,7 @@ foreach(@{$tables}) my $type; my $size; my $name= $_; + my $is_varsize= 0; if($$info{$_}{Type} =~ /^(.*?)\((\d+)\)/) { @@ -154,6 +156,7 @@ foreach(@{$tables}) $dynamic[0]=0 if !$dynamic[0]; $dynamic[0]+=ceil($dynamic[0]/256); # size bit $nrvarsize++; + $is_varsize= 1; $varsize[3]= ceil($dynamic[0]); @realsize= ($fixed,$fixed,ceil($dynamic[0]),$fixed); } @@ -161,10 +164,38 @@ foreach(@{$tables}) {@realsize=($size,$size,$size,$size)} elsif($type =~ /text/ || $type =~ /blob/) { - @realsize=(256,256,256,256); - $NoOfTables[$_]{val} += 1 foreach 0..$#releases; # blob uses table + @realsize=(8+256,8+256,8+256,8+256); + + my $blobhunk= 2000; + $blobhunk= 8000 if $type=~ /longblob/; + $blobhunk= 4000 if $type=~ /mediumblob/; + + my @blobsize=$dbh->selectrow_array("select SUM(CEILING(". + "length(`$name`)/$blobhunk))". + "from `".$table."`"); + $blobsize[0]=0 if !defined($blobsize[0]); + #$NoOfTables[$_]{val} += 1 foreach 0..$#releases; # blob uses table + do_table($table."\$BLOB_$name", + {'PK'=>{Type=>'int'}, + 'DIST'=>{Type=>'int'}, + 'PART'=>{Type=>'int'}, + 'DATA'=>{Type=>"binary($blobhunk)"} + }, + {'PRIMARY' => { + 'unique' => 1, + 'comment' => '', + 'columns' => [ + 'PK', + 'DIST', + 'PART', + ], + 'type' => 'HASH' + } + }, + \@blobsize); } + @realsize= @realsize[0..$#releases]; @realsize= align(4,@realsize); $totalsize[$_]+=$realsize[$_] foreach 0..$#totalsize; @@ -175,6 +206,7 @@ foreach(@{$tables}) push @columns, { name=>$name, type=>$type, + is_varsize=>$is_varsize, size=>$size, key=>$$info{$_}{Key}, datamemory=>\@realout, @@ -188,24 +220,10 @@ foreach(@{$tables}) # Firstly, we assemble some information about the indexes. # We use SHOW INDEX instead of using INFORMATION_SCHEMA so # we can still connect to pre-5.0 mysqlds. - my %indexes; - { - my $sth= $dbh->prepare("show index from `".$table.'`'); - $sth->execute; - while(my $i = $sth->fetchrow_hashref) - { - $indexes{${%$i}{Key_name}}= { - type=>${%$i}{Index_type}, - unique=>!${%$i}{Non_unique}, - comment=>${%$i}{Comment}, - } if !defined($indexes{${%$i}{Key_name}}); - - $indexes{${%$i}{Key_name}}{columns}[${%$i}{Seq_in_index}-1]= - ${%$i}{Column_name}; - } - } if(!defined($indexes{PRIMARY})) { + my @usage= ({val=>8},{val=>8},{val=>8},{val=>8}); + @usage= @usage[0..$#releases]; $indexes{PRIMARY}= { type=>'BTREE', unique=>1, @@ -217,20 +235,22 @@ foreach(@{$tables}) type=>'bigint', size=>8, key=>'PRI', - datamemory=>[{val=>8},{val=>8},{val=>8},{val=>8}], + datamemory=>\@usage, }; $columnsize{'HIDDEN_NDB_PKEY'}= [8,8,8]; } my @IndexDataMemory= ({val=>0},{val=>0},{val=>0},{val=>0}); my @RowIndexMemory= ({val=>0},{val=>0},{val=>0},{val=>0}); + @IndexDataMemory= @IndexDataMemory[0..$#releases]; + @RowIndexMemory= @RowIndexMemory[0..$#releases]; my @indexes; foreach my $index (keys %indexes) { my $im41= 25; $im41+=$columnsize{$_}[0] foreach @{$indexes{$index}{columns}}; - my @im = ({val=>$im41},{val=>25},{val=>25},{val=>25}); - my @dm = ({val=>10},{val=>10},{val=>10},{val=>10}); + my @im = ({val=>$im41},{val=>25},{val=>25}); #,{val=>25}); + my @dm = ({val=>10},{val=>10},{val=>10}); #,{val=>10}); push @indexes, { name=>$index, type=>$indexes{$index}{type}, @@ -244,10 +264,10 @@ foreach(@{$tables}) # total size + 16 bytes overhead my @TotalDataMemory; - my @RowOverhead = ({val=>16},{val=>16},{val=>16},{val=>24}); + my @RowOverhead = ({val=>16},{val=>16},{val=>16}); #,{val=>24}); # 5.1 has ptr to varsize page, and per-varsize overhead my @nrvarsize_mem= ({val=>0},{val=>0}, - {val=>8},{val=>0}); + {val=>8}); #,{val=>0}); { my @a= align(4,$nrvarsize*2); $nrvarsize_mem[2]{val}+=$a[0]+$nrvarsize*4; @@ -275,7 +295,7 @@ foreach(@{$tables}) $counts[$_]{val}= $count foreach 0..$#releases; my @nrvarsize_rel= ({val=>0},{val=>0}, - {val=>$nrvarsize},{val=>0}); + {val=>$nrvarsize}); #,{val=>0}); push @table_size, { table=>$table, @@ -303,6 +323,31 @@ foreach(@{$tables}) $NoOfIndexes[$_]{val} += @indexes foreach 0..$#releases; } +foreach(@{$tables}) +{ + my $table= @{$_}[0]; + my $info= $dbh->selectall_hashref('describe `'.$table.'`',"Field"); + my @count = $dbh->selectrow_array('select count(*) from `'.$table.'`'); + + my %indexes; + { + my $sth= $dbh->prepare("show index from `".$table.'`'); + $sth->execute; + while(my $i = $sth->fetchrow_hashref) + { + $indexes{${%$i}{Key_name}}= { + type=>${%$i}{Index_type}, + unique=>!${%$i}{Non_unique}, + comment=>${%$i}{Comment}, + } if !defined($indexes{${%$i}{Key_name}}); + + $indexes{${%$i}{Key_name}}{columns}[${%$i}{Seq_in_index}-1]= + ${%$i}{Column_name}; + } + } + do_table($table, $info, \%indexes, \@count); +} + my @NoOfTriggers; # for unique hash indexes $NoOfTriggers[$_]{val} += $NoOfIndexes[$_]{val}*3 foreach 0..$#releases; diff --git a/ndb/tools/ndb_size.tmpl b/ndb/tools/ndb_size.tmpl index 048b3e8ed14..1e19ea132ba 100644 --- a/ndb/tools/ndb_size.tmpl +++ b/ndb/tools/ndb_size.tmpl @@ -71,6 +71,7 @@ td,th { border: 1px solid black } + @@ -81,6 +82,7 @@ td,th { border: 1px solid black } + From afdae2f3b7245b5242ef27ff850365cd4a43dd93 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Oct 2006 18:42:59 +0400 Subject: [PATCH 03/47] Patch for BUG#15934: im_daemon_life_cycle fails sporadically. The problem was a race condition in a test case. The fix eliminates the race condition by explicit wait on UNIX socket to start accepting connections. The patch affects only test suite (i.e. does not touch server codebase). mysql-test/mysql-test-run.pl: Expose necessary environment variables. mysql-test/r/im_daemon_life_cycle.result: Update result file. mysql-test/t/im_daemon_life_cycle.imtest: Wait for Instance Manager to start accepting connections after restart. mysql-test/t/wait_for_socket.sh: Helper script: waits for UNIX socket to start accepting connections. --- mysql-test/mysql-test-run.pl | 6 +++ mysql-test/r/im_daemon_life_cycle.result | 1 + mysql-test/t/im_daemon_life_cycle.imtest | 6 +++ mysql-test/t/wait_for_socket.sh | 62 ++++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100755 mysql-test/t/wait_for_socket.sh diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 06dd3864212..41d86944ada 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1249,6 +1249,9 @@ sub environment_setup () { $ENV{'IM_PATH_PID'}= $instance_manager->{path_pid}; $ENV{'IM_PATH_ANGEL_PID'}= $instance_manager->{path_angel_pid}; $ENV{'IM_PORT'}= $instance_manager->{port}; + $ENV{'IM_PATH_SOCK'}= $instance_manager->{path_sock}; + $ENV{'IM_USERNAME'}= $instance_manager->{admin_login}; + $ENV{'IM_PASSWORD'}= $instance_manager->{admin_password}; $ENV{'IM_MYSQLD1_SOCK'}= $instance_manager->{instances}->[0]->{path_sock}; $ENV{'IM_MYSQLD1_PORT'}= $instance_manager->{instances}->[0]->{port}; @@ -1257,6 +1260,9 @@ sub environment_setup () { $ENV{'IM_MYSQLD2_PORT'}= $instance_manager->{instances}->[1]->{port}; $ENV{'IM_MYSQLD2_PATH_PID'}=$instance_manager->{instances}->[1]->{path_pid}; + $ENV{'EXE_MYSQL'}= $exe_mysql; + + $ENV{MTR_BUILD_THREAD}= 0 unless $ENV{MTR_BUILD_THREAD}; # Set if not set # We are nice and report a bit about our settings diff --git a/mysql-test/r/im_daemon_life_cycle.result b/mysql-test/r/im_daemon_life_cycle.result index 52a69d98fcf..a0849313b19 100644 --- a/mysql-test/r/im_daemon_life_cycle.result +++ b/mysql-test/r/im_daemon_life_cycle.result @@ -8,6 +8,7 @@ mysqld2 offline Killing the process... Sleeping... Success: the process was restarted. +Success: server is ready to accept connection on socket. -------------------------------------------------------------------- -- Test for BUG#12751 diff --git a/mysql-test/t/im_daemon_life_cycle.imtest b/mysql-test/t/im_daemon_life_cycle.imtest index acd1f0d887b..408133ca3ba 100644 --- a/mysql-test/t/im_daemon_life_cycle.imtest +++ b/mysql-test/t/im_daemon_life_cycle.imtest @@ -17,6 +17,12 @@ ########################################################################### +# Wait for IM to start accepting connections. + +--exec $MYSQL_TEST_DIR/t/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 30 + +########################################################################### + # # BUG#12751: Instance Manager: client hangs # diff --git a/mysql-test/t/wait_for_socket.sh b/mysql-test/t/wait_for_socket.sh new file mode 100755 index 00000000000..3b900fa2208 --- /dev/null +++ b/mysql-test/t/wait_for_socket.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +########################################################################### + +if [ $# -ne 6 ]; then + echo "Usage: wait_for_socket.sh " + exit 0 +fi + +client_exe="$1" +socket_path="$2" +username="$3" +password="$4" +db="$5" +total_timeout="$6" + +########################################################################### + +if [ -z "$client_exe" ]; then + echo "Error: invalid path to client executable ($client_exe)." + exit 0; +fi + +if [ ! -x "$client_exe" ]; then + echo "Error: client by path '$client_exe' is not available." + exit 0; +fi + +if [ -z "$socket_path" ]; then + echo "Error: invalid socket patch." + exit 0 +fi + +########################################################################### + +client_args="--silent --socket=$socket_path " + +[ -n "$username" ] && client_args="$client_args --user=$username " +[ -n "$password" ] && client_args="$client_args --password=$password " +[ -n "$db" ] && client_args="$client_args $db" + +########################################################################### + +cur_attempt=1 + +while true; do + + if ( echo 'quit' | "$client_exe" $client_args >/dev/null 2>&1 ); then + echo "Success: server is ready to accept connection on socket." + exit 0 + fi + + [ $cur_attempt -ge $total_timeout ] && break + + sleep 1 + + cur_attempt=`expr $cur_attempt + 1` + +done + +echo "Error: server does not accept connections after $total_timeout seconds." +exit 0 From 6acdc271f21b5e1d45fe33bc0254c61761db2abd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Oct 2006 01:24:53 +0400 Subject: [PATCH 04/47] Fix Bug #22472 IM: --socket option should be removed from Windows version the option is useless on windows. It was removed from listing of mysqlmanager --help on Windows server-tools/instance-manager/options.cc: move socket_file_name under unix-specific define server-tools/instance-manager/options.h: move socket_file_name under unix-specific define --- server-tools/instance-manager/options.cc | 4 ++-- server-tools/instance-manager/options.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc index a98c0e291be..c6c709295bc 100644 --- a/server-tools/instance-manager/options.cc +++ b/server-tools/instance-manager/options.cc @@ -45,10 +45,10 @@ const char *default_password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME); const char *default_log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME); const char *Options::config_file= QUOTE(DEFAULT_CONFIG_FILE); const char *Options::angel_pid_file_name= NULL; +const char *Options::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME); #endif const char *Options::log_file_name= default_log_file_name; const char *Options::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME); -const char *Options::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME); const char *Options::password_file_name= default_password_file_name; const char *Options::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH); const char *Options::bind_address= 0; /* No default value */ @@ -106,11 +106,11 @@ static struct my_option my_long_options[] = (gptr *) &Options::angel_pid_file_name, (gptr *) &Options::angel_pid_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, -#endif { "socket", OPT_SOCKET, "Socket file to use for connection.", (gptr *) &Options::socket_file_name, (gptr *) &Options::socket_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, +#endif { "passwd", 'P', "Prepare entry for passwd file and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, diff --git a/server-tools/instance-manager/options.h b/server-tools/instance-manager/options.h index ad3458869b6..f32e106bd7a 100644 --- a/server-tools/instance-manager/options.h +++ b/server-tools/instance-manager/options.h @@ -36,11 +36,11 @@ struct Options static char run_as_service; /* handle_options doesn't support bool */ static const char *user; static const char *angel_pid_file_name; + static const char *socket_file_name; #endif static bool is_forced_default_file; static const char *log_file_name; static const char *pid_file_name; - static const char *socket_file_name; static const char *password_file_name; static const char *default_mysqld_path; /* the option which should be passed to process_default_option_files */ From 777bab9853a950b37b752bfc9c757ec0fdfa7fe0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Oct 2006 22:07:21 +0400 Subject: [PATCH 05/47] Fix Bug #19368 Failure in "flush_instances" causes assert in Thread_registry Stop guardian and all the rest of threads before shutdown in case of an error server-tools/instance-manager/instance_map.cc: flush_instances shouldn't reinit guardian, if it failed to load info about them server-tools/instance-manager/manager.cc: On error we should 1) stop guardian 2) terminate all other threads and exit --- server-tools/instance-manager/instance_map.cc | 4 +++- server-tools/instance-manager/manager.cc | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc index 3b7f58d8a09..f6662847440 100644 --- a/server-tools/instance-manager/instance_map.cc +++ b/server-tools/instance-manager/instance_map.cc @@ -215,7 +215,9 @@ int Instance_map::flush_instances() hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0, get_instance_key, delete_instance, 0); rc= load(); - guardian->init(); // TODO: check error status. + /* don't init guardian if we failed to load instances */ + if (!rc) + guardian->init(); // TODO: check error status. pthread_mutex_unlock(&LOCK_instance_map); guardian->unlock(); return rc; diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc index 353dfcf64dc..6f28c39da77 100644 --- a/server-tools/instance-manager/manager.cc +++ b/server-tools/instance-manager/manager.cc @@ -104,6 +104,19 @@ int my_sigwait(const sigset_t *set, int *sig) #endif +void stop_all(Guardian_thread *guardian, Thread_registry *registry) +{ + /* + Let guardian thread know that it should break it's processing cycle, + once it wakes up. + */ + guardian->request_shutdown(true); + /* wake guardian */ + pthread_cond_signal(&guardian->COND_guardian); + /* stop all threads */ + registry->deliver_shutdown(); +} + /* manager - entry point to the main instance manager process: start listener thread, write pid file and enter into signal handling. @@ -210,7 +223,8 @@ void manager(const Options &options) log_error("Cannot init instances repository. This might be caused by " "the wrong config file options. For instance, missing mysqld " "binary. Aborting."); - return; + stop_all(&guardian_thread, &thread_registry); + goto err; } /* create the listener */ @@ -227,6 +241,7 @@ void manager(const Options &options) if (rc) { log_error("manager(): set_stacksize_n_create_thread(listener) failed"); + stop_all(&guardian_thread, &thread_registry); goto err; } @@ -245,6 +260,7 @@ void manager(const Options &options) if ((status= my_sigwait(&mask, &signo)) != 0) { log_error("sigwait() failed"); + stop_all(&guardian_thread, &thread_registry); goto err; } From f603c1cce8fb44772f30d69ab402b036d1fb1593 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 6 Oct 2006 13:34:07 +0400 Subject: [PATCH 06/47] BUG#21726: Incorrect result with multiple invocations of LAST_INSERT_ID. Note: bug#21726 does not directly apply to 4.1, as it doesn't have stored procedures. However, 4.1 had some bugs that were fixed in 5.0 by the patch for bug#21726, and this patch is a backport of those fixes. Namely, in 4.1 it fixes: - LAST_INSERT_ID(expr) didn't return value of expr (4.1 specific). - LAST_INSERT_ID() could return the value generated by current statement if the call happens after the generation, like in CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY, j INT); INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); - Redundant binary log LAST_INSERT_ID_EVENTs could be generated. mysql-test/r/rpl_insert_id.result: Add result for bug#21726: Incorrect result with multiple invocations of LAST_INSERT_ID. mysql-test/t/rpl_insert_id.test: Add test case for bug#21726: Incorrect result with multiple invocations of LAST_INSERT_ID. sql/item_func.cc: Add implementation of Item_func_last_insert_id::fix_fields(), where we set THD::last_insert_id_used when statement calls LAST_INSERT_ID(). In Item_func_last_insert_id::val_int(), return THD::current_insert_id if called like LAST_INSERT_ID(), otherwise return value of argument if called like LAST_INSERT_ID(expr). sql/item_func.h: Add declaration of Item_func_last_insert_id::fix_fields(). sql/log_event.cc: Do not set THD::last_insert_id_used on LAST_INSERT_ID_EVENT. Though we know the statement will call LAST_INSERT_ID(), it wasn't called yet. sql/set_var.cc: In sys_var_last_insert_id::value_ptr(), set THD::last_insert_id_used, and return THD::current_insert_id for @@LAST_INSERT_ID. sql/sql_class.h: Update comments. Remove THD::insert_id(), as it has lost its purpose now. sql/sql_insert.cc: Now it is OK to read THD::last_insert_id directly. sql/sql_load.cc: Now it is OK to read THD::last_insert_id directly. sql/sql_parse.cc: In mysql_execute_command(), remember THD::last_insert_id (first generated value of the previous statement) in THD::current_insert_id, which then will be returned for LAST_INSERT_ID() and @@LAST_INSERT_ID. sql/sql_select.cc: If "IS NULL" is replaced with "= ", use right value, which is THD::current_insert_id, and also set THD::last_insert_id_used to issue binary log LAST_INSERT_ID_EVENT. sql/sql_update.cc: Now it is OK to read THD::last_insert_id directly. tests/mysql_client_test.c: Add test case for bug#21726: Incorrect result with multiple invocations of LAST_INSERT_ID. --- mysql-test/r/rpl_insert_id.result | 27 +++++++++++++++++ mysql-test/t/rpl_insert_id.test | 32 +++++++++++++++++++++ sql/item_func.cc | 31 ++++++++++++++++++-- sql/item_func.h | 1 + sql/log_event.cc | 1 - sql/set_var.cc | 8 ++++-- sql/sql_class.h | 48 +++++++++++++++++++++---------- sql/sql_insert.cc | 8 ++---- sql/sql_load.cc | 12 +++----- sql/sql_parse.cc | 6 ++++ sql/sql_select.cc | 11 +++++-- sql/sql_update.cc | 4 +-- tests/mysql_client_test.c | 38 ++++++++++++++++++++++++ 13 files changed, 189 insertions(+), 38 deletions(-) diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index fbdc9dc06cf..43aba68d041 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -108,6 +108,33 @@ a 1 drop table t1; drop table t2; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 ( +i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +j INT DEFAULT 0 +); +INSERT INTO t1 VALUES (NULL, -1); +INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)), +(NULL, @@LAST_INSERT_ID); +INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); +UPDATE t1 SET j= -1 WHERE i IS NULL; +SELECT * FROM t1; +i j +1 -1 +2 1 +3 5 +4 1 +5 -1 +6 2 +SELECT * FROM t1; +i j +1 -1 +2 1 +3 5 +4 1 +5 -1 +6 2 +DROP TABLE t1; # # End of 4.1 tests # diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test index 327094a1394..7fb514fb7af 100644 --- a/mysql-test/t/rpl_insert_id.test +++ b/mysql-test/t/rpl_insert_id.test @@ -108,6 +108,38 @@ drop table t1; drop table t2; sync_slave_with_master; + +# +# BUG#21726: Incorrect result with multiple invocations of +# LAST_INSERT_ID +# +connection master; + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 ( + i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + j INT DEFAULT 0 +); + +INSERT INTO t1 VALUES (NULL, -1); +INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)), + (NULL, @@LAST_INSERT_ID); +# Test replication of substitution "IS NULL" -> "= LAST_INSERT_ID". +INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); +UPDATE t1 SET j= -1 WHERE i IS NULL; + +SELECT * FROM t1; + +sync_slave_with_master; +SELECT * FROM t1; + +connection master; +DROP TABLE t1; + + --echo # --echo # End of 4.1 tests --echo # diff --git a/sql/item_func.cc b/sql/item_func.cc index 91ccef6511f..6f8eed42e51 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2230,6 +2230,30 @@ longlong Item_func_release_lock::val_int() } +bool Item_func_last_insert_id::fix_fields(THD *thd, TABLE_LIST *tables, + Item **ref) +{ + DBUG_ASSERT(fixed == 0); + + if (Item_int_func::fix_fields(thd, tables, ref)) + return TRUE; + + if (arg_count == 0) + { + /* + As this statement calls LAST_INSERT_ID(), set + THD::last_insert_id_used. + */ + thd->last_insert_id_used= TRUE; + null_value= FALSE; + } + + thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); + + return FALSE; +} + + longlong Item_func_last_insert_id::val_int() { DBUG_ASSERT(fixed == 1); @@ -2239,12 +2263,13 @@ longlong Item_func_last_insert_id::val_int() longlong value=args[0]->val_int(); thd->insert_id(value); null_value=args[0]->null_value; + return value; } - else - thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - return thd->last_insert_id_used ? thd->current_insert_id : thd->insert_id(); + + return thd->current_insert_id; } + /* This function is just used to test speed of different functions */ longlong Item_func_benchmark::val_int() diff --git a/sql/item_func.h b/sql/item_func.h index bc6c955b99f..467b88eda76 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -758,6 +758,7 @@ public: longlong val_int(); const char *func_name() const { return "last_insert_id"; } void fix_length_and_dec() { if (arg_count) max_length= args[0]->max_length; } + bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); }; class Item_func_benchmark :public Item_int_func diff --git a/sql/log_event.cc b/sql/log_event.cc index 19c32b2d28e..412ebbce0ac 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2255,7 +2255,6 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli) { switch (type) { case LAST_INSERT_ID_EVENT: - thd->last_insert_id_used = 1; thd->last_insert_id = val; break; case INSERT_ID_EVENT: diff --git a/sql/set_var.cc b/sql/set_var.cc index 4acedc7bcbd..88e120632e2 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2404,8 +2404,12 @@ bool sys_var_last_insert_id::update(THD *thd, set_var *var) byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - thd->sys_var_tmp.long_value= (long) thd->insert_id(); - return (byte*) &thd->last_insert_id; + /* + As this statement reads @@LAST_INSERT_ID, set + THD::last_insert_id_used. + */ + thd->last_insert_id_used= TRUE; + return (byte*) &thd->current_insert_id; } diff --git a/sql/sql_class.h b/sql/sql_class.h index a995a492bc8..5c4c3af7acb 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -835,17 +835,29 @@ public: generated auto_increment value in handler.cc */ ulonglong next_insert_id; + /* - The insert_id used for the last statement or set by SET LAST_INSERT_ID=# - or SELECT LAST_INSERT_ID(#). Used for binary log and returned by - LAST_INSERT_ID() + At the beginning of the statement last_insert_id holds the first + generated value of the previous statement. During statement + execution it is updated to the value just generated, but then + restored to the value that was generated first, so for the next + statement it will again be "the first generated value of the + previous statement". + + It may also be set with "LAST_INSERT_ID(expr)" or + "@@LAST_INSERT_ID= expr", but the effect of such setting will be + seen only in the next statement. */ ulonglong last_insert_id; + /* - Set to the first value that LAST_INSERT_ID() returned for the last - statement. When this is set, last_insert_id_used is set to true. + current_insert_id remembers the first generated value of the + previous statement, and does not change during statement + execution. Its value returned from LAST_INSERT_ID() and + @@LAST_INSERT_ID. */ ulonglong current_insert_id; + ulonglong limit_found_rows; ha_rows cuted_fields, sent_row_count, examined_row_count; @@ -896,7 +908,22 @@ public: bool locked, some_tables_deleted; bool last_cuted_field; bool no_errors, password, is_fatal_error; - bool query_start_used,last_insert_id_used,insert_id_used,rand_used; + bool query_start_used, rand_used; + + /* + last_insert_id_used is set when current statement calls + LAST_INSERT_ID() or reads @@LAST_INSERT_ID, so that binary log + LAST_INSERT_ID_EVENT be generated. + */ + bool last_insert_id_used; + + /* + insert_id_used is set when current statement updates + THD::last_insert_id, so that binary log INSERT_ID_EVENT be + generated. + */ + bool insert_id_used; + /* for IS NULL => = last_insert_id() fix in remove_eq_conds() */ bool substitute_null_with_insert_id; bool time_zone_used; @@ -996,15 +1023,6 @@ public: insert_id_used=1; substitute_null_with_insert_id= TRUE; } - inline ulonglong insert_id(void) - { - if (!last_insert_id_used) - { - last_insert_id_used=1; - current_insert_id=last_insert_id; - } - return last_insert_id; - } inline ulonglong found_rows(void) { return limit_found_rows; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 283fe571d53..43c7e5d456f 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -374,10 +374,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, if (error) break; /* - If auto_increment values are used, save the first one - for LAST_INSERT_ID() and for the update log. - We can't use insert_id() as we don't want to touch the - last_insert_id_used flag. + If auto_increment values are used, save the first one for + LAST_INSERT_ID() and for the update log. */ if (! id && thd->insert_id_used) { // Get auto increment value @@ -1687,7 +1685,7 @@ bool select_insert::send_data(List &values) { table->next_number_field->reset(); if (! last_insert_id && thd->insert_id_used) - last_insert_id=thd->insert_id(); + last_insert_id= thd->last_insert_id; } } DBUG_RETURN(error); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 4e6c458cc43..48862506729 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -466,10 +466,8 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List &fields, if (write_record(table,&info)) DBUG_RETURN(1); /* - If auto_increment values are used, save the first one - for LAST_INSERT_ID() and for the binary/update log. - We can't use insert_id() as we don't want to touch the - last_insert_id_used flag. + If auto_increment values are used, save the first one for + LAST_INSERT_ID() and for the binary/update log. */ if (!id && thd->insert_id_used) id= thd->last_insert_id; @@ -572,10 +570,8 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, if (write_record(table,&info)) DBUG_RETURN(1); /* - If auto_increment values are used, save the first one - for LAST_INSERT_ID() and for the binary/update log. - We can't use insert_id() as we don't want to touch the - last_insert_id_used flag. + If auto_increment values are used, save the first one for + LAST_INSERT_ID() and for the binary/update log. */ if (!id && thd->insert_id_used) id= thd->last_insert_id; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 98199ed22f1..cb2fa0f7014 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1977,6 +1977,12 @@ mysql_execute_command(THD *thd) SELECT_LEX_UNIT *unit= &lex->unit; DBUG_ENTER("mysql_execute_command"); + /* + Remember first generated insert id value of the previous + statement. + */ + thd->current_insert_id= thd->last_insert_id; + /* Reset warning count for each query that uses tables A better approach would be to reset this for any commands diff --git a/sql/sql_select.cc b/sql/sql_select.cc index da96c98cd4f..117795059f0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4820,7 +4820,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) Field *field=((Item_field*) args[0])->field; if (field->flags & AUTO_INCREMENT_FLAG && !field->table->maybe_null && (thd->options & OPTION_AUTO_IS_NULL) && - thd->insert_id() && thd->substitute_null_with_insert_id) + thd->current_insert_id && thd->substitute_null_with_insert_id) { #ifdef HAVE_QUERY_CACHE query_cache_abort(&thd->net); @@ -4828,9 +4828,16 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) COND *new_cond; if ((new_cond= new Item_func_eq(args[0], new Item_int("last_insert_id()", - thd->insert_id(), + thd->current_insert_id, 21)))) { + /* + Set THD::last_insert_id_used manually, as this statement + uses LAST_INSERT_ID() in a sense, and should issue + LAST_INSERT_ID_EVENT. + */ + thd->last_insert_id_used= TRUE; + cond=new_cond; cond->fix_fields(thd, 0, &cond); } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index af4ba8025f9..51643fc611d 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -408,7 +408,7 @@ int mysql_update(THD *thd, (ulong) thd->cuted_fields); send_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated, - thd->insert_id_used ? thd->insert_id() : 0L,buff); + thd->insert_id_used ? thd->last_insert_id : 0L,buff); DBUG_PRINT("info",("%d records updated",updated)); } thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */ @@ -1318,6 +1318,6 @@ bool multi_update::send_eof() (ulong) thd->cuted_fields); ::send_ok(thd, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated, - thd->insert_id_used ? thd->insert_id() : 0L,buff); + thd->insert_id_used ? thd->last_insert_id : 0L,buff); return 0; } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 9fabde993b8..6ae9dcb9476 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11908,6 +11908,43 @@ static void test_bug20152() } +/* + Bug#21726: Incorrect result with multiple invocations of + LAST_INSERT_ID + + Test that client gets updated value of insert_id on UPDATE that uses + LAST_INSERT_ID(expr). +*/ +static void test_bug21726() +{ + const char *update_query = "UPDATE t1 SET i= LAST_INSERT_ID(i + 1)"; + int rc; + my_ulonglong insert_id; + + DBUG_ENTER("test_bug21726"); + myheader("test_bug21726"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + rc= mysql_query(mysql, "CREATE TABLE t1 (i INT)"); + myquery(rc); + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)"); + myquery(rc); + + rc= mysql_query(mysql, update_query); + myquery(rc); + insert_id= mysql_insert_id(mysql); + DIE_UNLESS(insert_id == 2); + + rc= mysql_query(mysql, update_query); + myquery(rc); + insert_id= mysql_insert_id(mysql); + DIE_UNLESS(insert_id == 3); + + DBUG_VOID_RETURN; +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -12134,6 +12171,7 @@ static struct my_tests_st my_tests[]= { { "test_bug12925", test_bug12925 }, { "test_bug15613", test_bug15613 }, { "test_bug20152", test_bug20152 }, + { "test_bug21726", test_bug21726 }, { 0, 0 } }; From e1e0f829e6ac97c6bb4aaf1f919fde481a2a1a0c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 Oct 2006 09:59:02 -0700 Subject: [PATCH 07/47] Bug#21462 (Stored procedures with no arguments require parenthesis) The syntax of the CALL statement, to invoke a stored procedure, has been changed to make the use of parenthesis optional in the argument list. With this change, "CALL p;" is equivalent to "CALL p();". While the SQL spec does not explicitely mandate this syntax, supporting it is needed for practical reasons, for integration with JDBC / ODBC connectors. Also, warnings in the sql/sql_yacc.yy file, which were not reported by Bison 2.1 but are now reported by Bison 2.2, have been fixed. The warning found were: bison -y -p MYSQL -d --debug --verbose sql_yacc.yy sql_yacc.yy:653.9-18: warning: symbol UNLOCK_SYM redeclared sql_yacc.yy:656.9-17: warning: symbol UNTIL_SYM redeclared sql_yacc.yy:658.9-18: warning: symbol UPDATE_SYM redeclared sql_yacc.yy:5169.11-5174.11: warning: unused value: $2 sql_yacc.yy:5208.11-5220.11: warning: unused value: $5 sql_yacc.yy:5221.11-5234.11: warning: unused value: $5 conflicts: 249 shift/reduce "unused value: $2" correspond to the $$=$1 assignment in the 1st {} block in table_ref -> join_table {} {}, which does not procude a result ($$) for the rule but an intermediate $2 value for the action instead. "unused value: $5" are similar, with $$ assignments in {} actions blocks which are not for the final reduce. mysql-test/r/sp.result: New test case for Bug#21462 mysql-test/t/sp.test: New test case for Bug#21462 sql/sql_yacc.yy: "CALL p;" syntax for calling a stored procedure Fixed bison 2.2 warnings. --- mysql-test/r/sp.result | 27 +++++++++++++++++++++++++++ mysql-test/t/sp.test | 33 +++++++++++++++++++++++++++++++++ sql/sql_yacc.yy | 20 +++++++++++--------- 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 31aa96ab05d..6e8a609d669 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5470,5 +5470,32 @@ CAD CHF DROP FUNCTION bug21493| DROP TABLE t3,t4| +drop procedure if exists proc_21462_a| +drop procedure if exists proc_21462_b| +create procedure proc_21462_a() +begin +select "Called A"; +end| +create procedure proc_21462_b(x int) +begin +select "Called B"; +end| +call proc_21462_a| +Called A +Called A +call proc_21462_a()| +Called A +Called A +call proc_21462_a(1)| +ERROR 42000: Incorrect number of arguments for PROCEDURE test.proc_21462_a; expected 0, got 1 +call proc_21462_b| +ERROR 42000: Incorrect number of arguments for PROCEDURE test.proc_21462_b; expected 1, got 0 +call proc_21462_b()| +ERROR 42000: Incorrect number of arguments for PROCEDURE test.proc_21462_b; expected 1, got 0 +call proc_21462_b(1)| +Called B +Called B +drop procedure proc_21462_a| +drop procedure proc_21462_b| End of 5.0 tests drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 87d19baf888..ffbbf56d3ac 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -6420,6 +6420,39 @@ SELECT bug21493(Member_ID) FROM t3| DROP FUNCTION bug21493| DROP TABLE t3,t4| +# +# Bug#21462 Stored procedures with no arguments require parenthesis +# + +--disable_warnings +drop procedure if exists proc_21462_a| +drop procedure if exists proc_21462_b| +--enable_warnings + +create procedure proc_21462_a() +begin + select "Called A"; +end| + +create procedure proc_21462_b(x int) +begin + select "Called B"; +end| + +call proc_21462_a| +call proc_21462_a()| +-- error ER_SP_WRONG_NO_OF_ARGS +call proc_21462_a(1)| + +-- error ER_SP_WRONG_NO_OF_ARGS +call proc_21462_b| +-- error ER_SP_WRONG_NO_OF_ARGS +call proc_21462_b()| +call proc_21462_b(1)| + +drop procedure proc_21462_a| +drop procedure proc_21462_b| + --echo End of 5.0 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index cb105d05332..06afbabbba4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -650,11 +650,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token UNIX_TIMESTAMP %token UNKNOWN_SYM %token UNLOCK_SYM -%token UNLOCK_SYM %token UNSIGNED %token UNTIL_SYM -%token UNTIL_SYM -%token UPDATE_SYM %token UPDATE_SYM %token UPGRADE_SYM %token USAGE @@ -1447,15 +1444,20 @@ call: lex->value_list.empty(); sp_add_used_routine(lex, YYTHD, $2, TYPE_ENUM_PROCEDURE); } - '(' sp_cparam_list ')' {} + opt_sp_cparam_list {} ; /* CALL parameters */ -sp_cparam_list: +opt_sp_cparam_list: /* Empty */ - | sp_cparams + | '(' opt_sp_cparams ')' ; +opt_sp_cparams: + /* Empty */ + | sp_cparams + ; + sp_cparams: sp_cparams ',' expr { @@ -5166,7 +5168,7 @@ when_list2: /* Warning - may return NULL in case of incomplete SELECT */ table_ref: table_factor { $$=$1; } - | join_table { $$=$1; } + | join_table { LEX *lex= Lex; if (!($$= lex->current_select->nest_last_join(lex->thd))) @@ -5208,7 +5210,7 @@ join_table: | table_ref normal_join table_ref ON { - YYERROR_UNLESS($1 && ($$=$3)); + YYERROR_UNLESS($1 && $3); /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $3)) YYABORT; @@ -5223,7 +5225,7 @@ join_table: | table_ref STRAIGHT_JOIN table_factor ON { - YYERROR_UNLESS($1 && ($$=$3)); + YYERROR_UNLESS($1 && $3); /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $3)) YYABORT; From 469ff92d81d496862ed1fcb7cf700390b7c2de72 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Oct 2006 13:44:04 +0400 Subject: [PATCH 08/47] Bug#19111: TRIGGERs selecting from a VIEW on the firing base table fail. In a trigger or a function used in a statement it is possible to do SELECT from a table being modified by the statement. However, encapsulation of such SELECT into a view and selecting from a view instead of direct SELECT was not possible. This happened because tables used by views (which in their turn were used from functions/triggers) were not excluded from checks in unique_table() routine as it happens for the rest of tables added to the statement table list for prelocking. With this fix we ignore all such tables in unique_table(), thus providing consistency: inside a trigger or a functions SELECT from a view may be used where plain SELECT is allowed. Modification of the same table from function or trigger is still disallowed. Also, this patch doesn't affect the case where SELECT from the table being modified is done outside of function of trigger, such SELECTs are still disallowed (this limitation and visibility problem when function select from a table being modified are subjects of bug 21326). See also bug 22427. mysql-test/r/view.result: Add result for bug#19111: TRIGGERs selecting from a VIEW on the firing base table fail. mysql-test/t/view.test: Add test case for bug#19111: TRIGGERs selecting from a VIEW on the firing base table fail. sql/sql_base.cc: In unique_table() do not check tables that are used in a stored function or a trigger ('prelocking_placeholder' is set). If such function or a trigger will attempt to modify a table, the error will be given, however select is allowed there. --- mysql-test/r/view.result | 17 ++++++++++++++++- mysql-test/t/view.test | 39 ++++++++++++++++++++++++++++++++++++++- sql/sql_base.cc | 11 ++++++++--- 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 72cffb9531c..39db2164f2f 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2735,4 +2735,19 @@ m e 4 a 1 b DROP VIEW v1; -DROP TABLE IF EXISTS t1,t2; +DROP TABLE t1,t2; +DROP FUNCTION IF EXISTS f1; +DROP VIEW IF EXISTS v1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1); +CREATE VIEW v1 AS SELECT MAX(i) FROM t1; +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW +SET NEW.i = (SELECT * FROM v1) + 1; +INSERT INTO t1 VALUES (1); +CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1); +UPDATE t1 SET i= f1(); +DROP FUNCTION f1; +DROP VIEW v1; +DROP TABLE t1; +End of 5.0 tests. diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index a1c1e9b2ad1..56c0529a67b 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2595,4 +2595,41 @@ CREATE TABLE t2 SELECT * FROM v1; SELECT * FROM t2; DROP VIEW v1; -DROP TABLE IF EXISTS t1,t2; +DROP TABLE t1,t2; + + +# +# Bug#19111: TRIGGERs selecting from a VIEW on the firing base table +# fail +# +# Allow to select from a view on a table being modified in a trigger +# and stored function, since plain select is allowed there. +# +--disable_warnings +DROP FUNCTION IF EXISTS f1; +DROP VIEW IF EXISTS v1; +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1); + +CREATE VIEW v1 AS SELECT MAX(i) FROM t1; + +# Plain 'SET NEW.i = (SELECT MAX(i) FROM t1) + 1' works, so select +# from a view should work too. +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW + SET NEW.i = (SELECT * FROM v1) + 1; +INSERT INTO t1 VALUES (1); + +# Plain 'RETURN (SELECT MAX(i) FROM t1)' works in INSERT, so select +# from a view should work too. +CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1); +UPDATE t1 SET i= f1(); + +DROP FUNCTION f1; +DROP VIEW v1; +DROP TABLE t1; + + +--echo End of 5.0 tests. diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 5383bb52aaa..858d820c85e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -805,6 +805,10 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, Also SELECT::exclude_from_table_unique_test used to exclude from check tables of main SELECT of multi-delete and multi-update + We also skip tables with TABLE_LIST::prelocking_placeholder set, + because we want to allow SELECTs from them, and their modification + will rise the error anyway. + TODO: when we will have table/view change detection we can do this check only once for PS/SP @@ -851,12 +855,13 @@ TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list) if (((! (res= find_table_in_global_list(table_list, d_name, t_name))) && (! (res= mysql_lock_have_duplicate(thd, table, table_list)))) || ((!res->table || res->table != table->table) && - res->select_lex && !res->select_lex->exclude_from_table_unique_test)) + res->select_lex && !res->select_lex->exclude_from_table_unique_test && + !res->prelocking_placeholder)) break; /* - If we found entry of this table or or table of SELECT which already + If we found entry of this table or table of SELECT which already processed in derived table or top select of multi-update/multi-delete - (exclude_from_table_unique_test). + (exclude_from_table_unique_test) or prelocking placeholder. */ table_list= res->next_global; DBUG_PRINT("info", From 3177e8ebc49d95bb9c7768e5fc6aceb66bbb1783 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Oct 2006 17:08:47 +0400 Subject: [PATCH 09/47] BUG#21354: (COUNT(*) = 1) not working in SELECT inside prepared statement. The problem was that during statement re-execution if the result was empty the old result could be returned for group functions. The solution is to implement proper cleanup() method in group functions. mysql-test/r/ps.result: Add result for bug#21354: (COUNT(*) = 1) not working in SELECT inside prepared statement. mysql-test/t/func_gconcat.test: Add a comment that the test case is from bug#836. mysql-test/t/ps.test: Add test case for bug#21354: (COUNT(*) = 1) not working in SELECT inside prepared statement. sql/item_sum.cc: Call clear() in Item_sum_count::cleanup(). sql/item_sum.h: Add comments. Add proper cleanup() methods. Change Item_sum::no_rows_in_result() to call clear() instead of reset(), as the latter also issues add(), and there is nothing to add when there are no rows in result. --- mysql-test/r/ps.result | 97 ++++++++++++++++++++++++++++++++++ mysql-test/t/func_gconcat.test | 2 +- mysql-test/t/ps.test | 74 +++++++++++++++++++++++++- sql/item_sum.cc | 1 + sql/item_sum.h | 48 ++++++++++++++++- 5 files changed, 219 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 01aa4ddf859..82d8ba275b6 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -889,3 +889,100 @@ create temporary table if not exists t1 (a1 int); execute stmt; drop temporary table t1; deallocate prepare stmt; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT, INDEX(i)); +INSERT INTO t1 VALUES (1); +PREPARE stmt FROM "SELECT (COUNT(i) = 1), COUNT(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(COUNT(i) = 1) COUNT(i) +0 0 +SET @a = 1; +EXECUTE stmt USING @a; +(COUNT(i) = 1) COUNT(i) +1 1 +SET @a = 0; +EXECUTE stmt USING @a; +(COUNT(i) = 1) COUNT(i) +0 0 +PREPARE stmt FROM "SELECT (AVG(i) = 1), AVG(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(AVG(i) = 1) AVG(i) +NULL NULL +SET @a = 1; +EXECUTE stmt USING @a; +(AVG(i) = 1) AVG(i) +1 1.0000 +SET @a = 0; +EXECUTE stmt USING @a; +(AVG(i) = 1) AVG(i) +NULL NULL +PREPARE stmt FROM "SELECT (VARIANCE(i) = 1), VARIANCE(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(VARIANCE(i) = 1) VARIANCE(i) +NULL NULL +SET @a = 1; +EXECUTE stmt USING @a; +(VARIANCE(i) = 1) VARIANCE(i) +0 0.0000 +SET @a = 0; +EXECUTE stmt USING @a; +(VARIANCE(i) = 1) VARIANCE(i) +NULL NULL +PREPARE stmt FROM "SELECT (STDDEV(i) = 1), STDDEV(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(STDDEV(i) = 1) STDDEV(i) +NULL NULL +SET @a = 1; +EXECUTE stmt USING @a; +(STDDEV(i) = 1) STDDEV(i) +0 0.0000 +SET @a = 0; +EXECUTE stmt USING @a; +(STDDEV(i) = 1) STDDEV(i) +NULL NULL +PREPARE stmt FROM "SELECT (BIT_OR(i) = 1), BIT_OR(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_OR(i) = 1) BIT_OR(i) +0 0 +SET @a = 1; +EXECUTE stmt USING @a; +(BIT_OR(i) = 1) BIT_OR(i) +1 1 +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_OR(i) = 1) BIT_OR(i) +0 0 +PREPARE stmt FROM "SELECT (BIT_AND(i) = 1), BIT_AND(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_AND(i) = 1) BIT_AND(i) +0 18446744073709551615 +SET @a = 1; +EXECUTE stmt USING @a; +(BIT_AND(i) = 1) BIT_AND(i) +1 1 +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_AND(i) = 1) BIT_AND(i) +0 18446744073709551615 +PREPARE stmt FROM "SELECT (BIT_XOR(i) = 1), BIT_XOR(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_XOR(i) = 1) BIT_XOR(i) +0 0 +SET @a = 1; +EXECUTE stmt USING @a; +(BIT_XOR(i) = 1) BIT_XOR(i) +1 1 +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_XOR(i) = 1) BIT_XOR(i) +0 0 +DEALLOCATE PREPARE stmt; +DROP TABLE t1; +End of 4.1 tests. diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 8f50690dd8b..21ec7362877 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -99,7 +99,7 @@ select ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'withou select distinct ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'with distinct: cutoff at length of shortname' from t1; drop table t1; -# check zero rows +# check zero rows (bug#836) create table t1(id int); create table t2(id int); insert into t1 values(0),(1); diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 0ca293eb1ba..03fcc241d23 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -951,4 +951,76 @@ execute stmt; drop temporary table t1; deallocate prepare stmt; -# End of 4.1 tests + +# +# BUG#21354: (COUNT(*) = 1) not working in SELECT inside prepared +# statement +# +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (i INT, INDEX(i)); +INSERT INTO t1 VALUES (1); + +PREPARE stmt FROM "SELECT (COUNT(i) = 1), COUNT(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +SET @a = 1; +EXECUTE stmt USING @a; +SET @a = 0; +EXECUTE stmt USING @a; + +PREPARE stmt FROM "SELECT (AVG(i) = 1), AVG(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +SET @a = 1; +EXECUTE stmt USING @a; +SET @a = 0; +EXECUTE stmt USING @a; + +PREPARE stmt FROM "SELECT (VARIANCE(i) = 1), VARIANCE(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +SET @a = 1; +EXECUTE stmt USING @a; +SET @a = 0; +EXECUTE stmt USING @a; + +PREPARE stmt FROM "SELECT (STDDEV(i) = 1), STDDEV(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +SET @a = 1; +EXECUTE stmt USING @a; +SET @a = 0; +EXECUTE stmt USING @a; + +PREPARE stmt FROM "SELECT (BIT_OR(i) = 1), BIT_OR(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +SET @a = 1; +EXECUTE stmt USING @a; +SET @a = 0; +EXECUTE stmt USING @a; + +PREPARE stmt FROM "SELECT (BIT_AND(i) = 1), BIT_AND(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +SET @a = 1; +EXECUTE stmt USING @a; +SET @a = 0; +EXECUTE stmt USING @a; + +PREPARE stmt FROM "SELECT (BIT_XOR(i) = 1), BIT_XOR(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +SET @a = 1; +EXECUTE stmt USING @a; +SET @a = 0; +EXECUTE stmt USING @a; + +DEALLOCATE PREPARE stmt; +DROP TABLE t1; + + +--echo End of 4.1 tests. diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 0b9b10d05d4..e480cb031d8 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -312,6 +312,7 @@ longlong Item_sum_count::val_int() void Item_sum_count::cleanup() { DBUG_ENTER("Item_sum_count::cleanup"); + clear(); Item_sum_int::cleanup(); used_table_cache= ~(table_map) 0; DBUG_VOID_RETURN; diff --git a/sql/item_sum.h b/sql/item_sum.h index 0cc2a20faa3..ea0863fc41c 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -58,9 +58,30 @@ public: Item_sum(THD *thd, Item_sum *item); enum Type type() const { return SUM_FUNC_ITEM; } virtual enum Sumfunctype sum_func () const=0; + + /* + This method is similar to add(), but it is called when the current + aggregation group changes. Thus it performs a combination of + clear() and add(). + */ inline bool reset() { clear(); return add(); }; + + /* + Prepare this item for evaluation of an aggregate value. This is + called by reset() when a group changes, or, for correlated + subqueries, between subquery executions. E.g. for COUNT(), this + method should set count= 0; + */ virtual void clear()= 0; + + /* + This method is called for the next row in the same group. Its + purpose is to aggregate the new value to the previous values in + the group (i.e. since clear() was called last time). For example, + for COUNT(), do count++. + */ virtual bool add()=0; + /* Called when new group is started and results are being saved in a temporary table. Similar to reset(), but must also store value in @@ -86,7 +107,17 @@ public: void make_field(Send_field *field); void print(String *str); void fix_num_length_and_dec(); - void no_rows_in_result() { reset(); } + + /* + This function is called by the execution engine to assign 'NO ROWS + FOUND' value to an aggregate item, when the underlying result set + has no rows. Such value, in a general case, may be different from + the default value of the item after 'clear()': e.g. a numeric item + may be initialized to 0 by clear() and to NULL by + no_rows_in_result(). + */ + void no_rows_in_result() { clear(); } + virtual bool setup(THD *thd) {return 0;} virtual void make_unique() {} Item *get_tmp_table_item(THD *thd); @@ -304,6 +335,11 @@ class Item_sum_avg :public Item_sum_num void no_rows_in_result() {} const char *func_name() const { return "avg"; } Item *copy_or_same(THD* thd); + void cleanup() + { + clear(); + Item_sum_num::cleanup(); + } }; class Item_sum_variance; @@ -361,6 +397,11 @@ class Item_sum_variance : public Item_sum_num void no_rows_in_result() {} const char *func_name() const { return "variance"; } Item *copy_or_same(THD* thd); + void cleanup() + { + clear(); + Item_sum_num::cleanup(); + } }; class Item_sum_std; @@ -485,6 +526,11 @@ public: void update_field(); void fix_length_and_dec() { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; } + void cleanup() + { + clear(); + Item_sum_int::cleanup(); + } }; From c942d5bfb1344567c9ea081a2d3907cff35f535d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Oct 2006 17:51:12 +0400 Subject: [PATCH 10/47] Fix after manial merge. --- mysql-test/r/view.result | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 92123d16b3f..1b2f20702b2 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2736,20 +2736,6 @@ m e 1 b DROP VIEW v1; DROP TABLE t1,t2; -DROP FUNCTION IF EXISTS f1; -DROP VIEW IF EXISTS v1; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 (i INT); -INSERT INTO t1 VALUES (1); -CREATE VIEW v1 AS SELECT MAX(i) FROM t1; -CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW -SET NEW.i = (SELECT * FROM v1) + 1; -INSERT INTO t1 VALUES (1); -CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1); -UPDATE t1 SET i= f1(); -DROP FUNCTION f1; -DROP VIEW v1; -DROP TABLE t1; CREATE TABLE t1 (a INT NOT NULL, b INT NULL DEFAULT NULL); CREATE VIEW v1 AS SELECT a, b FROM t1; INSERT INTO v1 (b) VALUES (2); @@ -2970,4 +2956,18 @@ View Create View v1 CREATE ALGORITHM=MERGE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`pk` AS `pk` from (`t1` join `t2` on(((`t2`.`fk` = `t1`.`pk`) and (`t2`.`ver` = (select max(`t`.`ver`) AS `MAX(t.ver)` from `t2` `t` where (`t`.`org` = `t2`.`org`)))))) DROP VIEW v1; DROP TABLE t1, t2; +DROP FUNCTION IF EXISTS f1; +DROP VIEW IF EXISTS v1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1); +CREATE VIEW v1 AS SELECT MAX(i) FROM t1; +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW +SET NEW.i = (SELECT * FROM v1) + 1; +INSERT INTO t1 VALUES (1); +CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1); +UPDATE t1 SET i= f1(); +DROP FUNCTION f1; +DROP VIEW v1; +DROP TABLE t1; End of 5.0 tests. From 0540c6ad4bc0e293382ba54a908abaaf3d8a6278 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Oct 2006 18:06:08 +0400 Subject: [PATCH 11/47] Fix after manual merge. --- mysql-test/r/ps.result | 335 ++++++++++++----------------------------- 1 file changed, 97 insertions(+), 238 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index e7b41ac5ed6..b28192c2e73 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -546,7 +546,103 @@ GROUP_CONCAT(Track SEPARATOR ', ') CAD DEALLOCATE PREPARE STMT; DROP TABLE t1; -End of 4.1 tests +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT, INDEX(i)); +INSERT INTO t1 VALUES (1); +PREPARE stmt FROM "SELECT (COUNT(i) = 1), COUNT(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(COUNT(i) = 1) COUNT(i) +0 0 +SET @a = 1; +EXECUTE stmt USING @a; +(COUNT(i) = 1) COUNT(i) +1 1 +SET @a = 0; +EXECUTE stmt USING @a; +(COUNT(i) = 1) COUNT(i) +0 0 +PREPARE stmt FROM "SELECT (AVG(i) = 1), AVG(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(AVG(i) = 1) AVG(i) +NULL NULL +SET @a = 1; +EXECUTE stmt USING @a; +(AVG(i) = 1) AVG(i) +1 1.0000 +SET @a = 0; +EXECUTE stmt USING @a; +(AVG(i) = 1) AVG(i) +NULL NULL +PREPARE stmt FROM "SELECT (VARIANCE(i) = 1), VARIANCE(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(VARIANCE(i) = 1) VARIANCE(i) +NULL NULL +SET @a = 1; +EXECUTE stmt USING @a; +(VARIANCE(i) = 1) VARIANCE(i) +0 0.0000 +SET @a = 0; +EXECUTE stmt USING @a; +(VARIANCE(i) = 1) VARIANCE(i) +NULL NULL +PREPARE stmt FROM "SELECT (STDDEV(i) = 1), STDDEV(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(STDDEV(i) = 1) STDDEV(i) +NULL NULL +SET @a = 1; +EXECUTE stmt USING @a; +(STDDEV(i) = 1) STDDEV(i) +0 0.0000 +SET @a = 0; +EXECUTE stmt USING @a; +(STDDEV(i) = 1) STDDEV(i) +NULL NULL +PREPARE stmt FROM "SELECT (BIT_OR(i) = 1), BIT_OR(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_OR(i) = 1) BIT_OR(i) +0 0 +SET @a = 1; +EXECUTE stmt USING @a; +(BIT_OR(i) = 1) BIT_OR(i) +1 1 +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_OR(i) = 1) BIT_OR(i) +0 0 +PREPARE stmt FROM "SELECT (BIT_AND(i) = 1), BIT_AND(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_AND(i) = 1) BIT_AND(i) +0 18446744073709551615 +SET @a = 1; +EXECUTE stmt USING @a; +(BIT_AND(i) = 1) BIT_AND(i) +1 1 +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_AND(i) = 1) BIT_AND(i) +0 18446744073709551615 +PREPARE stmt FROM "SELECT (BIT_XOR(i) = 1), BIT_XOR(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_XOR(i) = 1) BIT_XOR(i) +0 0 +SET @a = 1; +EXECUTE stmt USING @a; +(BIT_XOR(i) = 1) BIT_XOR(i) +1 1 +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_XOR(i) = 1) BIT_XOR(i) +0 0 +DEALLOCATE PREPARE stmt; +DROP TABLE t1; +End of 4.1 tests. create table t1 (a varchar(20)); insert into t1 values ('foo'); prepare stmt FROM 'SELECT char_length (a) FROM t1'; @@ -1064,243 +1160,6 @@ select @@max_prepared_stmt_count, @@prepared_stmt_count; @@max_prepared_stmt_count @@prepared_stmt_count 3 0 set global max_prepared_stmt_count= @old_max_prepared_stmt_count; -drop table if exists t1; -create temporary table if not exists t1 (a1 int); -prepare stmt from "delete t1 from t1 where (cast(a1/3 as unsigned) * 3) = a1"; -drop temporary table t1; -create temporary table if not exists t1 (a1 int); -execute stmt; -drop temporary table t1; -create temporary table if not exists t1 (a1 int); -execute stmt; -drop temporary table t1; -create temporary table if not exists t1 (a1 int); -execute stmt; -drop temporary table t1; -deallocate prepare stmt; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 (i INT, INDEX(i)); -INSERT INTO t1 VALUES (1); -PREPARE stmt FROM "SELECT (COUNT(i) = 1), COUNT(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(COUNT(i) = 1) COUNT(i) -0 0 -SET @a = 1; -EXECUTE stmt USING @a; -(COUNT(i) = 1) COUNT(i) -1 1 -SET @a = 0; -EXECUTE stmt USING @a; -(COUNT(i) = 1) COUNT(i) -0 0 -PREPARE stmt FROM "SELECT (AVG(i) = 1), AVG(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(AVG(i) = 1) AVG(i) -NULL NULL -SET @a = 1; -EXECUTE stmt USING @a; -(AVG(i) = 1) AVG(i) -1 1.0000 -SET @a = 0; -EXECUTE stmt USING @a; -(AVG(i) = 1) AVG(i) -NULL NULL -PREPARE stmt FROM "SELECT (VARIANCE(i) = 1), VARIANCE(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(VARIANCE(i) = 1) VARIANCE(i) -NULL NULL -SET @a = 1; -EXECUTE stmt USING @a; -(VARIANCE(i) = 1) VARIANCE(i) -0 0.0000 -SET @a = 0; -EXECUTE stmt USING @a; -(VARIANCE(i) = 1) VARIANCE(i) -NULL NULL -PREPARE stmt FROM "SELECT (STDDEV(i) = 1), STDDEV(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(STDDEV(i) = 1) STDDEV(i) -NULL NULL -SET @a = 1; -EXECUTE stmt USING @a; -(STDDEV(i) = 1) STDDEV(i) -0 0.0000 -SET @a = 0; -EXECUTE stmt USING @a; -(STDDEV(i) = 1) STDDEV(i) -NULL NULL -PREPARE stmt FROM "SELECT (BIT_OR(i) = 1), BIT_OR(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(BIT_OR(i) = 1) BIT_OR(i) -0 0 -SET @a = 1; -EXECUTE stmt USING @a; -(BIT_OR(i) = 1) BIT_OR(i) -1 1 -SET @a = 0; -EXECUTE stmt USING @a; -(BIT_OR(i) = 1) BIT_OR(i) -0 0 -PREPARE stmt FROM "SELECT (BIT_AND(i) = 1), BIT_AND(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(BIT_AND(i) = 1) BIT_AND(i) -0 18446744073709551615 -SET @a = 1; -EXECUTE stmt USING @a; -(BIT_AND(i) = 1) BIT_AND(i) -1 1 -SET @a = 0; -EXECUTE stmt USING @a; -(BIT_AND(i) = 1) BIT_AND(i) -0 18446744073709551615 -PREPARE stmt FROM "SELECT (BIT_XOR(i) = 1), BIT_XOR(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(BIT_XOR(i) = 1) BIT_XOR(i) -0 0 -SET @a = 1; -EXECUTE stmt USING @a; -(BIT_XOR(i) = 1) BIT_XOR(i) -1 1 -SET @a = 0; -EXECUTE stmt USING @a; -(BIT_XOR(i) = 1) BIT_XOR(i) -0 0 -DEALLOCATE PREPARE stmt; -DROP TABLE t1; -End of 4.1 tests. -create table t1 (a varchar(20)); -insert into t1 values ('foo'); -prepare stmt FROM 'SELECT char_length (a) FROM t1'; -ERROR 42000: FUNCTION test.char_length does not exist -drop table t1; -create table t1 (a char(3) not null, b char(3) not null, -c char(3) not null, primary key (a, b, c)); -create table t2 like t1; -prepare stmt from -"select t1.a from (t1 left outer join t2 on t2.a=1 and t1.b=t2.b) - where t1.a=1"; -execute stmt; -a -execute stmt; -a -execute stmt; -a -prepare stmt from -"select t1.a, t1.b, t1.c, t2.a, t2.b, t2.c from -(t1 left outer join t2 on t2.a=? and t1.b=t2.b) -left outer join t2 t3 on t3.a=? where t1.a=?"; -set @a:=1, @b:=1, @c:=1; -execute stmt using @a, @b, @c; -a b c a b c -execute stmt using @a, @b, @c; -a b c a b c -execute stmt using @a, @b, @c; -a b c a b c -deallocate prepare stmt; -drop table t1,t2; -SET @aux= "SELECT COUNT(*) - FROM INFORMATION_SCHEMA.COLUMNS A, - INFORMATION_SCHEMA.COLUMNS B - WHERE A.TABLE_SCHEMA = B.TABLE_SCHEMA - AND A.TABLE_NAME = B.TABLE_NAME - AND A.COLUMN_NAME = B.COLUMN_NAME AND - A.TABLE_NAME = 'user'"; -prepare my_stmt from @aux; -execute my_stmt; -COUNT(*) -37 -execute my_stmt; -COUNT(*) -37 -execute my_stmt; -COUNT(*) -37 -deallocate prepare my_stmt; -drop procedure if exists p1| -drop table if exists t1| -create table t1 (id int)| -insert into t1 values(1)| -create procedure p1(a int, b int) -begin -declare c int; -select max(id)+1 into c from t1; -insert into t1 select a+b; -insert into t1 select a-b; -insert into t1 select a-c; -end| -set @a= 3, @b= 4| -prepare stmt from "call p1(?, ?)"| -execute stmt using @a, @b| -execute stmt using @a, @b| -select * from t1| -id -1 -7 --1 -1 -7 --1 --5 -deallocate prepare stmt| -drop procedure p1| -drop table t1| -create table t1 (a int); -insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); -prepare stmt from "select * from t1 limit ?, ?"; -set @offset=0, @limit=1; -execute stmt using @offset, @limit; -a -1 -select * from t1 limit 0, 1; -a -1 -set @offset=3, @limit=2; -execute stmt using @offset, @limit; -a -4 -5 -select * from t1 limit 3, 2; -a -4 -5 -prepare stmt from "select * from t1 limit ?"; -execute stmt using @limit; -a -1 -2 -prepare stmt from "select * from t1 where a in (select a from t1 limit ?)"; -ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' -prepare stmt from "select * from t1 union all select * from t1 limit ?, ?"; -set @offset=9; -set @limit=2; -execute stmt using @offset, @limit; -a -10 -1 -prepare stmt from "(select * from t1 limit ?, ?) union all - (select * from t1 limit ?, ?) order by a limit ?"; -execute stmt using @offset, @limit, @offset, @limit, @limit; -a -10 -10 -drop table t1; -deallocate prepare stmt; -CREATE TABLE b12651_T1(a int) ENGINE=MYISAM; -CREATE TABLE b12651_T2(b int) ENGINE=MYISAM; -CREATE VIEW b12651_V1 as SELECT b FROM b12651_T2; -PREPARE b12651 FROM 'SELECT 1 FROM b12651_T1 WHERE a IN (SELECT b FROM b12651_V1)'; -EXECUTE b12651; -1 -DROP VIEW b12651_V1; -DROP TABLE b12651_T1, b12651_T2; -DEALLOCATE PREPARE b12651; create table t1 (id int); prepare ins_call from "insert into t1 (id) values (1)"; execute ins_call; From 92b3a32b50f113da22233b8c6393d6242bb11437 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Oct 2006 17:59:46 +0200 Subject: [PATCH 12/47] Remove direct mapping of enum interval_type to mysql.event.interval_field This decoupling allows in further versions of MySQL enum interval_type to be reordered without this affecting any backward compatibility in the events code. This changeset doesn't change any exposed behavior but makes events' code more durable to changes outside of their code base. To the reviewer: There is no regression test included as it is impossible to construct one with the current infrastructure which can test it. To test the code one has create and event, then change the order of enum interval_type in my_time.h, update sql/time.cc, recompile the server and run it with scheduler running. include/my_time.h: Add a reminder to keep enum interval_type and interval_type_to_name in sync sql/event_data_objects.cc: When loading from disk don't use the integer value of mysql.event.interval_field because it could be different of the values of enum interval_type, if the latter is reordered in a later version of MySQL. Loaded from disk is the string value which is then resolved against interval_type_to_name to get the exact enum value we need for Event_queue_element::interval. sql/event_db_repository.cc: Use interval_type_to_name from sql/time.cc during storage thus decoupling the value stored on disk (the enum) from the integer representation in memory. interval_type can be changed and as long as interval_type_to_name is kept in sync correct values will be saved to disk. sql/mysql_priv.h: add proto of find_string_in_array sql/strfunc.cc: Add a function for searching a LEX_STRING in an array of LEX_STRINGs --- include/my_time.h | 2 ++ sql/event_data_objects.cc | 27 +++++++++++++++++++++------ sql/event_db_repository.cc | 10 +++++----- sql/mysql_priv.h | 2 ++ sql/strfunc.cc | 30 ++++++++++++++++++++++++++++++ 5 files changed, 60 insertions(+), 11 deletions(-) diff --git a/include/my_time.h b/include/my_time.h index d0f2fc323d8..6f053e71000 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -100,6 +100,8 @@ int my_TIME_to_str(const MYSQL_TIME *l_time, char *to); /* The following must be sorted so that simple intervals comes first. (get_interval_value() depends on this) + When updating this enum please update + LEX_STRING interval_type_to_name[] in sql/time.cc */ enum interval_type diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 4b9aa43b14b..afd10350bb5 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -886,14 +886,29 @@ Event_queue_element::load_from_row(TABLE *table) goto error; /* - In DB the values start from 1 but enum interval_type starts - from 0 + We load the interval type from disk as string and then map it to + an integer. This decouples the values of enum interval_type + and values actually stored on disk. Therefore the type can be + reordered without risking incompatibilities of data between versions. */ if (!table->field[ET_FIELD_TRANSIENT_INTERVAL]->is_null()) - interval= (interval_type) ((ulonglong) - table->field[ET_FIELD_TRANSIENT_INTERVAL]->val_int() - 1); - else - interval= (interval_type) 0; + { + int i; + char buff[MAX_FIELD_WIDTH]; + String str(buff, sizeof(buff), &my_charset_bin); + LEX_STRING tmp; + + table->field[ET_FIELD_TRANSIENT_INTERVAL]->val_str(&str); + if (!(tmp.length= str.length())) + goto error; + + tmp.str= str.c_ptr_safe(); + + i= find_string_in_array(interval_type_to_name, &tmp, system_charset_info); + if (i < 0) + goto error; + interval= (interval_type) i; + } table->field[ET_FIELD_LAST_EXECUTED]->get_date(&last_executed, TIME_NO_ZERO_DATE); diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 464c26044c7..3d30aff669b 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -188,11 +188,11 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et, fields[ET_FIELD_INTERVAL_EXPR]->store((longlong)et->expression, TRUE); fields[ET_FIELD_TRANSIENT_INTERVAL]->set_notnull(); - /* - In the enum (C) intervals start from 0 but in mysql enum valid values - start from 1. Thus +1 offset is needed! - */ - fields[ET_FIELD_TRANSIENT_INTERVAL]->store((longlong)et->interval+1, TRUE); + + fields[ET_FIELD_TRANSIENT_INTERVAL]-> + store(interval_type_to_name[et->interval].str, + interval_type_to_name[et->interval].length, + scs); fields[ET_FIELD_EXECUTE_AT]->set_null(); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 339ca9d965a..89a3a30c338 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1481,6 +1481,8 @@ uint find_type2(TYPELIB *lib, const char *find, uint length, CHARSET_INFO *cs); void unhex_type2(TYPELIB *lib); uint check_word(TYPELIB *lib, const char *val, const char *end, const char **end_of_word); +int find_string_in_array(LEX_STRING * const haystack, LEX_STRING * const needle, + CHARSET_INFO *cs); bool is_keyword(const char *name, uint len); diff --git a/sql/strfunc.cc b/sql/strfunc.cc index 2525703172f..ef769a5b16e 100644 --- a/sql/strfunc.cc +++ b/sql/strfunc.cc @@ -312,3 +312,33 @@ outp: return (uint32) (to - to_start); } + + +/* + Searches for a LEX_STRING in an LEX_STRING array. + + SYNOPSIS + find_string_in_array() + heap The array + needle The string to search for + + NOTE + The last LEX_STRING in the array should have str member set to NULL + + RETURN VALUES + -1 Not found + >=0 Ordinal position +*/ + +int find_string_in_array(LEX_STRING * const haystack, LEX_STRING * const needle, + CHARSET_INFO * const cs) +{ + const LEX_STRING *pos; + for (pos= haystack; pos->str; pos++) + if (!cs->coll->strnncollsp(cs, (uchar *) pos->str, pos->length, + (uchar *) needle->str, needle->length, 0)) + { + return (pos - haystack); + } + return -1; +} From d07b5b24efe20d795ba1ca3aba3e4544cb0c0142 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 Oct 2006 21:19:34 +0200 Subject: [PATCH 13/47] fix build failure on Solaris10 sql/mysql_priv.h: synchronize definition and declaration --- sql/mysql_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 89a3a30c338..f06f38e3bcb 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1482,7 +1482,7 @@ void unhex_type2(TYPELIB *lib); uint check_word(TYPELIB *lib, const char *val, const char *end, const char **end_of_word); int find_string_in_array(LEX_STRING * const haystack, LEX_STRING * const needle, - CHARSET_INFO *cs); + CHARSET_INFO * const cs); bool is_keyword(const char *name, uint len); From 6d1fdc7308d73c439d7a2da6851199939cde93f4 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Oct 2006 18:02:57 +0400 Subject: [PATCH 14/47] BUG#20953: create proc with a create view that uses local vars/params should fail to create The problem was that this type of errors was checked during view creation, which doesn't happen when CREATE VIEW is a statement of a created stored routine. The solution is to perform the checks at parse time. The idea of the fix is that the parser checks if a construction just parsed is allowed in current circumstances by testing certain flags, and this flags are reset for VIEWs. The side effect of this change is that if the user already have such bogus routines, it will now get a error when trying to do SHOW CREATE PROCEDURE proc; (and some other) and when trying to execute such routine he will get ERROR 1457 (HY000): Failed to load routine test.p5. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6) However there should be very few such users (if any), and they may (and should) drop these bogus routines. mysql-test/r/sp-error.result: Add result for bug#20953: create proc with a create view that uses local vars/params should fail to create. mysql-test/r/view.result: Update results. mysql-test/t/sp-error.test: Add test case for bug#20953: create proc with a create view that uses local vars/params should fail to create. mysql-test/t/view.test: Add second test for variable in a view. Remove SP variable in a view test, as it tests wrong behaviour. Add test for derived table in a view. sql/sql_lex.cc: Remove LEX::variables_used. sql/sql_lex.h: Remove LEX::variables_used and add st_parsing_options structure and LEX::parsing_options member. sql/sql_view.cc: Move some error checking to sql/sql_yacc.yy. sql/sql_yacc.yy: Check for disallowed syntax in a CREATE VIEW at parse time to rise a error when it is used inside CREATE PROCEDURE and CREATE FUNCTION, as well as by itself. --- mysql-test/r/sp-error.result | 24 ++++++ mysql-test/r/view.result | 10 +-- mysql-test/t/sp-error.test | 42 +++++++++++ mysql-test/t/view.test | 20 ++--- sql/sql_lex.cc | 1 - sql/sql_lex.h | 21 +++++- sql/sql_view.cc | 22 +----- sql/sql_yacc.yy | 139 ++++++++++++++++++++++++++--------- 8 files changed, 204 insertions(+), 75 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 924963017eb..a967f4de10c 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1174,3 +1174,27 @@ drop procedure bug15091; drop function if exists bug16896; create aggregate function bug16896() returns int return 1; ERROR 42000: AGGREGATE is not supported for stored functions +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT); +CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO @a; +ERROR HY000: View's SELECT contains a 'INTO' clause +CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO DUMPFILE "file"; +ERROR HY000: View's SELECT contains a 'INTO' clause +CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO OUTFILE "file"; +ERROR HY000: View's SELECT contains a 'INTO' clause +CREATE PROCEDURE bug20953() +CREATE VIEW v AS SELECT i FROM t1 PROCEDURE ANALYSE(); +ERROR HY000: View's SELECT contains a 'PROCEDURE' clause +CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 FROM (SELECT 1) AS d1; +ERROR HY000: View's SELECT contains a subquery in the FROM clause +CREATE PROCEDURE bug20953(i INT) CREATE VIEW v AS SELECT i; +ERROR HY000: View's SELECT contains a variable or parameter +CREATE PROCEDURE bug20953() +BEGIN +DECLARE i INT; +CREATE VIEW v AS SELECT i; +END | +ERROR HY000: View's SELECT contains a variable or parameter +PREPARE stmt FROM "CREATE VIEW v AS SELECT ?"; +ERROR HY000: View's SELECT contains a variable or parameter +DROP TABLE t1; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 72cffb9531c..99e71dd30bd 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -12,6 +12,9 @@ create table t1 (a int, b int); insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10); create view v1 (c,d) as select a,b+@@global.max_user_connections from t1; ERROR HY000: View's SELECT contains a variable or parameter +create view v1 (c,d) as select a,b from t1 +where a = @@global.max_user_connections; +ERROR HY000: View's SELECT contains a variable or parameter create view v1 (c) as select b+1 from t1; select c from v1; c @@ -596,11 +599,6 @@ ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function drop view v1; create view v1 (a,a) as select 'a','a'; ERROR 42S21: Duplicate column name 'a' -drop procedure if exists p1; -create procedure p1 () begin declare v int; create view v1 as select v; end;// -call p1(); -ERROR HY000: View's SELECT contains a variable or parameter -drop procedure p1; create table t1 (col1 int,col2 char(22)); insert into t1 values(5,'Hello, world of views'); create view v1 as select * from t1; @@ -886,6 +884,8 @@ ERROR HY000: View's SELECT contains a 'INTO' clause create table t1 (a int); create view v1 as select a from t1 procedure analyse(); ERROR HY000: View's SELECT contains a 'PROCEDURE' clause +create view v1 as select 1 from (select 1) as d1; +ERROR HY000: View's SELECT contains a subquery in the FROM clause drop table t1; create table t1 (s1 int, primary key (s1)); create view v1 as select * from t1; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index a4ab5d98922..2340bfdc899 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1706,6 +1706,48 @@ drop function if exists bug16896; create aggregate function bug16896() returns int return 1; + +# +# BUG#20953: create proc with a create view that uses local +# vars/params should fail to create +# +# See test case for what syntax is forbidden in a view. +# +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (i INT); + +# We do not have to drop this procedure and view because they won't be +# created. +--error ER_VIEW_SELECT_CLAUSE +CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO @a; +--error ER_VIEW_SELECT_CLAUSE +CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO DUMPFILE "file"; +--error ER_VIEW_SELECT_CLAUSE +CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO OUTFILE "file"; +--error ER_VIEW_SELECT_CLAUSE +CREATE PROCEDURE bug20953() + CREATE VIEW v AS SELECT i FROM t1 PROCEDURE ANALYSE(); +--error ER_VIEW_SELECT_DERIVED +CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 FROM (SELECT 1) AS d1; +--error ER_VIEW_SELECT_VARIABLE +CREATE PROCEDURE bug20953(i INT) CREATE VIEW v AS SELECT i; +delimiter |; +--error ER_VIEW_SELECT_VARIABLE +CREATE PROCEDURE bug20953() +BEGIN + DECLARE i INT; + CREATE VIEW v AS SELECT i; +END | +delimiter ;| +--error ER_VIEW_SELECT_VARIABLE +PREPARE stmt FROM "CREATE VIEW v AS SELECT ?"; + +DROP TABLE t1; + + # # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index a1c1e9b2ad1..48555960924 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -23,8 +23,11 @@ create table t1 (a int, b int); insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10); # view with variable --- error 1351 +-- error ER_VIEW_SELECT_VARIABLE create view v1 (c,d) as select a,b+@@global.max_user_connections from t1; +-- error ER_VIEW_SELECT_VARIABLE +create view v1 (c,d) as select a,b from t1 + where a = @@global.max_user_connections; # simple view create view v1 (c) as select b+1 from t1; @@ -486,19 +489,6 @@ drop view v1; -- error 1060 create view v1 (a,a) as select 'a','a'; -# -# SP variables inside view test -# ---disable_warnings -drop procedure if exists p1; ---enable_warnings -delimiter //; -create procedure p1 () begin declare v int; create view v1 as select v; end;// -delimiter ;// --- error 1351 -call p1(); -drop procedure p1; - # # updatablity should be transitive # @@ -820,6 +810,8 @@ create view v1 as select 5 into outfile 'ttt'; create table t1 (a int); -- error 1350 create view v1 as select a from t1 procedure analyse(); +-- error ER_VIEW_SELECT_DERIVED +create view v1 as select 1 from (select 1) as d1; drop table t1; # diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index efbf29cf207..6f3b785d87e 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -150,7 +150,6 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->safe_to_cache_query= 1; lex->time_zone_tables_used= 0; lex->leaf_tables_insert= 0; - lex->variables_used= 0; lex->empty_field_list_on_rset= 0; lex->select_lex.select_number= 1; lex->next_state=MY_LEX_START; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index e5b087fc72a..d2669fb4ec3 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -801,6 +801,25 @@ public: }; +/* + st_parsing_options contains the flags for constructions that are + allowed in the current statement. +*/ + +struct st_parsing_options +{ + bool allows_variable; + bool allows_select_into; + bool allows_select_procedure; + bool allows_derived; + + st_parsing_options() + : allows_variable(TRUE), allows_select_into(TRUE), + allows_select_procedure(TRUE), allows_derived(TRUE) + {} +}; + + /* The state of the lex parsing. This is saved in the THD struct */ typedef struct st_lex : public Query_tables_list @@ -944,7 +963,7 @@ typedef struct st_lex : public Query_tables_list bool stmt_prepare_mode; bool safe_to_cache_query; bool subqueries, ignore; - bool variables_used; + st_parsing_options parsing_options; ALTER_INFO alter_info; /* Prepared statements SQL syntax:*/ LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */ diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 1561ade78af..a53e6bcf9a5 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -186,25 +186,9 @@ bool mysql_create_view(THD *thd, bool res= FALSE; DBUG_ENTER("mysql_create_view"); - if (lex->proc_list.first || - lex->result) - { - my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), (lex->result ? - "INTO" : - "PROCEDURE")); - res= TRUE; - goto err; - } - if (lex->derived_tables || - lex->variables_used || lex->param_list.elements) - { - int err= (lex->derived_tables ? - ER_VIEW_SELECT_DERIVED : - ER_VIEW_SELECT_VARIABLE); - my_message(err, ER(err), MYF(0)); - res= TRUE; - goto err; - } + /* This is ensured in the parser. */ + DBUG_ASSERT(!lex->proc_list.first && !lex->result && + !lex->param_list.elements && !lex->derived_tables); if (mode != VIEW_CREATE_NEW) sp_cache_invalidate(); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index deac9cb5c40..523a359e3dd 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -721,7 +721,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type literal text_literal insert_ident order_ident simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr - bool_term bool_factor bool_test bool_pri + variable variable_aux bool_term bool_factor bool_test bool_pri predicate bit_expr bit_term bit_factor value_expr term factor table_wild simple_expr udf_expr expr_or_default set_expr_or_default interval_expr @@ -4281,32 +4281,7 @@ simple_expr: } | literal | param_marker - | '@' ident_or_text SET_VAR expr - { - $$= new Item_func_set_user_var($2,$4); - LEX *lex= Lex; - lex->uncacheable(UNCACHEABLE_RAND); - lex->variables_used= 1; - } - | '@' ident_or_text - { - $$= new Item_func_get_user_var($2); - LEX *lex= Lex; - lex->uncacheable(UNCACHEABLE_RAND); - lex->variables_used= 1; - } - | '@' '@' opt_var_ident_type ident_or_text opt_component - { - - if ($4.str && $5.str && check_reserved_words(&$4)) - { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; - } - if (!($$= get_system_var(YYTHD, $3, $4, $5))) - YYABORT; - Lex->variables_used= 1; - } + | variable | sum_expr | simple_expr OR_OR_SYM simple_expr { $$= new Item_func_concat($1, $3); } @@ -5006,6 +4981,46 @@ sum_expr: $5->empty(); }; +variable: + '@' + { + if (! Lex->parsing_options.allows_variable) + { + my_error(ER_VIEW_SELECT_VARIABLE, MYF(0)); + YYABORT; + } + } + variable_aux + { + $$= $3; + } + ; + +variable_aux: + ident_or_text SET_VAR expr + { + $$= new Item_func_set_user_var($1, $3); + LEX *lex= Lex; + lex->uncacheable(UNCACHEABLE_RAND); + } + | ident_or_text + { + $$= new Item_func_get_user_var($1); + LEX *lex= Lex; + lex->uncacheable(UNCACHEABLE_RAND); + } + | '@' opt_var_ident_type ident_or_text opt_component + { + if ($3.str && $4.str && check_reserved_words(&$3)) + { + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } + if (!($$= get_system_var(YYTHD, $2, $3, $4))) + YYABORT; + } + ; + opt_distinct: /* empty */ { $$ = 0; } |DISTINCT { $$ = 1; }; @@ -5428,6 +5443,13 @@ select_derived_init: SELECT_SYM { LEX *lex= Lex; + + if (! lex->parsing_options.allows_derived) + { + my_error(ER_VIEW_SELECT_DERIVED, MYF(0)); + YYABORT; + } + SELECT_LEX *sel= lex->current_select; TABLE_LIST *embedding; if (!sel->embedding || sel->end_nested_join(lex->thd)) @@ -5787,6 +5809,13 @@ procedure_clause: | PROCEDURE ident /* Procedure name */ { LEX *lex=Lex; + + if (! lex->parsing_options.allows_select_procedure) + { + my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "PROCEDURE"); + YYABORT; + } + if (&lex->select_lex != lex->current_select) { my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery"); @@ -5886,28 +5915,40 @@ select_var_ident: ; into: - INTO OUTFILE TEXT_STRING_filesystem + INTO + { + if (! Lex->parsing_options.allows_select_into) + { + my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "INTO"); + YYABORT; + } + } + into_destination + ; + +into_destination: + OUTFILE TEXT_STRING_filesystem { LEX *lex= Lex; lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - if (!(lex->exchange= new sql_exchange($3.str, 0)) || + if (!(lex->exchange= new sql_exchange($2.str, 0)) || !(lex->result= new select_export(lex->exchange))) YYABORT; } opt_field_term opt_line_term - | INTO DUMPFILE TEXT_STRING_filesystem + | DUMPFILE TEXT_STRING_filesystem { LEX *lex=Lex; if (!lex->describe) { lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - if (!(lex->exchange= new sql_exchange($3.str,1))) + if (!(lex->exchange= new sql_exchange($2.str,1))) YYABORT; if (!(lex->result= new select_dump(lex->exchange))) YYABORT; } } - | INTO select_var_list_init + | select_var_list_init { Lex->uncacheable(UNCACHEABLE_SIDEEFFECT); } @@ -7067,8 +7108,13 @@ param_marker: { THD *thd=YYTHD; LEX *lex= thd->lex; - Item_param *item= new Item_param((uint) (lex->tok_start - - (uchar *) thd->query)); + Item_param *item; + if (! lex->parsing_options.allows_variable) + { + my_error(ER_VIEW_SELECT_VARIABLE, MYF(0)); + YYABORT; + } + item= new Item_param((uint) (lex->tok_start - (uchar *) thd->query)); if (!($$= item) || lex->param_list.push_back(item)) { my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); @@ -7188,6 +7234,12 @@ simple_ident: if (spc && (spv = spc->find_variable(&$1))) { /* We're compiling a stored procedure and found a variable */ + if (! lex->parsing_options.allows_variable) + { + my_error(ER_VIEW_SELECT_VARIABLE, MYF(0)); + YYABORT; + } + Item_splocal *splocal; splocal= new Item_splocal($1, spv->offset, spv->type, lex->tok_start_prev - @@ -7197,7 +7249,6 @@ simple_ident: splocal->m_sp= lex->sphead; #endif $$ = (Item*) splocal; - lex->variables_used= 1; lex->safe_to_cache_query=0; } else @@ -9038,6 +9089,24 @@ view_list: ; view_select: + { + LEX *lex= Lex; + lex->parsing_options.allows_variable= FALSE; + lex->parsing_options.allows_select_into= FALSE; + lex->parsing_options.allows_select_procedure= FALSE; + lex->parsing_options.allows_derived= FALSE; + } + view_select_aux + { + LEX *lex= Lex; + lex->parsing_options.allows_variable= TRUE; + lex->parsing_options.allows_select_into= TRUE; + lex->parsing_options.allows_select_procedure= TRUE; + lex->parsing_options.allows_derived= TRUE; + } + ; + +view_select_aux: SELECT_SYM remember_name select_init2 { THD *thd=YYTHD; From 788c31022ee2240780a794db7e360f78aa1b39ee Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Oct 2006 18:30:59 +0400 Subject: [PATCH 15/47] Fix after manual merge. mysql-test/r/sp-error.result: After merge fix. mysql-test/t/sp-error.test: Fix delimiter restoration. --- mysql-test/r/sp-error.result | 8 ++--- mysql-test/t/sp-error.test | 57 +++++++++++++++++++----------------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index cde4f7d5f3a..d955b69bde2 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1258,9 +1258,9 @@ show authors; return 42; end| ERROR 0A000: Not allowed to return a result set from a function -drop function if exists bug20701| -create function bug20701() returns varchar(25) binary return "test"| +drop function if exists bug20701; +create function bug20701() returns varchar(25) binary return "test"; ERROR 42000: This version of MySQL doesn't yet support 'return value collation' -create function bug20701() returns varchar(25) return "test"| -drop function bug20701| +create function bug20701() returns varchar(25) return "test"; +drop function bug20701; End of 5.1 tests diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index bd89b1b7344..8754d9ca82d 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1769,27 +1769,6 @@ BEGIN END; -# -# End of 5.0 tests -# ---echo End of 5.0 tests - -# -# Bug#16164 "Easter egg": check that SHOW AUTHORS is disabled in -# stored functions/triggers -# ---disable_warnings -drop function if exists bug16164; ---enable_warnings -delimiter |; ---error ER_SP_NO_RETSET -create function bug16164() returns int -begin - show authors; - return 42; -end| - - # # BUG#20953: create proc with a create view that uses local # vars/params should fail to create @@ -1831,11 +1810,33 @@ PREPARE stmt FROM "CREATE VIEW v AS SELECT ?"; DROP TABLE t1; +# +# End of 5.0 tests +# +--echo End of 5.0 tests + +# +# Bug#16164 "Easter egg": check that SHOW AUTHORS is disabled in +# stored functions/triggers +# +--disable_warnings +drop function if exists bug16164; +--enable_warnings +delimiter |; +--error ER_SP_NO_RETSET +create function bug16164() returns int +begin + show authors; + return 42; +end| +delimiter ;| + + # # BUG#20701: BINARY keyword should be forbidden in stored routines # --disable_warnings -drop function if exists bug20701| +drop function if exists bug20701; --enable_warnings # # This was disabled in 5.1.12. See bug #20701 @@ -1843,17 +1844,19 @@ drop function if exists bug20701| # be removed. # --error ER_NOT_SUPPORTED_YET -create function bug20701() returns varchar(25) binary return "test"| -create function bug20701() returns varchar(25) return "test"| -drop function bug20701| +create function bug20701() returns varchar(25) binary return "test"; +create function bug20701() returns varchar(25) return "test"; +drop function bug20701; + + --echo End of 5.1 tests # # BUG#NNNN: New bug synopsis # #--disable_warnings -#drop procedure if exists bugNNNN| -#drop function if exists bugNNNN| +#drop procedure if exists bugNNNN; +#drop function if exists bugNNNN; #--enable_warnings #create procedure bugNNNN... #create function bugNNNN... From 1c1fd2a46ef95d556a78a34bfcf3525e8d598cb4 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Oct 2006 19:36:43 +0400 Subject: [PATCH 16/47] Fix after manual merge. mysql-test/t/sp-error.test: Move test for bug#20953 to the end of file. --- mysql-test/t/sp-error.test | 43 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 058c45f7f2f..7dbf64e35c1 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1745,6 +1745,27 @@ drop function if exists bug16896; create aggregate function bug16896() returns int return 1; +# +# BUG#14702: misleading error message when syntax error in CREATE +# PROCEDURE +# +# Misleading error message was given when IF NOT EXISTS was used in +# CREATE PROCEDURE. +# +--disable_warnings +DROP PROCEDURE IF EXISTS bug14702; +--enable_warnings + +--error ER_PARSE_ERROR +CREATE IF NOT EXISTS PROCEDURE bug14702() +BEGIN +END; + +--error ER_PARSE_ERROR +CREATE PROCEDURE IF NOT EXISTS bug14702() +BEGIN +END; + # # BUG#20953: create proc with a create view that uses local @@ -1787,28 +1808,6 @@ PREPARE stmt FROM "CREATE VIEW v AS SELECT ?"; DROP TABLE t1; -# -# BUG#14702: misleading error message when syntax error in CREATE -# PROCEDURE -# -# Misleading error message was given when IF NOT EXISTS was used in -# CREATE PROCEDURE. -# ---disable_warnings -DROP PROCEDURE IF EXISTS bug14702; ---enable_warnings - ---error ER_PARSE_ERROR -CREATE IF NOT EXISTS PROCEDURE bug14702() -BEGIN -END; - ---error ER_PARSE_ERROR -CREATE PROCEDURE IF NOT EXISTS bug14702() -BEGIN -END; - - # # BUG#NNNN: New bug synopsis # From 9438b9851901c48f8e280c2665f9469c2f998c2f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Oct 2006 17:26:46 +0400 Subject: [PATCH 17/47] Fix for Bug #17544 "Cannot do atomic log rotate", Bug #21785 "Server crashes after rename of the log table" and Bug #21966 "Strange warnings on create like/repair of the log tables" According to the patch, from now on, one should use RENAME to perform a log table rotation (this should also be reflected in the manual). Here is a sample: use mysql; CREATE TABLE IF NOT EXISTS general_log2 LIKE general_log; RENAME TABLE general_log TO general_log_backup, general_log2 TO general_log; The rules for Rename of the log tables are following: IF 1. Log tables are enabled AND 2. Rename operates on the log table and nothing is being renamed to the log table. DO 3. Throw an error message. ELSE 4. Perform rename. The very RENAME query will go the the old (backup) table. This is consistent with the behavoiur we have with binlog ROTATE LOGS statement. Other problems, which are solved by the patch are: 1) Now REPAIR of the log table is exclusive operation (as it should be), this also eliminates lock-related warnings. and 2) CREATE LIKE TABLE now usese usual read lock on the source table rather then name lock, which is too restrictive. This way we get rid of another log table-related warning, which occured because of the above fact (as a side-effect, name lock resulted in a warning). mysql-test/r/log_tables.result: update result file mysql-test/t/log_tables.test: Add tests for the bugs sql/handler.cc: update comment sql/handler.h: update function to reflect changes in log tables locking logic. sql/lock.cc: Now we allow locking of the log tables for "privileged" threads Privileged thread must explicitly close and lock log tables. This is required for admin operations such as REPAIR. sql/log.cc: Changes to the file: 1) Add checks for table schema. It's more important now, as we allow rename of the log tables. Since we should check for schema when writing to a log table. E.g. if one created a table with one-only comlumn and renamed it to general_log, the server should cope with it. 2) refactor LOGGER::flush(), so that we can now use the same machinery as we use in FLUSH LOGS in other statements: whenever we have to perform a serious operation on the log tables, we have to (a) lock logger, which blocks other concurrent statements (such as selects) (b) close logs. Then perform an exclusive operation, c) reenable logs and d) unlock logger. 3) Add a function to check if a given table is a log table. 4) Add support for "privileged" thread 5) merge is_[general/slow]_log_table_enabled() into one function. 6) Add new function: reopen _log_tables, which reopens the tables, which were enabled (after temporary close, required for admin operation) sql/log.h: 1) add a new call close_n_lock_tables(). Now we use it instead of LOGGER::flush() in FLUSH LOGS implementation. 2) add a prototype for the function to check if a given table is a log table; 3) add privileged table flag to table logger 4) merge is_[general/slow]_log_table_enabled() into one function. sql/mysql_priv.h: move log table defines to log.h sql/sql_delete.cc: use new function check_if_log_table() instead of direct strcmp sql/sql_rename.cc: Traverse the list of tables in mysql_rename_tables to make sure that log tables are processed correctly (that is, according to the rules specified in the main CS comment) sql/sql_table.cc: 1) mysql_admin_table() should disable logs if it performs exclusive admin operation on a log table. This way we also eliminate warning on REPAIR of the log table. 2) mysql_create_like_table should read-lock the source table instead getting name lock on it. Name lock is too restrictive in this case. sql/share/errmsg.txt: Add a new error message for rename of the log tables sql/table.cc: use new function instead of direct strcmp. change my_strcasecmp() -> strcmp(), when comparing system db and table names storage/csv/ha_tina.cc: update function to reflect changes in log tables locking logic. storage/myisam/ha_myisam.cc: update function to reflect changes in log tables locking logic. --- mysql-test/r/log_tables.result | 68 ++++++++++ mysql-test/t/log_tables.test | 83 ++++++++++++ sql/handler.cc | 5 +- sql/handler.h | 6 +- sql/lock.cc | 3 +- sql/log.cc | 236 +++++++++++++++++++++------------ sql/log.h | 49 +++++-- sql/mysql_priv.h | 4 - sql/share/errmsg.txt | 2 + sql/sql_delete.cc | 28 ++-- sql/sql_rename.cc | 102 +++++++++++++- sql/sql_table.cc | 106 ++++++++++----- sql/table.cc | 19 ++- storage/csv/ha_tina.cc | 4 +- storage/myisam/ha_myisam.cc | 8 +- 15 files changed, 553 insertions(+), 170 deletions(-) diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result index 638c05dd712..8bec1887e47 100644 --- a/mysql-test/r/log_tables.result +++ b/mysql-test/r/log_tables.result @@ -218,3 +218,71 @@ unlock tables; use mysql; lock tables general_log read local, help_category read local; unlock tables; +use mysql; +RENAME TABLE general_log TO renamed_general_log; +ERROR HY000: Cannot rename 'general_log'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to 'general_log' +RENAME TABLE slow_log TO renamed_slow_log; +ERROR HY000: Cannot rename 'slow_log'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to 'slow_log' +truncate table general_log; +select * from general_log; +event_time user_host thread_id server_id command_type argument +TIMESTAMP USER_HOST THREAD_ID 1 Query select * from general_log +truncate table slow_log; +select * from slow_log; +start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text +create table general_log_new like general_log; +rename table general_log TO renamed_general_log, general_log_new TO general_log; +create table slow_log_new like slow_log; +rename table slow_log TO renamed_slow_log, slow_log_new TO slow_log; +rename table general_log TO general_log_new, renamed_general_log TO general_log, slow_log to renamed_slow_log; +ERROR HY000: Cannot rename 'slow_log'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to 'slow_log' +select * from general_log; +event_time user_host thread_id server_id command_type argument +TIMESTAMP USER_HOST THREAD_ID 1 Query create table slow_log_new like slow_log +TIMESTAMP USER_HOST THREAD_ID 1 Query rename table slow_log TO renamed_slow_log, slow_log_new TO slow_log +TIMESTAMP USER_HOST THREAD_ID 1 Query rename table general_log TO general_log_new, renamed_general_log TO general_log, slow_log to renamed_slow_log +TIMESTAMP USER_HOST THREAD_ID 1 Query select * from general_log +select * from renamed_general_log; +event_time user_host thread_id server_id command_type argument +TIMESTAMP USER_HOST THREAD_ID 1 Query select * from general_log +TIMESTAMP USER_HOST THREAD_ID 1 Query truncate table slow_log +TIMESTAMP USER_HOST THREAD_ID 1 Query select * from slow_log +TIMESTAMP USER_HOST THREAD_ID 1 Query create table general_log_new like general_log +TIMESTAMP USER_HOST THREAD_ID 1 Query rename table general_log TO renamed_general_log, general_log_new TO general_log +select * from slow_log; +start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text +select * from renamed_slow_log; +start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text +set global general_log='OFF'; +RENAME TABLE general_log TO general_log2; +set global slow_query_log='OFF'; +RENAME TABLE slow_log TO slow_log2; +set global general_log='ON'; +ERROR HY000: Cannot activate 'general' log +set global slow_query_log='ON'; +ERROR HY000: Cannot activate 'slow query' log +RENAME TABLE general_log2 TO general_log; +RENAME TABLE slow_log2 TO slow_log; +set global general_log='ON'; +set global slow_query_log='ON'; +flush logs; +flush logs; +drop table renamed_general_log, renamed_slow_log; +use test; +use mysql; +repair table general_log; +Table Op Msg_type Msg_text +mysql.general_log repair status OK +repair table slow_log; +Table Op Msg_type Msg_text +mysql.slow_log repair status OK +create table general_log_new like general_log; +create table slow_log_new like slow_log; +show tables like "%log%"; +Tables_in_mysql (%log%) +general_log +general_log_new +slow_log +slow_log_new +drop table slow_log_new, general_log_new; +use test; diff --git a/mysql-test/t/log_tables.test b/mysql-test/t/log_tables.test index 97c83310b4d..f814b258663 100644 --- a/mysql-test/t/log_tables.test +++ b/mysql-test/t/log_tables.test @@ -314,6 +314,89 @@ use mysql; lock tables general_log read local, help_category read local; unlock tables; +# +# Bug #17544 Cannot do atomic log rotate and +# Bug #21785 Server crashes after rename of the log table +# + +use mysql; +# Should result in error +--error ER_CANT_RENAME_LOG_TABLE +RENAME TABLE general_log TO renamed_general_log; +--error ER_CANT_RENAME_LOG_TABLE +RENAME TABLE slow_log TO renamed_slow_log; + +#check rotate logs +truncate table general_log; +--replace_column 1 TIMESTAMP 2 USER_HOST 3 THREAD_ID +select * from general_log; + +truncate table slow_log; +--replace_column 1 TIMESTAMP 2 USER_HOST +select * from slow_log; + +create table general_log_new like general_log; +rename table general_log TO renamed_general_log, general_log_new TO general_log; + +create table slow_log_new like slow_log; +rename table slow_log TO renamed_slow_log, slow_log_new TO slow_log; + +# check that rename checks more then first table in the list +--error ER_CANT_RENAME_LOG_TABLE +rename table general_log TO general_log_new, renamed_general_log TO general_log, slow_log to renamed_slow_log; + +# now check the content of tables +--replace_column 1 TIMESTAMP 2 USER_HOST 3 THREAD_ID +select * from general_log; +--replace_column 1 TIMESTAMP 2 USER_HOST 3 THREAD_ID +select * from renamed_general_log; + +# the content of the slow log is empty, but we will try a select anyway +--replace_column 1 TIMESTAMP 2 USER_HOST +select * from slow_log; +--replace_column 1 TIMESTAMP 2 USER_HOST +select * from renamed_slow_log; + +# check that we can do whatever we want with disabled log +set global general_log='OFF'; +RENAME TABLE general_log TO general_log2; + +set global slow_query_log='OFF'; +RENAME TABLE slow_log TO slow_log2; + +# this should fail +--error ER_CANT_ACTIVATE_LOG +set global general_log='ON'; +--error ER_CANT_ACTIVATE_LOG +set global slow_query_log='ON'; + +RENAME TABLE general_log2 TO general_log; +RENAME TABLE slow_log2 TO slow_log; + +# this should work +set global general_log='ON'; +set global slow_query_log='ON'; +# now check flush logs +flush logs; +flush logs; +drop table renamed_general_log, renamed_slow_log; +use test; + +# +# Bug #21966 Strange warnings on repair of the log tables +# + +use mysql; +# check that no warning occurs on repair of the log tables +repair table general_log; +repair table slow_log; +# check that no warning occurs on "create like" for the log tables +create table general_log_new like general_log; +create table slow_log_new like slow_log; +show tables like "%log%"; +drop table slow_log_new, general_log_new; +use test; + # kill all connections disconnect con1; disconnect con2; diff --git a/sql/handler.cc b/sql/handler.cc index dd1be47e3c2..db2dcfb0079 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1427,8 +1427,9 @@ bool handler::check_if_log_table_locking_is_allowed(uint sql_command, { /* Deny locking of the log tables, which is incompatible with - concurrent insert. Unless called from a logger THD: - general_log_thd or slow_log_thd. + concurrent insert. The routine is not called if the table is + being locked from a logger THD (general_log_thd or slow_log_thd) + or from a privileged thread (see log.cc for details) */ if (table->s->log_table && sql_command != SQLCOM_TRUNCATE && diff --git a/sql/handler.h b/sql/handler.h index df40a207916..8cfd20a5854 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -957,6 +957,10 @@ public: thd Handler of the thread, trying to lock the table table Table handler to check count Number of locks already granted to the table + called_by_privileged_thread TRUE if called from a logger THD + (general_log_thd or slow_log_thd) + or by a privileged thread, which + has the right to lock log tables. DESCRIPTION Check whether a handler allows to lock the table. For instance, @@ -972,7 +976,7 @@ public: virtual bool check_if_locking_is_allowed(uint sql_command, ulong type, TABLE *table, uint count, - bool called_by_logger_thread) + bool called_by_privileged_thread) { return TRUE; } diff --git a/sql/lock.cc b/sql/lock.cc index 06f538a2a03..f36ecf58620 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -691,7 +691,8 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, check_if_locking_is_allowed(thd->lex->sql_command, thd->lex->type, table_ptr[i], count, (thd == logger.get_general_log_thd()) || - (thd == logger.get_slow_log_thd()))) + (thd == logger.get_slow_log_thd()) || + (thd == logger.get_privileged_thread()))) DBUG_RETURN(0); } diff --git a/sql/log.cc b/sql/log.cc index b93d36cf630..0d9453cb02a 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -92,6 +92,31 @@ struct binlog_trx_data { handlerton binlog_hton; +/* Check if a given table is opened log table */ +int check_if_log_table(uint db_len, const char *db, uint table_name_len, + const char *table_name, uint check_if_opened) +{ + if (db_len == 5 && + !(lower_case_table_names ? + my_strcasecmp(system_charset_info, db, "mysql") : + strcmp(db, "mysql"))) + { + if (table_name_len == 11 && !(lower_case_table_names ? + my_strcasecmp(system_charset_info, + table_name, "general_log") : + strcmp(table_name, "general_log")) && + (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_GENERAL))) + return QUERY_LOG_GENERAL; + else + if (table_name_len == 8 && !(lower_case_table_names ? + my_strcasecmp(system_charset_info, table_name, "slow_log") : + strcmp(table_name, "slow_log")) && + (!check_if_opened ||logger.is_log_table_enabled(QUERY_LOG_SLOW))) + return QUERY_LOG_SLOW; + } + return 0; +} + /* Open log table of a given type (general or slow log) @@ -192,6 +217,12 @@ bool Log_to_csv_event_handler::open_log_table(uint log_table_type) my_pthread_setspecific_ptr(THR_MALLOC, 0); } + /* + After a log table was opened, we should clear privileged thread + flag (which allows locking of a log table by a special thread, usually + the one who closed log tables temporarily). + */ + privileged_thread= 0; DBUG_RETURN(error); } @@ -208,6 +239,8 @@ Log_to_csv_event_handler::Log_to_csv_event_handler() /* logger thread always works with mysql database */ slow_log_thd->db= my_strdup("mysql", MYF(0));; slow_log_thd->db_length= 5; + /* no privileged thread exists at the moment */ + privileged_thread= 0; } @@ -260,6 +293,7 @@ bool Log_to_csv_event_handler::reopen_log_table(uint log_table_type) return open_log_table(log_table_type); } + void Log_to_csv_event_handler::cleanup() { if (opt_log) @@ -314,9 +348,6 @@ bool Log_to_csv_event_handler:: filled by the Logger (=> no need to load default ones). */ - /* log table entries are not replicated at the moment */ - tmp_disable_binlog(current_thd); - /* Set current time. Required for CURRENT_TIMESTAMP to work */ general_log_thd->start_time= event_time; @@ -325,21 +356,36 @@ bool Log_to_csv_event_handler:: default value (which is CURRENT_TIMESTAMP). */ - table->field[1]->store(user_host, user_host_len, client_cs); + /* check that all columns exist */ + if (!table->field[1] || !table->field[2] || !table->field[3] || + !table->field[4] || !table->field[5]) + goto err; + + /* do a write */ + if (table->field[1]->store(user_host, user_host_len, client_cs) || + table->field[2]->store((longlong) thread_id, TRUE) || + table->field[3]->store((longlong) server_id, TRUE) || + table->field[4]->store(command_type, command_type_len, client_cs) || + table->field[5]->store(sql_text, sql_text_len, client_cs)) + goto err; + + /* mark tables as not null */ table->field[1]->set_notnull(); - table->field[2]->store((longlong) thread_id, TRUE); table->field[2]->set_notnull(); - table->field[3]->store((longlong) server_id, TRUE); table->field[3]->set_notnull(); - table->field[4]->store(command_type, command_type_len, client_cs); table->field[4]->set_notnull(); - table->field[5]->store(sql_text, sql_text_len, client_cs); table->field[5]->set_notnull(); + + /* log table entries are not replicated at the moment */ + tmp_disable_binlog(current_thd); + table->file->ha_write_row(table->record[0]); reenable_binlog(current_thd); return FALSE; +err: + return TRUE; } @@ -388,9 +434,6 @@ bool Log_to_csv_event_handler:: if (unlikely(!logger.is_log_tables_initialized)) return FALSE; - /* log table entries are not replicated at the moment */ - tmp_disable_binlog(current_thd); - /* Set start time for CURRENT_TIMESTAMP to the start of the query. This will be default value for the field[0] @@ -403,19 +446,30 @@ bool Log_to_csv_event_handler:: default value. */ + if (!table->field[1] || !table->field[2] || !table->field[3] || + !table->field[4] || !table->field[5] || !table->field[6] || + !table->field[7] || !table->field[8] || !table->field[9] || + !table->field[10]) + goto err; + /* store the value */ - table->field[1]->store(user_host, user_host_len, client_cs); + if (table->field[1]->store(user_host, user_host_len, client_cs)) + goto err; if (query_start_arg) { /* fill in query_time field */ - table->field[2]->store(query_time, TRUE); + if (table->field[2]->store(query_time, TRUE)) + goto err; /* lock_time */ - table->field[3]->store(lock_time, TRUE); + if (table->field[3]->store(lock_time, TRUE)) + goto err; /* rows_sent */ - table->field[4]->store((longlong) thd->sent_row_count, TRUE); + if (table->field[4]->store((longlong) thd->sent_row_count, TRUE)) + goto err; /* rows_examined */ - table->field[5]->store((longlong) thd->examined_row_count, TRUE); + if (table->field[5]->store((longlong) thd->examined_row_count, TRUE)) + goto err; } else { @@ -428,14 +482,18 @@ bool Log_to_csv_event_handler:: /* fill database field */ if (thd->db) { - table->field[6]->store(thd->db, thd->db_length, client_cs); + if (table->field[6]->store(thd->db, thd->db_length, client_cs)) + goto err; table->field[6]->set_notnull(); } if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt) { - table->field[7]->store((longlong) - thd->first_successful_insert_id_in_prev_stmt_for_binlog, TRUE); + if (table-> + field[7]->store((longlong) + thd->first_successful_insert_id_in_prev_stmt_for_binlog, + TRUE)) + goto err; table->field[7]->set_notnull(); } @@ -447,16 +505,23 @@ bool Log_to_csv_event_handler:: */ if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0) { - table->field[8]->store((longlong) - thd->auto_inc_intervals_in_cur_stmt_for_binlog.minimum(), TRUE); + if (table-> + field[8]->store((longlong) + thd->auto_inc_intervals_in_cur_stmt_for_binlog.minimum(), TRUE)) + goto err; table->field[8]->set_notnull(); } - table->field[9]->store((longlong) server_id, TRUE); + if (table->field[9]->store((longlong) server_id, TRUE)) + goto err; table->field[9]->set_notnull(); /* sql_text */ - table->field[10]->store(sql_text,sql_text_len, client_cs); + if (table->field[10]->store(sql_text,sql_text_len, client_cs)) + goto err; + + /* log table entries are not replicated at the moment */ + tmp_disable_binlog(current_thd); /* write the row */ table->file->ha_write_row(table->record[0]); @@ -464,6 +529,8 @@ bool Log_to_csv_event_handler:: reenable_binlog(current_thd); DBUG_RETURN(0); +err: + DBUG_RETURN(1); } bool Log_to_csv_event_handler:: @@ -652,61 +719,48 @@ bool LOGGER::reopen_log_table(uint log_table_type) return table_log_handler->reopen_log_table(log_table_type); } +bool LOGGER::reopen_log_tables() +{ + /* + we use | and not || here, to ensure that both reopen_log_table + are called, even if the first one fails + */ + if ((opt_slow_log && logger.reopen_log_table(QUERY_LOG_SLOW)) | + (opt_log && logger.reopen_log_table(QUERY_LOG_GENERAL))) + return TRUE; + return FALSE; +} + + +void LOGGER::tmp_close_log_tables(THD *thd) +{ + table_log_handler->tmp_close_log_tables(thd); +} bool LOGGER::flush_logs(THD *thd) { - TABLE_LIST close_slow_log, close_general_log; - - /* reopen log tables */ - bzero((char*) &close_slow_log, sizeof(TABLE_LIST)); - close_slow_log.alias= close_slow_log.table_name=(char*) "slow_log"; - close_slow_log.table_name_length= 8; - close_slow_log.db= (char*) "mysql"; - close_slow_log.db_length= 5; - - bzero((char*) &close_general_log, sizeof(TABLE_LIST)); - close_general_log.alias= close_general_log.table_name=(char*) "general_log"; - close_general_log.table_name_length= 11; - close_general_log.db= (char*) "mysql"; - close_general_log.db_length= 5; - - /* lock tables, in the case they are enabled */ - if (logger.is_log_tables_initialized) - { - /* - This will lock and wait for all but the logger thread to release the - tables. Then we could reopen log tables. Then release the name locks. - - NOTE: in fact, the first parameter used in lock_and_wait_for_table_name() - and table_log_handler->flush() could be any non-NULL THD, as the - underlying code makes certain assumptions about this. - Here we use one of the logger handler THD's. Simply because it - seems appropriate. - */ - if (opt_slow_log) - lock_and_wait_for_table_name(table_log_handler->general_log_thd, - &close_slow_log); - if (opt_log) - lock_and_wait_for_table_name(table_log_handler->general_log_thd, - &close_general_log); - } + int rc= 0; /* - Deny others from logging to general and slow log, - while reopening tables. + Now we lock logger, as nobody should be able to use logging routines while + log tables are closed */ logger.lock(); + if (logger.is_log_tables_initialized) + table_log_handler->tmp_close_log_tables(thd); // the locking happens here /* reopen log files */ file_log_handler->flush(); - /* flush tables, in the case they are enabled */ + /* reopen tables in the case they were enabled */ if (logger.is_log_tables_initialized) - table_log_handler->flush(table_log_handler->general_log_thd, - &close_slow_log, &close_general_log); + { + if (reopen_log_tables()) + rc= TRUE; + } /* end of log flush */ logger.unlock(); - return FALSE; + return rc; } @@ -1014,31 +1068,50 @@ void LOGGER::deactivate_log_handler(THD *thd, uint log_type) } -bool Log_to_csv_event_handler::flush(THD *thd, TABLE_LIST *close_slow_log, - TABLE_LIST *close_general_log) +/* + Close log tables temporarily. The thread which closed + them this way can lock them in any mode it needs. + NOTE: one should call logger.lock() before entering this + function. +*/ +void Log_to_csv_event_handler::tmp_close_log_tables(THD *thd) { + TABLE_LIST close_slow_log, close_general_log; + + /* fill lists, we will need to perform operations on tables */ + bzero((char*) &close_slow_log, sizeof(TABLE_LIST)); + close_slow_log.alias= close_slow_log.table_name=(char*) "slow_log"; + close_slow_log.table_name_length= 8; + close_slow_log.db= (char*) "mysql"; + close_slow_log.db_length= 5; + + bzero((char*) &close_general_log, sizeof(TABLE_LIST)); + close_general_log.alias= close_general_log.table_name=(char*) "general_log"; + close_general_log.table_name_length= 11; + close_general_log.db= (char*) "mysql"; + close_general_log.db_length= 5; + + privileged_thread= thd; + VOID(pthread_mutex_lock(&LOCK_open)); + /* + NOTE: in fact, the first parameter used in query_cache_invalidate3() + could be any non-NULL THD, as the underlying code makes certain + assumptions about this. + Here we use one of the logger handler THD's. Simply because it + seems appropriate. + */ if (opt_log) { close_log_table(QUERY_LOG_GENERAL, TRUE); - query_cache_invalidate3(thd, close_general_log, 0); - unlock_table_name(thd, close_general_log); + query_cache_invalidate3(general_log_thd, &close_general_log, 0); } if (opt_slow_log) { close_log_table(QUERY_LOG_SLOW, TRUE); - query_cache_invalidate3(thd, close_slow_log, 0); - unlock_table_name(thd, close_slow_log); + query_cache_invalidate3(general_log_thd, &close_slow_log, 0); } VOID(pthread_mutex_unlock(&LOCK_open)); - /* - we use | and not || here, to ensure that both reopen_log_table - are called, even if the first one fails - */ - if ((opt_slow_log && reopen_log_table(QUERY_LOG_SLOW)) | - (opt_log && reopen_log_table(QUERY_LOG_GENERAL))) - return 1; - return 0; } /* the parameters are unused for the log tables */ @@ -1106,16 +1179,15 @@ void Log_to_csv_event_handler:: THD *log_thd, *curr= current_thd; TABLE_LIST *table; + if (!logger.is_log_table_enabled(log_table_type)) + return; /* do nothing */ + switch (log_table_type) { case QUERY_LOG_GENERAL: - if (!logger.is_general_log_table_enabled()) - return; /* do nothing */ log_thd= general_log_thd; table= &general_log; break; case QUERY_LOG_SLOW: - if (!logger.is_slow_log_table_enabled()) - return; /* do nothing */ log_thd= slow_log_thd; table= &slow_log; break; diff --git a/sql/log.h b/sql/log.h index d598952a853..fd8453649b3 100644 --- a/sql/log.h +++ b/sql/log.h @@ -403,6 +403,9 @@ public: }; +int check_if_log_table(uint db_len, const char *db, uint table_name_len, + const char *table_name, uint check_if_opened); + class Log_to_csv_event_handler: public Log_event_handler { /* @@ -411,6 +414,16 @@ class Log_to_csv_event_handler: public Log_event_handler THD's of the query. The reason is the locking order and duration. */ THD *general_log_thd, *slow_log_thd; + /* + This is for the thread, which called tmp_close_log_tables. The thread + will be allowed to write-lock the log tables (as it explicitly disabled + logging). This is used for such operations as REPAIR, which require + exclusive lock on the log tables. + NOTE: there can be only one priviliged thread, as one should + lock logger with logger.lock() before calling tmp_close_log_tables(). + So no other thread could get privileged status at the same time. + */ + THD *privileged_thread; friend class LOGGER; TABLE_LIST general_log, slow_log; @@ -435,13 +448,20 @@ public: const char *command_type, uint command_type_len, const char *sql_text, uint sql_text_len, CHARSET_INFO *client_cs); - bool flush(THD *thd, TABLE_LIST *close_slow_Log, - TABLE_LIST* close_general_log); + void tmp_close_log_tables(THD *thd); void close_log_table(uint log_type, bool lock_in_use); bool reopen_log_table(uint log_type); + THD* get_privileged_thread() + { + return privileged_thread; + } }; +/* type of the log table */ +#define QUERY_LOG_SLOW 1 +#define QUERY_LOG_GENERAL 2 + class Log_to_file_event_handler: public Log_event_handler { MYSQL_QUERY_LOG mysql_log; @@ -497,13 +517,18 @@ public: {} void lock() { (void) pthread_mutex_lock(&LOCK_logger); } void unlock() { (void) pthread_mutex_unlock(&LOCK_logger); } - bool is_general_log_table_enabled() + void tmp_close_log_tables(THD *thd); + bool is_log_table_enabled(uint log_table_type) { - return table_log_handler && table_log_handler->general_log.table != 0; - } - bool is_slow_log_table_enabled() - { - return table_log_handler && table_log_handler->slow_log.table != 0; + switch (log_table_type) { + case QUERY_LOG_SLOW: + return table_log_handler && table_log_handler->slow_log.table != 0; + case QUERY_LOG_GENERAL: + return table_log_handler && table_log_handler->general_log.table != 0; + default: + DBUG_ASSERT(0); + return FALSE; /* make compiler happy */ + } } /* We want to initialize all log mutexes as soon as possible, @@ -541,6 +566,7 @@ public: void close_log_table(uint log_type, bool lock_in_use); bool reopen_log_table(uint log_type); + bool reopen_log_tables(); /* we use this function to setup all enabled log event handlers */ int set_handlers(uint error_log_printer, @@ -563,6 +589,13 @@ public: return file_log_handler->get_mysql_log(); return NULL; } + THD* get_privileged_thread() + { + if (table_log_handler) + return table_log_handler->get_privileged_thread(); + else + return NULL; + } }; enum enum_binlog_format { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 473de1951e5..568d8496891 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1428,10 +1428,6 @@ void sql_print_information(const char *format, ...); typedef void (*sql_print_message_func)(const char *format, ...); extern sql_print_message_func sql_print_message_handlers[]; -/* type of the log table */ -#define QUERY_LOG_SLOW 1 -#define QUERY_LOG_GENERAL 2 - int error_log_print(enum loglevel level, const char *format, va_list args); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 2228ded870b..ca9804c5c83 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5960,3 +5960,5 @@ ER_HOSTNAME eng "host name" ER_WRONG_STRING_LENGTH eng "String '%-.70s' is too long for %s (should be no longer than %d)" +ER_CANT_RENAME_LOG_TABLE + eng "Cannot rename '%s'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to '%s'" diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 4c91ba6d8ff..0e9e36d9177 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -912,28 +912,16 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) DBUG_RETURN(TRUE); } + uint log_type= check_if_log_table(table_list->db_length, table_list->db, + table_list->table_name_length, + table_list->table_name, 1); /* close log tables in use */ - if (!my_strcasecmp(system_charset_info, table_list->db, "mysql")) + if (log_type) { - if (opt_log && - !my_strcasecmp(system_charset_info, table_list->table_name, - "general_log")) - { - lock_logger= 1; - logger.lock(); - logger.close_log_table(QUERY_LOG_GENERAL, FALSE); - closed_log_tables= closed_log_tables | QUERY_LOG_GENERAL; - } - else - if (opt_slow_log && - !my_strcasecmp(system_charset_info, table_list->table_name, - "slow_log")) - { - lock_logger= 1; - logger.lock(); - logger.close_log_table(QUERY_LOG_SLOW, FALSE); - closed_log_tables= closed_log_tables | QUERY_LOG_SLOW; - } + lock_logger= 1; + logger.lock(); + logger.close_log_table(log_type, FALSE); + closed_log_tables= closed_log_tables | log_type; } // Remove the .frm extension AIX 5.2 64-bit compiler bug (BUG#16155): this diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 73473ddd24b..47e85cc0884 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -35,7 +35,10 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list); bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) { bool error= 1; - TABLE_LIST *ren_table= 0; + TABLE_LIST *ren_table= 0, *new_table; + int to_table; + char *rename_log_table[2]= {NULL, NULL}; + int disable_logs= 0; DBUG_ENTER("mysql_rename_tables"); /* @@ -52,6 +55,96 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) if (wait_if_global_read_lock(thd,0,1)) DBUG_RETURN(1); + + if (logger.is_log_table_enabled(QUERY_LOG_GENERAL) || + logger.is_log_table_enabled(QUERY_LOG_SLOW)) + { + + /* + Rules for rename of a log table: + + IF 1. Log tables are enabled + AND 2. Rename operates on the log table and nothing is being + renamed to the log table. + DO 3. Throw an error message. + ELSE 4. Perform rename. + */ + + for (to_table= 0, ren_table= table_list; ren_table; + to_table= 1 - to_table, ren_table= ren_table->next_local) + { + int log_table_rename= 0; + + if ((log_table_rename= + check_if_log_table(ren_table->db_length, ren_table->db, + ren_table->table_name_length, + ren_table->table_name, 1))) + { + /* + Log table encoutered we will need to disable and lock logs + for duration of rename. + */ + disable_logs= TRUE; + + /* + as we use log_table_rename as an array index, we need it to start + with 0, while QUERY_LOG_SLOW == 1 and QUERY_LOG_GENERAL == 2. + So, we shift the value to start with 0; + */ + log_table_rename--; + if (rename_log_table[log_table_rename]) + { + if (to_table) + rename_log_table[log_table_rename]= NULL; + else + { + /* + Two renames of "log_table TO" w/o rename "TO log_table" in + between. + */ + my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), ren_table->table_name, + ren_table->table_name); + DBUG_RETURN(1); + } + } + else + { + if (to_table) + { + /* + Attempt to rename a table TO log_table w/o renaming + log_table TO some table. + */ + my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), ren_table->table_name, + ren_table->table_name); + DBUG_RETURN(1); + } + else + { + /* save the name of the log table to report an error */ + rename_log_table[log_table_rename]= ren_table->table_name; + } + } + } + } + if (rename_log_table[0] || rename_log_table[1]) + { + if (rename_log_table[0]) + my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), rename_log_table[0], + rename_log_table[0]); + else + my_error(ER_CANT_RENAME_LOG_TABLE, MYF(0), rename_log_table[1], + rename_log_table[1]); + DBUG_RETURN(1); + } + + if (disable_logs) + { + logger.lock(); + logger.tmp_close_log_tables(thd); + } + } + VOID(pthread_mutex_lock(&LOCK_open)); if (lock_table_names(thd, table_list)) goto err; @@ -95,6 +188,13 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) err: pthread_mutex_unlock(&LOCK_open); + /* enable logging back if needed */ + if (disable_logs) + { + if (logger.reopen_log_tables()) + error= TRUE; + logger.unlock(); + } start_waiting_global_read_lock(thd); DBUG_RETURN(error); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f0f69676ed2..053de467921 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1622,11 +1622,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, /* Disable drop of enabled log tables */ if (share && share->log_table && - ((!my_strcasecmp(system_charset_info, table->table_name, - "general_log") && opt_log && - logger.is_general_log_table_enabled()) || - (!my_strcasecmp(system_charset_info, table->table_name, "slow_log") - && opt_slow_log && logger.is_slow_log_table_enabled()))) + check_if_log_table(table->db_length, table->db, + table->table_name_length, table->table_name, 1)) { my_error(ER_CANT_DROP_LOG_TABLE, MYF(0)); DBUG_RETURN(1); @@ -4019,7 +4016,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, Item *item; Protocol *protocol= thd->protocol; LEX *lex= thd->lex; - int result_code; + int result_code, disable_logs= 0; DBUG_ENTER("mysql_admin_table"); if (end_active_trans(thd)) @@ -4064,6 +4061,23 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, thd->no_warnings_for_error= no_warnings_for_error; if (view_operator_func == NULL) table->required_type=FRMTYPE_TABLE; + + /* + If we want to perform an admin operation on the log table + (E.g. rename) and lock_type >= TL_READ_NO_INSERT disable + log tables + */ + + if (check_if_log_table(table->db_length, table->db, + table->table_name_length, + table->table_name, 1) && + lock_type >= TL_READ_NO_INSERT) + { + disable_logs= 1; + logger.lock(); + logger.tmp_close_log_tables(thd); + } + open_and_lock_tables(thd, table); thd->no_warnings_for_error= 0; table->next_global= save_next_global; @@ -4380,11 +4394,24 @@ send_result_message: } send_eof(thd); + if (disable_logs) + { + if (logger.reopen_log_tables()) + my_error(ER_CANT_ACTIVATE_LOG, MYF(0)); + logger.unlock(); + } DBUG_RETURN(FALSE); err: ha_autocommit_or_rollback(thd, 1); close_thread_tables(thd); // Shouldn't be needed + /* enable logging back if needed */ + if (disable_logs) + { + if (logger.reopen_log_tables()) + my_error(ER_CANT_ACTIVATE_LOG, MYF(0)); + logger.unlock(); + } if (table) table->table=0; DBUG_RETURN(TRUE); @@ -4549,6 +4576,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, { TABLE *tmp_table; char src_path[FN_REFLEN], dst_path[FN_REFLEN], tmp_path[FN_REFLEN]; + char src_table_name_buff[FN_REFLEN], src_db_name_buff[FN_REFLEN]; uint dst_path_length; char *db= table->db; char *table_name= table->table_name; @@ -4585,13 +4613,6 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, DBUG_RETURN(-1); } - bzero((gptr)&src_tables_list, sizeof(src_tables_list)); - src_tables_list.db= src_db; - src_tables_list.table_name= src_table; - - if (lock_and_wait_for_table_name(thd, &src_tables_list)) - goto err; - if ((tmp_table= find_temporary_table(thd, src_db, src_table))) strxmov(src_path, tmp_table->s->path.str, reg_ext, NullS); else @@ -4618,6 +4639,34 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, goto err; } + if (lower_case_table_names) + { + if (src_db) + { + strmake(src_db_name_buff, src_db, + min(sizeof(src_db_name_buff) - 1, table_ident->db.length)); + my_casedn_str(files_charset_info, src_db_name_buff); + src_db= src_db_name_buff; + } + if (src_table) + { + strmake(src_table_name_buff, src_table, + min(sizeof(src_table_name_buff) - 1, table_ident->table.length)); + my_casedn_str(files_charset_info, src_table_name_buff); + src_table= src_table_name_buff; + } + } + + bzero((gptr)&src_tables_list, sizeof(src_tables_list)); + src_tables_list.db= src_db; + src_tables_list.db_length= table_ident->db.length; + src_tables_list.lock_type= TL_READ; + src_tables_list.table_name= src_table; + src_tables_list.alias= src_table; + + if (simple_open_n_lock_tables(thd, &src_tables_list)) + DBUG_RETURN(TRUE); + /* Validate the destination table @@ -4764,9 +4813,6 @@ table_exists: my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name); err: - pthread_mutex_lock(&LOCK_open); - unlock_table_name(thd, &src_tables_list); - pthread_mutex_unlock(&LOCK_open); DBUG_RETURN(res); } @@ -5153,37 +5199,27 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, LINT_INIT(index_add_buffer); LINT_INIT(index_drop_buffer); - if (table_list && table_list->db && - !my_strcasecmp(system_charset_info, table_list->db, "mysql") && - table_list->table_name) + if (table_list && table_list->db && table_list->table_name) { - enum enum_table_kind { NOT_LOG_TABLE= 1, GENERAL_LOG, SLOW_LOG } - table_kind= NOT_LOG_TABLE; + int table_kind= 0; - if (!my_strcasecmp(system_charset_info, table_list->table_name, - "general_log")) - table_kind= GENERAL_LOG; - else - if (!my_strcasecmp(system_charset_info, table_list->table_name, - "slow_log")) - table_kind= SLOW_LOG; + table_kind= check_if_log_table(table_list->db_length, table_list->db, + table_list->table_name_length, + table_list->table_name, 0); /* Disable alter of enabled log tables */ - if ((table_kind == GENERAL_LOG && opt_log && - logger.is_general_log_table_enabled()) || - (table_kind == SLOW_LOG && opt_slow_log && - logger.is_slow_log_table_enabled())) + if (table_kind && logger.is_log_table_enabled(table_kind)) { my_error(ER_CANT_ALTER_LOG_TABLE, MYF(0)); DBUG_RETURN(TRUE); } /* Disable alter of log tables to unsupported engine */ - if ((table_kind == GENERAL_LOG || table_kind == SLOW_LOG) && + if (table_kind && (lex_create_info->used_fields & HA_CREATE_USED_ENGINE) && (!lex_create_info->db_type || /* unknown engine */ - !(lex_create_info->db_type->db_type == DB_TYPE_MYISAM || - lex_create_info->db_type->db_type == DB_TYPE_CSV_DB))) + !(lex_create_info->db_type->db_type == DB_TYPE_MYISAM || + lex_create_info->db_type->db_type == DB_TYPE_CSV_DB))) { my_error(ER_BAD_LOG_ENGINE, MYF(0)); DBUG_RETURN(TRUE); diff --git a/sql/table.cc b/sql/table.cc index fe83398115d..da4f9799a64 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -363,25 +363,24 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) error= open_binary_frm(thd, share, head, file); *root_ptr= old_root; - if (share->db.length == 5 && - !my_strcasecmp(system_charset_info, share->db.str, "mysql")) + if (share->db.length == 5 && !(lower_case_table_names ? + my_strcasecmp(system_charset_info, share->db.str, "mysql") : + strcmp(share->db.str, "mysql"))) { /* We can't mark all tables in 'mysql' database as system since we don't allow to lock such tables for writing with any other tables (even with other system tables) and some privilege tables need this. */ - if (!my_strcasecmp(system_charset_info, share->table_name.str, "proc")) + if (!(lower_case_table_names ? + my_strcasecmp(system_charset_info, share->table_name.str, "proc") : + strcmp(share->table_name.str, "proc"))) share->system_table= 1; else { - if (!my_strcasecmp(system_charset_info, share->table_name.str, - "general_log")) - share->log_table= QUERY_LOG_GENERAL; - else - if (!my_strcasecmp(system_charset_info, share->table_name.str, - "slow_log")) - share->log_table= QUERY_LOG_SLOW; + share->log_table= check_if_log_table(share->db.length, share->db.str, + share->table_name.length, + share->table_name.str, 0); } } error_given= 1; diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index 2fe2afeb470..5a7a15e93c5 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -817,9 +817,9 @@ void ha_tina::update_status() bool ha_tina::check_if_locking_is_allowed(uint sql_command, ulong type, TABLE *table, uint count, - bool called_by_logger_thread) + bool called_by_privileged_thread) { - if (!called_by_logger_thread) + if (!called_by_privileged_thread) return check_if_log_table_locking_is_allowed(sql_command, type, table); return TRUE; diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 209478ee9a5..321ebab29e7 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -255,7 +255,7 @@ err: bool ha_myisam::check_if_locking_is_allowed(uint sql_command, ulong type, TABLE *table, uint count, - bool called_by_logger_thread) + bool called_by_privileged_thread) { /* To be able to open and lock for reading system tables like 'mysql.proc', @@ -273,10 +273,10 @@ bool ha_myisam::check_if_locking_is_allowed(uint sql_command, /* Deny locking of the log tables, which is incompatible with - concurrent insert. Unless called from a logger THD: - general_log_thd or slow_log_thd. + concurrent insert. Unless called from a logger THD (general_log_thd + or slow_log_thd) or by a privileged thread. */ - if (!called_by_logger_thread) + if (!called_by_privileged_thread) return check_if_log_table_locking_is_allowed(sql_command, type, table); return TRUE; From cc558cfba34ee39cf447849626db09e7b252ab9d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Oct 2006 15:20:34 +0400 Subject: [PATCH 18/47] Fix for valgrind warning introduced by the fix for bug#21354: (COUNT(*) = 1) not working in SELECT inside prepared statement. Note: the warning was introduced in 5.0 and 5.1, 4.1 is OK with the original fix. The problem was that in 5.0 and 5.1 clear() for group functions may access hybrid_type member, and this member is initialized in fix_fields(). So we should not call clear() from item cleanup() methods, as cleanup() may be called for unfixed items. sql/item_sum.cc: Do not call clear() from item cleanup() methods, as cleanup() may be called for unfixed items, and clear() assumes the item was fixed. sql/item_sum.h: Do not call clear() from item cleanup() methods, as cleanup() may be called for unfixed items, and clear() assumes the item was fixed. --- sql/item_sum.cc | 2 +- sql/item_sum.h | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 513fa46ecb3..397293bc131 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1055,7 +1055,7 @@ longlong Item_sum_count::val_int() void Item_sum_count::cleanup() { DBUG_ENTER("Item_sum_count::cleanup"); - clear(); + count= 0; Item_sum_int::cleanup(); used_table_cache= ~(table_map) 0; DBUG_VOID_RETURN; diff --git a/sql/item_sum.h b/sql/item_sum.h index 4a0930184c7..fe7edd76ecf 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -643,8 +643,8 @@ public: Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); void cleanup() { - clear(); - Item_sum_num::cleanup(); + count= 0; + Item_sum_sum::cleanup(); } }; @@ -727,7 +727,8 @@ public: enum Item_result result_type () const { return REAL_RESULT; } void cleanup() { - clear(); + cur_dec= 0; + count= 0; Item_sum_num::cleanup(); } }; @@ -862,7 +863,7 @@ public: { decimals= 0; max_length=21; unsigned_flag= 1; maybe_null= null_value= 0; } void cleanup() { - clear(); + bits= reset_bits; Item_sum_int::cleanup(); } }; From ef2d2165d1062f0a4d60ca3947de64fd9b6638d0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Oct 2006 14:43:52 +0400 Subject: [PATCH 19/47] BUG#21856: Prepared Statements: crash if bad create When statement to be prepared contained CREATE PROCEDURE, CREATE FUNCTION or CREATE TRIGGER statements with a syntax error in it, the preparation would fail with syntax error message, but the memory could be corrupted. The problem occurred because we switch memroot when parse stored routine or trigger definitions, and on parse error we restored the original memroot only after performing some memory operations. In more detail: - prepared statement would activate its own memory root to parse the definition of the stored procedure. - SP would reset this memory root with its own memory root to parse SP statements - a syntax error would happen - prepared statement would restore the original memory root - stored procedure would restore what it thinks was the original memory root, but actually was the statement memory root. That led to double free - in destruction of the statement and in a next call to mysql_parse(). The solution is to restore memroot right after the failed parsing. mysql-test/r/ps.result: Add result for bug#21856: Prepared Statements: crash if bad create. mysql-test/t/ps.test: Add test case for bug#21856: Prepared Statements: crash if bad create. sql/sql_parse.cc: On parse error if thd->lex->sphead is set we have to free sp_head object to restore statement memroot, if it was switched during parsing. The change here is for safety, currently query_cache_abort() and lex->unit.cleanup() calls do not use current memroot. sql/sql_prepare.cc: On parse error if thd->lex->sphead is set we have to free sp_head object to restore statement memroot, if it was switched during parsing. --- mysql-test/r/ps.result | 1 + mysql-test/t/ps.test | 20 ++++++++++++++++++++ sql/sql_parse.cc | 9 +++++++-- sql/sql_prepare.cc | 11 +++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 080187cfa7b..c895ef54e55 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1311,4 +1311,5 @@ EXECUTE stmt USING @a; i j i i j DEALLOCATE PREPARE stmt; DROP TABLE IF EXISTS t1, t2, t3; +DROP PROCEDURE IF EXISTS p1; End of 5.0 tests. diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 5b2e37ecc94..fd74c52f3d5 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1358,4 +1358,24 @@ DEALLOCATE PREPARE stmt; DROP TABLE IF EXISTS t1, t2, t3; +# +# BUG#21856: Prepared Statments: crash if bad create +# +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +--enable_warnings + +let $iterations= 100; +--disable_query_log +--disable_result_log +while ($iterations > 0) +{ + --error ER_PARSE_ERROR + PREPARE stmt FROM "CREATE PROCEDURE p1()"; + dec $iterations; +} +--enable_query_log +--enable_result_log + + --echo End of 5.0 tests. diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2acbf18f1e6..f75bc5f073c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5852,14 +5852,19 @@ void mysql_parse(THD *thd, char *inBuf, uint length) DBUG_ASSERT(thd->net.report_error); DBUG_PRINT("info",("Command aborted. Fatal_error: %d", thd->is_fatal_error)); - query_cache_abort(&thd->net); - lex->unit.cleanup(); + + /* + The first thing we do after parse error is freeing sp_head to + ensure that we have restored original memroot. + */ if (thd->lex->sphead) { /* Clean up after failed stored procedure/function */ delete thd->lex->sphead; thd->lex->sphead= NULL; } + query_cache_abort(&thd->net); + lex->unit.cleanup(); } thd->proc_info="freeing items"; thd->end_statement(); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 32f0ca6859d..fcbf495463a 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2773,6 +2773,16 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) error= MYSQLparse((void *)thd) || thd->is_fatal_error || thd->net.report_error || init_param_array(this); + + /* + The first thing we do after parse error is freeing sp_head to + ensure that we have restored original memroot. + */ + if (error && lex->sphead) + { + delete lex->sphead; + lex->sphead= NULL; + } /* While doing context analysis of the query (in check_prepared_statement) we allocate a lot of additional memory: for open tables, JOINs, derived @@ -2798,6 +2808,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) if (error == 0) error= check_prepared_statement(this, name.str != 0); + /* Free sp_head if check_prepared_statement() failed. */ if (error && lex->sphead) { delete lex->sphead; From 5bd58f3e00ad7e7430c8d728f94209dce4c1a4e4 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Oct 2006 11:39:51 -0700 Subject: [PATCH 20/47] Bug#20028 (Function with select return no data) This patch reverts a change introduced by Bug 6951, which incorrectly set thd->abort_on_warning for stored procedures. As per internal discussions about the SQL_MODE=TRADITIONAL, the correct behavior is to *not* abort on warnings even inside an INSERT/UPDATE trigger. Tests for Stored Procedures, Stored Functions, Triggers involving SQL_MODE have been included or revised, to reflect the intended behavior. (reposting approved patch, to work around source control issues, no review needed) mysql-test/include/sp-vars.inc: Tests for SQL_MODE='TRADITIONAL' mysql-test/r/sp-vars.result: Tests for SQL_MODE='TRADITIONAL' mysql-test/r/sp.result: Tests for SQL_MODE='TRADITIONAL' mysql-test/r/trigger.result: Tests for SQL_MODE='TRADITIONAL' mysql-test/t/sp-vars.test: Tests for SQL_MODE='TRADITIONAL' mysql-test/t/sp.test: Tests for SQL_MODE='TRADITIONAL' mysql-test/t/trigger.test: Tests for SQL_MODE='TRADITIONAL' sql/sp_head.cc: For SQL_MODE='TRADITIONAL', thd->abort_on_warning should be set only when assigning a *column* --- mysql-test/include/sp-vars.inc | 9 +++ mysql-test/r/sp-vars.result | 23 ++++++ mysql-test/r/sp.result | 129 ++++++++++++++++++++++++++++++++ mysql-test/r/trigger.result | 64 +++++++++++++++- mysql-test/t/sp-vars.test | 10 +++ mysql-test/t/sp.test | 131 +++++++++++++++++++++++++++++++++ mysql-test/t/trigger.test | 63 +++++++++++++++- sql/sp_head.cc | 3 +- 8 files changed, 424 insertions(+), 8 deletions(-) diff --git a/mysql-test/include/sp-vars.inc b/mysql-test/include/sp-vars.inc index 3e02c9d1709..4bac883ee0e 100644 --- a/mysql-test/include/sp-vars.inc +++ b/mysql-test/include/sp-vars.inc @@ -119,4 +119,13 @@ END| --------------------------------------------------------------------------- +CREATE FUNCTION sp_vars_div_zero() RETURNS INTEGER +BEGIN + DECLARE div_zero INTEGER; + SELECT 1/0 INTO div_zero; + RETURN div_zero; +END| + +--------------------------------------------------------------------------- + delimiter ;| diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result index 14040f8420e..f362187cd14 100644 --- a/mysql-test/r/sp-vars.result +++ b/mysql-test/r/sp-vars.result @@ -4,6 +4,7 @@ DROP FUNCTION IF EXISTS sp_vars_check_ret1; DROP FUNCTION IF EXISTS sp_vars_check_ret2; DROP FUNCTION IF EXISTS sp_vars_check_ret3; DROP FUNCTION IF EXISTS sp_vars_check_ret4; +DROP FUNCTION IF EXISTS sp_vars_div_zero; SET @@sql_mode = 'ansi'; CREATE PROCEDURE sp_vars_check_dflt() BEGIN @@ -88,6 +89,12 @@ CREATE FUNCTION sp_vars_check_ret4() RETURNS DECIMAL(64, 2) BEGIN RETURN 12 * 10 + 34 + 0.1234; END| +CREATE FUNCTION sp_vars_div_zero() RETURNS INTEGER +BEGIN +DECLARE div_zero INTEGER; +SELECT 1/0 INTO div_zero; +RETURN div_zero; +END| --------------------------------------------------------------- Calling the routines, created in ANSI mode. @@ -172,6 +179,9 @@ sp_vars_check_ret4() 154.12 Warnings: Note 1265 Data truncated for column 'sp_vars_check_ret4()' at row 1 +SELECT sp_vars_div_zero(); +sp_vars_div_zero() +NULL SET @@sql_mode = 'traditional'; --------------------------------------------------------------- @@ -257,12 +267,16 @@ sp_vars_check_ret4() 154.12 Warnings: Note 1265 Data truncated for column 'sp_vars_check_ret4()' at row 1 +SELECT sp_vars_div_zero(); +sp_vars_div_zero() +NULL DROP PROCEDURE sp_vars_check_dflt; DROP PROCEDURE sp_vars_check_assignment; DROP FUNCTION sp_vars_check_ret1; DROP FUNCTION sp_vars_check_ret2; DROP FUNCTION sp_vars_check_ret3; DROP FUNCTION sp_vars_check_ret4; +DROP FUNCTION sp_vars_div_zero; CREATE PROCEDURE sp_vars_check_dflt() BEGIN DECLARE v1 TINYINT DEFAULT 1e200; @@ -346,6 +360,12 @@ CREATE FUNCTION sp_vars_check_ret4() RETURNS DECIMAL(64, 2) BEGIN RETURN 12 * 10 + 34 + 0.1234; END| +CREATE FUNCTION sp_vars_div_zero() RETURNS INTEGER +BEGIN +DECLARE div_zero INTEGER; +SELECT 1/0 INTO div_zero; +RETURN div_zero; +END| --------------------------------------------------------------- Calling the routines, created in TRADITIONAL mode. @@ -366,6 +386,8 @@ sp_vars_check_ret4() 154.12 Warnings: Note 1265 Data truncated for column 'sp_vars_check_ret4()' at row 1 +SELECT sp_vars_div_zero(); +ERROR 22012: Division by 0 SET @@sql_mode = 'ansi'; DROP PROCEDURE sp_vars_check_dflt; DROP PROCEDURE sp_vars_check_assignment; @@ -373,6 +395,7 @@ DROP FUNCTION sp_vars_check_ret1; DROP FUNCTION sp_vars_check_ret2; DROP FUNCTION sp_vars_check_ret3; DROP FUNCTION sp_vars_check_ret4; +DROP FUNCTION sp_vars_div_zero; --------------------------------------------------------------- BIT data type tests diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 6e8a609d669..1bb4b3a405b 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5470,6 +5470,135 @@ CAD CHF DROP FUNCTION bug21493| DROP TABLE t3,t4| +drop function if exists func_20028_a| +drop function if exists func_20028_b| +drop function if exists func_20028_c| +drop procedure if exists proc_20028_a| +drop procedure if exists proc_20028_b| +drop procedure if exists proc_20028_c| +drop table if exists table_20028| +create table table_20028 (i int)| +SET @save_sql_mode=@@sql_mode| +SET sql_mode=''| +create function func_20028_a() returns integer +begin +declare temp integer; +select i into temp from table_20028 limit 1; +return ifnull(temp, 0); +end| +create function func_20028_b() returns integer +begin +return func_20028_a(); +end| +create function func_20028_c() returns integer +begin +declare div_zero integer; +set SQL_MODE='TRADITIONAL'; +select 1/0 into div_zero; +return div_zero; +end| +create procedure proc_20028_a() +begin +declare temp integer; +select i into temp from table_20028 limit 1; +end| +create procedure proc_20028_b() +begin +call proc_20028_a(); +end| +create procedure proc_20028_c() +begin +declare div_zero integer; +set SQL_MODE='TRADITIONAL'; +select 1/0 into div_zero; +end| +select func_20028_a()| +func_20028_a() +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +select func_20028_b()| +func_20028_b() +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +select func_20028_c()| +ERROR 22012: Division by 0 +call proc_20028_a()| +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +call proc_20028_b()| +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +call proc_20028_c()| +ERROR 22012: Division by 0 +SET sql_mode='TRADITIONAL'| +drop function func_20028_a| +drop function func_20028_b| +drop function func_20028_c| +drop procedure proc_20028_a| +drop procedure proc_20028_b| +drop procedure proc_20028_c| +create function func_20028_a() returns integer +begin +declare temp integer; +select i into temp from table_20028 limit 1; +return ifnull(temp, 0); +end| +create function func_20028_b() returns integer +begin +return func_20028_a(); +end| +create function func_20028_c() returns integer +begin +declare div_zero integer; +set SQL_MODE=''; +select 1/0 into div_zero; +return div_zero; +end| +create procedure proc_20028_a() +begin +declare temp integer; +select i into temp from table_20028 limit 1; +end| +create procedure proc_20028_b() +begin +call proc_20028_a(); +end| +create procedure proc_20028_c() +begin +declare div_zero integer; +set SQL_MODE=''; +select 1/0 into div_zero; +end| +select func_20028_a()| +func_20028_a() +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +select func_20028_b()| +func_20028_b() +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +select func_20028_c()| +func_20028_c() +NULL +call proc_20028_a()| +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +call proc_20028_b()| +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +call proc_20028_c()| +SET @@sql_mode=@save_sql_mode| +drop function func_20028_a| +drop function func_20028_b| +drop function func_20028_c| +drop procedure proc_20028_a| +drop procedure proc_20028_b| +drop procedure proc_20028_c| +drop table table_20028| drop procedure if exists proc_21462_a| drop procedure if exists proc_21462_b| create procedure proc_21462_a() diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 0b0bf1086db..5d643057666 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1073,10 +1073,11 @@ SELECT @x; NULL SET @x=2; UPDATE t1 SET i1 = @x; -ERROR 22012: Division by 0 +Warnings: +Error 1365 Division by 0 SELECT @x; @x -2 +NULL SET SQL_MODE=''; SET @x=3; INSERT INTO t1 VALUES (@x); @@ -1085,10 +1086,12 @@ SELECT @x; NULL SET @x=4; UPDATE t1 SET i1 = @x; -ERROR 22012: Division by 0 +Warnings: +Error 1365 Division by 0 +Error 1365 Division by 0 SELECT @x; @x -4 +NULL SET @@sql_mode=@save_sql_mode; DROP TRIGGER t1_ai; DROP TRIGGER t1_au; @@ -1174,6 +1177,59 @@ ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghi DROP TABLE t1; DROP TABLE t2; drop table if exists t1; +drop table if exists t2; +drop table if exists t3; +drop table if exists t4; +SET @save_sql_mode=@@sql_mode; +SET sql_mode='TRADITIONAL'| +create table t1 (id int(10) not null primary key, v int(10) )| +create table t2 (id int(10) not null primary key, v int(10) )| +create table t3 (id int(10) not null primary key, v int(10) )| +create table t4 (c int)| +create trigger t4_bi before insert on t4 for each row set @t4_bi_called:=1| +create trigger t4_bu before update on t4 for each row set @t4_bu_called:=1| +insert into t1 values(10, 10)| +set @a:=1/0| +Warnings: +Error 1365 Division by 0 +select 1/0 from t1| +1/0 +NULL +Warnings: +Error 1365 Division by 0 +create trigger t1_bi before insert on t1 for each row set @a:=1/0| +insert into t1 values(20, 20)| +Warnings: +Error 1365 Division by 0 +drop trigger t1_bi| +create trigger t1_bi before insert on t1 for each row +begin +insert into t2 values (new.id, new.v); +update t2 set v=v+1 where id= new.id; +replace t3 values (new.id, 0); +update t2, t3 set t2.v=new.v, t3.v=new.v where t2.id=t3.id; +create temporary table t5 select * from t1; +delete from t5; +insert into t5 select * from t1; +insert into t4 values (0); +set @check= (select count(*) from t5); +update t4 set c= @check; +drop temporary table t5; +set @a:=1/0; +end| +set @check=0, @t4_bi_called=0, @t4_bu_called=0| +insert into t1 values(30, 30)| +Warnings: +Error 1365 Division by 0 +select @check, @t4_bi_called, @t4_bu_called| +@check @t4_bi_called @t4_bu_called +2 1 1 +SET @@sql_mode=@save_sql_mode; +drop table t1; +drop table t2; +drop table t3; +drop table t4; +drop table if exists t1; create table t1 (i int, j int key); insert into t1 values (1,1), (2,2), (3,3); create trigger t1_bu before update on t1 for each row diff --git a/mysql-test/t/sp-vars.test b/mysql-test/t/sp-vars.test index 48dbd4de7aa..7cf92dc5d0d 100644 --- a/mysql-test/t/sp-vars.test +++ b/mysql-test/t/sp-vars.test @@ -15,6 +15,7 @@ DROP FUNCTION IF EXISTS sp_vars_check_ret1; DROP FUNCTION IF EXISTS sp_vars_check_ret2; DROP FUNCTION IF EXISTS sp_vars_check_ret3; DROP FUNCTION IF EXISTS sp_vars_check_ret4; +DROP FUNCTION IF EXISTS sp_vars_div_zero; --enable_warnings @@ -49,6 +50,8 @@ SELECT sp_vars_check_ret3(); SELECT sp_vars_check_ret4(); +SELECT sp_vars_div_zero(); + # Check that changing sql_mode after creating a store procedure does not # matter. @@ -72,6 +75,8 @@ SELECT sp_vars_check_ret3(); SELECT sp_vars_check_ret4(); +SELECT sp_vars_div_zero(); + # Create the procedure in TRADITIONAL mode. Check that error will be thrown on # execution. @@ -81,6 +86,7 @@ DROP FUNCTION sp_vars_check_ret1; DROP FUNCTION sp_vars_check_ret2; DROP FUNCTION sp_vars_check_ret3; DROP FUNCTION sp_vars_check_ret4; +DROP FUNCTION sp_vars_div_zero; --source include/sp-vars.inc @@ -110,6 +116,9 @@ SELECT sp_vars_check_ret3(); SELECT sp_vars_check_ret4(); +--error ER_DIVISION_BY_ZERO +SELECT sp_vars_div_zero(); + SET @@sql_mode = 'ansi'; # @@ -122,6 +131,7 @@ DROP FUNCTION sp_vars_check_ret1; DROP FUNCTION sp_vars_check_ret2; DROP FUNCTION sp_vars_check_ret3; DROP FUNCTION sp_vars_check_ret4; +DROP FUNCTION sp_vars_div_zero; ########################################################################### # diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index ffbbf56d3ac..95444a04ce5 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -6420,6 +6420,137 @@ SELECT bug21493(Member_ID) FROM t3| DROP FUNCTION bug21493| DROP TABLE t3,t4| +# +# Bug#20028 Function with select return no data +# + +--disable_warnings +drop function if exists func_20028_a| +drop function if exists func_20028_b| +drop function if exists func_20028_c| +drop procedure if exists proc_20028_a| +drop procedure if exists proc_20028_b| +drop procedure if exists proc_20028_c| +drop table if exists table_20028| +--enable_warnings + +create table table_20028 (i int)| + +SET @save_sql_mode=@@sql_mode| + +SET sql_mode=''| + +create function func_20028_a() returns integer +begin + declare temp integer; + select i into temp from table_20028 limit 1; + return ifnull(temp, 0); +end| + +create function func_20028_b() returns integer +begin + return func_20028_a(); +end| + +create function func_20028_c() returns integer +begin + declare div_zero integer; + set SQL_MODE='TRADITIONAL'; + select 1/0 into div_zero; + return div_zero; +end| + +create procedure proc_20028_a() +begin + declare temp integer; + select i into temp from table_20028 limit 1; +end| + +create procedure proc_20028_b() +begin + call proc_20028_a(); +end| + +create procedure proc_20028_c() +begin + declare div_zero integer; + set SQL_MODE='TRADITIONAL'; + select 1/0 into div_zero; +end| + +select func_20028_a()| +select func_20028_b()| +--error ER_DIVISION_BY_ZERO +select func_20028_c()| +call proc_20028_a()| +call proc_20028_b()| +--error ER_DIVISION_BY_ZERO +call proc_20028_c()| + +SET sql_mode='TRADITIONAL'| + +drop function func_20028_a| +drop function func_20028_b| +drop function func_20028_c| +drop procedure proc_20028_a| +drop procedure proc_20028_b| +drop procedure proc_20028_c| + +create function func_20028_a() returns integer +begin + declare temp integer; + select i into temp from table_20028 limit 1; + return ifnull(temp, 0); +end| + +create function func_20028_b() returns integer +begin + return func_20028_a(); +end| + +create function func_20028_c() returns integer +begin + declare div_zero integer; + set SQL_MODE=''; + select 1/0 into div_zero; + return div_zero; +end| + +create procedure proc_20028_a() +begin + declare temp integer; + select i into temp from table_20028 limit 1; +end| + +create procedure proc_20028_b() +begin + call proc_20028_a(); +end| + +create procedure proc_20028_c() +begin + declare div_zero integer; + set SQL_MODE=''; + select 1/0 into div_zero; +end| + +select func_20028_a()| +select func_20028_b()| +select func_20028_c()| +call proc_20028_a()| +call proc_20028_b()| +call proc_20028_c()| + +SET @@sql_mode=@save_sql_mode| + +drop function func_20028_a| +drop function func_20028_b| +drop function func_20028_c| +drop procedure proc_20028_a| +drop procedure proc_20028_b| +drop procedure proc_20028_c| +drop table table_20028| + # # Bug#21462 Stored procedures with no arguments require parenthesis # diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 6bd812d473e..92320648033 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -1274,7 +1274,6 @@ INSERT INTO t1 VALUES (@x); SELECT @x; SET @x=2; ---error ER_DIVISION_BY_ZERO UPDATE t1 SET i1 = @x; SELECT @x; @@ -1285,7 +1284,6 @@ INSERT INTO t1 VALUES (@x); SELECT @x; SET @x=4; ---error ER_DIVISION_BY_ZERO UPDATE t1 SET i1 = @x; SELECT @x; @@ -1420,6 +1418,67 @@ CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890 DROP TABLE t1; DROP TABLE t2; +# +# Bug#20028 Function with select return no data +# + +--disable_warnings +drop table if exists t1; +drop table if exists t2; +drop table if exists t3; +drop table if exists t4; +--enable_warnings + +SET @save_sql_mode=@@sql_mode; + +delimiter |; +SET sql_mode='TRADITIONAL'| +create table t1 (id int(10) not null primary key, v int(10) )| +create table t2 (id int(10) not null primary key, v int(10) )| +create table t3 (id int(10) not null primary key, v int(10) )| +create table t4 (c int)| + +create trigger t4_bi before insert on t4 for each row set @t4_bi_called:=1| +create trigger t4_bu before update on t4 for each row set @t4_bu_called:=1| + +insert into t1 values(10, 10)| +set @a:=1/0| +select 1/0 from t1| + +create trigger t1_bi before insert on t1 for each row set @a:=1/0| + +insert into t1 values(20, 20)| + +drop trigger t1_bi| +create trigger t1_bi before insert on t1 for each row +begin + insert into t2 values (new.id, new.v); + update t2 set v=v+1 where id= new.id; + replace t3 values (new.id, 0); + update t2, t3 set t2.v=new.v, t3.v=new.v where t2.id=t3.id; + create temporary table t5 select * from t1; + delete from t5; + insert into t5 select * from t1; + insert into t4 values (0); + set @check= (select count(*) from t5); + update t4 set c= @check; + drop temporary table t5; + + set @a:=1/0; +end| + +set @check=0, @t4_bi_called=0, @t4_bu_called=0| +insert into t1 values(30, 30)| +select @check, @t4_bi_called, @t4_bu_called| + +delimiter ;| + +SET @@sql_mode=@save_sql_mode; + +drop table t1; +drop table t2; +drop table t3; +drop table t4; # # Bug#20670 "UPDATE using key and invoking trigger that modifies diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 9761de625be..a06bfe28a6f 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -991,8 +991,7 @@ sp_head::execute(THD *thd) save_sql_mode= thd->variables.sql_mode; thd->variables.sql_mode= m_sql_mode; save_abort_on_warning= thd->abort_on_warning; - thd->abort_on_warning= - (m_sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)); + thd->abort_on_warning= 0; /* It is also more efficient to save/restore current thd->lex once when From 1a793de9e40179845b98454e9f1333464ef54e62 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Oct 2006 15:47:52 +0400 Subject: [PATCH 21/47] Fix for bug#15228 "'invalid access to non-static data member' warnings in sql_trigger.cc and sql_view.cc". According to the current version of C++ standard offsetof() macro can't be used for non-POD types. So warnings were emitted when we tried to use this macro for TABLE_LIST and Table_triggers_list classes. Note that despite of these warnings it was probably safe thing to do. This fix tries to circumvent this limitation by implementing custom version of offsetof() macro to be used with these classes. This hack should go away once we will refactor File_parser class. Alternative approaches such as disabling this warning for sql_trigger.cc/sql_view.cc or for the whole server were considered less explicit. Also I was unable to find a way to disable particular warning for particular _part_ of file in GCC. sql/parse_file.h: Introduced auxillary macro which can be used instead of offsetof() to get offsets of members in class for non-POD types without getting warnings (assuming that all instances of the class has same offsets for same members). sql/sql_trigger.cc: Use my_offsetof() macro instead of standard offsetof() macro with Table_triggers_list class in order to avoid warnings (offsetof() cannot be used for non-POD types according to the standard). sql/sql_view.cc: Use my_offsetof() macro instead of standard offsetof() macro with TABLE_LIST class in order to avoid warnings (offsetof() cannot be used for non-POD types according to the standard). --- sql/parse_file.h | 16 ++++++++++++++++ sql/sql_trigger.cc | 8 ++++---- sql/sql_view.cc | 24 ++++++++++++------------ 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/sql/parse_file.h b/sql/parse_file.h index 33871588e11..5fb65b4c7ec 100644 --- a/sql/parse_file.h +++ b/sql/parse_file.h @@ -107,4 +107,20 @@ public: bool bad_format_errors); }; + +/* + Custom version of standard offsetof() macro which can be used to get + offsets of members in class for non-POD types (according to the current + version of C++ standard offsetof() macro can't be used in such cases and + attempt to do so causes warnings to be emitted, OTOH in many cases it is + still OK to assume that all instances of the class has the same offsets + for the same members). + + This is temporary solution which should be removed once File_parser class + and related routines are refactored. +*/ + +#define my_offsetof(TYPE, MEMBER) \ + ((size_t)((char *)&(((TYPE *)0x10)->MEMBER) - (char*)0x10)) + #endif /* _PARSE_FILE_H_ */ diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 6bb50d602c3..c6d85934820 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -36,17 +36,17 @@ static File_option triggers_file_parameters[]= { { {(char *) STRING_WITH_LEN("triggers") }, - offsetof(class Table_triggers_list, definitions_list), + my_offsetof(class Table_triggers_list, definitions_list), FILE_OPTIONS_STRLIST }, { {(char *) STRING_WITH_LEN("sql_modes") }, - offsetof(class Table_triggers_list, definition_modes_list), + my_offsetof(class Table_triggers_list, definition_modes_list), FILE_OPTIONS_ULLLIST }, { {(char *) STRING_WITH_LEN("definers") }, - offsetof(class Table_triggers_list, definers_list), + my_offsetof(class Table_triggers_list, definers_list), FILE_OPTIONS_STRLIST }, { { 0, 0 }, 0, FILE_OPTIONS_STRING } @@ -55,7 +55,7 @@ static File_option triggers_file_parameters[]= File_option sql_modes_parameters= { {(char*) STRING_WITH_LEN("sql_modes") }, - offsetof(class Table_triggers_list, definition_modes_list), + my_offsetof(class Table_triggers_list, definition_modes_list), FILE_OPTIONS_ULLLIST }; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 4e2b48d9faf..12fa8cfc06a 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -582,40 +582,40 @@ static const int num_view_backups= 3; */ static File_option view_parameters[]= {{{(char*) STRING_WITH_LEN("query")}, - offsetof(TABLE_LIST, query), + my_offsetof(TABLE_LIST, query), FILE_OPTIONS_ESTRING}, {{(char*) STRING_WITH_LEN("md5")}, - offsetof(TABLE_LIST, md5), + my_offsetof(TABLE_LIST, md5), FILE_OPTIONS_STRING}, {{(char*) STRING_WITH_LEN("updatable")}, - offsetof(TABLE_LIST, updatable_view), + my_offsetof(TABLE_LIST, updatable_view), FILE_OPTIONS_ULONGLONG}, {{(char*) STRING_WITH_LEN("algorithm")}, - offsetof(TABLE_LIST, algorithm), + my_offsetof(TABLE_LIST, algorithm), FILE_OPTIONS_ULONGLONG}, {{(char*) STRING_WITH_LEN("definer_user")}, - offsetof(TABLE_LIST, definer.user), + my_offsetof(TABLE_LIST, definer.user), FILE_OPTIONS_STRING}, {{(char*) STRING_WITH_LEN("definer_host")}, - offsetof(TABLE_LIST, definer.host), + my_offsetof(TABLE_LIST, definer.host), FILE_OPTIONS_STRING}, {{(char*) STRING_WITH_LEN("suid")}, - offsetof(TABLE_LIST, view_suid), + my_offsetof(TABLE_LIST, view_suid), FILE_OPTIONS_ULONGLONG}, {{(char*) STRING_WITH_LEN("with_check_option")}, - offsetof(TABLE_LIST, with_check), + my_offsetof(TABLE_LIST, with_check), FILE_OPTIONS_ULONGLONG}, {{(char*) STRING_WITH_LEN("revision")}, - offsetof(TABLE_LIST, revision), + my_offsetof(TABLE_LIST, revision), FILE_OPTIONS_REV}, {{(char*) STRING_WITH_LEN("timestamp")}, - offsetof(TABLE_LIST, timestamp), + my_offsetof(TABLE_LIST, timestamp), FILE_OPTIONS_TIMESTAMP}, {{(char*)STRING_WITH_LEN("create-version")}, - offsetof(TABLE_LIST, file_version), + my_offsetof(TABLE_LIST, file_version), FILE_OPTIONS_ULONGLONG}, {{(char*) STRING_WITH_LEN("source")}, - offsetof(TABLE_LIST, source), + my_offsetof(TABLE_LIST, source), FILE_OPTIONS_ESTRING}, {{NullS, 0}, 0, FILE_OPTIONS_STRING} From 8db4dc3f91dfbe03181e63ed45bdf35a5d65aeb0 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Oct 2006 22:26:40 +0400 Subject: [PATCH 22/47] Instance Manager polishing. server-tools/instance-manager/guardian.cc: 1. Removed unused stop_instances_arg from request_shutdown() and stop_instances() methods. 2. Changed log-output statements so that instance name is passed correctly (char *, not LEX_STRING) server-tools/instance-manager/guardian.h: Removed unused stop_instances_arg from request_shutdown() and stop_instances() methods. server-tools/instance-manager/instance.cc: Removed unused stop_instances_arg from request_shutdown() and stop_instances() methods. server-tools/instance-manager/listener.cc: Be more verbose in log. server-tools/instance-manager/manager.cc: Removed unused stop_instances argument. --- server-tools/instance-manager/guardian.cc | 72 +++++++++-------------- server-tools/instance-manager/guardian.h | 4 +- server-tools/instance-manager/instance.cc | 23 ++++---- server-tools/instance-manager/listener.cc | 4 +- server-tools/instance-manager/manager.cc | 5 +- 5 files changed, 47 insertions(+), 61 deletions(-) diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc index e2142c97f33..3587a599160 100644 --- a/server-tools/instance-manager/guardian.cc +++ b/server-tools/instance-manager/guardian.cc @@ -66,11 +66,11 @@ Guardian_thread::~Guardian_thread() } -void Guardian_thread::request_shutdown(bool stop_instances_arg) +void Guardian_thread::request_shutdown() { pthread_mutex_lock(&LOCK_guardian); /* stop instances or just clean up Guardian repository */ - stop_instances(stop_instances_arg); + stop_instances(); shutdown_requested= TRUE; pthread_mutex_unlock(&LOCK_guardian); } @@ -118,11 +118,11 @@ void Guardian_thread::process_instance(Instance *instance, { /* Pid file not created yet, don't go to STARTED state yet */ } - else + else if (current_node->state != STARTED) { /* clear status fields */ - log_info("guardian: instance %s is running, set state to STARTED", - instance->options.instance_name); + log_info("guardian: instance '%s' is running, set state to STARTED.", + (const char *) instance->options.instance_name); current_node->restart_counter= 0; current_node->crash_moment= 0; current_node->state= STARTED; @@ -132,8 +132,8 @@ void Guardian_thread::process_instance(Instance *instance, { switch (current_node->state) { case NOT_STARTED: - log_info("guardian: starting instance %s", - instance->options.instance_name); + log_info("guardian: starting instance '%s'...", + (const char *) instance->options.instance_name); /* NOTE, set state to STARTING _before_ start() is called */ current_node->state= STARTING; @@ -157,8 +157,8 @@ void Guardian_thread::process_instance(Instance *instance, if (instance->is_crashed()) { instance->start(); - log_info("guardian: starting instance %s", - instance->options.instance_name); + log_info("guardian: starting instance '%s'...", + (const char *) instance->options.instance_name); } } else @@ -175,8 +175,8 @@ void Guardian_thread::process_instance(Instance *instance, instance->start(); current_node->last_checked= current_time; current_node->restart_counter++; - log_info("guardian: restarting instance %s", - instance->options.instance_name); + log_info("guardian: restarting instance '%s'...", + (const char *) instance->options.instance_name); } } else @@ -382,12 +382,11 @@ int Guardian_thread::stop_guard(Instance *instance) SYNOPSYS stop_instances() - stop_instances_arg whether we should stop instances at shutdown DESCRIPTION Loops through the guarded_instances list and prepares them for shutdown. - If stop_instances was requested, we need to issue a stop command and change - the state accordingly. Otherwise we simply delete an entry. + For each instance we issue a stop command and change the state + accordingly. NOTE Guardian object should be locked by the calling function. @@ -397,42 +396,29 @@ int Guardian_thread::stop_guard(Instance *instance) 1 - error occured */ -int Guardian_thread::stop_instances(bool stop_instances_arg) +int Guardian_thread::stop_instances() { LIST *node; node= guarded_instances; while (node != NULL) { - if (!stop_instances_arg) + GUARD_NODE *current_node= (GUARD_NODE *) node->data; + /* + If instance is running or was running (and now probably hanging), + request stop. + */ + if (current_node->instance->is_running() || + (current_node->state == STARTED)) { - /* just forget about an instance */ - guarded_instances= list_delete(guarded_instances, node); - /* - This should still work fine, as we have only removed the - node from the list. The pointer to the next one is still valid - */ - node= node->next; + current_node->state= STOPPING; + current_node->last_checked= time(NULL); } else - { - GUARD_NODE *current_node= (GUARD_NODE *) node->data; - /* - If instance is running or was running (and now probably hanging), - request stop. - */ - if (current_node->instance->is_running() || - (current_node->state == STARTED)) - { - current_node->state= STOPPING; - current_node->last_checked= time(NULL); - } - else - /* otherwise remove it from the list */ - guarded_instances= list_delete(guarded_instances, node); - /* But try to kill it anyway. Just in case */ - current_node->instance->kill_instance(SIGTERM); - node= node->next; - } + /* otherwise remove it from the list */ + guarded_instances= list_delete(guarded_instances, node); + /* But try to kill it anyway. Just in case */ + current_node->instance->kill_instance(SIGTERM); + node= node->next; } return 0; } @@ -440,7 +426,7 @@ int Guardian_thread::stop_instances(bool stop_instances_arg) void Guardian_thread::lock() { - pthread_mutex_lock(&LOCK_guardian); + pthread_mutex_lock(&LOCK_guardian); } diff --git a/server-tools/instance-manager/guardian.h b/server-tools/instance-manager/guardian.h index 16b4c373c91..f1c54262c12 100644 --- a/server-tools/instance-manager/guardian.h +++ b/server-tools/instance-manager/guardian.h @@ -89,7 +89,7 @@ public: /* Initialize or refresh the list of guarded instances */ int init(); /* Request guardian shutdown. Stop instances if needed */ - void request_shutdown(bool stop_instances); + void request_shutdown(); /* Start instance protection */ int guard(Instance *instance, bool nolock= FALSE); /* Stop instance protection */ @@ -104,7 +104,7 @@ public: private: /* Prepares Guardian shutdown. Stops instances is needed */ - int stop_instances(bool stop_instances_arg); + int stop_instances(); /* check instance state and act accordingly */ void process_instance(Instance *instance, GUARD_NODE *current_node, LIST **guarded_instances, LIST *elem); diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index b792d132da0..daa8082ef2f 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -156,8 +156,8 @@ static int start_process(Instance_options *instance_options, /* exec never returns */ exit(1); case -1: - log_info("cannot create a new process to start instance %s", - instance_options->instance_name); + log_info("cannot create a new process to start instance '%s'.", + (const char *) instance_options->instance_name); return 1; } return 0; @@ -252,7 +252,8 @@ static void start_and_monitor_instance(Instance_options *old_instance_options, MAX_INSTANCE_NAME_LEN - 1); instance_name_len= old_instance_options->instance_name_len; - log_info("starting instance %s", instance_name_buff); + log_info("starting instance '%s'...", + (const char *) instance_name_buff); if (start_process(old_instance_options, &process_info)) { @@ -286,9 +287,9 @@ void Instance::remove_pid() int pid; if ((pid= options.get_pid()) != 0) /* check the pidfile */ if (options.unlink_pidfile()) /* remove stalled pidfile */ - log_error("cannot remove pidfile for instance %i, this might be \ + log_error("cannot remove pidfile for instance '%s', this might be \ since IM lacks permmissions or hasn't found the pidifle", - options.instance_name); + (const char *) options.instance_name); } @@ -435,9 +436,9 @@ bool Instance::is_running() We have successfully connected to the server using fake username/password. Write a warning to the logfile. */ - log_info("The Instance Manager was able to log into you server \ - with faked compiled-in password while checking server status. \ - Looks like something is wrong."); + log_info("The Instance Manager was able to log into you server " + "with faked compiled-in password while checking server status. " + "Looks like something is wrong."); pthread_mutex_unlock(&LOCK_instance); return_val= TRUE; /* server is alive */ } @@ -577,10 +578,10 @@ void Instance::kill_instance(int signum) /* Kill suceeded */ if (signum == SIGKILL) /* really killed instance with SIGKILL */ { - log_error("The instance %s is being stopped forcibly. Normally" \ - "it should not happen. Probably the instance has been" \ + log_error("The instance '%s' is being stopped forcibly. Normally" + "it should not happen. Probably the instance has been" "hanging. You should also check your IM setup", - options.instance_name); + (const char *) options.instance_name); /* After sucessful hard kill the pidfile need to be removed */ options.unlink_pidfile(); } diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc index 58a4093dd05..3f60c2cc74a 100644 --- a/server-tools/instance-manager/listener.cc +++ b/server-tools/instance-manager/listener.cc @@ -280,7 +280,7 @@ int Listener_thread::create_tcp_socket() FD_SET(ip_socket, &read_fds); sockets[num_sockets++]= ip_socket; - log_info("accepting connections on ip socket"); + log_info("accepting connections on ip socket (port: %d)", (int) im_port); return 0; } @@ -334,7 +334,7 @@ create_unix_socket(struct sockaddr_un &unix_socket_address) /* make sure that instances won't be listening our sockets */ set_no_inherit(unix_socket); - log_info("accepting connections on unix socket %s", + log_info("accepting connections on unix socket '%s'", unix_socket_address.sun_path); sockets[num_sockets++]= unix_socket; FD_SET(unix_socket, &read_fds); diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc index 6f28c39da77..ec22e5c4fbb 100644 --- a/server-tools/instance-manager/manager.cc +++ b/server-tools/instance-manager/manager.cc @@ -110,7 +110,7 @@ void stop_all(Guardian_thread *guardian, Thread_registry *registry) Let guardian thread know that it should break it's processing cycle, once it wakes up. */ - guardian->request_shutdown(true); + guardian->request_shutdown(); /* wake guardian */ pthread_cond_signal(&guardian->COND_guardian); /* stop all threads */ @@ -282,8 +282,7 @@ void manager(const Options &options) { if (!guardian_thread.is_stopped()) { - bool stop_instances= true; - guardian_thread.request_shutdown(stop_instances); + guardian_thread.request_shutdown(); pthread_cond_signal(&guardian_thread.COND_guardian); } else From a71a524eeb5d70414f43d2708a47d729f2ad6640 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Oct 2006 17:17:24 -0400 Subject: [PATCH 23/47] Bug #23427: incompatible ABI change in 5.0.26? Revert 1 June change enough to restore ABI compatibility with previous versions. include/mysql.h: Revert patch that breaks ABI compatibility libmysqld/lib_sql.cc: Remove useless assignment. --- include/mysql.h | 6 ------ libmysqld/lib_sql.cc | 1 - 2 files changed, 7 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index ae4a8222c5b..8ef3f1273ec 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -293,12 +293,6 @@ typedef struct st_mysql /* needed for embedded server - no net buffer to store the 'info' */ char *info_buffer; #endif - /* - In embedded server it points to the statement that is processed - in the current query. We store some results directly in statement - fields then. - */ - struct st_mysql_stmt *current_stmt; } MYSQL; typedef struct st_mysql_res { diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 40966be46a5..98c75dfe719 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -100,7 +100,6 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, mysql->affected_rows= ~(my_ulonglong) 0; mysql->field_count= 0; net->last_errno= 0; - mysql->current_stmt= stmt; thd->store_globals(); // Fix if more than one connect /* From 644dcbf256de1150a49891d12a3a79e642c439aa Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 21 Oct 2006 00:57:08 +0200 Subject: [PATCH 24/47] make_win_bin_dist: Copy udf examples and raid.h Create target "include" directory before copying files to it CMakeLists.txt: Only compile in bdb if configured configure.in: Raised version number to 5.0.27 scripts/make_win_bin_dist: Copy udf examples and raid.h Create target "include" directory before copying files to it CMakeLists.txt: Only compile in bdb if configured configure.in: Raised version number to 5.0.27 --- CMakeLists.txt | 4 +++- configure.in | 4 ++-- scripts/make_win_bin_dist | 15 +++++++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd780ec6a13..f202c15c200 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,7 +123,9 @@ ADD_SUBDIRECTORY(heap) ADD_SUBDIRECTORY(myisam) ADD_SUBDIRECTORY(myisammrg) ADD_SUBDIRECTORY(client) -ADD_SUBDIRECTORY(bdb) +IF(WITH_BERKELEY_STORAGE_ENGINE) + ADD_SUBDIRECTORY(bdb) +ENDIF(WITH_BERKELEY_STORAGE_ENGINE) ADD_SUBDIRECTORY(innobase) ADD_SUBDIRECTORY(sql) ADD_SUBDIRECTORY(sql/examples) diff --git a/configure.in b/configure.in index 7bc4fe77675..55da1dfb241 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.26) +AM_INIT_AUTOMAKE(mysql, 5.0.27) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -19,7 +19,7 @@ SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=26 +NDB_VERSION_BUILD=27 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? diff --git a/scripts/make_win_bin_dist b/scripts/make_win_bin_dist index cc75245e5d9..38e7ab88f22 100755 --- a/scripts/make_win_bin_dist +++ b/scripts/make_win_bin_dist @@ -144,8 +144,6 @@ fi # Copy data directory, readme files etc # ---------------------------------------------------------------------- -cp COPYING EXCEPTIONS-CLIENT $DESTDIR/ - # FIXME is there ever a data directory to copy? if [ -d win/data ] ; then cp -pR win/data $DESTDIR/data @@ -159,9 +157,13 @@ mkdir $DESTDIR/Docs cp Docs/INSTALL-BINARY $DESTDIR/Docs/ cp Docs/manual.chm $DESTDIR/Docs/ || /bin/true cp ChangeLog $DESTDIR/Docs/ || /bin/true -cp COPYING $DESTDIR/Docs/ cp support-files/my-*.ini $DESTDIR/ +if [ -f COPYING ] ; then + cp COPYING EXCEPTIONS-CLIENT $DESTDIR/ + cp COPYING $DESTDIR/Docs/ +fi + # ---------------------------------------------------------------------- # These will be filled in when we enable embedded. Note that if no # argument is given, it is copied if exists, else a check is done. @@ -170,7 +172,8 @@ cp support-files/my-*.ini $DESTDIR/ copy_embedded() { mkdir -p $DESTDIR/Embedded/DLL/release \ - $DESTDIR/Embedded/static/release + $DESTDIR/Embedded/static/release \ + $DESTDIR/include cp libmysqld/libmysqld.def $DESTDIR/include/ cp libmysqld/$TARGET/mysqlserver.lib $DESTDIR/Embedded/static/release/ cp libmysqld/$TARGET/libmysqld.dll $DESTDIR/Embedded/DLL/release/ @@ -211,6 +214,9 @@ fi mkdir -p $DESTDIR/examples/tests cp tests/*.res tests/*.tst tests/*.pl tests/*.c $DESTDIR/examples/tests/ +mkdir -p $DESTDIR/examples/udf_example +cp sql/udf_example.def sql/udf_example.vcproj sql/udf_example.c $DESTDIR/examples/udf_example/ + # ---------------------------------------------------------------------- # FIXME why not copy it all in "include"?! # ---------------------------------------------------------------------- @@ -228,6 +234,7 @@ cp include/conf*.h \ include/m_string.h \ include/m_ctype.h \ include/my_global.h \ + include/raid.h \ include/typelib.h $DESTDIR/include/ cp libmysql/libmysql.def $DESTDIR/include/ From 71fee03efe804e5000195cbc33e9d1c4ed5e62c0 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 21 Oct 2006 01:22:16 +0200 Subject: [PATCH 25/47] configure.in: Raised version number to 5.0.28 configure.in: Raised version number to 5.0.28 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 55da1dfb241..18c08722fff 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.27) +AM_INIT_AUTOMAKE(mysql, 5.0.28) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -19,7 +19,7 @@ SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=27 +NDB_VERSION_BUILD=28 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 6831ea7da790dafdaacb0c5bf6bae0cfb268d3e2 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Oct 2006 13:55:29 +0400 Subject: [PATCH 26/47] A post-merge fix. --- mysql-test/r/view.result | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index e13ec2165b9..6f53a56a4ce 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2968,6 +2968,8 @@ INSERT INTO t1 VALUES (1); CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1); UPDATE t1 SET i= f1(); DROP FUNCTION f1; +DROP VIEW v1; +DROP TABLE t1; CREATE TABLE t1(id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, val INT UNSIGNED NOT NULL); CREATE VIEW v1 AS SELECT id, val FROM t1 WHERE val >= 1 AND val <= 5 WITH CHECK OPTION; INSERT INTO v1 (val) VALUES (2); From 66b872805cbd542c6012eef7141443d95a697f7d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Oct 2006 20:08:00 +0400 Subject: [PATCH 27/47] Post-merge fixes. mysql-test/r/sp.result: Update results. mysql-test/r/view.result: Update results. server-tools/instance-manager/guardian.cc: Post-merge fixes (instance_name is a LEX_STRING). server-tools/instance-manager/instance.cc: Post-merge fixes (instance_name is a LEX_STRING). --- mysql-test/r/sp.result | 156 ++++++++++++++++++++++ mysql-test/r/view.result | 2 + server-tools/instance-manager/guardian.cc | 10 +- server-tools/instance-manager/instance.cc | 10 +- 4 files changed, 168 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 79e32b921cc..aeccfd9c951 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5470,5 +5470,161 @@ CAD CHF DROP FUNCTION bug21493| DROP TABLE t3,t4| +drop function if exists func_20028_a| +drop function if exists func_20028_b| +drop function if exists func_20028_c| +drop procedure if exists proc_20028_a| +drop procedure if exists proc_20028_b| +drop procedure if exists proc_20028_c| +drop table if exists table_20028| +create table table_20028 (i int)| +SET @save_sql_mode=@@sql_mode| +SET sql_mode=''| +create function func_20028_a() returns integer +begin +declare temp integer; +select i into temp from table_20028 limit 1; +return ifnull(temp, 0); +end| +create function func_20028_b() returns integer +begin +return func_20028_a(); +end| +create function func_20028_c() returns integer +begin +declare div_zero integer; +set SQL_MODE='TRADITIONAL'; +select 1/0 into div_zero; +return div_zero; +end| +create procedure proc_20028_a() +begin +declare temp integer; +select i into temp from table_20028 limit 1; +end| +create procedure proc_20028_b() +begin +call proc_20028_a(); +end| +create procedure proc_20028_c() +begin +declare div_zero integer; +set SQL_MODE='TRADITIONAL'; +select 1/0 into div_zero; +end| +select func_20028_a()| +func_20028_a() +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +select func_20028_b()| +func_20028_b() +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +select func_20028_c()| +ERROR 22012: Division by 0 +call proc_20028_a()| +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +call proc_20028_b()| +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +call proc_20028_c()| +ERROR 22012: Division by 0 +SET sql_mode='TRADITIONAL'| +drop function func_20028_a| +drop function func_20028_b| +drop function func_20028_c| +drop procedure proc_20028_a| +drop procedure proc_20028_b| +drop procedure proc_20028_c| +create function func_20028_a() returns integer +begin +declare temp integer; +select i into temp from table_20028 limit 1; +return ifnull(temp, 0); +end| +create function func_20028_b() returns integer +begin +return func_20028_a(); +end| +create function func_20028_c() returns integer +begin +declare div_zero integer; +set SQL_MODE=''; +select 1/0 into div_zero; +return div_zero; +end| +create procedure proc_20028_a() +begin +declare temp integer; +select i into temp from table_20028 limit 1; +end| +create procedure proc_20028_b() +begin +call proc_20028_a(); +end| +create procedure proc_20028_c() +begin +declare div_zero integer; +set SQL_MODE=''; +select 1/0 into div_zero; +end| +select func_20028_a()| +func_20028_a() +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +select func_20028_b()| +func_20028_b() +0 +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +select func_20028_c()| +func_20028_c() +NULL +call proc_20028_a()| +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +call proc_20028_b()| +Warnings: +Warning 1329 No data - zero rows fetched, selected, or processed +call proc_20028_c()| +SET @@sql_mode=@save_sql_mode| +drop function func_20028_a| +drop function func_20028_b| +drop function func_20028_c| +drop procedure proc_20028_a| +drop procedure proc_20028_b| +drop procedure proc_20028_c| +drop table table_20028| +drop procedure if exists proc_21462_a| +drop procedure if exists proc_21462_b| +create procedure proc_21462_a() +begin +select "Called A"; +end| +create procedure proc_21462_b(x int) +begin +select "Called B"; +end| +call proc_21462_a| +Called A +Called A +call proc_21462_a()| +Called A +Called A +call proc_21462_a(1)| +ERROR 42000: Incorrect number of arguments for PROCEDURE test.proc_21462_a; expected 0, got 1 +call proc_21462_b| +ERROR 42000: Incorrect number of arguments for PROCEDURE test.proc_21462_b; expected 1, got 0 +call proc_21462_b()| +ERROR 42000: Incorrect number of arguments for PROCEDURE test.proc_21462_b; expected 1, got 0 +call proc_21462_b(1)| +Called B +Called B +drop procedure proc_21462_a| +drop procedure proc_21462_b| End of 5.0 tests drop table t1,t2; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index d58acfeafa5..7c467749ee6 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2968,6 +2968,8 @@ INSERT INTO t1 VALUES (1); CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1); UPDATE t1 SET i= f1(); DROP FUNCTION f1; +DROP VIEW v1; +DROP TABLE t1; CREATE TABLE t1(id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, val INT UNSIGNED NOT NULL); CREATE VIEW v1 AS SELECT id, val FROM t1 WHERE val >= 1 AND val <= 5 WITH CHECK OPTION; INSERT INTO v1 (val) VALUES (2); diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc index 9fc3a6583ef..af57f1decbc 100644 --- a/server-tools/instance-manager/guardian.cc +++ b/server-tools/instance-manager/guardian.cc @@ -158,7 +158,7 @@ void Guardian_thread::process_instance(Instance *instance, { /* clear status fields */ log_info("guardian: instance '%s' is running, set state to STARTED.", - (const char *) instance->options.instance_name); + (const char *) instance->options.instance_name.str); current_node->restart_counter= 0; current_node->crash_moment= 0; current_node->state= STARTED; @@ -169,7 +169,7 @@ void Guardian_thread::process_instance(Instance *instance, switch (current_node->state) { case NOT_STARTED: log_info("guardian: starting instance '%s'...", - (const char *) instance->options.instance_name); + (const char *) instance->options.instance_name.str); /* NOTE, set state to STARTING _before_ start() is called */ current_node->state= STARTING; @@ -194,7 +194,7 @@ void Guardian_thread::process_instance(Instance *instance, { instance->start(); log_info("guardian: starting instance '%s'...", - (const char *) instance->options.instance_name); + (const char *) instance->options.instance_name.str); } } else @@ -212,13 +212,13 @@ void Guardian_thread::process_instance(Instance *instance, current_node->last_checked= current_time; current_node->restart_counter++; log_info("guardian: restarting instance '%s'...", - (const char *) instance->options.instance_name); + (const char *) instance->options.instance_name.str); } } else { log_info("guardian: cannot start instance %s. Abandoning attempts " - "to (re)start it", instance->options.instance_name); + "to (re)start it", instance->options.instance_name.str); current_node->state= CRASHED_AND_ABANDONED; } } diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index c4bd1e211e1..1dfe6167020 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -166,7 +166,7 @@ static int start_process(Instance_options *instance_options, exit(1); case -1: log_info("cannot create a new process to start instance '%s'.", - (const char *) instance_options->instance_name); + (const char *) instance_options->instance_name.str); return 1; } return 0; @@ -312,9 +312,9 @@ void Instance::remove_pid() int pid; if ((pid= options.get_pid()) != 0) /* check the pidfile */ if (options.unlink_pidfile()) /* remove stalled pidfile */ - log_error("cannot remove pidfile for instance '%s', this might be \ - since IM lacks permmissions or hasn't found the pidifle", - (const char *) options.instance_name); + log_error("cannot remove pidfile for instance '%s', this might be " + "since IM lacks permmissions or hasn't found the pidifle", + (const char *) options.instance_name.str); } @@ -620,7 +620,7 @@ void Instance::kill_instance(int signum) log_error("The instance '%s' is being stopped forcibly. Normally" "it should not happen. Probably the instance has been" "hanging. You should also check your IM setup", - (const char *) options.instance_name); + (const char *) options.instance_name.str); /* After sucessful hard kill the pidfile need to be removed */ options.unlink_pidfile(); } From 69c7200219dd2010de7ca33d89432aff4fbd9e3a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Oct 2006 10:57:17 +0200 Subject: [PATCH 28/47] Bump version number to 5.0.29, as 28 will be based directly on 27. --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 18c08722fff..7c2d3e77b27 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.28) +AM_INIT_AUTOMAKE(mysql, 5.0.29) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -19,7 +19,7 @@ SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=28 +NDB_VERSION_BUILD=29 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From aeec459369c951b66a65fa2238dd0e4185ab2aa3 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Oct 2006 18:23:16 +0400 Subject: [PATCH 29/47] Fix for BUG#17486: IM: race condition on exit. The problem was that IM stoped guarded instances on shutdown, but didn't wait for them to stop. The fix is to wait for guarded instances to stop before exitting from the main thread. The idea is that Instance-monitoring thread should add itself to Thread_registry so that it will be taken into account on shutdown. However, Thread_registry should not signal it on shutdown in order to not interrupt wait()/waitpid(). server-tools/instance-manager/guardian.cc: Be more verbose. server-tools/instance-manager/instance.cc: Register mysqld-monitoring thread in Thread_registry. server-tools/instance-manager/instance.h: Add reference to Thread_registry. server-tools/instance-manager/instance_map.cc: Pass Thread_registry reference to Instance. server-tools/instance-manager/instance_map.h: Add reference to Thread_registry. server-tools/instance-manager/listener.cc: Be more verbose. server-tools/instance-manager/manager.cc: Be more verbose. server-tools/instance-manager/mysql_connection.cc: Eliminate type-conversion warnings. server-tools/instance-manager/thread_registry.cc: Be more verbose. server-tools/instance-manager/thread_registry.h: Eliminate copy&paste, make impl-specific constructor private. --- server-tools/instance-manager/guardian.cc | 8 +- server-tools/instance-manager/instance.cc | 43 +++++-- server-tools/instance-manager/instance.h | 4 +- server-tools/instance-manager/instance_map.cc | 10 +- server-tools/instance-manager/instance_map.h | 6 +- server-tools/instance-manager/listener.cc | 22 ++-- server-tools/instance-manager/manager.cc | 23 +++- .../instance-manager/mysql_connection.cc | 29 +++-- .../instance-manager/thread_registry.cc | 117 +++++++++++++----- .../instance-manager/thread_registry.h | 12 +- 10 files changed, 203 insertions(+), 71 deletions(-) diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc index af57f1decbc..03bfadd8571 100644 --- a/server-tools/instance-manager/guardian.cc +++ b/server-tools/instance-manager/guardian.cc @@ -74,7 +74,7 @@ Guardian_thread::Guardian_thread(Thread_registry &thread_registry_arg, uint monitoring_interval_arg) : Guardian_thread_args(thread_registry_arg, instance_map_arg, monitoring_interval_arg), - thread_info(pthread_self()), guarded_instances(0) + thread_info(pthread_self(), TRUE), guarded_instances(0) { pthread_mutex_init(&LOCK_guardian, 0); pthread_cond_init(&COND_guardian, 0); @@ -250,6 +250,8 @@ void Guardian_thread::run() LIST *node; struct timespec timeout; + log_info("Guardian: started."); + thread_registry.register_thread(&thread_info); my_thread_init(); @@ -277,12 +279,16 @@ void Guardian_thread::run() &LOCK_guardian, &timeout); } + log_info("Guardian: stopped."); + stopped= TRUE; pthread_mutex_unlock(&LOCK_guardian); /* now, when the Guardian is stopped we can stop the IM */ thread_registry.unregister_thread(&thread_info); thread_registry.request_shutdown(); my_thread_end(); + + log_info("Guardian: finished."); } diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index 1dfe6167020..3927363a3e5 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -34,6 +34,7 @@ #include "mysql_manager_error.h" #include "portability.h" #include "priv.h" +#include "thread_registry.h" const LEX_STRING @@ -44,7 +45,8 @@ static const int INSTANCE_NAME_PREFIX_LEN= Instance::DFLT_INSTANCE_NAME.length; static void start_and_monitor_instance(Instance_options *old_instance_options, - Instance_map *instance_map); + Instance_map *instance_map, + Thread_registry *thread_registry); #ifndef __WIN__ typedef pid_t My_process_info; @@ -63,7 +65,8 @@ pthread_handler_t proxy(void *arg) { Instance *instance= (Instance *) arg; start_and_monitor_instance(&instance->options, - instance->get_map()); + instance->get_map(), + &instance->thread_registry); return 0; } @@ -99,6 +102,7 @@ static int wait_process(My_process_info *pi) thread, but we don't know this one). Or we could use waitpid(), but couldn't use wait(), because it could return in any wait() in the program. */ + if (linuxthreads) wait(NULL); /* LinuxThreads were detected */ else @@ -239,11 +243,28 @@ static int start_process(Instance_options *instance_options, */ static void start_and_monitor_instance(Instance_options *old_instance_options, - Instance_map *instance_map) + Instance_map *instance_map, + Thread_registry *thread_registry) { Instance_name instance_name(&old_instance_options->instance_name); Instance *current_instance; My_process_info process_info; + Thread_info thread_info(pthread_self(), FALSE); + + log_info("Monitoring thread (instance: '%s'): started.", + (const char *) instance_name.get_c_str()); + + if (!old_instance_options->nonguarded) + { + /* + Register thread in Thread_registry to wait for it to stop on shutdown + only if instance is nuarded. If instance is guarded, the thread will not + finish, because nonguarded instances are not stopped on shutdown. + */ + + thread_registry->register_thread(&thread_info); + my_thread_init(); + } /* Lock instance map to guarantee that no instances are deleted during @@ -280,7 +301,14 @@ static void start_and_monitor_instance(Instance_options *old_instance_options, instance_map->unlock(); - return; + if (!old_instance_options->nonguarded) + { + thread_registry->unregister_thread(&thread_info); + my_thread_end(); + } + + log_info("Monitoring thread (instance: '%s'): finished.", + (const char *) instance_name.get_c_str()); } @@ -343,10 +371,6 @@ int Instance::start() { remove_pid(); - /* - No need to monitor this thread in the Thread_registry, as all - instances are to be stopped during shutdown. - */ pthread_t proxy_thd_id; pthread_attr_t proxy_thd_attr; int rc; @@ -404,7 +428,8 @@ void Instance::set_crash_flag_n_wake_all() -Instance::Instance(): crashed(FALSE), configured(FALSE) +Instance::Instance(Thread_registry &thread_registry_arg): + crashed(FALSE), configured(FALSE), thread_registry(thread_registry_arg) { pthread_mutex_init(&LOCK_instance, 0); pthread_cond_init(&COND_instance_stopped, 0); diff --git a/server-tools/instance-manager/instance.h b/server-tools/instance-manager/instance.h index 1f06cabebf7..329eaa68b1a 100644 --- a/server-tools/instance-manager/instance.h +++ b/server-tools/instance-manager/instance.h @@ -27,6 +27,7 @@ #endif class Instance_map; +class Thread_registry; /* @@ -87,7 +88,7 @@ public: static bool is_mysqld_compatible_name(const LEX_STRING *name); public: - Instance(); + Instance(Thread_registry &thread_registry_arg); ~Instance(); int init(const LEX_STRING *name_arg); @@ -120,6 +121,7 @@ public: public: enum { DEFAULT_SHUTDOWN_DELAY= 35 }; Instance_options options; + Thread_registry &thread_registry; private: /* This attributes is a flag, specifies if the instance has been crashed. */ diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc index b7704c027f1..2f830e616c4 100644 --- a/server-tools/instance-manager/instance_map.cc +++ b/server-tools/instance-manager/instance_map.cc @@ -169,7 +169,7 @@ int Instance_map::process_one_option(const LEX_STRING *group, if (!(instance= (Instance *) hash_search(&hash, (byte *) group->str, group->length))) { - if (!(instance= new Instance())) + if (!(instance= new Instance(thread_registry))) return 1; if (instance->init(group) || add_instance(instance)) @@ -213,8 +213,10 @@ int Instance_map::process_one_option(const LEX_STRING *group, } -Instance_map::Instance_map(const char *default_mysqld_path_arg): -mysqld_path(default_mysqld_path_arg) +Instance_map::Instance_map(const char *default_mysqld_path_arg, + Thread_registry &thread_registry_arg): + mysqld_path(default_mysqld_path_arg), + thread_registry(thread_registry_arg) { pthread_mutex_init(&LOCK_instance_map, 0); } @@ -333,7 +335,7 @@ int Instance_map::remove_instance(Instance *instance) int Instance_map::create_instance(const LEX_STRING *instance_name, const Named_value_arr *options) { - Instance *instance= new Instance(); + Instance *instance= new Instance(thread_registry); if (!instance) { diff --git a/server-tools/instance-manager/instance_map.h b/server-tools/instance-manager/instance_map.h index 8e6d2360652..9de40e35e0f 100644 --- a/server-tools/instance-manager/instance_map.h +++ b/server-tools/instance-manager/instance_map.h @@ -28,6 +28,7 @@ class Guardian_thread; class Instance; class Named_value_arr; +class Thread_registry; extern int load_all_groups(char ***groups, const char *filename); extern void free_groups(char **groups); @@ -104,7 +105,8 @@ public: int create_instance(const LEX_STRING *instance_name, const Named_value_arr *options); - Instance_map(const char *default_mysqld_path_arg); + Instance_map(const char *default_mysqld_path_arg, + Thread_registry &thread_registry_arg); ~Instance_map(); /* @@ -130,6 +132,8 @@ private: enum { START_HASH_SIZE = 16 }; pthread_mutex_t LOCK_instance_map; HASH hash; + + Thread_registry &thread_registry; }; #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_MAP_H */ diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc index 0ab85c0e7aa..62962c00957 100644 --- a/server-tools/instance-manager/listener.cc +++ b/server-tools/instance-manager/listener.cc @@ -87,7 +87,7 @@ private: Listener_thread::Listener_thread(const Listener_thread_args &args) : Listener_thread_args(args.thread_registry, args.user_map, args.instance_map) ,total_connection_count(0) - ,thread_info(pthread_self()) + ,thread_info(pthread_self(), TRUE) ,num_sockets(0) { } @@ -112,6 +112,8 @@ void Listener_thread::run() { int i, n= 0; + log_info("Listener_thread: started."); + #ifndef __WIN__ /* we use this var to check whether we are running on LinuxThreads */ pid_t thread_pid; @@ -164,7 +166,7 @@ void Listener_thread::run() if (rc == 0 || rc == -1) { if (rc == -1 && errno != EINTR) - log_error("Listener_thread::run(): select() failed, %s", + log_error("Listener_thread: select() failed, %s", strerror(errno)); continue; } @@ -198,7 +200,7 @@ void Listener_thread::run() /* III. Release all resources and exit */ - log_info("Listener_thread::run(): shutdown requested, exiting..."); + log_info("Listener_thread: shutdown requested, exiting..."); for (i= 0; i < num_sockets; i++) close(sockets[i]); @@ -209,6 +211,8 @@ void Listener_thread::run() thread_registry.unregister_thread(&thread_info); my_thread_end(); + + log_info("Listener_thread: finished."); return; err: @@ -230,7 +234,7 @@ int Listener_thread::create_tcp_socket() int ip_socket= socket(AF_INET, SOCK_STREAM, 0); if (ip_socket == INVALID_SOCKET) { - log_error("Listener_thead::run(): socket(AF_INET) failed, %s", + log_error("Listener_thead: socket(AF_INET) failed, %s", strerror(errno)); return -1; } @@ -261,7 +265,7 @@ int Listener_thread::create_tcp_socket() if (bind(ip_socket, (struct sockaddr *) &ip_socket_address, sizeof(ip_socket_address))) { - log_error("Listener_thread::run(): bind(ip socket) failed, '%s'", + log_error("Listener_thread: bind(ip socket) failed, '%s'", strerror(errno)); close(ip_socket); return -1; @@ -269,7 +273,7 @@ int Listener_thread::create_tcp_socket() if (listen(ip_socket, LISTEN_BACK_LOG_SIZE)) { - log_error("Listener_thread::run(): listen(ip socket) failed, %s", + log_error("Listener_thread: listen(ip socket) failed, %s", strerror(errno)); close(ip_socket); return -1; @@ -294,7 +298,7 @@ create_unix_socket(struct sockaddr_un &unix_socket_address) int unix_socket= socket(AF_UNIX, SOCK_STREAM, 0); if (unix_socket == INVALID_SOCKET) { - log_error("Listener_thead::run(): socket(AF_UNIX) failed, %s", + log_error("Listener_thead: socket(AF_UNIX) failed, %s", strerror(errno)); return -1; } @@ -314,7 +318,7 @@ create_unix_socket(struct sockaddr_un &unix_socket_address) if (bind(unix_socket, (struct sockaddr *) &unix_socket_address, sizeof(unix_socket_address))) { - log_error("Listener_thread::run(): bind(unix socket) failed, " + log_error("Listener_thread: bind(unix socket) failed, " "socket file name is '%s', error '%s'", unix_socket_address.sun_path, strerror(errno)); close(unix_socket); @@ -325,7 +329,7 @@ create_unix_socket(struct sockaddr_un &unix_socket_address) if (listen(unix_socket, LISTEN_BACK_LOG_SIZE)) { - log_error("Listener_thread::run(): listen(unix socket) failed, %s", + log_error("Listener_thread: listen(unix socket) failed, %s", strerror(errno)); close(unix_socket); return -1; diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc index 3fb967fc352..4bd298eedec 100644 --- a/server-tools/instance-manager/manager.cc +++ b/server-tools/instance-manager/manager.cc @@ -156,7 +156,8 @@ void manager() */ User_map user_map; - Instance_map instance_map(Options::Main::default_mysqld_path); + Instance_map instance_map(Options::Main::default_mysqld_path, + thread_registry); Guardian_thread guardian_thread(thread_registry, &instance_map, Options::Main::monitoring_interval); @@ -308,6 +309,8 @@ void manager() */ pthread_cond_signal(&guardian_thread.COND_guardian); + log_info("Main loop: started."); + while (!shutdown_complete) { int signo; @@ -320,6 +323,20 @@ void manager() goto err; } + /* + The general idea in this loop is the following: + - we are waiting for SIGINT, SIGTERM -- signals that mean we should + shutdown; + - as shutdown signal is caught, we stop Guardian thread (by calling + Guardian_thread::request_shutdown()); + - as Guardian_thread is stopped, it sends SIGTERM to this thread + (by calling Thread_registry::request_shutdown()), so that the + my_sigwait() above returns; + - as we catch the second SIGTERM, we send signals to all threads + registered in Thread_registry (by calling + Thread_registry::deliver_shutdown()) and waiting for threads to stop; + */ + #ifndef __WIN__ /* On some Darwin kernels SIGHUP is delivered along with most @@ -336,6 +353,8 @@ void manager() else #endif { + log_info("Main loop: got shutdown signal."); + if (!guardian_thread.is_stopped()) { guardian_thread.request_shutdown(); @@ -349,6 +368,8 @@ void manager() } } + log_info("Main loop: finished."); + err: /* delete the pid file */ my_delete(Options::Main::pid_file_name, MYF(0)); diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc index 17cda3af704..1c49d3cd83b 100644 --- a/server-tools/instance-manager/mysql_connection.cc +++ b/server-tools/instance-manager/mysql_connection.cc @@ -97,7 +97,7 @@ Mysql_connection_thread::Mysql_connection_thread( args.user_map, args.connection_id, args.instance_map) - ,thread_info(pthread_self()) + ,thread_info(pthread_self(), TRUE) { thread_registry.register_thread(&thread_info); } @@ -165,7 +165,7 @@ Mysql_connection_thread::~Mysql_connection_thread() void Mysql_connection_thread::run() { - log_info("accepted mysql connection %d", connection_id); + log_info("accepted mysql connection %d", (int) connection_id); my_thread_init(); @@ -175,7 +175,7 @@ void Mysql_connection_thread::run() return; } - log_info("connection %d is checked successfully", connection_id); + log_info("connection %d is checked successfully", (int) connection_id); vio_keepalive(vio, TRUE); @@ -315,7 +315,7 @@ int Mysql_connection_thread::do_command() enum enum_server_command command= (enum enum_server_command) (uchar) *packet; log_info("connection %d: packet_length=%d, command=%d", - connection_id, packet_length, command); + (int) connection_id, (int) packet_length, (int) command); return dispatch_command(command, packet + 1, packet_length - 1); } } @@ -325,27 +325,33 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command, { switch (command) { case COM_QUIT: // client exit - log_info("query for connection %d received quit command", connection_id); + log_info("query for connection %d received quit command", + (int) connection_id); return 1; case COM_PING: - log_info("query for connection %d received ping command", connection_id); + log_info("query for connection %d received ping command", + (int) connection_id); net_send_ok(&net, connection_id, NULL); break; case COM_QUERY: { log_info("query for connection %d : ----\n%s\n-------------------------", - connection_id,packet); + (int) connection_id, + (const char *) packet); if (Command *command= parse_command(&instance_map, packet)) { int res= 0; - log_info("query for connection %d successfully parsed",connection_id); + log_info("query for connection %d successfully parsed", + (int) connection_id); res= command->execute(&net, connection_id); delete command; if (!res) - log_info("query for connection %d executed ok",connection_id); + log_info("query for connection %d executed ok", + (int) connection_id); else { - log_info("query for connection %d executed err=%d",connection_id,res); + log_info("query for connection %d executed err=%d", + (int) connection_id, (int) res); net_send_error(&net, res); return 0; } @@ -358,7 +364,8 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command, break; } default: - log_info("query for connection %d received unknown command",connection_id); + log_info("query for connection %d received unknown command", + (int) connection_id); net_send_error(&net, ER_UNKNOWN_COM_ERROR); break; } diff --git a/server-tools/instance-manager/thread_registry.cc b/server-tools/instance-manager/thread_registry.cc index a424860548d..10370e0981e 100644 --- a/server-tools/instance-manager/thread_registry.cc +++ b/server-tools/instance-manager/thread_registry.cc @@ -43,8 +43,10 @@ static void handle_signal(int __attribute__((unused)) sig_no) */ Thread_info::Thread_info() {} -Thread_info::Thread_info(pthread_t thread_id_arg) : - thread_id(thread_id_arg) {} +Thread_info::Thread_info(pthread_t thread_id_arg, + bool send_signal_on_shutdown_arg) : + thread_id(thread_id_arg), + send_signal_on_shutdown(send_signal_on_shutdown_arg) {} /* TODO: think about moving signal information (now it's shutdown_in_progress) @@ -86,6 +88,9 @@ Thread_registry::~Thread_registry() void Thread_registry::register_thread(Thread_info *info) { + log_info("Thread_registry: registering thread %d...", + (int) info->thread_id); + #ifndef __WIN__ struct sigaction sa; sa.sa_handler= handle_signal; @@ -112,11 +117,19 @@ void Thread_registry::register_thread(Thread_info *info) void Thread_registry::unregister_thread(Thread_info *info) { + log_info("Thread_registry: unregistering thread %d...", + (int) info->thread_id); + pthread_mutex_lock(&LOCK_thread_registry); info->prev->next= info->next; info->next->prev= info->prev; + if (head.next == &head) + { + log_info("Thread_registry: thread registry is empty!"); pthread_cond_signal(&COND_thread_registry_is_empty); + } + pthread_mutex_unlock(&LOCK_thread_registry); } @@ -181,11 +194,6 @@ int Thread_registry::cond_timedwait(Thread_info *info, pthread_cond_t *cond, void Thread_registry::deliver_shutdown() { - Thread_info *info; - struct timespec shutdown_time; - int error; - set_timespec(shutdown_time, 1); - pthread_mutex_lock(&LOCK_thread_registry); shutdown_in_progress= TRUE; @@ -199,29 +207,14 @@ void Thread_registry::deliver_shutdown() process_alarm(THR_SERVER_ALARM); #endif - for (info= head.next; info != &head; info= info->next) - { - pthread_kill(info->thread_id, THREAD_KICK_OFF_SIGNAL); - /* - sic: race condition here, the thread may not yet fall into - pthread_cond_wait. - */ - if (info->current_cond) - pthread_cond_signal(info->current_cond); - } /* - The common practice is to test predicate before pthread_cond_wait. - I don't do that here because the predicate is practically always false - before wait - is_shutdown's been just set, and the lock's still not - released - the only case when the predicate is false is when no other - threads exist. + sic: race condition here, the thread may not yet fall into + pthread_cond_wait. */ - while (((error= pthread_cond_timedwait(&COND_thread_registry_is_empty, - &LOCK_thread_registry, - &shutdown_time)) != ETIMEDOUT && - error != ETIME) && - head.next != &head) - ; + + interrupt_threads(); + + wait_for_threads_to_unregister(); /* If previous signals did not reach some threads, they must be sleeping @@ -230,11 +223,28 @@ void Thread_registry::deliver_shutdown() so this time everybody should be informed (presumably each worker can get CPU during shutdown_time.) */ - for (info= head.next; info != &head; info= info->next) + + interrupt_threads(); + + /* Get the last chance to threads to stop. */ + + wait_for_threads_to_unregister(); + + /* + Print out threads, that didn't stopped. Thread_registry destructor will + probably abort the program if there is still any alive thread. + */ + + if (head.next != &head) { - pthread_kill(info->thread_id, THREAD_KICK_OFF_SIGNAL); - if (info->current_cond) - pthread_cond_signal(info->current_cond); + log_info("Thread_registry: non-stopped threads:"); + + for (Thread_info *info= head.next; info != &head; info= info->next) + log_info(" - %ld", (long int) info->thread_id); + } + else + { + log_info("Thread_registry: all threads stopped."); } pthread_mutex_unlock(&LOCK_thread_registry); @@ -245,3 +255,46 @@ void Thread_registry::request_shutdown() { pthread_kill(sigwait_thread_pid, SIGTERM); } + + +void Thread_registry::interrupt_threads() +{ + for (Thread_info *info= head.next; info != &head; info= info->next) + { + if (!info->send_signal_on_shutdown) + continue; + + pthread_kill(info->thread_id, THREAD_KICK_OFF_SIGNAL); + if (info->current_cond) + pthread_cond_signal(info->current_cond); + } +} + + +void Thread_registry::wait_for_threads_to_unregister() +{ + struct timespec shutdown_time; + + set_timespec(shutdown_time, 1); + + log_info("Thread_registry: joining threads..."); + + while (true) + { + if (head.next == &head) + { + log_info("Thread_registry: emptied."); + return; + } + + int error= pthread_cond_timedwait(&COND_thread_registry_is_empty, + &LOCK_thread_registry, + &shutdown_time); + + if (error == ETIMEDOUT || error == ETIME) + { + log_info("Thread_registry: threads shutdown timed out."); + return; + } + } +} diff --git a/server-tools/instance-manager/thread_registry.h b/server-tools/instance-manager/thread_registry.h index 6dc320a8533..503d24e5fb0 100644 --- a/server-tools/instance-manager/thread_registry.h +++ b/server-tools/instance-manager/thread_registry.h @@ -67,13 +67,17 @@ class Thread_info { public: - Thread_info(); - Thread_info(pthread_t thread_id_arg); + Thread_info(pthread_t thread_id_arg, bool send_signal_on_shutdown_arg); friend class Thread_registry; + +private: + Thread_info(); + private: pthread_cond_t *current_cond; Thread_info *prev, *next; pthread_t thread_id; + bool send_signal_on_shutdown; }; @@ -97,6 +101,10 @@ public: pthread_mutex_t *mutex); int cond_timedwait(Thread_info *info, pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *wait_time); +private: + void interrupt_threads(); + void wait_for_threads_to_unregister(); + private: Thread_info head; bool shutdown_in_progress; From 1e3c6cab960ea79664f75c1c8199f1aee48ac18b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Oct 2006 18:25:24 +0400 Subject: [PATCH 30/47] Enable im_daemon_life_cycle.imtest, since BUG#22379 is closed. --- mysql-test/t/disabled.def | 2 -- 1 file changed, 2 deletions(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 8c4a76c78a9..d3314660089 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -14,8 +14,6 @@ #events : BUG#17619 2006-02-21 andrey Race conditions #events_scheduling : BUG#19170 2006-04-26 andrey Test case of 19170 fails on some platforms. Has to be checked. im_options : Bug#20294 2006-07-24 stewart Instance manager test im_options fails randomly -#im_life_cycle : Bug#20368 2006-06-10 alik im_life_cycle test fails -im_daemon_life_cycle : BUG#22379 2006-09-15 ingo im_daemon_life_cycle.test fails on merge of 5.1 -> 5.1-engines im_instance_conf : BUG#20294 2006-09-16 ingo Instance manager test im_instance_conf fails randomly concurrent_innodb : BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences ndb_autodiscover : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog From f0ad68c9d5c7a24406228f9e9356cc6158451fcd Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Oct 2006 18:31:10 +0400 Subject: [PATCH 31/47] IM polishing: log more information in log. server-tools/instance-manager/log.cc: Add pid/thread id to the each log record; split date time fields. --- server-tools/instance-manager/log.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/server-tools/instance-manager/log.cc b/server-tools/instance-manager/log.cc index a88344f0b91..7214cde7193 100644 --- a/server-tools/instance-manager/log.cc +++ b/server-tools/instance-manager/log.cc @@ -52,14 +52,16 @@ static inline void log(FILE *file, const char *format, va_list args) struct tm bd_time; // broken-down time localtime_r(&now, &bd_time); - char buff_date[32]; - sprintf(buff_date, "%02d%02d%02d %2d:%02d:%02d\t", - bd_time.tm_year % 100, - bd_time.tm_mon + 1, - bd_time.tm_mday, - bd_time.tm_hour, - bd_time.tm_min, - bd_time.tm_sec); + char buff_date[128]; + sprintf(buff_date, "[%d/%lu] [%02d/%02d/%02d %02d:%02d:%02d] ", + (int) getpid(), + (unsigned long) pthread_self(), + bd_time.tm_year % 100, + bd_time.tm_mon + 1, + bd_time.tm_mday, + bd_time.tm_hour, + bd_time.tm_min, + bd_time.tm_sec); /* Format the message */ char buff_stack[256]; From 7d7acda2e2c4cce618302bdc57ec2d05748effef Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Oct 2006 18:16:11 -0700 Subject: [PATCH 32/47] Fixed build break. --- sql/sql_delete.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index ba6b6df1a3d..2b3ad83cfe4 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -862,6 +862,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) bool error; uint closed_log_tables= 0, lock_logger= 0; uint path_length; + uint log_type; DBUG_ENTER("mysql_truncate"); bzero((char*) &create_info,sizeof(create_info)); @@ -913,9 +914,9 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) DBUG_RETURN(TRUE); } - uint log_type= check_if_log_table(table_list->db_length, table_list->db, - table_list->table_name_length, - table_list->table_name, 1); + log_type= check_if_log_table(table_list->db_length, table_list->db, + table_list->table_name_length, + table_list->table_name, 1); /* close log tables in use */ if (log_type) { From e4bacda5b25d0d4afaa559974d2e6b576073cb4a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 25 Oct 2006 12:54:59 +0400 Subject: [PATCH 33/47] fix test failures in the runtime tree sql/log.cc: NULL table pointer during initilization sql/sql_table.cc: don't lock the destination table with table lock, but use name lock instead --- sql/log.cc | 2 ++ sql/sql_table.cc | 36 +++++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index e64696cbe38..8b666faccff 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -317,11 +317,13 @@ Log_to_csv_event_handler::Log_to_csv_event_handler() /* logger thread always works with mysql database */ general_log_thd->db= my_strdup("mysql", MYF(0)); general_log_thd->db_length= 5; + general_log.table= 0; slow_log_thd= new THD; /* logger thread always works with mysql database */ slow_log_thd->db= my_strdup("mysql", MYF(0));; slow_log_thd->db_length= 5; + slow_log.table= 0; /* no privileged thread exists at the moment */ privileged_thread= 0; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 5773213eba1..6a868f07ce9 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4607,11 +4607,11 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, char *src_db; char *src_table= table_ident->table.str; int err; - bool res= TRUE; + bool res= TRUE, unlock_dst_table= FALSE; enum legacy_db_type not_used; HA_CREATE_INFO *create_info; - TABLE_LIST src_tables_list; + TABLE_LIST src_tables_list, dst_tables_list; DBUG_ENTER("mysql_create_like_table"); if (!(create_info= copy_create_info(lex_create_info))) @@ -4794,17 +4794,29 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, char buf[2048]; String query(buf, sizeof(buf), system_charset_info); query.length(0); // Have to zero it since constructor doesn't - TABLE *table_ptr; - int error; + uint counter; /* - Let's open and lock the table: it will be closed (and - unlocked) by close_thread_tables() at the end of the - statement anyway. - */ - if (!(table_ptr= open_ltable(thd, table, TL_READ_NO_INSERT))) + Here we open the destination table. This is needed for + store_create_info() to work. The table will be closed + by close_thread_tables() at the end of the statement. + */ + if (open_tables(thd, &table, &counter, 0)) goto err; + bzero((gptr)&dst_tables_list, sizeof(dst_tables_list)); + dst_tables_list.db= table->db; + dst_tables_list.table_name= table->table_name; + + /* + lock destination table name, to make sure that nobody + can drop/alter the table while we execute store_create_info() + */ + if (lock_and_wait_for_table_name(thd, &dst_tables_list)) + goto err; + else + unlock_dst_table= TRUE; + int result= store_create_info(thd, table, &query, create_info); DBUG_ASSERT(result == 0); // store_create_info() always return 0 @@ -4837,6 +4849,12 @@ table_exists: my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name); err: + if (unlock_dst_table) + { + pthread_mutex_lock(&LOCK_open); + unlock_table_name(thd, &dst_tables_list); + pthread_mutex_unlock(&LOCK_open); + } DBUG_RETURN(res); } From e3d49f0c3f7995e2c618cfa764a1ceaa2418a669 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 25 Oct 2006 19:53:26 +0400 Subject: [PATCH 34/47] BUG#18819: DELETE IGNORE hangs on foreign key parent delete If the error happens during DELETE IGNORE, nothing could be send to the client, thus leaving it frozen expecting the reply. The problem was that if some error occurred, it wouldn't be reported to the client because of IGNORE, but neither success would be reported. MySQL 4.1 would not freeze the client, but will report ERROR 1105 (HY000): Unknown error instead, which is also a bug. The solution is to report success if we are in DELETE IGNORE and some non-fatal error has happened. mysql-test/r/innodb_mysql.result: Add result for bug#18819: DELETE IGNORE hangs on foreign key parent delete. mysql-test/t/innodb_mysql.test: Add test case for bug#18819: DELETE IGNORE hangs on foreign key parent delete. sql/sql_delete.cc: Report success if we have got an error, but we are in DELETE IGNORE, and the error is not fatal (if it is, it would be reported to the client). --- mysql-test/r/innodb_mysql.result | 16 ++++++++++++++++ mysql-test/t/innodb_mysql.test | 29 +++++++++++++++++++++++++++++ sql/sql_delete.cc | 3 ++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index ee4c114087d..68995565752 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -104,3 +104,19 @@ SELECT `id1` FROM `t1` WHERE `id1` NOT IN (SELECT `id1` FROM `t2` WHERE `id2` = id1 2 DROP TABLE t1, t2; +DROP TABLE IF EXISTS t2, t1; +CREATE TABLE t1 (i INT NOT NULL PRIMARY KEY) ENGINE= InnoDB; +CREATE TABLE t2 ( +i INT NOT NULL, +FOREIGN KEY (i) REFERENCES t1 (i) ON DELETE NO ACTION +) ENGINE= InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +DELETE IGNORE FROM t1 WHERE i = 1; +Warnings: +Error 1217 Cannot delete or update a parent row: a foreign key constraint fails +SELECT * FROM t1, t2; +i i +1 1 +DROP TABLE t2, t1; +End of 4.1 tests. diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index a5fe248604f..9593982826b 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -117,3 +117,32 @@ INSERT INTO `t2`(`id1`,`id2`,`id3`,`id4`) VALUES SELECT `id1` FROM `t1` WHERE `id1` NOT IN (SELECT `id1` FROM `t2` WHERE `id2` = 1 AND `id3` = 2); DROP TABLE t1, t2; + + +# +# BUG#18819: DELETE IGNORE hangs on foreign key parent delete +# +# The bug itself does not relate to InnoDB, but we have to use foreign +# keys to reproduce it. +# +--disable_warnings +DROP TABLE IF EXISTS t2, t1; +--enable_warnings + +CREATE TABLE t1 (i INT NOT NULL PRIMARY KEY) ENGINE= InnoDB; +CREATE TABLE t2 ( + i INT NOT NULL, + FOREIGN KEY (i) REFERENCES t1 (i) ON DELETE NO ACTION +) ENGINE= InnoDB; + +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +DELETE IGNORE FROM t1 WHERE i = 1; + +SELECT * FROM t1, t2; + +DROP TABLE t2, t1; + + +--echo End of 4.1 tests. diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index b085d37be78..506eec88500 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -253,7 +253,8 @@ cleanup: mysql_unlock_tables(thd, thd->lock); thd->lock=0; } - if (error >= 0 || thd->net.report_error) + if ((error >= 0 || thd->net.report_error) && + (!thd->lex->ignore || thd->is_fatal_error)) send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0); else { From 6137ef86a98745cc818ed1de0580e628efc0d3ec Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 25 Oct 2006 20:09:31 +0400 Subject: [PATCH 35/47] Fix after manual merge. --- mysql-test/r/innodb_mysql.result | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index cc0fc4289dc..a96bc4786fa 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -295,7 +295,6 @@ b c d drop table t1,t4; - DROP TABLE IF EXISTS t2, t1; CREATE TABLE t1 (i INT NOT NULL PRIMARY KEY) ENGINE= InnoDB; CREATE TABLE t2 ( @@ -306,7 +305,7 @@ INSERT INTO t1 VALUES (1); INSERT INTO t2 VALUES (1); DELETE IGNORE FROM t1 WHERE i = 1; Warnings: -Error 1217 Cannot delete or update a parent row: a foreign key constraint fails +Error 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`i`) REFERENCES `t1` (`i`) ON DELETE NO ACTION) SELECT * FROM t1, t2; i i 1 1 From f132d192de1b8c054bc197ce5fec27f19f8473a9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 25 Oct 2006 20:12:23 +0400 Subject: [PATCH 36/47] After merge fix. --- mysql-test/r/innodb_mysql.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index c8c73a3a14a..efd200354e6 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -258,7 +258,7 @@ INSERT INTO t1 VALUES (1); INSERT INTO t2 VALUES (1); DELETE IGNORE FROM t1 WHERE i = 1; Warnings: -Error 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`i`) REFERENCES `t1` (`i`) ON DELETE NO ACTION) +Error 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`i`) REFERENCES `t1` (`i`) ON DELETE NO ACTION) SELECT * FROM t1, t2; i i 1 1 From 532735e6c8fa330e256149f0c0d94822596ac18c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Oct 2006 13:32:41 +0400 Subject: [PATCH 37/47] BUG#22584: last_insert_id not updated after inserting a record through a updatable view. When there's a VIEW on a base table that have AUTO_INCREMENT column, and this VIEW doesn't provide an access such column, after INSERT to such VIEW LAST_INSERT_ID() did not return the value just generated. This behaviour is intended and correct, because if the VIEW doesn't list some columns then these columns are effectively hidden from the user, and so any side effects of inserting default values to them. However, there was a bug that such statement inserting into a view would reset LAST_INSERT_ID() instead of leaving it unchanged. This patch restores the original value of LAST_INSERT_ID() instead of resetting it to zero. mysql-test/r/view.result: Add result for bug#22584: last_insert_id not updated after inserting a record through a updatable view. mysql-test/t/view.test: Add test case for bug#22584: last_insert_id not updated after inserting a record through a updatable view. sql/sql_parse.cc: When we have inserted into a view, and AUTO_INCREMENT column is not accessed from this view, instead of setting LAST_INSERT_ID to zero set it to the value it had before this statement was executed. --- mysql-test/r/view.result | 34 ++++++++++++++++++++++++++++++++++ mysql-test/t/view.test | 38 ++++++++++++++++++++++++++++++++++++++ sql/sql_parse.cc | 19 +++++++++++++++++-- 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 13921dc88d7..198233adf71 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2970,4 +2970,38 @@ UPDATE t1 SET i= f1(); DROP FUNCTION f1; DROP VIEW v1; DROP TABLE t1; +DROP VIEW IF EXISTS v1, v2; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY, j INT); +CREATE VIEW v1 AS SELECT j FROM t1; +CREATE VIEW v2 AS SELECT * FROM t1; +INSERT INTO t1 (j) VALUES (1); +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +1 +INSERT INTO v1 (j) VALUES (2); +# LAST_INSERT_ID() should not change. +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +1 +INSERT INTO v2 (j) VALUES (3); +# LAST_INSERT_ID() should be updated. +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +3 +INSERT INTO v1 (j) SELECT j FROM t1; +# LAST_INSERT_ID() should not change. +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +3 +SELECT * FROM t1; +i j +1 1 +2 2 +3 3 +4 1 +5 2 +6 3 +DROP VIEW v1, v2; +DROP TABLE t1; End of 5.0 tests. diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index d3dcd857e62..401bda27bb4 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2908,4 +2908,42 @@ DROP VIEW v1; DROP TABLE t1; +# +# BUG#22584: last_insert_id not updated after inserting a record +# through a updatable view +# +# We still do not update LAST_INSERT_ID if AUTO_INCREMENT column is +# not accessible through a view. However, we do not reset the value +# of LAST_INSERT_ID, but keep it unchanged. +# +--disable_warnings +DROP VIEW IF EXISTS v1, v2; +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY, j INT); +CREATE VIEW v1 AS SELECT j FROM t1; +CREATE VIEW v2 AS SELECT * FROM t1; + +INSERT INTO t1 (j) VALUES (1); +SELECT LAST_INSERT_ID(); + +INSERT INTO v1 (j) VALUES (2); +--echo # LAST_INSERT_ID() should not change. +SELECT LAST_INSERT_ID(); + +INSERT INTO v2 (j) VALUES (3); +--echo # LAST_INSERT_ID() should be updated. +SELECT LAST_INSERT_ID(); + +INSERT INTO v1 (j) SELECT j FROM t1; +--echo # LAST_INSERT_ID() should not change. +SELECT LAST_INSERT_ID(); + +SELECT * FROM t1; + +DROP VIEW v1, v2; +DROP TABLE t1; + + --echo End of 5.0 tests. diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7b5387e5e2f..d2cbd5b0008 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3369,8 +3369,16 @@ end_with_restore_list: res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values, lex->update_list, lex->value_list, lex->duplicates, lex->ignore); + + /* + If we have inserted into a VIEW, and the base table has + AUTO_INCREMENT column, but this column is not accessible through + a view, then we should restore LAST_INSERT_ID to the value it + had before the statement. + */ if (first_table->view && !first_table->contain_auto_increment) - thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it + thd->last_insert_id= thd->current_insert_id; + break; } case SQLCOM_REPLACE_SELECT: @@ -3431,8 +3439,15 @@ end_with_restore_list: select_lex->table_list.first= (byte*) first_table; } + /* + If we have inserted into a VIEW, and the base table has + AUTO_INCREMENT column, but this column is not accessible through + a view, then we should restore LAST_INSERT_ID to the value it + had before the statement. + */ if (first_table->view && !first_table->contain_auto_increment) - thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it + thd->last_insert_id= thd->current_insert_id; + break; } case SQLCOM_TRUNCATE: From f6e92be9b10c5c4e3af1aab25574d780ac461baf Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 30 Oct 2006 11:36:30 +0300 Subject: [PATCH 38/47] Cleanup. sql/sql_table.cc: Remove unused code (it's also made obsolete by work in 5.1) --- sql/sql_table.cc | 202 ----------------------------------------------- 1 file changed, 202 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f6dbba4aa79..73dd2c809a6 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2934,208 +2934,6 @@ err: } -#ifdef NOT_USED -/* - CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with - the proper arguments. This isn't very fast but it should work for most - cases. - One should normally create all indexes with CREATE TABLE or ALTER TABLE. -*/ - -int mysql_create_indexes(THD *thd, TABLE_LIST *table_list, List &keys) -{ - List fields; - List drop; - List alter; - HA_CREATE_INFO create_info; - int rc; - uint idx; - uint db_options; - uint key_count; - TABLE *table; - Field **f_ptr; - KEY *key_info_buffer; - char path[FN_REFLEN+1]; - DBUG_ENTER("mysql_create_index"); - - /* - Try to use online generation of index. - This requires that all indexes can be created online. - Otherwise, the old alter table procedure is executed. - - Open the table to have access to the correct table handler. - */ - if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ))) - DBUG_RETURN(-1); - - /* - The add_index method takes an array of KEY structs for the new indexes. - Preparing a new table structure generates this array. - It needs a list with all fields of the table, which does not need to - be correct in every respect. The field names are important. - */ - for (f_ptr= table->field; *f_ptr; f_ptr++) - { - create_field *c_fld= new create_field(*f_ptr, *f_ptr); - c_fld->unireg_check= Field::NONE; /*avoid multiple auto_increments*/ - fields.push_back(c_fld); - } - bzero((char*) &create_info,sizeof(create_info)); - create_info.db_type=DB_TYPE_DEFAULT; - create_info.default_table_charset= thd->variables.collation_database; - db_options= 0; - if (mysql_prepare_table(thd, &create_info, &fields, - &keys, /*tmp_table*/ 0, &db_options, table->file, - &key_info_buffer, key_count, - /*select_field_count*/ 0)) - DBUG_RETURN(-1); - - /* - Check if all keys can be generated with the add_index method. - If anyone cannot, then take the old way. - */ - for (idx=0; idx< key_count; idx++) - { - DBUG_PRINT("info", ("creating index %s", key_info_buffer[idx].name)); - if (!(table->file->index_ddl_flags(key_info_buffer+idx)& - (HA_DDL_ONLINE| HA_DDL_WITH_LOCK))) - break ; - } - if ((idx < key_count)|| !key_count) - { - /* Re-initialize the create_info, which was changed by prepare table. */ - bzero((char*) &create_info,sizeof(create_info)); - create_info.db_type=DB_TYPE_DEFAULT; - create_info.default_table_charset= thd->variables.collation_database; - /* Cleanup the fields list. We do not want to create existing fields. */ - fields.delete_elements(); - if (real_alter_table(thd, table_list->db, table_list->table_name, - &create_info, table_list, table, - fields, keys, drop, alter, 0, (ORDER*)0, - ALTER_ADD_INDEX, DUP_ERROR)) - /* Don't need to free((gptr) key_info_buffer);*/ - DBUG_RETURN(-1); - } - else - { - if (table->file->add_index(table, key_info_buffer, key_count)|| - build_table_path(path, sizeof(path), table_list->db, - (lower_case_table_names == 2) ? - table_list->alias : table_list->table_name, - reg_ext) == 0 || - mysql_create_frm(thd, path, &create_info, - fields, key_count, key_info_buffer, table->file)) - /* don't need to free((gptr) key_info_buffer);*/ - DBUG_RETURN(-1); - } - /* don't need to free((gptr) key_info_buffer);*/ - DBUG_RETURN(0); -} - - -int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list, - List &drop) -{ - List fields; - List keys; - List alter; - HA_CREATE_INFO create_info; - uint idx; - uint db_options; - uint key_count; - uint *key_numbers; - TABLE *table; - Field **f_ptr; - KEY *key_info; - KEY *key_info_buffer; - char path[FN_REFLEN]; - DBUG_ENTER("mysql_drop_index"); - - /* - Try to use online generation of index. - This requires that all indexes can be created online. - Otherwise, the old alter table procedure is executed. - - Open the table to have access to the correct table handler. - */ - if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ))) - DBUG_RETURN(-1); - - /* - The drop_index method takes an array of key numbers. - It cannot get more entries than keys in the table. - */ - key_numbers= (uint*) thd->alloc(sizeof(uint*)*table->keys); - key_count= 0; - - /* - Get the number of each key and check if it can be created online. - */ - List_iterator drop_it(drop); - Alter_drop *drop_key; - while ((drop_key= drop_it++)) - { - /* Find the key in the table. */ - key_info=table->key_info; - for (idx=0; idx< table->keys; idx++, key_info++) - { - if (!my_strcasecmp(system_charset_info, key_info->name, drop_key->name)) - break; - } - if (idx>= table->keys) - { - my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop_key->name); - /*don't need to free((gptr) key_numbers);*/ - DBUG_RETURN(-1); - } - /* - Check if the key can be generated with the add_index method. - If anyone cannot, then take the old way. - */ - DBUG_PRINT("info", ("dropping index %s", table->key_info[idx].name)); - if (!(table->file->index_ddl_flags(table->key_info+idx)& - (HA_DDL_ONLINE| HA_DDL_WITH_LOCK))) - break ; - key_numbers[key_count++]= idx; - } - - bzero((char*) &create_info,sizeof(create_info)); - create_info.db_type=DB_TYPE_DEFAULT; - create_info.default_table_charset= thd->variables.collation_database; - - if ((drop_key)|| (drop.elements<= 0)) - { - if (real_alter_table(thd, table_list->db, table_list->table_name, - &create_info, table_list, table, - fields, keys, drop, alter, 0, (ORDER*)0, - ALTER_DROP_INDEX, DUP_ERROR)) - /*don't need to free((gptr) key_numbers);*/ - DBUG_RETURN(-1); - } - else - { - db_options= 0; - if (table->file->drop_index(table, key_numbers, key_count)|| - mysql_prepare_table(thd, &create_info, &fields, - &keys, /*tmp_table*/ 0, &db_options, table->file, - &key_info_buffer, key_count, - /*select_field_count*/ 0)|| - build_table_path(path, sizeof(path), table_list->db, - (lower_case_table_names == 2) ? - table_list->alias : table_list->table_name, - reg_ext) == 0 || - mysql_create_frm(thd, path, &create_info, - fields, key_count, key_info_buffer, table->file)) - /*don't need to free((gptr) key_numbers);*/ - DBUG_RETURN(-1); - } - - /*don't need to free((gptr) key_numbers);*/ - DBUG_RETURN(0); -} -#endif /* NOT_USED */ - - /* Alter table */ From 26770e3a1b40c4646cf4c926fe1e76175a0d82cb Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 30 Oct 2006 12:03:42 +0300 Subject: [PATCH 39/47] A cleanup. sql/sql_parse.cc: ALTER TABLE should not be affected by DONT_ALLOW_SHOW_COMMANDS (a bug that's there since version 1.1) --- sql/sql_parse.cc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d2cbd5b0008..2a46656e8d2 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3045,11 +3045,6 @@ end_with_restore_list: case SQLCOM_ALTER_TABLE: DBUG_ASSERT(first_table == all_tables && first_table != 0); -#if defined(DONT_ALLOW_SHOW_COMMANDS) - my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), - MYF(0)); /* purecov: inspected */ - goto error; -#else { ulong priv=0; if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN)) @@ -3115,7 +3110,6 @@ end_with_restore_list: } break; } -#endif /*DONT_ALLOW_SHOW_COMMANDS*/ case SQLCOM_RENAME_TABLE: { DBUG_ASSERT(first_table == all_tables && first_table != 0); From 885dc1cb9b7ddbf28ad72c754165a2b87ea79da7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 30 Oct 2006 17:47:02 +0300 Subject: [PATCH 40/47] BUG#21915: Changing limits of table_cache when setting max_connections If the user has specified --max-connections=N or --table-open-cache=M options to the server, a warning could be given that some values were recalculated, and table-open-cache could be assigned greater value. Note that both warning and increase of table-open-cache were totally harmless. This patch fixes recalculation code to ensure that table-open-cache will be never increased automatically and that a warning will be given only if some values had to be decreased due to operating system limits. No test case is provided because we neither can't predict nor control operating system limits for maximal number of open files. sql/mysql_priv.h: Add constants for table_cache minimum and default values. sql/mysqld.cc: Fix max_connections and table_cache_size re-computation. --- sql/mysql_priv.h | 2 ++ sql/mysqld.cc | 42 +++++++++++++++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 4a5658c5ccf..c2d378c0be9 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -95,6 +95,8 @@ MY_LOCALE *my_locale_by_name(const char *name); #define MAX_ACCEPT_RETRY 10 // Test accept this many times #define MAX_FIELDS_BEFORE_HASH 32 #define USER_VARS_HASH_SIZE 16 +#define TABLE_OPEN_CACHE_MIN 64 +#define TABLE_OPEN_CACHE_DEFAULT 64 #define STACK_MIN_SIZE 8192 // Abort if less stack during eval. #define STACK_BUFF_ALLOC 64 // For stack overrun checks #ifndef MYSQLD_NET_RETRY_COUNT diff --git a/sql/mysqld.cc b/sql/mysqld.cc index bf83772a8d8..f7b1a2687ea 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2526,19 +2526,43 @@ static int init_common_variables(const char *conf_file_name, int argc, /* connections and databases needs lots of files */ { - uint files, wanted_files; + uint files, wanted_files, max_open_files; - wanted_files= 10+(uint) max(max_connections*5, - max_connections+table_cache_size*2); - set_if_bigger(wanted_files, open_files_limit); - files= my_set_max_open_files(wanted_files); + /* MyISAM requires two file handles per table. */ + wanted_files= 10+max_connections+table_cache_size*2; + /* + We are trying to allocate no less than max_connections*5 file + handles (i.e. we are trying to set the limit so that they will + be available). In addition, we allocate no less than how much + was already allocated. However below we report a warning and + recompute values only if we got less file handles than were + explicitly requested. No warning and re-computation occur if we + can't get max_connections*5 but still got no less than was + requested (value of wanted_files). + */ + max_open_files= max(max(wanted_files, max_connections*5), + open_files_limit); + files= my_set_max_open_files(max_open_files); if (files < wanted_files) { if (!open_files_limit) { - max_connections= (ulong) min((files-10),max_connections); - table_cache_size= (ulong) max((files-10-max_connections)/2,64); + /* + If we have requested too much file handles than we bring + max_connections in supported bounds. + */ + max_connections= (ulong) min(files-10-TABLE_OPEN_CACHE_MIN*2, + max_connections); + /* + Decrease table_cache_size according to max_connections, but + not below TABLE_OPEN_CACHE_MIN. Outer min() ensures that we + never increase table_cache_size automatically (that could + happen if max_connections is decreased above). + */ + table_cache_size= (ulong) min(max((files-10-max_connections)/2, + TABLE_OPEN_CACHE_MIN), + table_cache_size); DBUG_PRINT("warning", ("Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld", files, max_connections, table_cache_size)); @@ -5511,8 +5535,8 @@ The minimum value for this variable is 4096.", 0, 0, 0, 0}, {"table_cache", OPT_TABLE_CACHE, "The number of open tables for all threads.", (gptr*) &table_cache_size, - (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 512*1024L, - 0, 1, 0}, + (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, + TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0}, {"thread_cache_size", OPT_THREAD_CACHE_SIZE, "How many threads we should keep in a cache for reuse.", (gptr*) &thread_cache_size, (gptr*) &thread_cache_size, 0, GET_ULONG, From 57c2f22a54f33267e2f9cc7437f78f36b47a32fe Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 1 Nov 2006 15:41:48 +0300 Subject: [PATCH 41/47] Small cleanup in code handling stored routines/table prelocking. Use lazy initialization for Query_tables_list::sroutines hash. This step should significantly decrease amount of memory consumed by stored routines as we no longer will allocate chunk of memory required for this HASH for each statement in routine. include/hash.h: Introduced auxillary hash_init_opt() macro which simplifies lazy initialization of HASH objects. sql/sp.cc: Use lazy initialization for Query_tables_list::sroutines hash. This step should significantly decrease amount of memory consumed by stored routines as we no longer will allocate chunk of memory required for this HASH for each statement in routine. sql/sql_lex.cc: Use lazy initialization for Query_tables_list::sroutines hash. This step should significantly decrease amount of memory consumed by stored routines as we no longer will allocate chunk of memory required for this HASH for each statement in routine. sql/sql_lex.h: Updated comment describing Query_tables_list::sroutines to reflect that now we are use lazy initialization for this hash. Added constant for initial size of this hash. --- include/hash.h | 2 ++ sql/sp.cc | 4 ++++ sql/sql_lex.cc | 11 ++++++++++- sql/sql_lex.h | 6 +++++- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/include/hash.h b/include/hash.h index 8f5ff21ae5e..4d6ee77fa0c 100644 --- a/include/hash.h +++ b/include/hash.h @@ -65,6 +65,8 @@ my_bool hash_check(HASH *hash); /* Only in debug library */ #define hash_clear(H) bzero((char*) (H),sizeof(*(H))) #define hash_inited(H) ((H)->array.buffer != 0) +#define hash_init_opt(A,B,C,D,E,F,G,H) \ + (!hash_inited(A) && _hash_init(A,B,C,D,E,F,G, H CALLER_INFO)) #ifdef __cplusplus } diff --git a/sql/sp.cc b/sql/sp.cc index 49dbed79fe5..5d5c2b148d4 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1369,6 +1369,10 @@ static bool add_used_routine(LEX *lex, Query_arena *arena, const LEX_STRING *key, TABLE_LIST *belong_to_view) { + hash_init_opt(&lex->sroutines, system_charset_info, + Query_tables_list::START_SROUTINES_HASH_SIZE, + 0, 0, sp_sroutine_key, 0, 0); + if (!hash_search(&lex->sroutines, (byte *)key->str, key->length)) { Sroutine_hash_entry *rn= diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 405f576ac04..24b9766a658 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1634,9 +1634,18 @@ void Query_tables_list::reset_query_tables_list(bool init) query_tables_last= &query_tables; query_tables_own_last= 0; if (init) - hash_init(&sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0); + { + /* + We delay real initialization of hash (and therefore related + memory allocation) until first insertion into this hash. + */ + hash_clear(&sroutines); + } else if (sroutines.records) + { + /* Non-zero sroutines.records means that hash was initialized. */ my_hash_reset(&sroutines); + } sroutines_list.empty(); sroutines_list_own_last= sroutines_list.next; sroutines_list_own_elements= 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 378f968118e..bfe7d9518f3 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -742,7 +742,11 @@ public: 0 - indicates that this query does not need prelocking. */ TABLE_LIST **query_tables_own_last; - /* Set of stored routines called by statement. */ + /* + Set of stored routines called by statement. + (Note that we use lazy-initialization for this hash). + */ + enum { START_SROUTINES_HASH_SIZE= 16 }; HASH sroutines; /* List linking elements of 'sroutines' set. Allows you to add new elements From 0c9fc6ba4064168316f75af929f56e9328cd23af Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 1 Nov 2006 16:14:49 +0100 Subject: [PATCH 42/47] ndb - revert bug to wait for "proper" bug fix bug#21052 ndb/src/mgmsrv/Services.cpp: revert bug to wait for "proper" bug fix --- ndb/src/mgmsrv/Services.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp index 95afeba30ac..7d59a303df2 100644 --- a/ndb/src/mgmsrv/Services.cpp +++ b/ndb/src/mgmsrv/Services.cpp @@ -1353,12 +1353,6 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId) if (ndb_logevent_body[i].index_fn) val= (*(ndb_logevent_body[i].index_fn))(val); str.appfmt("%s=%d\n",ndb_logevent_body[i].token, val); - if(strcmp(ndb_logevent_body[i].token,"error") == 0) - { - int m_text_len= strlen(m_text); - snprintf(m_text+m_text_len, 4 , " - "); - ndb_error_string(theData[3], m_text+(m_text_len+3), sizeof(m_text)-m_text_len-3); - } } Vector copy; From 74a15e2f8e73ec23c69d667e7c36b03822ba3fb4 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Nov 2006 08:58:51 +0300 Subject: [PATCH 43/47] A post-merge fix. --- mysql-test/r/ps.result | 195 ++++++++++++++++++++--------------------- 1 file changed, 97 insertions(+), 98 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 884bb94e8f7..36b69497e89 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -499,103 +499,6 @@ create temporary table if not exists t1 (a1 int); execute stmt; drop temporary table t1; deallocate prepare stmt; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 (i INT, INDEX(i)); -INSERT INTO t1 VALUES (1); -PREPARE stmt FROM "SELECT (COUNT(i) = 1), COUNT(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(COUNT(i) = 1) COUNT(i) -0 0 -SET @a = 1; -EXECUTE stmt USING @a; -(COUNT(i) = 1) COUNT(i) -1 1 -SET @a = 0; -EXECUTE stmt USING @a; -(COUNT(i) = 1) COUNT(i) -0 0 -PREPARE stmt FROM "SELECT (AVG(i) = 1), AVG(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(AVG(i) = 1) AVG(i) -NULL NULL -SET @a = 1; -EXECUTE stmt USING @a; -(AVG(i) = 1) AVG(i) -1 1.0000 -SET @a = 0; -EXECUTE stmt USING @a; -(AVG(i) = 1) AVG(i) -NULL NULL -PREPARE stmt FROM "SELECT (VARIANCE(i) = 1), VARIANCE(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(VARIANCE(i) = 1) VARIANCE(i) -NULL NULL -SET @a = 1; -EXECUTE stmt USING @a; -(VARIANCE(i) = 1) VARIANCE(i) -0 0.0000 -SET @a = 0; -EXECUTE stmt USING @a; -(VARIANCE(i) = 1) VARIANCE(i) -NULL NULL -PREPARE stmt FROM "SELECT (STDDEV(i) = 1), STDDEV(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(STDDEV(i) = 1) STDDEV(i) -NULL NULL -SET @a = 1; -EXECUTE stmt USING @a; -(STDDEV(i) = 1) STDDEV(i) -0 0.0000 -SET @a = 0; -EXECUTE stmt USING @a; -(STDDEV(i) = 1) STDDEV(i) -NULL NULL -PREPARE stmt FROM "SELECT (BIT_OR(i) = 1), BIT_OR(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(BIT_OR(i) = 1) BIT_OR(i) -0 0 -SET @a = 1; -EXECUTE stmt USING @a; -(BIT_OR(i) = 1) BIT_OR(i) -1 1 -SET @a = 0; -EXECUTE stmt USING @a; -(BIT_OR(i) = 1) BIT_OR(i) -0 0 -PREPARE stmt FROM "SELECT (BIT_AND(i) = 1), BIT_AND(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(BIT_AND(i) = 1) BIT_AND(i) -0 18446744073709551615 -SET @a = 1; -EXECUTE stmt USING @a; -(BIT_AND(i) = 1) BIT_AND(i) -1 1 -SET @a = 0; -EXECUTE stmt USING @a; -(BIT_AND(i) = 1) BIT_AND(i) -0 18446744073709551615 -PREPARE stmt FROM "SELECT (BIT_XOR(i) = 1), BIT_XOR(i) FROM t1 WHERE i = ?"; -SET @a = 0; -EXECUTE stmt USING @a; -(BIT_XOR(i) = 1) BIT_XOR(i) -0 0 -SET @a = 1; -EXECUTE stmt USING @a; -(BIT_XOR(i) = 1) BIT_XOR(i) -1 1 -SET @a = 0; -EXECUTE stmt USING @a; -(BIT_XOR(i) = 1) BIT_XOR(i) -0 0 -DEALLOCATE PREPARE stmt; -DROP TABLE t1; -End of 4.1 tests. create table t1 (a varchar(20)); insert into t1 values ('foo'); prepare stmt FROM 'SELECT char_length (a) FROM t1'; @@ -1053,7 +956,103 @@ GROUP_CONCAT(Track SEPARATOR ', ') CAD DEALLOCATE PREPARE STMT; DROP TABLE t1; -End of 4.1 tests +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT, INDEX(i)); +INSERT INTO t1 VALUES (1); +PREPARE stmt FROM "SELECT (COUNT(i) = 1), COUNT(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(COUNT(i) = 1) COUNT(i) +0 0 +SET @a = 1; +EXECUTE stmt USING @a; +(COUNT(i) = 1) COUNT(i) +1 1 +SET @a = 0; +EXECUTE stmt USING @a; +(COUNT(i) = 1) COUNT(i) +0 0 +PREPARE stmt FROM "SELECT (AVG(i) = 1), AVG(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(AVG(i) = 1) AVG(i) +NULL NULL +SET @a = 1; +EXECUTE stmt USING @a; +(AVG(i) = 1) AVG(i) +1 1.0000 +SET @a = 0; +EXECUTE stmt USING @a; +(AVG(i) = 1) AVG(i) +NULL NULL +PREPARE stmt FROM "SELECT (VARIANCE(i) = 1), VARIANCE(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(VARIANCE(i) = 1) VARIANCE(i) +NULL NULL +SET @a = 1; +EXECUTE stmt USING @a; +(VARIANCE(i) = 1) VARIANCE(i) +0 0.0000 +SET @a = 0; +EXECUTE stmt USING @a; +(VARIANCE(i) = 1) VARIANCE(i) +NULL NULL +PREPARE stmt FROM "SELECT (STDDEV(i) = 1), STDDEV(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(STDDEV(i) = 1) STDDEV(i) +NULL NULL +SET @a = 1; +EXECUTE stmt USING @a; +(STDDEV(i) = 1) STDDEV(i) +0 0.0000 +SET @a = 0; +EXECUTE stmt USING @a; +(STDDEV(i) = 1) STDDEV(i) +NULL NULL +PREPARE stmt FROM "SELECT (BIT_OR(i) = 1), BIT_OR(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_OR(i) = 1) BIT_OR(i) +0 0 +SET @a = 1; +EXECUTE stmt USING @a; +(BIT_OR(i) = 1) BIT_OR(i) +1 1 +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_OR(i) = 1) BIT_OR(i) +0 0 +PREPARE stmt FROM "SELECT (BIT_AND(i) = 1), BIT_AND(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_AND(i) = 1) BIT_AND(i) +0 18446744073709551615 +SET @a = 1; +EXECUTE stmt USING @a; +(BIT_AND(i) = 1) BIT_AND(i) +1 1 +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_AND(i) = 1) BIT_AND(i) +0 18446744073709551615 +PREPARE stmt FROM "SELECT (BIT_XOR(i) = 1), BIT_XOR(i) FROM t1 WHERE i = ?"; +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_XOR(i) = 1) BIT_XOR(i) +0 0 +SET @a = 1; +EXECUTE stmt USING @a; +(BIT_XOR(i) = 1) BIT_XOR(i) +1 1 +SET @a = 0; +EXECUTE stmt USING @a; +(BIT_XOR(i) = 1) BIT_XOR(i) +0 0 +DEALLOCATE PREPARE stmt; +DROP TABLE t1; +End of 4.1 tests. create table t1 (a varchar(20)); insert into t1 values ('foo'); prepare stmt FROM 'SELECT char_length (a) FROM t1'; From 63030d767c98ff0bd57cddfe610b9bbe9ca06a63 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Nov 2006 13:51:43 +0100 Subject: [PATCH 44/47] Better fix for bug#22830 Events: crash with procedure which alters events with function Post-review CS This fix also changes the handling of KILL command combined with subquery. It changes the error message given back to "not supported", from parse error. The error for CREATE|ALTER EVENT has also been changed to generate "not supported yet" instead of parse error. In case of a SP call, the error is "not supported yet". This change cleans the parser from code which should not belong to there. Still LEX::expr_allows_subselect is existant because it simplifies the handling of SQLCOM_HA_READ which forbids subselects. mysql-test/r/events_bugs.result: update resut mysql-test/r/events_grant.result: update result mysql-test/r/kill.result: the error message has been changed for KILL mysql-test/t/events_bugs.test: Update old tests with the new emitted error Add a test case for BUG#22830 Events: crash with procedure which alters events with function mysql-test/t/events_grant.test: add ORDER BY clause to keep the result deterministic. mysql-test/t/kill.test: use name of the error, and change the error from parse error, to not supported sql/sql_lex.cc: Add an auxiliary function that checks whether SP and/or tables are used in the statement. This function is helpful for statements that cannot handle subqueries ans SP calls. Adding out of the parser cleans the latter of handling of special cases and letting it do its job of parsing. sql/sql_lex.h: helper function to check whether a table or SP was used sql/sql_parse.cc: Use LEX::table_or_sp_used() for SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT and SQLCOM_KILL. SQLCOM_DROP event does not use `expr` rule and thus a check is not needed. sql/sql_yacc.yy: Remove usage of LEX::expr_allows_subselect for CREATE|ALTER EVENT and KILL. There is only one left occurence - SQLCOM_HAREAD, but it adds one table to the list of tables --- mysql-test/r/events_bugs.result | 50 ++++++++++++++++++++++++++++--- mysql-test/r/events_grant.result | 22 +++++++------- mysql-test/r/kill.result | 2 +- mysql-test/t/events_bugs.test | 51 +++++++++++++++++++++++++++++--- mysql-test/t/events_grant.test | 12 ++++---- mysql-test/t/kill.test | 2 +- sql/sql_lex.cc | 23 ++++++++++++++ sql/sql_lex.h | 2 ++ sql/sql_parse.cc | 13 ++++++++ sql/sql_yacc.yy | 16 ++-------- 10 files changed, 153 insertions(+), 40 deletions(-) diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result index 08be6924e03..363033e487a 100644 --- a/mysql-test/r/events_bugs.result +++ b/mysql-test/r/events_bugs.result @@ -206,13 +206,13 @@ drop event events_test.mysqltest_user1; drop user mysqltest_user1@localhost; drop database mysqltest_db1; create event e_53 on schedule at (select s1 from ttx) do drop table t; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select s1 from ttx) do drop table t' at line 1 +ERROR 42000: This version of MySQL doesn't yet support 'Usage of subqueries or stored function calls as part of this statement' create event e_53 on schedule every (select s1 from ttx) second do drop table t; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select s1 from ttx) second do drop table t' at line 1 +ERROR 42000: This version of MySQL doesn't yet support 'Usage of subqueries or stored function calls as part of this statement' create event e_53 on schedule every 5 second starts (select s1 from ttx) do drop table t; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select s1 from ttx) do drop table t' at line 1 +ERROR 42000: This version of MySQL doesn't yet support 'Usage of subqueries or stored function calls as part of this statement' create event e_53 on schedule every 5 second ends (select s1 from ttx) do drop table t; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select s1 from ttx) do drop table t' at line 1 +ERROR 42000: This version of MySQL doesn't yet support 'Usage of subqueries or stored function calls as part of this statement' drop event if exists e_16; drop procedure if exists p_16; create event e_16 on schedule every 1 second do set @a=5; @@ -226,4 +226,46 @@ set @a= 6; call p_16(); drop procedure p_16; drop event e_16; +drop function if exists f22830; +drop event if exists e22830; +drop event if exists e22830_1; +drop event if exists e22830_2; +drop event if exists e22830_3; +drop event if exists e22830_4; +drop table if exists t1; +drop table if exists t2; +create table t1 (a int); +insert into t1 values (2); +create table t2 (a char(20)); +insert into t2 values ("e22830_1"); +create function f22830 () returns int return 5; +create event e22830 on schedule every f22830() second do select 123; +ERROR 42000: This version of MySQL doesn't yet support 'Usage of subqueries or stored function calls as part of this statement' +create event e22830_1 on schedule every 1 hour do alter event e22830_1 on schedule every (select 8 from dual) hour; +create event e22830_2 on schedule every 1 hour do alter event e22830_2 on schedule every (select 8 from t1) hour; +create event e22830_3 on schedule every 1 hour do alter event e22830_3 on schedule every f22830() hour; +create event e22830_4 on schedule every 1 hour do alter event e22830_4 on schedule every (select f22830() from dual) hour; +select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name; +event_name event_definition interval_value interval_field +e22830_1 alter event e22830_1 on schedule every (select 8 from dual) hour 1 HOUR +e22830_2 alter event e22830_2 on schedule every (select 8 from t1) hour 1 HOUR +e22830_3 alter event e22830_3 on schedule every f22830() hour 1 HOUR +e22830_4 alter event e22830_4 on schedule every (select f22830() from dual) hour 1 HOUR +set global event_scheduler=on; +set global event_scheduler=off; +select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name; +event_name event_definition interval_value interval_field +e22830_1 alter event e22830_1 on schedule every (select 8 from dual) hour 8 HOUR +e22830_2 alter event e22830_2 on schedule every (select 8 from t1) hour 1 HOUR +e22830_3 alter event e22830_3 on schedule every f22830() hour 1 HOUR +e22830_4 alter event e22830_4 on schedule every (select f22830() from dual) hour 1 HOUR +drop function f22830; +drop event (select a from t2); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(select a from t2)' at line 1 +drop event e22830_1; +drop event e22830_2; +drop event e22830_3; +drop event e22830_4; +drop table t1; +drop table t2; drop database events_test; diff --git a/mysql-test/r/events_grant.result b/mysql-test/r/events_grant.result index eda0759d518..a28c30a9345 100644 --- a/mysql-test/r/events_grant.result +++ b/mysql-test/r/events_grant.result @@ -4,7 +4,7 @@ CREATE EVENT one_event ON SCHEDULE EVERY 10 SECOND DO SELECT 123; SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME; EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT NULL events_test one_event root@localhost SQL SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE CREATE DATABASE events_test2; @@ -57,37 +57,37 @@ USE events_test2; CREATE EVENT four_event ON SCHEDULE EVERY 20 SECOND DO SELECT 42; USE events_test; "We should see 4 events : one_event, two_event, three_event & four_event" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME; EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT NULL events_test one_event root@localhost SQL SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE -NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event NULL events_test three_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event +NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event NULL events_test2 four_event ev_test@localhost SQL SELECT 42 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE DROP DATABASE events_test2; "We should see 3 events : one_event, two_event, three_event" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME; EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT NULL events_test one_event root@localhost SQL SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE -NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event NULL events_test three_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event +NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event CREATE DATABASE events_test2; USE events_test2; CREATE EVENT five_event ON SCHEDULE EVERY 20 SECOND DO SELECT 42; "Should see 4 events - one, two, three & five" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME; EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT NULL events_test one_event root@localhost SQL SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE -NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event NULL events_test three_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event +NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event NULL events_test2 five_event root@localhost SQL SELECT 42 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE REVOKE EVENT ON events_test2.* FROM ev_test@localhost; USE test; "Should see 3 events - one, two & three" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME; EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT NULL events_test one_event root@localhost SQL SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE -NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event NULL events_test three_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event +NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event "Let's test ALTER EVENT which changes the definer" USE events_test; ALTER EVENT one_event ON SCHEDULE EVERY 10 SECOND; @@ -111,10 +111,10 @@ ALTER EVENT one_event COMMENT "new comment"; "test DROP by another user" DROP EVENT one_event; "One event should not be there" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME; EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT -NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event NULL events_test three_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event +NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event NULL events_test2 five_event root@localhost SQL SELECT 42 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE DROP USER ev_test@localhost; DROP DATABASE events_test2; diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result index b78c677fb02..1795457220b 100644 --- a/mysql-test/r/kill.result +++ b/mysql-test/r/kill.result @@ -16,7 +16,7 @@ select 4; 4 drop table t1; kill (select count(*) from mysql.user); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select count(*) from mysql.user)' at line 1 +ERROR 42000: This version of MySQL doesn't yet support 'Usage of subqueries or stored function calls as part of this statement' create table t1 (id int primary key); create table t2 (id int unsigned not null); insert into t2 select id from t1; diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test index 60e8c78d8bb..6223395bfd9 100644 --- a/mysql-test/t/events_bugs.test +++ b/mysql-test/t/events_bugs.test @@ -222,13 +222,13 @@ drop database mysqltest_db1; # # START - BUG#16394: Events: Crash if schedule contains SELECT # ---error ER_PARSE_ERROR +--error ER_NOT_SUPPORTED_YET create event e_53 on schedule at (select s1 from ttx) do drop table t; ---error ER_PARSE_ERROR +--error ER_NOT_SUPPORTED_YET create event e_53 on schedule every (select s1 from ttx) second do drop table t; ---error ER_PARSE_ERROR +--error ER_NOT_SUPPORTED_YET create event e_53 on schedule every 5 second starts (select s1 from ttx) do drop table t; ---error ER_PARSE_ERROR +--error ER_NOT_SUPPORTED_YET create event e_53 on schedule every 5 second ends (select s1 from ttx) do drop table t; # # END - BUG#16394: Events: Crash if schedule contains SELECT @@ -253,4 +253,47 @@ call p_16(); drop procedure p_16; drop event e_16; + +# +# START - BUG#22830 Events: crash with procedure which alters events with function +# +--disable_warnings +drop function if exists f22830; +drop event if exists e22830; +drop event if exists e22830_1; +drop event if exists e22830_2; +drop event if exists e22830_3; +drop event if exists e22830_4; +drop table if exists t1; +drop table if exists t2; +--enable_warnings +create table t1 (a int); +insert into t1 values (2); +create table t2 (a char(20)); +insert into t2 values ("e22830_1"); +create function f22830 () returns int return 5; +--error ER_NOT_SUPPORTED_YET +create event e22830 on schedule every f22830() second do select 123; +create event e22830_1 on schedule every 1 hour do alter event e22830_1 on schedule every (select 8 from dual) hour; +create event e22830_2 on schedule every 1 hour do alter event e22830_2 on schedule every (select 8 from t1) hour; +create event e22830_3 on schedule every 1 hour do alter event e22830_3 on schedule every f22830() hour; +create event e22830_4 on schedule every 1 hour do alter event e22830_4 on schedule every (select f22830() from dual) hour; +select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name; +set global event_scheduler=on; +--sleep 0.7 +set global event_scheduler=off; +select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name; +drop function f22830; +--error ER_PARSE_ERROR +drop event (select a from t2); +drop event e22830_1; +drop event e22830_2; +drop event e22830_3; +drop event e22830_4; +drop table t1; +drop table t2; + +# +# End of tests +# drop database events_test; diff --git a/mysql-test/t/events_grant.test b/mysql-test/t/events_grant.test index 3ead141c27c..44288fc1ac6 100644 --- a/mysql-test/t/events_grant.test +++ b/mysql-test/t/events_grant.test @@ -9,7 +9,7 @@ use events_test; CREATE EVENT one_event ON SCHEDULE EVERY 10 SECOND DO SELECT 123; --replace_column 8 # 9 # SHOW EVENTS; -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME; CREATE DATABASE events_test2; CREATE USER ev_test@localhost; GRANT ALL ON events_test.* to ev_test@localhost; @@ -55,10 +55,10 @@ CREATE EVENT four_event ON SCHEDULE EVERY 20 SECOND DO SELECT 42; connection default; USE events_test; --echo "We should see 4 events : one_event, two_event, three_event & four_event" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME; DROP DATABASE events_test2; --echo "We should see 3 events : one_event, two_event, three_event" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME; connection default; CREATE DATABASE events_test2; @@ -67,13 +67,13 @@ CREATE EVENT five_event ON SCHEDULE EVERY 20 SECOND DO SELECT 42; connection ev_con1; --echo "Should see 4 events - one, two, three & five" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME; connection default; REVOKE EVENT ON events_test2.* FROM ev_test@localhost; connection ev_con1; USE test; --echo "Should see 3 events - one, two & three" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME; --echo "Let's test ALTER EVENT which changes the definer" USE events_test; ALTER EVENT one_event ON SCHEDULE EVERY 10 SECOND; @@ -96,7 +96,7 @@ connection ev_con1; DROP EVENT one_event; connection default; --echo "One event should not be there" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS ORDER BY EVENT_SCHEMA, EVENT_NAME; disconnect ev_con1; connection default; DROP USER ev_test@localhost; diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index f8ba649b3eb..53a88df7bd9 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -48,7 +48,7 @@ select 4; drop table t1; connection default; ---error 1064 +--error ER_NOT_SUPPORTED_YET kill (select count(*) from mysql.user); # diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 2aa7e1c11c4..5ae6c0cb77b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2140,6 +2140,28 @@ void st_lex::restore_backup_query_tables_list(Query_tables_list *backup) } +/* + Checks for usage of routines and/or tables in a parsed statement + + SYNOPSIS + st_lex:table_or_sp_used() + + RETURN + FALSE No routines and tables used + TRUE Either or both routines and tables are used. +*/ + +bool st_lex::table_or_sp_used() +{ + DBUG_ENTER("table_or_sp_used"); + + if (sroutines.records || query_tables) + DBUG_RETURN(TRUE); + + DBUG_RETURN(FALSE); +} + + /* Do end-of-prepare fixup for list of tables and their merge-VIEWed tables @@ -2207,6 +2229,7 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds, } } + /* There are st_select_lex::add_table_to_list & st_select_lex::set_lock_for_tables are in sql_parse.cc diff --git a/sql/sql_lex.h b/sql/sql_lex.h index c8acc9aeca4..0b01cbb7be4 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1199,6 +1199,8 @@ typedef struct st_lex : public Query_tables_list void reset_n_backup_query_tables_list(Query_tables_list *backup); void restore_backup_query_tables_list(Query_tables_list *backup); + + bool table_or_sp_used(); } LEX; struct st_lex_local: public st_lex diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0dd9823ffe3..5f7a50cd18b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3906,6 +3906,12 @@ end_with_restore_list: case SQLCOM_ALTER_EVENT: { DBUG_ASSERT(lex->event_parse_data); + if (lex->table_or_sp_used()) + { + my_error(ER_NOT_SUPPORTED_YET, MYF(0), "Usage of subqueries or stored " + "function calls as part of this statement"); + break; + } switch (lex->sql_command) { case SQLCOM_CREATE_EVENT: res= Events::get_instance()-> @@ -4207,6 +4213,13 @@ end_with_restore_list: { Item *it= (Item *)lex->value_list.head(); + if (lex->table_or_sp_used()) + { + my_error(ER_NOT_SUPPORTED_YET, MYF(0), "Usage of subqueries or stored " + "function calls as part of this statement"); + break; + } + if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1)) { my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a6ae102fa0c..bbe8bac33ba 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1329,7 +1329,6 @@ event_tail: Lex->sql_command= SQLCOM_CREATE_EVENT; /* We need that for disallowing subqueries */ - Lex->expr_allows_subselect= FALSE; } ON SCHEDULE_SYM ev_schedule_time opt_ev_on_completion @@ -1351,7 +1350,6 @@ event_tail: can overwrite it */ Lex->sql_command= SQLCOM_CREATE_EVENT; - Lex->expr_allows_subselect= TRUE; } ; @@ -4736,8 +4734,6 @@ alter: YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; Lex->sql_command= SQLCOM_ALTER_EVENT; - /* we need that for disallowing subqueries */ - Lex->expr_allows_subselect= FALSE; } ev_alter_on_schedule_completion opt_ev_rename_to @@ -4763,7 +4759,6 @@ alter: can overwrite it */ Lex->sql_command= SQLCOM_ALTER_EVENT; - Lex->expr_allows_subselect= TRUE; } | ALTER TABLESPACE alter_tablespace_info { @@ -8638,17 +8633,12 @@ purge_option: /* kill threads */ kill: - KILL_SYM - { - Lex->sql_command= SQLCOM_KILL; - Lex->expr_allows_subselect= FALSE; - } - kill_option expr + KILL_SYM kill_option expr { LEX *lex=Lex; lex->value_list.empty(); - lex->value_list.push_front($4); - Lex->expr_allows_subselect= TRUE; + lex->value_list.push_front($3); + lex->sql_command= SQLCOM_KILL; }; kill_option: From 384407aaeb37dafe4826c31006cd47c611da0da2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Nov 2006 11:01:53 -0700 Subject: [PATCH 45/47] Bug#21114 (Foreign key creation fails to table with name format) Due to the complexity of this change, everything is documented in WL#3565 This patch is the third iteration, it takes into account the comments received to date. mysql-test/r/func_math.result: Improved test coverage mysql-test/r/view.result: Name collision, x() is a geometry native in function mysql-test/t/func_math.test: Improved test coverage mysql-test/t/view.test: Name collision, x() is a geometry native in function sql/item_create.cc: Revised the create_func implementation sql/item_create.h: Revised the create_func implementation sql/item_geofunc.h: Explicit Item allocation in the thread memory pool. sql/lex.h: Removed function parsing from the lexical parser sql/lex_symbol.h: Removed function parsing from the lexical parser sql/mysql_priv.h: Server initialization and shutdown sql/mysqld.cc: Server initialization and shutdown sql/share/errmsg.txt: New error messages sql/sql_yacc.yy: Removed function parsing from the lexical parser tests/mysql_client_test.c: Spaces are no longer significant for function calls mysql-test/include/parser_bug21114.inc: New tests mysql-test/r/parser.result: New tests mysql-test/r/parser_bug21114_innodb.result: New tests mysql-test/t/parser.test: New tests mysql-test/t/parser_bug21114_innodb.test: New tests --- mysql-test/include/parser_bug21114.inc | 59 + mysql-test/r/func_math.result | 12 + mysql-test/r/parser.result | 388 ++ mysql-test/r/parser_bug21114_innodb.result | 867 ++++ mysql-test/r/view.result | 8 +- mysql-test/t/func_math.test | 5 + mysql-test/t/parser.test | 510 ++ mysql-test/t/parser_bug21114_innodb.test | 422 ++ mysql-test/t/view.test | 6 +- sql/item_create.cc | 5118 ++++++++++++++++++-- sql/item_create.h | 274 +- sql/item_geofunc.h | 4 +- sql/lex.h | 216 +- sql/lex_symbol.h | 1 - sql/mysql_priv.h | 4 + sql/mysqld.cc | 3 + sql/share/errmsg.txt | 4 + sql/sql_yacc.yy | 1516 +++--- tests/mysql_client_test.c | 2 +- 19 files changed, 7792 insertions(+), 1627 deletions(-) create mode 100755 mysql-test/include/parser_bug21114.inc create mode 100644 mysql-test/r/parser.result create mode 100644 mysql-test/r/parser_bug21114_innodb.result create mode 100644 mysql-test/t/parser.test create mode 100644 mysql-test/t/parser_bug21114_innodb.test diff --git a/mysql-test/include/parser_bug21114.inc b/mysql-test/include/parser_bug21114.inc new file mode 100755 index 00000000000..eb709d5cc03 --- /dev/null +++ b/mysql-test/include/parser_bug21114.inc @@ -0,0 +1,59 @@ +# +# Bug#21114 (Foreign key creation fails to table with name format) +# +# Trying to trick the parser into thinking $FCT(...) is a function call, +# which is not in the CREATE TABLE and FOREIGN KEY ... REFERENCES syntax +# +# Usage : +# +# let $engine_type=InnoDb; +# let $verbose=1; +# let $FCT= ; +# -- source parser_stress_func.inc +# let $FCT= ; +# -- source parser_stress_func.inc +# let $verbose=0; +# let $FCT= ; +# -- source parser_stress_func.inc +# let $FCT= ; +# -- source parser_stress_func.inc + +-- disable_warnings +eval drop table if exists $FCT; +drop table if exists bug21114_child; +-- enable_warnings + +--disable_query_log +--disable_result_log + +eval CREATE TABLE $FCT( + col1 int not null, + col2 int not null, + col3 varchar(10), + CONSTRAINT pk PRIMARY KEY (col1, col2) +) ENGINE $engine_type; + +eval CREATE TABLE bug21114_child( + pk int not null, + fk_col1 int not null, + fk_col2 int not null, + fk_col3 int not null, + fk_col4 int not null, + CONSTRAINT fk_fct FOREIGN KEY (fk_col1, fk_col2) + REFERENCES $FCT(col1, col2), + CONSTRAINT fk_fct_space FOREIGN KEY (fk_col3, fk_col4) + REFERENCES $FCT (col1, col2) +) ENGINE $engine_type; + +--enable_query_log +--enable_result_log + +if ($verbose) +{ + eval SHOW CREATE TABLE $FCT; + SHOW CREATE TABLE bug21114_child; +} + +DROP TABLE bug21114_child; +eval DROP TABLE $FCT; + diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index 4bd18ae589e..9a2c55b802d 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -102,6 +102,18 @@ Note 1003 select pi() AS `pi()`,format(sin((pi() / 2)),6) AS `format(sin(pi()/2) select degrees(pi()),radians(360); degrees(pi()) radians(360) 180 6.2831853071796 +select format(atan(-2, 2), 6); +format(atan(-2, 2), 6) +-0.785398 +select format(atan(pi(), 0), 6); +format(atan(pi(), 0), 6) +1.570796 +select format(atan2(-2, 2), 6); +format(atan2(-2, 2), 6) +-0.785398 +select format(atan2(pi(), 0), 6); +format(atan2(pi(), 0), 6) +1.570796 SELECT ACOS(1.0); ACOS(1.0) 0 diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result new file mode 100644 index 00000000000..afd78561898 --- /dev/null +++ b/mysql-test/r/parser.result @@ -0,0 +1,388 @@ +SET @save_sql_mode=@@sql_mode; +set SQL_MODE=''; +create table ADDDATE(a int); +drop table ADDDATE; +create table ADDDATE (a int); +drop table ADDDATE; +create table BIT_AND(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BIT_AND(a int)' at line 1 +create table BIT_AND (a int); +drop table BIT_AND; +create table BIT_OR(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BIT_OR(a int)' at line 1 +create table BIT_OR (a int); +drop table BIT_OR; +create table BIT_XOR(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BIT_XOR(a int)' at line 1 +create table BIT_XOR (a int); +drop table BIT_XOR; +create table CAST(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CAST(a int)' at line 1 +create table CAST (a int); +drop table CAST; +create table COUNT(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'COUNT(a int)' at line 1 +create table COUNT (a int); +drop table COUNT; +create table CURDATE(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CURDATE(a int)' at line 1 +create table CURDATE (a int); +drop table CURDATE; +create table CURTIME(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CURTIME(a int)' at line 1 +create table CURTIME (a int); +drop table CURTIME; +create table DATE_ADD(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DATE_ADD(a int)' at line 1 +create table DATE_ADD (a int); +drop table DATE_ADD; +create table DATE_SUB(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DATE_SUB(a int)' at line 1 +create table DATE_SUB (a int); +drop table DATE_SUB; +create table EXTRACT(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'EXTRACT(a int)' at line 1 +create table EXTRACT (a int); +drop table EXTRACT; +create table GROUP_CONCAT(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GROUP_CONCAT(a int)' at line 1 +create table GROUP_CONCAT (a int); +drop table GROUP_CONCAT; +create table GROUP_UNIQUE_USERS(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GROUP_UNIQUE_USERS(a int)' at line 1 +create table GROUP_UNIQUE_USERS (a int); +drop table GROUP_UNIQUE_USERS; +create table MAX(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'MAX(a int)' at line 1 +create table MAX (a int); +drop table MAX; +create table MID(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'MID(a int)' at line 1 +create table MID (a int); +drop table MID; +create table MIN(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'MIN(a int)' at line 1 +create table MIN (a int); +drop table MIN; +create table NOW(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NOW(a int)' at line 1 +create table NOW (a int); +drop table NOW; +create table POSITION(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'POSITION(a int)' at line 1 +create table POSITION (a int); +drop table POSITION; +create table SESSION_USER(a int); +drop table SESSION_USER; +create table SESSION_USER (a int); +drop table SESSION_USER; +create table STD(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'STD(a int)' at line 1 +create table STD (a int); +drop table STD; +create table STDDEV(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'STDDEV(a int)' at line 1 +create table STDDEV (a int); +drop table STDDEV; +create table STDDEV_POP(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'STDDEV_POP(a int)' at line 1 +create table STDDEV_POP (a int); +drop table STDDEV_POP; +create table STDDEV_SAMP(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'STDDEV_SAMP(a int)' at line 1 +create table STDDEV_SAMP (a int); +drop table STDDEV_SAMP; +create table SUBDATE(a int); +drop table SUBDATE; +create table SUBDATE (a int); +drop table SUBDATE; +create table SUBSTR(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SUBSTR(a int)' at line 1 +create table SUBSTR (a int); +drop table SUBSTR; +create table SUBSTRING(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SUBSTRING(a int)' at line 1 +create table SUBSTRING (a int); +drop table SUBSTRING; +create table SUM(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SUM(a int)' at line 1 +create table SUM (a int); +drop table SUM; +create table SYSDATE(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SYSDATE(a int)' at line 1 +create table SYSDATE (a int); +drop table SYSDATE; +create table SYSTEM_USER(a int); +drop table SYSTEM_USER; +create table SYSTEM_USER (a int); +drop table SYSTEM_USER; +create table TRIM(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TRIM(a int)' at line 1 +create table TRIM (a int); +drop table TRIM; +create table UNIQUE_USERS(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNIQUE_USERS(a int)' at line 1 +create table UNIQUE_USERS (a int); +drop table UNIQUE_USERS; +create table VARIANCE(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VARIANCE(a int)' at line 1 +create table VARIANCE (a int); +drop table VARIANCE; +create table VAR_POP(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VAR_POP(a int)' at line 1 +create table VAR_POP (a int); +drop table VAR_POP; +create table VAR_SAMP(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VAR_SAMP(a int)' at line 1 +create table VAR_SAMP (a int); +drop table VAR_SAMP; +set SQL_MODE='IGNORE_SPACE'; +create table ADDDATE(a int); +drop table ADDDATE; +create table ADDDATE (a int); +drop table ADDDATE; +create table BIT_AND(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BIT_AND(a int)' at line 1 +create table BIT_AND (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BIT_AND (a int)' at line 1 +create table BIT_OR(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BIT_OR(a int)' at line 1 +create table BIT_OR (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BIT_OR (a int)' at line 1 +create table BIT_XOR(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BIT_XOR(a int)' at line 1 +create table BIT_XOR (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BIT_XOR (a int)' at line 1 +create table CAST(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CAST(a int)' at line 1 +create table CAST (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CAST (a int)' at line 1 +create table COUNT(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'COUNT(a int)' at line 1 +create table COUNT (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'COUNT (a int)' at line 1 +create table CURDATE(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CURDATE(a int)' at line 1 +create table CURDATE (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CURDATE (a int)' at line 1 +create table CURTIME(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CURTIME(a int)' at line 1 +create table CURTIME (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CURTIME (a int)' at line 1 +create table DATE_ADD(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DATE_ADD(a int)' at line 1 +create table DATE_ADD (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DATE_ADD (a int)' at line 1 +create table DATE_SUB(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DATE_SUB(a int)' at line 1 +create table DATE_SUB (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DATE_SUB (a int)' at line 1 +create table EXTRACT(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'EXTRACT(a int)' at line 1 +create table EXTRACT (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'EXTRACT (a int)' at line 1 +create table GROUP_CONCAT(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GROUP_CONCAT(a int)' at line 1 +create table GROUP_CONCAT (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GROUP_CONCAT (a int)' at line 1 +create table GROUP_UNIQUE_USERS(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GROUP_UNIQUE_USERS(a int)' at line 1 +create table GROUP_UNIQUE_USERS (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GROUP_UNIQUE_USERS (a int)' at line 1 +create table MAX(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'MAX(a int)' at line 1 +create table MAX (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'MAX (a int)' at line 1 +create table MID(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'MID(a int)' at line 1 +create table MID (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'MID (a int)' at line 1 +create table MIN(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'MIN(a int)' at line 1 +create table MIN (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'MIN (a int)' at line 1 +create table NOW(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NOW(a int)' at line 1 +create table NOW (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NOW (a int)' at line 1 +create table POSITION(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'POSITION(a int)' at line 1 +create table POSITION (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'POSITION (a int)' at line 1 +create table SESSION_USER(a int); +drop table SESSION_USER; +create table SESSION_USER (a int); +drop table SESSION_USER; +create table STD(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'STD(a int)' at line 1 +create table STD (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'STD (a int)' at line 1 +create table STDDEV(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'STDDEV(a int)' at line 1 +create table STDDEV (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'STDDEV (a int)' at line 1 +create table STDDEV_POP(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'STDDEV_POP(a int)' at line 1 +create table STDDEV_POP (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'STDDEV_POP (a int)' at line 1 +create table STDDEV_SAMP(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'STDDEV_SAMP(a int)' at line 1 +create table STDDEV_SAMP (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'STDDEV_SAMP (a int)' at line 1 +create table SUBDATE(a int); +drop table SUBDATE; +create table SUBDATE (a int); +drop table SUBDATE; +create table SUBSTR(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SUBSTR(a int)' at line 1 +create table SUBSTR (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SUBSTR (a int)' at line 1 +create table SUBSTRING(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SUBSTRING(a int)' at line 1 +create table SUBSTRING (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SUBSTRING (a int)' at line 1 +create table SUM(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SUM(a int)' at line 1 +create table SUM (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SUM (a int)' at line 1 +create table SYSDATE(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SYSDATE(a int)' at line 1 +create table SYSDATE (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SYSDATE (a int)' at line 1 +create table SYSTEM_USER(a int); +drop table SYSTEM_USER; +create table SYSTEM_USER (a int); +drop table SYSTEM_USER; +create table TRIM(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TRIM(a int)' at line 1 +create table TRIM (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TRIM (a int)' at line 1 +create table UNIQUE_USERS(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNIQUE_USERS(a int)' at line 1 +create table UNIQUE_USERS (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNIQUE_USERS (a int)' at line 1 +create table VARIANCE(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VARIANCE(a int)' at line 1 +create table VARIANCE (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VARIANCE (a int)' at line 1 +create table VAR_POP(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VAR_POP(a int)' at line 1 +create table VAR_POP (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VAR_POP (a int)' at line 1 +create table VAR_SAMP(a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VAR_SAMP(a int)' at line 1 +create table VAR_SAMP (a int); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VAR_SAMP (a int)' at line 1 +SET @@sql_mode=@save_sql_mode; +select pi(3.14); +ERROR 42000: Incorrect parameter count in the call to native function 'pi' +select tan(); +ERROR 42000: Incorrect parameter count in the call to native function 'tan' +select tan(1, 2); +ERROR 42000: Incorrect parameter count in the call to native function 'tan' +select makedate(1); +ERROR 42000: Incorrect parameter count in the call to native function 'makedate' +select makedate(1, 2, 3); +ERROR 42000: Incorrect parameter count in the call to native function 'makedate' +select maketime(); +ERROR 42000: Incorrect parameter count in the call to native function 'maketime' +select maketime(1); +ERROR 42000: Incorrect parameter count in the call to native function 'maketime' +select maketime(1, 2); +ERROR 42000: Incorrect parameter count in the call to native function 'maketime' +select maketime(1, 2, 3, 4); +ERROR 42000: Incorrect parameter count in the call to native function 'maketime' +select atan(); +ERROR 42000: Incorrect parameter count in the call to native function 'atan' +select atan2(1, 2, 3); +ERROR 42000: Incorrect parameter count in the call to native function 'atan2' +select benchmark(10, 1+1); +benchmark(10, 1+1) +0 +select benchmark(5+5, 2); +ERROR 42000: Incorrect parameters in the call to native function 'BENCHMARK' +select concat(); +ERROR 42000: Incorrect parameter count in the call to native function 'concat' +select concat("foo"); +concat("foo") +foo +select concat_ws(); +ERROR 42000: Incorrect parameter count in the call to native function 'concat_ws' +select concat_ws("foo"); +ERROR 42000: Incorrect parameter count in the call to native function 'concat_ws' +set @pwd="my password"; +select encode("secret", @pwd); +ERROR 42000: Incorrect parameters in the call to native function 'ENCODE' +select decode("encoded-secret", @pwd); +ERROR 42000: Incorrect parameters in the call to native function 'DECODE' +select encrypt(); +ERROR 42000: Incorrect parameter count in the call to native function 'encrypt' +select encrypt(1, 2, 3); +ERROR 42000: Incorrect parameter count in the call to native function 'encrypt' +select des_encrypt("p1", "p2", "not expected"); +ERROR 42000: Incorrect parameter count in the call to native function 'des_encrypt' +select des_decrypt("p1", "p2", "not expected"); +ERROR 42000: Incorrect parameter count in the call to native function 'des_decrypt' +select elt(); +ERROR 42000: Incorrect parameter count in the call to native function 'elt' +select elt(1); +ERROR 42000: Incorrect parameter count in the call to native function 'elt' +select export_set(); +ERROR 42000: Incorrect parameter count in the call to native function 'export_set' +select export_set("p1"); +ERROR 42000: Incorrect parameter count in the call to native function 'export_set' +select export_set("p1", "p2"); +ERROR 42000: Incorrect parameter count in the call to native function 'export_set' +select export_set("p1", "p2", "p3", "p4", "p5", "p6"); +ERROR 42000: Incorrect parameter count in the call to native function 'export_set' +select field(); +ERROR 42000: Incorrect parameter count in the call to native function 'field' +select field("p1"); +ERROR 42000: Incorrect parameter count in the call to native function 'field' +set @dec=2; +select format(pi(), @dec); +ERROR 42000: Incorrect parameters in the call to native function 'FORMAT' +select from_unixtime(); +ERROR 42000: Incorrect parameter count in the call to native function 'from_unixtime' +select from_unixtime(1, 2, 3); +ERROR 42000: Incorrect parameter count in the call to native function 'from_unixtime' +select unix_timestamp(1, 2); +ERROR 42000: Incorrect parameter count in the call to native function 'unix_timestamp' +select greatest(); +ERROR 42000: Incorrect parameter count in the call to native function 'greatest' +select greatest(12); +ERROR 42000: Incorrect parameter count in the call to native function 'greatest' +select last_insert_id(1, 2); +ERROR 42000: Incorrect parameter count in the call to native function 'last_insert_id' +select least(); +ERROR 42000: Incorrect parameter count in the call to native function 'least' +select least(12); +ERROR 42000: Incorrect parameter count in the call to native function 'least' +select locate(); +ERROR 42000: Incorrect parameter count in the call to native function 'locate' +select locate(1); +ERROR 42000: Incorrect parameter count in the call to native function 'locate' +select locate(1, 2, 3, 4); +ERROR 42000: Incorrect parameter count in the call to native function 'locate' +select log(); +ERROR 42000: Incorrect parameter count in the call to native function 'log' +select log(1, 2, 3); +ERROR 42000: Incorrect parameter count in the call to native function 'log' +select make_set(); +ERROR 42000: Incorrect parameter count in the call to native function 'make_set' +select make_set(1); +ERROR 42000: Incorrect parameter count in the call to native function 'make_set' +select master_pos_wait(); +ERROR 42000: Incorrect parameter count in the call to native function 'master_pos_wait' +select master_pos_wait(1); +ERROR 42000: Incorrect parameter count in the call to native function 'master_pos_wait' +select master_pos_wait(1, 2, 3, 4); +ERROR 42000: Incorrect parameter count in the call to native function 'master_pos_wait' +select rand(1, 2, 3); +ERROR 42000: Incorrect parameter count in the call to native function 'rand' +select round(1, 2, 3); +ERROR 42000: Incorrect parameter count in the call to native function 'round' +select yearweek(); +ERROR 42000: Incorrect parameter count in the call to native function 'yearweek' +select yearweek(1, 2, 3); +ERROR 42000: Incorrect parameter count in the call to native function 'yearweek' diff --git a/mysql-test/r/parser_bug21114_innodb.result b/mysql-test/r/parser_bug21114_innodb.result new file mode 100644 index 00000000000..d3ceda38979 --- /dev/null +++ b/mysql-test/r/parser_bug21114_innodb.result @@ -0,0 +1,867 @@ +drop table if exists ABS; +drop table if exists bug21114_child; +SHOW CREATE TABLE ABS; +Table Create Table +ABS CREATE TABLE `ABS` ( + `col1` int(11) NOT NULL, + `col2` int(11) NOT NULL, + `col3` varchar(10) DEFAULT NULL, + PRIMARY KEY (`col1`,`col2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE bug21114_child; +Table Create Table +bug21114_child CREATE TABLE `bug21114_child` ( + `pk` int(11) NOT NULL, + `fk_col1` int(11) NOT NULL, + `fk_col2` int(11) NOT NULL, + `fk_col3` int(11) NOT NULL, + `fk_col4` int(11) NOT NULL, + KEY `fk_fct` (`fk_col1`,`fk_col2`), + KEY `fk_fct_space` (`fk_col3`,`fk_col4`), + CONSTRAINT `fk_fct` FOREIGN KEY (`fk_col1`, `fk_col2`) REFERENCES `ABS` (`col1`, `col2`), + CONSTRAINT `fk_fct_space` FOREIGN KEY (`fk_col3`, `fk_col4`) REFERENCES `ABS` (`col1`, `col2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE bug21114_child; +DROP TABLE ABS; +drop table if exists FIELD; +drop table if exists bug21114_child; +SHOW CREATE TABLE FIELD; +Table Create Table +FIELD CREATE TABLE `FIELD` ( + `col1` int(11) NOT NULL, + `col2` int(11) NOT NULL, + `col3` varchar(10) DEFAULT NULL, + PRIMARY KEY (`col1`,`col2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE bug21114_child; +Table Create Table +bug21114_child CREATE TABLE `bug21114_child` ( + `pk` int(11) NOT NULL, + `fk_col1` int(11) NOT NULL, + `fk_col2` int(11) NOT NULL, + `fk_col3` int(11) NOT NULL, + `fk_col4` int(11) NOT NULL, + KEY `fk_fct` (`fk_col1`,`fk_col2`), + KEY `fk_fct_space` (`fk_col3`,`fk_col4`), + CONSTRAINT `fk_fct` FOREIGN KEY (`fk_col1`, `fk_col2`) REFERENCES `FIELD` (`col1`, `col2`), + CONSTRAINT `fk_fct_space` FOREIGN KEY (`fk_col3`, `fk_col4`) REFERENCES `FIELD` (`col1`, `col2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE bug21114_child; +DROP TABLE FIELD; +drop table if exists FORMAT; +drop table if exists bug21114_child; +SHOW CREATE TABLE FORMAT; +Table Create Table +FORMAT CREATE TABLE `FORMAT` ( + `col1` int(11) NOT NULL, + `col2` int(11) NOT NULL, + `col3` varchar(10) DEFAULT NULL, + PRIMARY KEY (`col1`,`col2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW CREATE TABLE bug21114_child; +Table Create Table +bug21114_child CREATE TABLE `bug21114_child` ( + `pk` int(11) NOT NULL, + `fk_col1` int(11) NOT NULL, + `fk_col2` int(11) NOT NULL, + `fk_col3` int(11) NOT NULL, + `fk_col4` int(11) NOT NULL, + KEY `fk_fct` (`fk_col1`,`fk_col2`), + KEY `fk_fct_space` (`fk_col3`,`fk_col4`), + CONSTRAINT `fk_fct` FOREIGN KEY (`fk_col1`, `fk_col2`) REFERENCES `FORMAT` (`col1`, `col2`), + CONSTRAINT `fk_fct_space` FOREIGN KEY (`fk_col3`, `fk_col4`) REFERENCES `FORMAT` (`col1`, `col2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE bug21114_child; +DROP TABLE FORMAT; +drop table if exists ACOS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ACOS; +drop table if exists ADDDATE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ADDDATE; +drop table if exists ADDTIME; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ADDTIME; +drop table if exists AES_DECRYPT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE AES_DECRYPT; +drop table if exists AES_ENCRYPT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE AES_ENCRYPT; +drop table if exists AREA; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE AREA; +drop table if exists ASBINARY; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ASBINARY; +drop table if exists ASIN; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ASIN; +drop table if exists ASTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ASTEXT; +drop table if exists ASWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ASWKB; +drop table if exists ASWKT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ASWKT; +drop table if exists ATAN; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ATAN; +drop table if exists ATAN2; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ATAN2; +drop table if exists BENCHMARK; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE BENCHMARK; +drop table if exists BIN; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE BIN; +drop table if exists BIT_COUNT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE BIT_COUNT; +drop table if exists BIT_LENGTH; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE BIT_LENGTH; +drop table if exists CEIL; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE CEIL; +drop table if exists CEILING; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE CEILING; +drop table if exists CENTROID; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE CENTROID; +drop table if exists CHARACTER_LENGTH; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE CHARACTER_LENGTH; +drop table if exists CHAR_LENGTH; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE CHAR_LENGTH; +drop table if exists COERCIBILITY; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE COERCIBILITY; +drop table if exists COMPRESS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE COMPRESS; +drop table if exists CONCAT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE CONCAT; +drop table if exists CONCAT_WS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE CONCAT_WS; +drop table if exists CONNECTION_ID; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE CONNECTION_ID; +drop table if exists CONV; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE CONV; +drop table if exists CONVERT_TZ; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE CONVERT_TZ; +drop table if exists COS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE COS; +drop table if exists COT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE COT; +drop table if exists CRC32; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE CRC32; +drop table if exists CROSSES; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE CROSSES; +drop table if exists DATEDIFF; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE DATEDIFF; +drop table if exists DATE_FORMAT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE DATE_FORMAT; +drop table if exists DAYNAME; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE DAYNAME; +drop table if exists DAYOFMONTH; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE DAYOFMONTH; +drop table if exists DAYOFWEEK; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE DAYOFWEEK; +drop table if exists DAYOFYEAR; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE DAYOFYEAR; +drop table if exists DECODE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE DECODE; +drop table if exists DEGREES; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE DEGREES; +drop table if exists DES_DECRYPT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE DES_DECRYPT; +drop table if exists DES_ENCRYPT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE DES_ENCRYPT; +drop table if exists DIMENSION; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE DIMENSION; +drop table if exists DISJOINT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE DISJOINT; +drop table if exists ELT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ELT; +drop table if exists ENCODE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ENCODE; +drop table if exists ENCRYPT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ENCRYPT; +drop table if exists ENDPOINT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ENDPOINT; +drop table if exists ENVELOPE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ENVELOPE; +drop table if exists EQUALS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE EQUALS; +drop table if exists EXP; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE EXP; +drop table if exists EXPORT_SET; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE EXPORT_SET; +drop table if exists EXTERIORRING; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE EXTERIORRING; +drop table if exists EXTRACTVALUE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE EXTRACTVALUE; +drop table if exists FIND_IN_SET; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE FIND_IN_SET; +drop table if exists FLOOR; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE FLOOR; +drop table if exists FOUND_ROWS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE FOUND_ROWS; +drop table if exists FROM_DAYS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE FROM_DAYS; +drop table if exists FROM_UNIXTIME; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE FROM_UNIXTIME; +drop table if exists GEOMCOLLFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE GEOMCOLLFROMTEXT; +drop table if exists GEOMCOLLFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE GEOMCOLLFROMWKB; +drop table if exists GEOMETRYCOLLECTIONFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE GEOMETRYCOLLECTIONFROMTEXT; +drop table if exists GEOMETRYCOLLECTIONFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE GEOMETRYCOLLECTIONFROMWKB; +drop table if exists GEOMETRYFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE GEOMETRYFROMTEXT; +drop table if exists GEOMETRYFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE GEOMETRYFROMWKB; +drop table if exists GEOMETRYN; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE GEOMETRYN; +drop table if exists GEOMETRYTYPE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE GEOMETRYTYPE; +drop table if exists GEOMFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE GEOMFROMTEXT; +drop table if exists GEOMFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE GEOMFROMWKB; +drop table if exists GET_LOCK; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE GET_LOCK; +drop table if exists GLENGTH; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE GLENGTH; +drop table if exists GREATEST; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE GREATEST; +drop table if exists HEX; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE HEX; +drop table if exists IFNULL; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE IFNULL; +drop table if exists INET_ATON; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE INET_ATON; +drop table if exists INET_NTOA; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE INET_NTOA; +drop table if exists INSTR; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE INSTR; +drop table if exists INTERIORRINGN; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE INTERIORRINGN; +drop table if exists INTERSECTS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE INTERSECTS; +drop table if exists ISCLOSED; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ISCLOSED; +drop table if exists ISEMPTY; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ISEMPTY; +drop table if exists ISNULL; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ISNULL; +drop table if exists ISSIMPLE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ISSIMPLE; +drop table if exists IS_FREE_LOCK; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE IS_FREE_LOCK; +drop table if exists IS_USED_LOCK; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE IS_USED_LOCK; +drop table if exists LAST_DAY; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LAST_DAY; +drop table if exists LAST_INSERT_ID; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LAST_INSERT_ID; +drop table if exists LCASE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LCASE; +drop table if exists LEAST; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LEAST; +drop table if exists LENGTH; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LENGTH; +drop table if exists LINEFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LINEFROMTEXT; +drop table if exists LINEFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LINEFROMWKB; +drop table if exists LINESTRINGFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LINESTRINGFROMTEXT; +drop table if exists LINESTRINGFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LINESTRINGFROMWKB; +drop table if exists LN; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LN; +drop table if exists LOAD_FILE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LOAD_FILE; +drop table if exists LOCATE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LOCATE; +drop table if exists LOG; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LOG; +drop table if exists LOG10; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LOG10; +drop table if exists LOG2; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LOG2; +drop table if exists LOWER; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LOWER; +drop table if exists LPAD; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LPAD; +drop table if exists LTRIM; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE LTRIM; +drop table if exists MAKEDATE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MAKEDATE; +drop table if exists MAKETIME; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MAKETIME; +drop table if exists MAKE_SET; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MAKE_SET; +drop table if exists MASTER_POS_WAIT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MASTER_POS_WAIT; +drop table if exists MBRCONTAINS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MBRCONTAINS; +drop table if exists MBRDISJOINT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MBRDISJOINT; +drop table if exists MBREQUAL; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MBREQUAL; +drop table if exists MBRINTERSECTS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MBRINTERSECTS; +drop table if exists MBROVERLAPS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MBROVERLAPS; +drop table if exists MBRTOUCHES; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MBRTOUCHES; +drop table if exists MBRWITHIN; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MBRWITHIN; +drop table if exists MD5; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MD5; +drop table if exists MLINEFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MLINEFROMTEXT; +drop table if exists MLINEFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MLINEFROMWKB; +drop table if exists MONTHNAME; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MONTHNAME; +drop table if exists MPOINTFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MPOINTFROMTEXT; +drop table if exists MPOINTFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MPOINTFROMWKB; +drop table if exists MPOLYFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MPOLYFROMTEXT; +drop table if exists MPOLYFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MPOLYFROMWKB; +drop table if exists MULTILINESTRINGFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MULTILINESTRINGFROMTEXT; +drop table if exists MULTILINESTRINGFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MULTILINESTRINGFROMWKB; +drop table if exists MULTIPOINTFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MULTIPOINTFROMTEXT; +drop table if exists MULTIPOINTFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MULTIPOINTFROMWKB; +drop table if exists MULTIPOLYGONFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MULTIPOLYGONFROMTEXT; +drop table if exists MULTIPOLYGONFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE MULTIPOLYGONFROMWKB; +drop table if exists NAME_CONST; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE NAME_CONST; +drop table if exists NULLIF; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE NULLIF; +drop table if exists NUMGEOMETRIES; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE NUMGEOMETRIES; +drop table if exists NUMINTERIORRINGS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE NUMINTERIORRINGS; +drop table if exists NUMPOINTS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE NUMPOINTS; +drop table if exists OCT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE OCT; +drop table if exists OCTET_LENGTH; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE OCTET_LENGTH; +drop table if exists ORD; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ORD; +drop table if exists OVERLAPS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE OVERLAPS; +drop table if exists PERIOD_ADD; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE PERIOD_ADD; +drop table if exists PERIOD_DIFF; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE PERIOD_DIFF; +drop table if exists PI; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE PI; +drop table if exists POINTFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE POINTFROMTEXT; +drop table if exists POINTFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE POINTFROMWKB; +drop table if exists POINTN; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE POINTN; +drop table if exists POLYFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE POLYFROMTEXT; +drop table if exists POLYFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE POLYFROMWKB; +drop table if exists POLYGONFROMTEXT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE POLYGONFROMTEXT; +drop table if exists POLYGONFROMWKB; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE POLYGONFROMWKB; +drop table if exists POW; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE POW; +drop table if exists POWER; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE POWER; +drop table if exists QUOTE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE QUOTE; +drop table if exists RADIANS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE RADIANS; +drop table if exists RAND; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE RAND; +drop table if exists RELEASE_LOCK; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE RELEASE_LOCK; +drop table if exists REVERSE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE REVERSE; +drop table if exists ROUND; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ROUND; +drop table if exists ROW_COUNT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE ROW_COUNT; +drop table if exists RPAD; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE RPAD; +drop table if exists RTRIM; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE RTRIM; +drop table if exists SEC_TO_TIME; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SEC_TO_TIME; +drop table if exists SESSION_USER; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SESSION_USER; +drop table if exists SHA; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SHA; +drop table if exists SHA1; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SHA1; +drop table if exists SIGN; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SIGN; +drop table if exists SIN; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SIN; +drop table if exists SLEEP; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SLEEP; +drop table if exists SOUNDEX; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SOUNDEX; +drop table if exists SPACE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SPACE; +drop table if exists SQRT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SQRT; +drop table if exists SRID; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SRID; +drop table if exists STARTPOINT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE STARTPOINT; +drop table if exists STRCMP; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE STRCMP; +drop table if exists STR_TO_DATE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE STR_TO_DATE; +drop table if exists SUBDATE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SUBDATE; +drop table if exists SUBSTRING_INDEX; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SUBSTRING_INDEX; +drop table if exists SUBTIME; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SUBTIME; +drop table if exists SYSTEM_USER; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE SYSTEM_USER; +drop table if exists TAN; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE TAN; +drop table if exists TIMEDIFF; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE TIMEDIFF; +drop table if exists TIME_FORMAT; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE TIME_FORMAT; +drop table if exists TIME_TO_SEC; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE TIME_TO_SEC; +drop table if exists TOUCHES; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE TOUCHES; +drop table if exists TO_DAYS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE TO_DAYS; +drop table if exists UCASE; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE UCASE; +drop table if exists UNCOMPRESS; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE UNCOMPRESS; +drop table if exists UNCOMPRESSED_LENGTH; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE UNCOMPRESSED_LENGTH; +drop table if exists UNHEX; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE UNHEX; +drop table if exists UNIX_TIMESTAMP; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE UNIX_TIMESTAMP; +drop table if exists UPDATEXML; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE UPDATEXML; +drop table if exists UPPER; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE UPPER; +drop table if exists UUID; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE UUID; +drop table if exists VERSION; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE VERSION; +drop table if exists WEEKDAY; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE WEEKDAY; +drop table if exists WEEKOFYEAR; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE WEEKOFYEAR; +drop table if exists WITHIN; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE WITHIN; +drop table if exists X; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE X; +drop table if exists Y; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE Y; +drop table if exists YEARWEEK; +drop table if exists bug21114_child; +DROP TABLE bug21114_child; +DROP TABLE YEARWEEK; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 7c467749ee6..1cdb782b2fe 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -791,13 +791,13 @@ test.`f``1` () 5 drop view v1; drop function `f``1`; -create function x () returns int return 5; -create view v1 as select x (); +create function a() returns int return 5; +create view v1 as select a(); select * from v1; -x () +a() 5 drop view v1; -drop function x; +drop function a; create table t2 (col1 char collate latin1_german2_ci); create view v2 as select col1 collate latin1_german1_ci from t2; show create view v2; diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index 4041c267134..09aa5751301 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -34,6 +34,11 @@ select pi(),format(sin(pi()/2),6),format(cos(pi()/2),6),format(abs(tan(pi())),6) explain extended select pi(),format(sin(pi()/2),6),format(cos(pi()/2),6),format(abs(tan(pi())),6),format(cot(1),6),format(asin(1),6),format(acos(0),6),format(atan(1),6); select degrees(pi()),radians(360); +select format(atan(-2, 2), 6); +select format(atan(pi(), 0), 6); +select format(atan2(-2, 2), 6); +select format(atan2(pi(), 0), 6); + # # Bug #2338 Trignometric arithmatic problems # diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test new file mode 100644 index 00000000000..11af7c691d8 --- /dev/null +++ b/mysql-test/t/parser.test @@ -0,0 +1,510 @@ +# +# This file contains tests covering the parser +# + +#============================================================================= +# LEXICAL PARSER (lex) +#============================================================================= + +SET @save_sql_mode=@@sql_mode; + +# +# Documenting the current behavior, to detect incompatible changes. +# In each cases: +# - no error is the correct result +# - an error is the expected result with the current implementation, +# and is a limitation. + +set SQL_MODE=''; + +create table ADDDATE(a int); +drop table ADDDATE; +create table ADDDATE (a int); +drop table ADDDATE; + +--error ER_PARSE_ERROR +create table BIT_AND(a int); +create table BIT_AND (a int); +drop table BIT_AND; + +--error ER_PARSE_ERROR +create table BIT_OR(a int); +create table BIT_OR (a int); +drop table BIT_OR; + +--error ER_PARSE_ERROR +create table BIT_XOR(a int); +create table BIT_XOR (a int); +drop table BIT_XOR; + +--error ER_PARSE_ERROR +create table CAST(a int); +create table CAST (a int); +drop table CAST; + +--error ER_PARSE_ERROR +create table COUNT(a int); +create table COUNT (a int); +drop table COUNT; + +--error ER_PARSE_ERROR +create table CURDATE(a int); +create table CURDATE (a int); +drop table CURDATE; + +--error ER_PARSE_ERROR +create table CURTIME(a int); +create table CURTIME (a int); +drop table CURTIME; + +--error ER_PARSE_ERROR +create table DATE_ADD(a int); +create table DATE_ADD (a int); +drop table DATE_ADD; + +--error ER_PARSE_ERROR +create table DATE_SUB(a int); +create table DATE_SUB (a int); +drop table DATE_SUB; + +--error ER_PARSE_ERROR +create table EXTRACT(a int); +create table EXTRACT (a int); +drop table EXTRACT; + +--error ER_PARSE_ERROR +create table GROUP_CONCAT(a int); +create table GROUP_CONCAT (a int); +drop table GROUP_CONCAT; + +--error ER_PARSE_ERROR +create table GROUP_UNIQUE_USERS(a int); +create table GROUP_UNIQUE_USERS (a int); +drop table GROUP_UNIQUE_USERS; + +--error ER_PARSE_ERROR +create table MAX(a int); +create table MAX (a int); +drop table MAX; + +--error ER_PARSE_ERROR +create table MID(a int); +create table MID (a int); +drop table MID; + +--error ER_PARSE_ERROR +create table MIN(a int); +create table MIN (a int); +drop table MIN; + +--error ER_PARSE_ERROR +create table NOW(a int); +create table NOW (a int); +drop table NOW; + +--error ER_PARSE_ERROR +create table POSITION(a int); +create table POSITION (a int); +drop table POSITION; + +create table SESSION_USER(a int); +drop table SESSION_USER; +create table SESSION_USER (a int); +drop table SESSION_USER; + +--error ER_PARSE_ERROR +create table STD(a int); +create table STD (a int); +drop table STD; + +--error ER_PARSE_ERROR +create table STDDEV(a int); +create table STDDEV (a int); +drop table STDDEV; + +--error ER_PARSE_ERROR +create table STDDEV_POP(a int); +create table STDDEV_POP (a int); +drop table STDDEV_POP; + +--error ER_PARSE_ERROR +create table STDDEV_SAMP(a int); +create table STDDEV_SAMP (a int); +drop table STDDEV_SAMP; + +create table SUBDATE(a int); +drop table SUBDATE; +create table SUBDATE (a int); +drop table SUBDATE; + +--error ER_PARSE_ERROR +create table SUBSTR(a int); +create table SUBSTR (a int); +drop table SUBSTR; + +--error ER_PARSE_ERROR +create table SUBSTRING(a int); +create table SUBSTRING (a int); +drop table SUBSTRING; + +--error ER_PARSE_ERROR +create table SUM(a int); +create table SUM (a int); +drop table SUM; + +--error ER_PARSE_ERROR +create table SYSDATE(a int); +create table SYSDATE (a int); +drop table SYSDATE; + +create table SYSTEM_USER(a int); +drop table SYSTEM_USER; +create table SYSTEM_USER (a int); +drop table SYSTEM_USER; + +--error ER_PARSE_ERROR +create table TRIM(a int); +create table TRIM (a int); +drop table TRIM; + +--error ER_PARSE_ERROR +create table UNIQUE_USERS(a int); +create table UNIQUE_USERS (a int); +drop table UNIQUE_USERS; + +--error ER_PARSE_ERROR +create table VARIANCE(a int); +create table VARIANCE (a int); +drop table VARIANCE; + +--error ER_PARSE_ERROR +create table VAR_POP(a int); +create table VAR_POP (a int); +drop table VAR_POP; + +--error ER_PARSE_ERROR +create table VAR_SAMP(a int); +create table VAR_SAMP (a int); +drop table VAR_SAMP; + +set SQL_MODE='IGNORE_SPACE'; + +create table ADDDATE(a int); +drop table ADDDATE; +create table ADDDATE (a int); +drop table ADDDATE; + +--error ER_PARSE_ERROR +create table BIT_AND(a int); +--error ER_PARSE_ERROR +create table BIT_AND (a int); + +--error ER_PARSE_ERROR +create table BIT_OR(a int); +--error ER_PARSE_ERROR +create table BIT_OR (a int); + +--error ER_PARSE_ERROR +create table BIT_XOR(a int); +--error ER_PARSE_ERROR +create table BIT_XOR (a int); + +--error ER_PARSE_ERROR +create table CAST(a int); +--error ER_PARSE_ERROR +create table CAST (a int); + +--error ER_PARSE_ERROR +create table COUNT(a int); +--error ER_PARSE_ERROR +create table COUNT (a int); + +--error ER_PARSE_ERROR +create table CURDATE(a int); +--error ER_PARSE_ERROR +create table CURDATE (a int); + +--error ER_PARSE_ERROR +create table CURTIME(a int); +--error ER_PARSE_ERROR +create table CURTIME (a int); + +--error ER_PARSE_ERROR +create table DATE_ADD(a int); +--error ER_PARSE_ERROR +create table DATE_ADD (a int); + +--error ER_PARSE_ERROR +create table DATE_SUB(a int); +--error ER_PARSE_ERROR +create table DATE_SUB (a int); + +--error ER_PARSE_ERROR +create table EXTRACT(a int); +--error ER_PARSE_ERROR +create table EXTRACT (a int); + +--error ER_PARSE_ERROR +create table GROUP_CONCAT(a int); +--error ER_PARSE_ERROR +create table GROUP_CONCAT (a int); + +--error ER_PARSE_ERROR +create table GROUP_UNIQUE_USERS(a int); +--error ER_PARSE_ERROR +create table GROUP_UNIQUE_USERS (a int); + +--error ER_PARSE_ERROR +create table MAX(a int); +--error ER_PARSE_ERROR +create table MAX (a int); + +--error ER_PARSE_ERROR +create table MID(a int); +--error ER_PARSE_ERROR +create table MID (a int); + +--error ER_PARSE_ERROR +create table MIN(a int); +--error ER_PARSE_ERROR +create table MIN (a int); + +--error ER_PARSE_ERROR +create table NOW(a int); +--error ER_PARSE_ERROR +create table NOW (a int); + +--error ER_PARSE_ERROR +create table POSITION(a int); +--error ER_PARSE_ERROR +create table POSITION (a int); + +create table SESSION_USER(a int); +drop table SESSION_USER; +create table SESSION_USER (a int); +drop table SESSION_USER; + +--error ER_PARSE_ERROR +create table STD(a int); +--error ER_PARSE_ERROR +create table STD (a int); + +--error ER_PARSE_ERROR +create table STDDEV(a int); +--error ER_PARSE_ERROR +create table STDDEV (a int); + +--error ER_PARSE_ERROR +create table STDDEV_POP(a int); +--error ER_PARSE_ERROR +create table STDDEV_POP (a int); + +--error ER_PARSE_ERROR +create table STDDEV_SAMP(a int); +--error ER_PARSE_ERROR +create table STDDEV_SAMP (a int); + +create table SUBDATE(a int); +drop table SUBDATE; +create table SUBDATE (a int); +drop table SUBDATE; + +--error ER_PARSE_ERROR +create table SUBSTR(a int); +--error ER_PARSE_ERROR +create table SUBSTR (a int); + +--error ER_PARSE_ERROR +create table SUBSTRING(a int); +--error ER_PARSE_ERROR +create table SUBSTRING (a int); + +--error ER_PARSE_ERROR +create table SUM(a int); +--error ER_PARSE_ERROR +create table SUM (a int); + +--error ER_PARSE_ERROR +create table SYSDATE(a int); +--error ER_PARSE_ERROR +create table SYSDATE (a int); + +create table SYSTEM_USER(a int); +drop table SYSTEM_USER; +create table SYSTEM_USER (a int); +drop table SYSTEM_USER; + +--error ER_PARSE_ERROR +create table TRIM(a int); +--error ER_PARSE_ERROR +create table TRIM (a int); + +--error ER_PARSE_ERROR +create table UNIQUE_USERS(a int); +--error ER_PARSE_ERROR +create table UNIQUE_USERS (a int); + +--error ER_PARSE_ERROR +create table VARIANCE(a int); +--error ER_PARSE_ERROR +create table VARIANCE (a int); + +--error ER_PARSE_ERROR +create table VAR_POP(a int); +--error ER_PARSE_ERROR +create table VAR_POP (a int); + +--error ER_PARSE_ERROR +create table VAR_SAMP(a int); +--error ER_PARSE_ERROR +create table VAR_SAMP (a int); + +SET @@sql_mode=@save_sql_mode; + +#============================================================================= +# SYNTACTIC PARSER (bison) +#============================================================================= + +# +# +# Bug#21114 (Foreign key creation fails to table with name format) +# + +# Test coverage with edge conditions + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select pi(3.14); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select tan(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select tan(1, 2); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select makedate(1); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select makedate(1, 2, 3); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select maketime(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select maketime(1); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select maketime(1, 2); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select maketime(1, 2, 3, 4); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select atan(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select atan2(1, 2, 3); + +select benchmark(10, 1+1); + +-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT +select benchmark(5+5, 2); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select concat(); +select concat("foo"); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select concat_ws(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select concat_ws("foo"); + +set @pwd="my password"; +-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT +select encode("secret", @pwd); +-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT +select decode("encoded-secret", @pwd); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select encrypt(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select encrypt(1, 2, 3); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select des_encrypt("p1", "p2", "not expected"); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select des_decrypt("p1", "p2", "not expected"); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select elt(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select elt(1); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select export_set(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select export_set("p1"); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select export_set("p1", "p2"); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select export_set("p1", "p2", "p3", "p4", "p5", "p6"); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select field(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select field("p1"); + +set @dec=2; +-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT +select format(pi(), @dec); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select from_unixtime(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select from_unixtime(1, 2, 3); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select unix_timestamp(1, 2); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select greatest(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select greatest(12); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select last_insert_id(1, 2); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select least(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select least(12); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select locate(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select locate(1); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select locate(1, 2, 3, 4); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select log(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select log(1, 2, 3); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select make_set(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select make_set(1); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select master_pos_wait(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select master_pos_wait(1); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select master_pos_wait(1, 2, 3, 4); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select rand(1, 2, 3); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select round(1, 2, 3); + +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select yearweek(); +-- error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select yearweek(1, 2, 3); + diff --git a/mysql-test/t/parser_bug21114_innodb.test b/mysql-test/t/parser_bug21114_innodb.test new file mode 100644 index 00000000000..d2101e2a28d --- /dev/null +++ b/mysql-test/t/parser_bug21114_innodb.test @@ -0,0 +1,422 @@ +-- source include/have_innodb.inc + +let $engine_type=InnoDb; + +# +# Bug#21114 (Foreign key creation fails to table with name format) +# + +# Testing with the full log for only a few functions, +# including FORMAT for witch the bug was reported. + +let $verbose=1; + +let $FCT=ABS; +-- source include/parser_bug21114.inc +let $FCT=FIELD; +-- source include/parser_bug21114.inc +let $FCT=FORMAT; +-- source include/parser_bug21114.inc + +# Ignoring the result of SHOW CREATE (this generates too much noise) +# Tests will fail if the create table statement can not be parsed + +let verbose=0; + +let $FCT=ACOS; +-- source include/parser_bug21114.inc +let $FCT=ADDDATE; +-- source include/parser_bug21114.inc +let $FCT=ADDTIME; +-- source include/parser_bug21114.inc +let $FCT=AES_DECRYPT; +-- source include/parser_bug21114.inc +let $FCT=AES_ENCRYPT; +-- source include/parser_bug21114.inc +let $FCT=AREA; +-- source include/parser_bug21114.inc +let $FCT=ASBINARY; +-- source include/parser_bug21114.inc +let $FCT=ASIN; +-- source include/parser_bug21114.inc +let $FCT=ASTEXT; +-- source include/parser_bug21114.inc +let $FCT=ASWKB; +-- source include/parser_bug21114.inc +let $FCT=ASWKT; +-- source include/parser_bug21114.inc +let $FCT=ATAN; +-- source include/parser_bug21114.inc +let $FCT=ATAN2; +-- source include/parser_bug21114.inc +let $FCT=BENCHMARK; +-- source include/parser_bug21114.inc +let $FCT=BIN; +-- source include/parser_bug21114.inc +let $FCT=BIT_COUNT; +-- source include/parser_bug21114.inc +let $FCT=BIT_LENGTH; +-- source include/parser_bug21114.inc +let $FCT=CEIL; +-- source include/parser_bug21114.inc +let $FCT=CEILING; +-- source include/parser_bug21114.inc +let $FCT=CENTROID; +-- source include/parser_bug21114.inc +let $FCT=CHARACTER_LENGTH; +-- source include/parser_bug21114.inc +let $FCT=CHAR_LENGTH; +-- source include/parser_bug21114.inc +let $FCT=COERCIBILITY; +-- source include/parser_bug21114.inc +let $FCT=COMPRESS; +-- source include/parser_bug21114.inc +let $FCT=CONCAT; +-- source include/parser_bug21114.inc +let $FCT=CONCAT_WS; +-- source include/parser_bug21114.inc +let $FCT=CONNECTION_ID; +-- source include/parser_bug21114.inc +let $FCT=CONV; +-- source include/parser_bug21114.inc +let $FCT=CONVERT_TZ; +-- source include/parser_bug21114.inc +let $FCT=COS; +-- source include/parser_bug21114.inc +let $FCT=COT; +-- source include/parser_bug21114.inc +let $FCT=CRC32; +-- source include/parser_bug21114.inc +let $FCT=CROSSES; +-- source include/parser_bug21114.inc +let $FCT=DATEDIFF; +-- source include/parser_bug21114.inc +let $FCT=DATE_FORMAT; +-- source include/parser_bug21114.inc +let $FCT=DAYNAME; +-- source include/parser_bug21114.inc +let $FCT=DAYOFMONTH; +-- source include/parser_bug21114.inc +let $FCT=DAYOFWEEK; +-- source include/parser_bug21114.inc +let $FCT=DAYOFYEAR; +-- source include/parser_bug21114.inc +let $FCT=DECODE; +-- source include/parser_bug21114.inc +let $FCT=DEGREES; +-- source include/parser_bug21114.inc +let $FCT=DES_DECRYPT; +-- source include/parser_bug21114.inc +let $FCT=DES_ENCRYPT; +-- source include/parser_bug21114.inc +let $FCT=DIMENSION; +-- source include/parser_bug21114.inc +let $FCT=DISJOINT; +-- source include/parser_bug21114.inc +let $FCT=ELT; +-- source include/parser_bug21114.inc +let $FCT=ENCODE; +-- source include/parser_bug21114.inc +let $FCT=ENCRYPT; +-- source include/parser_bug21114.inc +let $FCT=ENDPOINT; +-- source include/parser_bug21114.inc +let $FCT=ENVELOPE; +-- source include/parser_bug21114.inc +let $FCT=EQUALS; +-- source include/parser_bug21114.inc +let $FCT=EXP; +-- source include/parser_bug21114.inc +let $FCT=EXPORT_SET; +-- source include/parser_bug21114.inc +let $FCT=EXTERIORRING; +-- source include/parser_bug21114.inc +let $FCT=EXTRACTVALUE; +-- source include/parser_bug21114.inc +let $FCT=FIND_IN_SET; +-- source include/parser_bug21114.inc +let $FCT=FLOOR; +-- source include/parser_bug21114.inc +let $FCT=FOUND_ROWS; +-- source include/parser_bug21114.inc +let $FCT=FROM_DAYS; +-- source include/parser_bug21114.inc +let $FCT=FROM_UNIXTIME; +-- source include/parser_bug21114.inc +let $FCT=GEOMCOLLFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=GEOMCOLLFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=GEOMETRYCOLLECTIONFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=GEOMETRYCOLLECTIONFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=GEOMETRYFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=GEOMETRYFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=GEOMETRYN; +-- source include/parser_bug21114.inc +let $FCT=GEOMETRYTYPE; +-- source include/parser_bug21114.inc +let $FCT=GEOMFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=GEOMFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=GET_LOCK; +-- source include/parser_bug21114.inc +let $FCT=GLENGTH; +-- source include/parser_bug21114.inc +let $FCT=GREATEST; +-- source include/parser_bug21114.inc +let $FCT=HEX; +-- source include/parser_bug21114.inc +let $FCT=IFNULL; +-- source include/parser_bug21114.inc +let $FCT=INET_ATON; +-- source include/parser_bug21114.inc +let $FCT=INET_NTOA; +-- source include/parser_bug21114.inc +let $FCT=INSTR; +-- source include/parser_bug21114.inc +let $FCT=INTERIORRINGN; +-- source include/parser_bug21114.inc +let $FCT=INTERSECTS; +-- source include/parser_bug21114.inc +let $FCT=ISCLOSED; +-- source include/parser_bug21114.inc +let $FCT=ISEMPTY; +-- source include/parser_bug21114.inc +let $FCT=ISNULL; +-- source include/parser_bug21114.inc +let $FCT=ISSIMPLE; +-- source include/parser_bug21114.inc +let $FCT=IS_FREE_LOCK; +-- source include/parser_bug21114.inc +let $FCT=IS_USED_LOCK; +-- source include/parser_bug21114.inc +let $FCT=LAST_DAY; +-- source include/parser_bug21114.inc +let $FCT=LAST_INSERT_ID; +-- source include/parser_bug21114.inc +let $FCT=LCASE; +-- source include/parser_bug21114.inc +let $FCT=LEAST; +-- source include/parser_bug21114.inc +let $FCT=LENGTH; +-- source include/parser_bug21114.inc +let $FCT=LINEFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=LINEFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=LINESTRINGFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=LINESTRINGFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=LN; +-- source include/parser_bug21114.inc +let $FCT=LOAD_FILE; +-- source include/parser_bug21114.inc +let $FCT=LOCATE; +-- source include/parser_bug21114.inc +let $FCT=LOG; +-- source include/parser_bug21114.inc +let $FCT=LOG10; +-- source include/parser_bug21114.inc +let $FCT=LOG2; +-- source include/parser_bug21114.inc +let $FCT=LOWER; +-- source include/parser_bug21114.inc +let $FCT=LPAD; +-- source include/parser_bug21114.inc +let $FCT=LTRIM; +-- source include/parser_bug21114.inc +let $FCT=MAKEDATE; +-- source include/parser_bug21114.inc +let $FCT=MAKETIME; +-- source include/parser_bug21114.inc +let $FCT=MAKE_SET; +-- source include/parser_bug21114.inc +let $FCT=MASTER_POS_WAIT; +-- source include/parser_bug21114.inc +let $FCT=MBRCONTAINS; +-- source include/parser_bug21114.inc +let $FCT=MBRDISJOINT; +-- source include/parser_bug21114.inc +let $FCT=MBREQUAL; +-- source include/parser_bug21114.inc +let $FCT=MBRINTERSECTS; +-- source include/parser_bug21114.inc +let $FCT=MBROVERLAPS; +-- source include/parser_bug21114.inc +let $FCT=MBRTOUCHES; +-- source include/parser_bug21114.inc +let $FCT=MBRWITHIN; +-- source include/parser_bug21114.inc +let $FCT=MD5; +-- source include/parser_bug21114.inc +let $FCT=MLINEFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=MLINEFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=MONTHNAME; +-- source include/parser_bug21114.inc +let $FCT=MPOINTFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=MPOINTFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=MPOLYFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=MPOLYFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=MULTILINESTRINGFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=MULTILINESTRINGFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=MULTIPOINTFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=MULTIPOINTFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=MULTIPOLYGONFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=MULTIPOLYGONFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=NAME_CONST; +-- source include/parser_bug21114.inc +let $FCT=NULLIF; +-- source include/parser_bug21114.inc +let $FCT=NUMGEOMETRIES; +-- source include/parser_bug21114.inc +let $FCT=NUMINTERIORRINGS; +-- source include/parser_bug21114.inc +let $FCT=NUMPOINTS; +-- source include/parser_bug21114.inc +let $FCT=OCT; +-- source include/parser_bug21114.inc +let $FCT=OCTET_LENGTH; +-- source include/parser_bug21114.inc +let $FCT=ORD; +-- source include/parser_bug21114.inc +let $FCT=OVERLAPS; +-- source include/parser_bug21114.inc +let $FCT=PERIOD_ADD; +-- source include/parser_bug21114.inc +let $FCT=PERIOD_DIFF; +-- source include/parser_bug21114.inc +let $FCT=PI; +-- source include/parser_bug21114.inc +let $FCT=POINTFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=POINTFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=POINTN; +-- source include/parser_bug21114.inc +let $FCT=POLYFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=POLYFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=POLYGONFROMTEXT; +-- source include/parser_bug21114.inc +let $FCT=POLYGONFROMWKB; +-- source include/parser_bug21114.inc +let $FCT=POW; +-- source include/parser_bug21114.inc +let $FCT=POWER; +-- source include/parser_bug21114.inc +let $FCT=QUOTE; +-- source include/parser_bug21114.inc +let $FCT=RADIANS; +-- source include/parser_bug21114.inc +let $FCT=RAND; +-- source include/parser_bug21114.inc +let $FCT=RELEASE_LOCK; +-- source include/parser_bug21114.inc +let $FCT=REVERSE; +-- source include/parser_bug21114.inc +let $FCT=ROUND; +-- source include/parser_bug21114.inc +let $FCT=ROW_COUNT; +-- source include/parser_bug21114.inc +let $FCT=RPAD; +-- source include/parser_bug21114.inc +let $FCT=RTRIM; +-- source include/parser_bug21114.inc +let $FCT=SEC_TO_TIME; +-- source include/parser_bug21114.inc +let $FCT=SESSION_USER; +-- source include/parser_bug21114.inc +let $FCT=SHA; +-- source include/parser_bug21114.inc +let $FCT=SHA1; +-- source include/parser_bug21114.inc +let $FCT=SIGN; +-- source include/parser_bug21114.inc +let $FCT=SIN; +-- source include/parser_bug21114.inc +let $FCT=SLEEP; +-- source include/parser_bug21114.inc +let $FCT=SOUNDEX; +-- source include/parser_bug21114.inc +let $FCT=SPACE; +-- source include/parser_bug21114.inc +let $FCT=SQRT; +-- source include/parser_bug21114.inc +let $FCT=SRID; +-- source include/parser_bug21114.inc +let $FCT=STARTPOINT; +-- source include/parser_bug21114.inc +let $FCT=STRCMP; +-- source include/parser_bug21114.inc +let $FCT=STR_TO_DATE; +-- source include/parser_bug21114.inc +let $FCT=SUBDATE; +-- source include/parser_bug21114.inc +let $FCT=SUBSTRING_INDEX; +-- source include/parser_bug21114.inc +let $FCT=SUBTIME; +-- source include/parser_bug21114.inc +let $FCT=SYSTEM_USER; +-- source include/parser_bug21114.inc +let $FCT=TAN; +-- source include/parser_bug21114.inc +let $FCT=TIMEDIFF; +-- source include/parser_bug21114.inc +let $FCT=TIME_FORMAT; +-- source include/parser_bug21114.inc +let $FCT=TIME_TO_SEC; +-- source include/parser_bug21114.inc +let $FCT=TOUCHES; +-- source include/parser_bug21114.inc +let $FCT=TO_DAYS; +-- source include/parser_bug21114.inc +let $FCT=UCASE; +-- source include/parser_bug21114.inc +let $FCT=UNCOMPRESS; +-- source include/parser_bug21114.inc +let $FCT=UNCOMPRESSED_LENGTH; +-- source include/parser_bug21114.inc +let $FCT=UNHEX; +-- source include/parser_bug21114.inc +let $FCT=UNIX_TIMESTAMP; +-- source include/parser_bug21114.inc +let $FCT=UPDATEXML; +-- source include/parser_bug21114.inc +let $FCT=UPPER; +-- source include/parser_bug21114.inc +let $FCT=UUID; +-- source include/parser_bug21114.inc +let $FCT=VERSION; +-- source include/parser_bug21114.inc +let $FCT=WEEKDAY; +-- source include/parser_bug21114.inc +let $FCT=WEEKOFYEAR; +-- source include/parser_bug21114.inc +let $FCT=WITHIN; +-- source include/parser_bug21114.inc +let $FCT=X; +-- source include/parser_bug21114.inc +let $FCT=Y; +-- source include/parser_bug21114.inc +let $FCT=YEARWEEK; +-- source include/parser_bug21114.inc + diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 2446bedfc14..86cd5994346 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -698,11 +698,11 @@ drop function `f``1`; # # tested problem when function name length close to ALIGN_SIZE # -create function x () returns int return 5; -create view v1 as select x (); +create function a() returns int return 5; +create view v1 as select a(); select * from v1; drop view v1; -drop function x; +drop function a; # # VIEW with collation diff --git a/sql/item_create.cc b/sql/item_create.cc index 3a93ec6e516..7722ce28d4a 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -14,728 +14,4926 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Functions to create an item. Used by lex.h */ +/* Functions to create an item. Used by sql_yacc.yy */ #include "mysql_priv.h" +#include "item_create.h" +#include "sp_head.h" +#include "sp.h" -Item *create_func_abs(Item* a) +/* +============================================================================= + LOCAL DECLARATIONS +============================================================================= +*/ + +/** + Adapter for functions that takes exactly zero arguments. +*/ + +class Create_func_arg0 : public Create_func { - return new Item_func_abs(a); +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + /** + Builder method, with no arguments. + @param thd The current thread + @return An item representing the function call + */ + virtual Item* create(THD *thd) = 0; + +protected: + /** Constructor. */ + Create_func_arg0() {} + /** Destructor. */ + virtual ~Create_func_arg0() {} +}; + + +/** + Adapter for functions that takes exactly one argument. +*/ + +class Create_func_arg1 : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + /** + Builder method, with one argument. + @param thd The current thread + @param arg1 The first argument of the function + @return An item representing the function call + */ + virtual Item* create(THD *thd, Item *arg1) = 0; + +protected: + /** Constructor. */ + Create_func_arg1() {} + /** Destructor. */ + virtual ~Create_func_arg1() {} +}; + + +/** + Adapter for functions that takes exactly two arguments. +*/ + +class Create_func_arg2 : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + /** + Builder method, with two arguments. + @param thd The current thread + @param arg1 The first argument of the function + @param arg2 The second argument of the function + @return An item representing the function call + */ + virtual Item* create(THD *thd, Item *arg1, Item *arg2) = 0; + +protected: + /** Constructor. */ + Create_func_arg2() {} + /** Destructor. */ + virtual ~Create_func_arg2() {} +}; + + +/** + Adapter for functions that takes exactly three arguments. +*/ + +class Create_func_arg3 : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + /** + Builder method, with three arguments. + @param thd The current thread + @param arg1 The first argument of the function + @param arg2 The second argument of the function + @param arg3 The third argument of the function + @return An item representing the function call + */ + virtual Item* create(THD *thd, Item *arg1, Item *arg2, Item *arg3) = 0; + +protected: + /** Constructor. */ + Create_func_arg3() {} + /** Destructor. */ + virtual ~Create_func_arg3() {} +}; + + +/** + Function builder for Stored Functions. +*/ + +class Create_sp_func : public Create_qfunc +{ +public: + virtual Item* create(THD *thd, LEX_STRING db, LEX_STRING name, + List *item_list); + + static Create_sp_func s_singleton; + +protected: + /** Constructor. */ + Create_sp_func() {} + /** Destructor. */ + virtual ~Create_sp_func() {} +}; + + +#ifndef HAVE_SPATIAL +/** + Common (non) builder for geometry functions. + This builder is used in --without-geometry builds only, + to report an error. +*/ + +class Create_func_no_geom : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + /** Singleton. */ + static Create_func_no_geom s_singleton; + +protected: + /** Constructor. */ + Create_func_no_geom() {} + /** Destructor. */ + virtual ~Create_func_no_geom() {} +}; +#endif + + +/* + Concrete functions builders (native functions). + Please keep this list sorted in alphabetical order, + it helps to compare code between versions, and helps with merges conflicts. +*/ + +class Create_func_abs : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_abs s_singleton; + +protected: + Create_func_abs() {} + virtual ~Create_func_abs() {} +}; + + +class Create_func_acos : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_acos s_singleton; + +protected: + Create_func_acos() {} + virtual ~Create_func_acos() {} +}; + + +class Create_func_addtime : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_addtime s_singleton; + +protected: + Create_func_addtime() {} + virtual ~Create_func_addtime() {} +}; + + +class Create_func_aes_encrypt : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_aes_encrypt s_singleton; + +protected: + Create_func_aes_encrypt() {} + virtual ~Create_func_aes_encrypt() {} +}; + + +class Create_func_aes_decrypt : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_aes_decrypt s_singleton; + +protected: + Create_func_aes_decrypt() {} + virtual ~Create_func_aes_decrypt() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_area : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_area s_singleton; + +protected: + Create_func_area() {} + virtual ~Create_func_area() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_as_wkb : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_as_wkb s_singleton; + +protected: + Create_func_as_wkb() {} + virtual ~Create_func_as_wkb() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_as_wkt : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_as_wkt s_singleton; + +protected: + Create_func_as_wkt() {} + virtual ~Create_func_as_wkt() {} +}; +#endif + + +class Create_func_asin : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_asin s_singleton; + +protected: + Create_func_asin() {} + virtual ~Create_func_asin() {} +}; + + +class Create_func_atan : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_atan s_singleton; + +protected: + Create_func_atan() {} + virtual ~Create_func_atan() {} +}; + + +class Create_func_benchmark : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_benchmark s_singleton; + +protected: + Create_func_benchmark() {} + virtual ~Create_func_benchmark() {} +}; + + +class Create_func_bin : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_bin s_singleton; + +protected: + Create_func_bin() {} + virtual ~Create_func_bin() {} +}; + + +class Create_func_bit_count : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_bit_count s_singleton; + +protected: + Create_func_bit_count() {} + virtual ~Create_func_bit_count() {} +}; + + +class Create_func_bit_length : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_bit_length s_singleton; + +protected: + Create_func_bit_length() {} + virtual ~Create_func_bit_length() {} +}; + + +class Create_func_ceiling : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg); + + static Create_func_ceiling s_singleton; + +protected: + Create_func_ceiling() {} + virtual ~Create_func_ceiling() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_centroid : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_centroid s_singleton; + +protected: + Create_func_centroid() {} + virtual ~Create_func_centroid() {} +}; +#endif + + +class Create_func_char_length : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_char_length s_singleton; + +protected: + Create_func_char_length() {} + virtual ~Create_func_char_length() {} +}; + + +class Create_func_coercibility : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_coercibility s_singleton; + +protected: + Create_func_coercibility() {} + virtual ~Create_func_coercibility() {} +}; + + +class Create_func_compress : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_compress s_singleton; + +protected: + Create_func_compress() {} + virtual ~Create_func_compress() {} +}; + + +class Create_func_concat : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_concat s_singleton; + +protected: + Create_func_concat() {} + virtual ~Create_func_concat() {} +}; + + +class Create_func_concat_ws : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_concat_ws s_singleton; + +protected: + Create_func_concat_ws() {} + virtual ~Create_func_concat_ws() {} +}; + + +class Create_func_connection_id : public Create_func_arg0 +{ +public: + virtual Item* create(THD *thd); + + static Create_func_connection_id s_singleton; + +protected: + Create_func_connection_id() {} + virtual ~Create_func_connection_id() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_contains : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_contains s_singleton; + +protected: + Create_func_contains() {} + virtual ~Create_func_contains() {} +}; +#endif + + +class Create_func_conv : public Create_func_arg3 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + + static Create_func_conv s_singleton; + +protected: + Create_func_conv() {} + virtual ~Create_func_conv() {} +}; + + +class Create_func_convert_tz : public Create_func_arg3 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + + static Create_func_convert_tz s_singleton; + +protected: + Create_func_convert_tz() {} + virtual ~Create_func_convert_tz() {} +}; + + +class Create_func_cos : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_cos s_singleton; + +protected: + Create_func_cos() {} + virtual ~Create_func_cos() {} +}; + + +class Create_func_cot : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_cot s_singleton; + +protected: + Create_func_cot() {} + virtual ~Create_func_cot() {} +}; + + +class Create_func_crc32 : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_crc32 s_singleton; + +protected: + Create_func_crc32() {} + virtual ~Create_func_crc32() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_crosses : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_crosses s_singleton; + +protected: + Create_func_crosses() {} + virtual ~Create_func_crosses() {} +}; +#endif + + +class Create_func_date_format : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_date_format s_singleton; + +protected: + Create_func_date_format() {} + virtual ~Create_func_date_format() {} +}; + + +class Create_func_datediff : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_datediff s_singleton; + +protected: + Create_func_datediff() {} + virtual ~Create_func_datediff() {} +}; + + +class Create_func_dayname : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_dayname s_singleton; + +protected: + Create_func_dayname() {} + virtual ~Create_func_dayname() {} +}; + + +class Create_func_dayofmonth : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_dayofmonth s_singleton; + +protected: + Create_func_dayofmonth() {} + virtual ~Create_func_dayofmonth() {} +}; + + +class Create_func_dayofweek : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_dayofweek s_singleton; + +protected: + Create_func_dayofweek() {} + virtual ~Create_func_dayofweek() {} +}; + + +class Create_func_dayofyear : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_dayofyear s_singleton; + +protected: + Create_func_dayofyear() {} + virtual ~Create_func_dayofyear() {} +}; + + +class Create_func_decode : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_decode s_singleton; + +protected: + Create_func_decode() {} + virtual ~Create_func_decode() {} +}; + + +class Create_func_degrees : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_degrees s_singleton; + +protected: + Create_func_degrees() {} + virtual ~Create_func_degrees() {} +}; + + +class Create_func_des_decrypt : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_des_decrypt s_singleton; + +protected: + Create_func_des_decrypt() {} + virtual ~Create_func_des_decrypt() {} +}; + + +class Create_func_des_encrypt : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_des_encrypt s_singleton; + +protected: + Create_func_des_encrypt() {} + virtual ~Create_func_des_encrypt() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_dimension : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_dimension s_singleton; + +protected: + Create_func_dimension() {} + virtual ~Create_func_dimension() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_disjoint : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_disjoint s_singleton; + +protected: + Create_func_disjoint() {} + virtual ~Create_func_disjoint() {} +}; +#endif + + +class Create_func_elt : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_elt s_singleton; + +protected: + Create_func_elt() {} + virtual ~Create_func_elt() {} +}; + + +class Create_func_encode : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_encode s_singleton; + +protected: + Create_func_encode() {} + virtual ~Create_func_encode() {} +}; + + +class Create_func_encrypt : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_encrypt s_singleton; + +protected: + Create_func_encrypt() {} + virtual ~Create_func_encrypt() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_endpoint : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_endpoint s_singleton; + +protected: + Create_func_endpoint() {} + virtual ~Create_func_endpoint() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_envelope : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_envelope s_singleton; + +protected: + Create_func_envelope() {} + virtual ~Create_func_envelope() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_equals : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_equals s_singleton; + +protected: + Create_func_equals() {} + virtual ~Create_func_equals() {} +}; +#endif + + +class Create_func_exp : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_exp s_singleton; + +protected: + Create_func_exp() {} + virtual ~Create_func_exp() {} +}; + + +class Create_func_export_set : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_export_set s_singleton; + +protected: + Create_func_export_set() {} + virtual ~Create_func_export_set() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_exteriorring : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_exteriorring s_singleton; + +protected: + Create_func_exteriorring() {} + virtual ~Create_func_exteriorring() {} +}; +#endif + + +class Create_func_field : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_field s_singleton; + +protected: + Create_func_field() {} + virtual ~Create_func_field() {} +}; + + +class Create_func_find_in_set : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_find_in_set s_singleton; + +protected: + Create_func_find_in_set() {} + virtual ~Create_func_find_in_set() {} +}; + + +class Create_func_floor : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_floor s_singleton; + +protected: + Create_func_floor() {} + virtual ~Create_func_floor() {} +}; + + +class Create_func_format : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_format s_singleton; + +protected: + Create_func_format() {} + virtual ~Create_func_format() {} +}; + + +class Create_func_found_rows : public Create_func_arg0 +{ +public: + virtual Item* create(THD *thd); + + static Create_func_found_rows s_singleton; + +protected: + Create_func_found_rows() {} + virtual ~Create_func_found_rows() {} +}; + + +class Create_func_from_days : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_from_days s_singleton; + +protected: + Create_func_from_days() {} + virtual ~Create_func_from_days() {} +}; + + +class Create_func_from_unixtime : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_from_unixtime s_singleton; + +protected: + Create_func_from_unixtime() {} + virtual ~Create_func_from_unixtime() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_geometry_from_text : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_geometry_from_text s_singleton; + +protected: + Create_func_geometry_from_text() {} + virtual ~Create_func_geometry_from_text() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_geometry_from_wkb : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_geometry_from_wkb s_singleton; + +protected: + Create_func_geometry_from_wkb() {} + virtual ~Create_func_geometry_from_wkb() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_geometry_type : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_geometry_type s_singleton; + +protected: + Create_func_geometry_type() {} + virtual ~Create_func_geometry_type() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_geometryn : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_geometryn s_singleton; + +protected: + Create_func_geometryn() {} + virtual ~Create_func_geometryn() {} +}; +#endif + + +class Create_func_get_lock : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_get_lock s_singleton; + +protected: + Create_func_get_lock() {} + virtual ~Create_func_get_lock() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_glength : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_glength s_singleton; + +protected: + Create_func_glength() {} + virtual ~Create_func_glength() {} +}; +#endif + + +class Create_func_greatest : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_greatest s_singleton; + +protected: + Create_func_greatest() {} + virtual ~Create_func_greatest() {} +}; + + +class Create_func_hex : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_hex s_singleton; + +protected: + Create_func_hex() {} + virtual ~Create_func_hex() {} +}; + + +class Create_func_ifnull : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_ifnull s_singleton; + +protected: + Create_func_ifnull() {} + virtual ~Create_func_ifnull() {} +}; + + +class Create_func_inet_ntoa : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_inet_ntoa s_singleton; + +protected: + Create_func_inet_ntoa() {} + virtual ~Create_func_inet_ntoa() {} +}; + + +class Create_func_inet_aton : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_inet_aton s_singleton; + +protected: + Create_func_inet_aton() {} + virtual ~Create_func_inet_aton() {} +}; + + +class Create_func_instr : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_instr s_singleton; + +protected: + Create_func_instr() {} + virtual ~Create_func_instr() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_interiorringn : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_interiorringn s_singleton; + +protected: + Create_func_interiorringn() {} + virtual ~Create_func_interiorringn() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_intersects : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_intersects s_singleton; + +protected: + Create_func_intersects() {} + virtual ~Create_func_intersects() {} +}; +#endif + + +class Create_func_is_free_lock : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_is_free_lock s_singleton; + +protected: + Create_func_is_free_lock() {} + virtual ~Create_func_is_free_lock() {} +}; + + +class Create_func_is_used_lock : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_is_used_lock s_singleton; + +protected: + Create_func_is_used_lock() {} + virtual ~Create_func_is_used_lock() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_isclosed : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_isclosed s_singleton; + +protected: + Create_func_isclosed() {} + virtual ~Create_func_isclosed() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_isempty : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_isempty s_singleton; + +protected: + Create_func_isempty() {} + virtual ~Create_func_isempty() {} +}; +#endif + + +class Create_func_isnull : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_isnull s_singleton; + +protected: + Create_func_isnull() {} + virtual ~Create_func_isnull() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_issimple : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_issimple s_singleton; + +protected: + Create_func_issimple() {} + virtual ~Create_func_issimple() {} +}; +#endif + + +class Create_func_last_day : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_last_day s_singleton; + +protected: + Create_func_last_day() {} + virtual ~Create_func_last_day() {} +}; + + +class Create_func_last_insert_id : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_last_insert_id s_singleton; + +protected: + Create_func_last_insert_id() {} + virtual ~Create_func_last_insert_id() {} +}; + + +class Create_func_lcase : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_lcase s_singleton; + +protected: + Create_func_lcase() {} + virtual ~Create_func_lcase() {} +}; + + +class Create_func_least : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_least s_singleton; + +protected: + Create_func_least() {} + virtual ~Create_func_least() {} +}; + + +class Create_func_length : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_length s_singleton; + +protected: + Create_func_length() {} + virtual ~Create_func_length() {} +}; + + +class Create_func_ln : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_ln s_singleton; + +protected: + Create_func_ln() {} + virtual ~Create_func_ln() {} +}; + + +class Create_func_load_file : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_load_file s_singleton; + +protected: + Create_func_load_file() {} + virtual ~Create_func_load_file() {} +}; + + +class Create_func_locate : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_locate s_singleton; + +protected: + Create_func_locate() {} + virtual ~Create_func_locate() {} +}; + + +class Create_func_log : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_log s_singleton; + +protected: + Create_func_log() {} + virtual ~Create_func_log() {} +}; + + +class Create_func_log10 : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_log10 s_singleton; + +protected: + Create_func_log10() {} + virtual ~Create_func_log10() {} +}; + + +class Create_func_log2 : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_log2 s_singleton; + +protected: + Create_func_log2() {} + virtual ~Create_func_log2() {} +}; + + +class Create_func_lpad : public Create_func_arg3 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + + static Create_func_lpad s_singleton; + +protected: + Create_func_lpad() {} + virtual ~Create_func_lpad() {} +}; + + +class Create_func_ltrim : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_ltrim s_singleton; + +protected: + Create_func_ltrim() {} + virtual ~Create_func_ltrim() {} +}; + + +class Create_func_makedate : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_makedate s_singleton; + +protected: + Create_func_makedate() {} + virtual ~Create_func_makedate() {} +}; + + +class Create_func_maketime : public Create_func_arg3 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + + static Create_func_maketime s_singleton; + +protected: + Create_func_maketime() {} + virtual ~Create_func_maketime() {} +}; + + +class Create_func_make_set : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_make_set s_singleton; + +protected: + Create_func_make_set() {} + virtual ~Create_func_make_set() {} +}; + + +class Create_func_master_pos_wait : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_master_pos_wait s_singleton; + +protected: + Create_func_master_pos_wait() {} + virtual ~Create_func_master_pos_wait() {} +}; + + +class Create_func_md5 : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_md5 s_singleton; + +protected: + Create_func_md5() {} + virtual ~Create_func_md5() {} +}; + + +class Create_func_monthname : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_monthname s_singleton; + +protected: + Create_func_monthname() {} + virtual ~Create_func_monthname() {} +}; + + +class Create_func_name_const : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_name_const s_singleton; + +protected: + Create_func_name_const() {} + virtual ~Create_func_name_const() {} +}; + + +class Create_func_nullif : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_nullif s_singleton; + +protected: + Create_func_nullif() {} + virtual ~Create_func_nullif() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_numgeometries : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_numgeometries s_singleton; + +protected: + Create_func_numgeometries() {} + virtual ~Create_func_numgeometries() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_numinteriorring : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_numinteriorring s_singleton; + +protected: + Create_func_numinteriorring() {} + virtual ~Create_func_numinteriorring() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_numpoints : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_numpoints s_singleton; + +protected: + Create_func_numpoints() {} + virtual ~Create_func_numpoints() {} +}; +#endif + + +class Create_func_oct : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_oct s_singleton; + +protected: + Create_func_oct() {} + virtual ~Create_func_oct() {} +}; + + +class Create_func_ord : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_ord s_singleton; + +protected: + Create_func_ord() {} + virtual ~Create_func_ord() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_overlaps : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_overlaps s_singleton; + +protected: + Create_func_overlaps() {} + virtual ~Create_func_overlaps() {} +}; +#endif + + +class Create_func_period_add : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_period_add s_singleton; + +protected: + Create_func_period_add() {} + virtual ~Create_func_period_add() {} +}; + + +class Create_func_period_diff : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_period_diff s_singleton; + +protected: + Create_func_period_diff() {} + virtual ~Create_func_period_diff() {} +}; + + +class Create_func_pi : public Create_func_arg0 +{ +public: + virtual Item* create(THD *thd); + + static Create_func_pi s_singleton; + +protected: + Create_func_pi() {} + virtual ~Create_func_pi() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_pointn : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_pointn s_singleton; + +protected: + Create_func_pointn() {} + virtual ~Create_func_pointn() {} +}; +#endif + + +class Create_func_pow : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_pow s_singleton; + +protected: + Create_func_pow() {} + virtual ~Create_func_pow() {} +}; + + +class Create_func_quote : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_quote s_singleton; + +protected: + Create_func_quote() {} + virtual ~Create_func_quote() {} +}; + + +class Create_func_radians : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_radians s_singleton; + +protected: + Create_func_radians() {} + virtual ~Create_func_radians() {} +}; + + +class Create_func_rand : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_rand s_singleton; + +protected: + Create_func_rand() {} + virtual ~Create_func_rand() {} +}; + + +class Create_func_release_lock : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_release_lock s_singleton; + +protected: + Create_func_release_lock() {} + virtual ~Create_func_release_lock() {} +}; + + +class Create_func_reverse : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_reverse s_singleton; + +protected: + Create_func_reverse() {} + virtual ~Create_func_reverse() {} +}; + + +class Create_func_round : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_round s_singleton; + +protected: + Create_func_round() {} + virtual ~Create_func_round() {} +}; + + +class Create_func_row_count : public Create_func_arg0 +{ +public: + virtual Item* create(THD *thd); + + static Create_func_row_count s_singleton; + +protected: + Create_func_row_count() {} + virtual ~Create_func_row_count() {} +}; + + +class Create_func_rpad : public Create_func_arg3 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + + static Create_func_rpad s_singleton; + +protected: + Create_func_rpad() {} + virtual ~Create_func_rpad() {} +}; + + +class Create_func_rtrim : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_rtrim s_singleton; + +protected: + Create_func_rtrim() {} + virtual ~Create_func_rtrim() {} +}; + + +class Create_func_sec_to_time : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_sec_to_time s_singleton; + +protected: + Create_func_sec_to_time() {} + virtual ~Create_func_sec_to_time() {} +}; + + +class Create_func_sha : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_sha s_singleton; + +protected: + Create_func_sha() {} + virtual ~Create_func_sha() {} +}; + + +class Create_func_sign : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_sign s_singleton; + +protected: + Create_func_sign() {} + virtual ~Create_func_sign() {} +}; + + +class Create_func_sin : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_sin s_singleton; + +protected: + Create_func_sin() {} + virtual ~Create_func_sin() {} +}; + + +class Create_func_sleep : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_sleep s_singleton; + +protected: + Create_func_sleep() {} + virtual ~Create_func_sleep() {} +}; + + +class Create_func_soundex : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_soundex s_singleton; + +protected: + Create_func_soundex() {} + virtual ~Create_func_soundex() {} +}; + + +class Create_func_space : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_space s_singleton; + +protected: + Create_func_space() {} + virtual ~Create_func_space() {} +}; + + +class Create_func_sqrt : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_sqrt s_singleton; + +protected: + Create_func_sqrt() {} + virtual ~Create_func_sqrt() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_srid : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_srid s_singleton; + +protected: + Create_func_srid() {} + virtual ~Create_func_srid() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_startpoint : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_startpoint s_singleton; + +protected: + Create_func_startpoint() {} + virtual ~Create_func_startpoint() {} +}; +#endif + + +class Create_func_str_to_date : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_str_to_date s_singleton; + +protected: + Create_func_str_to_date() {} + virtual ~Create_func_str_to_date() {} +}; + + +class Create_func_strcmp : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_strcmp s_singleton; + +protected: + Create_func_strcmp() {} + virtual ~Create_func_strcmp() {} +}; + + +class Create_func_substr_index : public Create_func_arg3 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + + static Create_func_substr_index s_singleton; + +protected: + Create_func_substr_index() {} + virtual ~Create_func_substr_index() {} +}; + + +class Create_func_subtime : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_subtime s_singleton; + +protected: + Create_func_subtime() {} + virtual ~Create_func_subtime() {} +}; + + +class Create_func_tan : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_tan s_singleton; + +protected: + Create_func_tan() {} + virtual ~Create_func_tan() {} +}; + + +class Create_func_time_format : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_time_format s_singleton; + +protected: + Create_func_time_format() {} + virtual ~Create_func_time_format() {} +}; + + +class Create_func_time_to_sec : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_time_to_sec s_singleton; + +protected: + Create_func_time_to_sec() {} + virtual ~Create_func_time_to_sec() {} +}; + + +class Create_func_timediff : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_timediff s_singleton; + +protected: + Create_func_timediff() {} + virtual ~Create_func_timediff() {} +}; + + +class Create_func_to_days : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_to_days s_singleton; + +protected: + Create_func_to_days() {} + virtual ~Create_func_to_days() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_touches : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_touches s_singleton; + +protected: + Create_func_touches() {} + virtual ~Create_func_touches() {} +}; +#endif + + +class Create_func_ucase : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_ucase s_singleton; + +protected: + Create_func_ucase() {} + virtual ~Create_func_ucase() {} +}; + + +class Create_func_uncompress : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_uncompress s_singleton; + +protected: + Create_func_uncompress() {} + virtual ~Create_func_uncompress() {} +}; + + +class Create_func_uncompressed_length : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_uncompressed_length s_singleton; + +protected: + Create_func_uncompressed_length() {} + virtual ~Create_func_uncompressed_length() {} +}; + + +class Create_func_unhex : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_unhex s_singleton; + +protected: + Create_func_unhex() {} + virtual ~Create_func_unhex() {} +}; + + +class Create_func_unix_timestamp : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_unix_timestamp s_singleton; + +protected: + Create_func_unix_timestamp() {} + virtual ~Create_func_unix_timestamp() {} +}; + + +class Create_func_uuid : public Create_func_arg0 +{ +public: + virtual Item* create(THD *thd); + + static Create_func_uuid s_singleton; + +protected: + Create_func_uuid() {} + virtual ~Create_func_uuid() {} +}; + + +class Create_func_version : public Create_func_arg0 +{ +public: + virtual Item* create(THD *thd); + + static Create_func_version s_singleton; + +protected: + Create_func_version() {} + virtual ~Create_func_version() {} +}; + + +class Create_func_weekday : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_weekday s_singleton; + +protected: + Create_func_weekday() {} + virtual ~Create_func_weekday() {} +}; + + +class Create_func_weekofyear : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_weekofyear s_singleton; + +protected: + Create_func_weekofyear() {} + virtual ~Create_func_weekofyear() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_within : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_within s_singleton; + +protected: + Create_func_within() {} + virtual ~Create_func_within() {} +}; +#endif + + +#ifdef HAVE_SPATIAL +class Create_func_x : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_x s_singleton; + +protected: + Create_func_x() {} + virtual ~Create_func_x() {} +}; +#endif + + +class Create_func_xml_extractvalue : public Create_func_arg2 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2); + + static Create_func_xml_extractvalue s_singleton; + +protected: + Create_func_xml_extractvalue() {} + virtual ~Create_func_xml_extractvalue() {} +}; + + +class Create_func_xml_update : public Create_func_arg3 +{ +public: + virtual Item* create(THD *thd, Item *arg1, Item *arg2, Item *arg3); + + static Create_func_xml_update s_singleton; + +protected: + Create_func_xml_update() {} + virtual ~Create_func_xml_update() {} +}; + + +#ifdef HAVE_SPATIAL +class Create_func_y : public Create_func_arg1 +{ +public: + virtual Item* create(THD *thd, Item *arg1); + + static Create_func_y s_singleton; + +protected: + Create_func_y() {} + virtual ~Create_func_y() {} +}; +#endif + + +class Create_func_year_week : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_year_week s_singleton; + +protected: + Create_func_year_week() {} + virtual ~Create_func_year_week() {} +}; + + +/* +============================================================================= + IMPLEMENTATION +============================================================================= +*/ + +#ifndef HAVE_SPATIAL +Create_func_no_geom Create_func_no_geom::s_singleton; + +Item* +Create_func_no_geom::create(THD * /* unused */, + LEX_STRING /* unused */, + List * /* unused */) +{ + /* FIXME: error message can't be translated. */ + my_error(ER_FEATURE_DISABLED, MYF(0), + sym_group_geom.name, sym_group_geom.needed_define); + return NULL; +} +#endif + + +Item* +Create_qfunc::create(THD *thd, LEX_STRING name, List *item_list) +{ + LEX_STRING db; + if (thd->copy_db_to(&db.str, &db.length)) + return NULL; + + return create(thd, db, name, item_list); } -Item *create_func_acos(Item* a) + +#ifdef HAVE_DLOPEN +Create_udf_func Create_udf_func::s_singleton; + +Item* +Create_udf_func::create(THD *thd, LEX_STRING name, List *item_list) { - return new Item_func_acos(a); + udf_func *udf= find_udf(name.str, name.length); + DBUG_ASSERT(udf); + return create(thd, udf, item_list); } -Item *create_func_aes_encrypt(Item* a, Item* b) + +Item* +Create_udf_func::create(THD *thd, udf_func *udf, List *item_list) { - return new Item_func_aes_encrypt(a, b); + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + +#ifdef HAVE_ROW_BASED_REPLICATION + thd->lex->binlog_row_based_if_mixed= TRUE; +#endif + + DBUG_ASSERT( (udf->type == UDFTYPE_FUNCTION) + || (udf->type == UDFTYPE_AGGREGATE)); + + switch(udf->returns) { + case STRING_RESULT: + { + if (udf->type == UDFTYPE_FUNCTION) + { + if (arg_count) + func= new (thd->mem_root) Item_func_udf_str(udf, *item_list); + else + func= new (thd->mem_root) Item_func_udf_str(udf); + } + else + { + if (arg_count) + func= new (thd->mem_root) Item_sum_udf_str(udf, *item_list); + else + func= new (thd->mem_root) Item_sum_udf_str(udf); + } + break; + } + case REAL_RESULT: + { + if (udf->type == UDFTYPE_FUNCTION) + { + if (arg_count) + func= new (thd->mem_root) Item_func_udf_float(udf, *item_list); + else + func= new (thd->mem_root) Item_func_udf_float(udf); + } + else + { + if (arg_count) + func= new (thd->mem_root) Item_sum_udf_float(udf, *item_list); + else + func= new (thd->mem_root) Item_sum_udf_float(udf); + } + break; + } + case INT_RESULT: + { + if (udf->type == UDFTYPE_FUNCTION) + { + if (arg_count) + func= new (thd->mem_root) Item_func_udf_int(udf, *item_list); + else + func= new (thd->mem_root) Item_func_udf_int(udf); + } + else + { + if (arg_count) + func= new (thd->mem_root) Item_sum_udf_int(udf, *item_list); + else + func= new (thd->mem_root) Item_sum_udf_int(udf); + } + break; + } + case DECIMAL_RESULT: + { + if (udf->type == UDFTYPE_FUNCTION) + { + if (arg_count) + func= new (thd->mem_root) Item_func_udf_decimal(udf, *item_list); + else + func= new (thd->mem_root) Item_func_udf_decimal(udf); + } + else + { + if (arg_count) + func= new (thd->mem_root) Item_sum_udf_decimal(udf, *item_list); + else + func= new (thd->mem_root) Item_sum_udf_decimal(udf); + } + break; + } + default: + { + my_error(ER_NOT_SUPPORTED_YET, MYF(0), "UDF return type"); + } + } + return func; +} +#endif + + +Create_sp_func Create_sp_func::s_singleton; + +Item* +Create_sp_func::create(THD *thd, LEX_STRING db, LEX_STRING name, + List *item_list) +{ + int arg_count= 0; + Item *func= NULL; + LEX *lex= thd->lex; + sp_name *qname= new (thd->mem_root) sp_name(db, name); + + if (item_list != NULL) + arg_count= item_list->elements; + + qname->init_qname(thd); + sp_add_used_routine(lex, thd, qname, TYPE_ENUM_FUNCTION); + + if (arg_count > 0) + func= new (thd->mem_root) Item_func_sp(lex->current_context(), qname, + *item_list); + else + func= new (thd->mem_root) Item_func_sp(lex->current_context(), qname); + + lex->safe_to_cache_query= 0; + return func; } -Item *create_func_aes_decrypt(Item* a, Item* b) + +Item* +Create_func_arg0::create(THD *thd, LEX_STRING name, List *item_list) { - return new Item_func_aes_decrypt(a, b); + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + if (arg_count != 0) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + return NULL; + } + + return create(thd); } -Item *create_func_ascii(Item* a) + +Item* +Create_func_arg1::create(THD *thd, LEX_STRING name, List *item_list) { - return new Item_func_ascii(a); + int arg_count= 0; + + if (item_list) + arg_count= item_list->elements; + + if (arg_count != 1) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + return NULL; + } + + Item *param_1= item_list->pop(); + return create(thd, param_1); } -Item *create_func_ord(Item* a) + +Item* +Create_func_arg2::create(THD *thd, LEX_STRING name, List *item_list) { - return new Item_func_ord(a); + int arg_count= 0; + + if (item_list) + arg_count= item_list->elements; + + if (arg_count != 2) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + return NULL; + } + + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + return create(thd, param_1, param_2); } -Item *create_func_asin(Item* a) + +Item* +Create_func_arg3::create(THD *thd, LEX_STRING name, List *item_list) { - return new Item_func_asin(a); + int arg_count= 0; + + if (item_list) + arg_count= item_list->elements; + + if (arg_count != 3) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + return NULL; + } + + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + Item *param_3= item_list->pop(); + return create(thd, param_1, param_2, param_3); } -Item *create_func_bin(Item* a) + +Create_func_abs Create_func_abs::s_singleton; + +Item* +Create_func_abs::create(THD *thd, Item *arg1) { - return new Item_func_conv(a,new Item_int((int32) 10,2), - new Item_int((int32) 2,1)); + return new (thd->mem_root) Item_func_abs(arg1); } -Item *create_func_bit_count(Item* a) + +Create_func_acos Create_func_acos::s_singleton; + +Item* +Create_func_acos::create(THD *thd, Item *arg1) { - return new Item_func_bit_count(a); + return new (thd->mem_root) Item_func_acos(arg1); } -Item *create_func_ceiling(Item* a) + +Create_func_addtime Create_func_addtime::s_singleton; + +Item* +Create_func_addtime::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_ceiling(a); + return new (thd->mem_root) Item_func_add_time(arg1, arg2, 0, 0); } -Item *create_func_connection_id(void) + +Create_func_aes_encrypt Create_func_aes_encrypt::s_singleton; + +Item* +Create_func_aes_encrypt::create(THD *thd, Item *arg1, Item *arg2) { - current_thd->lex->safe_to_cache_query= 0; - return new Item_func_connection_id(); + return new (thd->mem_root) Item_func_aes_encrypt(arg1, arg2); } -Item *create_func_conv(Item* a, Item *b, Item *c) + +Create_func_aes_decrypt Create_func_aes_decrypt::s_singleton; + +Item* +Create_func_aes_decrypt::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_conv(a,b,c); + return new (thd->mem_root) Item_func_aes_decrypt(arg1, arg2); } -Item *create_func_cos(Item* a) + +#ifdef HAVE_SPATIAL +Create_func_area Create_func_area::s_singleton; + +Item* +Create_func_area::create(THD *thd, Item *arg1) { - return new Item_func_cos(a); + return new (thd->mem_root) Item_func_area(arg1); +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_as_wkb Create_func_as_wkb::s_singleton; + +Item* +Create_func_as_wkb::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_as_wkb(arg1); +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_as_wkt Create_func_as_wkt::s_singleton; + +Item* +Create_func_as_wkt::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_as_wkt(arg1); +} +#endif + + +Create_func_asin Create_func_asin::s_singleton; + +Item* +Create_func_asin::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_asin(arg1); } -Item *create_func_cot(Item* a) + +Create_func_atan Create_func_atan::s_singleton; + +Item* +Create_func_atan::create(THD *thd, LEX_STRING name, List *item_list) { - return new Item_func_div(new Item_int((char*) "1",1,1), - new Item_func_tan(a)); + Item* func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *param_1= item_list->pop(); + func= new (thd->mem_root) Item_func_atan(param_1); + break; + } + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_atan(param_1, param_2); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; } -Item *create_func_date_format(Item* a,Item *b) + +Create_func_benchmark Create_func_benchmark::s_singleton; + +Item* +Create_func_benchmark::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_date_format(a,b,0); + /* TODO: Known limitation, see Bug#22684 */ + if ((arg1->type() != Item::INT_ITEM) || ! arg1->basic_const_item()) + { + my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), "BENCHMARK"); + return NULL; + } + + thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); + return new (thd->mem_root) Item_func_benchmark(arg1->val_int(), arg2); } -Item *create_func_dayofmonth(Item* a) + +Create_func_bin Create_func_bin::s_singleton; + +Item* +Create_func_bin::create(THD *thd, Item *arg1) { - return new Item_func_dayofmonth(a); + Item *i10= new (thd->mem_root) Item_int((int32) 10,2); + Item *i2= new (thd->mem_root) Item_int((int32) 2,1); + return new (thd->mem_root) Item_func_conv(arg1, i10, i2); } -Item *create_func_dayofweek(Item* a) + +Create_func_bit_count Create_func_bit_count::s_singleton; + +Item* +Create_func_bit_count::create(THD *thd, Item *arg1) { - return new Item_func_weekday(a, 1); + return new (thd->mem_root) Item_func_bit_count(arg1); } -Item *create_func_dayofyear(Item* a) + +Create_func_bit_length Create_func_bit_length::s_singleton; + +Item* +Create_func_bit_length::create(THD *thd, Item *arg1) { - return new Item_func_dayofyear(a); + return new (thd->mem_root) Item_func_bit_length(arg1); } -Item *create_func_dayname(Item* a) + +Create_func_ceiling Create_func_ceiling::s_singleton; + +Item* +Create_func_ceiling::create(THD *thd, Item *arg1) { - return new Item_func_dayname(a); + return new (thd->mem_root) Item_func_ceiling(arg1); } -Item *create_func_degrees(Item *a) + +#ifdef HAVE_SPATIAL +Create_func_centroid Create_func_centroid::s_singleton; + +Item* +Create_func_centroid::create(THD *thd, Item *arg1) { - return new Item_func_units((char*) "degrees",a,180/M_PI,0.0); + return new (thd->mem_root) Item_func_centroid(arg1); +} +#endif + + +Create_func_char_length Create_func_char_length::s_singleton; + +Item* +Create_func_char_length::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_char_length(arg1); } -Item *create_func_exp(Item* a) + +Create_func_coercibility Create_func_coercibility::s_singleton; + +Item* +Create_func_coercibility::create(THD *thd, Item *arg1) { - return new Item_func_exp(a); + return new (thd->mem_root) Item_func_coercibility(arg1); } -Item *create_func_find_in_set(Item* a, Item *b) + +Create_func_concat Create_func_concat::s_singleton; + +Item* +Create_func_concat::create(THD *thd, LEX_STRING name, List *item_list) { - return new Item_func_find_in_set(a, b); + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + if (arg_count < 1) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + return NULL; + } + + return new (thd->mem_root) Item_func_concat(*item_list); } -Item *create_func_floor(Item* a) + +Create_func_concat_ws Create_func_concat_ws::s_singleton; + +Item* +Create_func_concat_ws::create(THD *thd, LEX_STRING name, List *item_list) { - return new Item_func_floor(a); + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + /* "WS" stands for "With Separator": this function takes 2+ arguments */ + if (arg_count < 2) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + return NULL; + } + + return new (thd->mem_root) Item_func_concat_ws(*item_list); } -Item *create_func_found_rows(void) + +Create_func_compress Create_func_compress::s_singleton; + +Item* +Create_func_compress::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_compress(arg1); +} + + +Create_func_connection_id Create_func_connection_id::s_singleton; + +Item* +Create_func_connection_id::create(THD *thd) { - THD *thd=current_thd; thd->lex->safe_to_cache_query= 0; - return new Item_func_found_rows(); -} - -Item *create_func_from_days(Item* a) -{ - return new Item_func_from_days(a); -} - -Item *create_func_get_lock(Item* a, Item *b) -{ - current_thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - return new Item_func_get_lock(a, b); -} - -Item *create_func_hex(Item *a) -{ - return new Item_func_hex(a); -} - -Item *create_func_inet_ntoa(Item* a) -{ - return new Item_func_inet_ntoa(a); -} - -Item *create_func_inet_aton(Item* a) -{ - return new Item_func_inet_aton(a); + return new (thd->mem_root) Item_func_connection_id(); } -Item *create_func_ifnull(Item* a, Item *b) +#ifdef HAVE_SPATIAL +Create_func_contains Create_func_contains::s_singleton; + +Item* +Create_func_contains::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_ifnull(a,b); + return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, + Item_func::SP_CONTAINS_FUNC); +} +#endif + + +Create_func_conv Create_func_conv::s_singleton; + +Item* +Create_func_conv::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) +{ + return new (thd->mem_root) Item_func_conv(arg1, arg2, arg3); } -Item *create_func_nullif(Item* a, Item *b) + +Create_func_convert_tz Create_func_convert_tz::s_singleton; + +Item* +Create_func_convert_tz::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) { - return new Item_func_nullif(a,b); + if (thd->lex->add_time_zone_tables_to_query_tables(thd)) + return NULL; + + return new (thd->mem_root) Item_func_convert_tz(arg1, arg2, arg3); } -Item *create_func_locate(Item* a, Item *b) + +Create_func_cos Create_func_cos::s_singleton; + +Item* +Create_func_cos::create(THD *thd, Item *arg1) { - return new Item_func_locate(b,a); + return new (thd->mem_root) Item_func_cos(arg1); } -Item *create_func_instr(Item* a, Item *b) + +Create_func_cot Create_func_cot::s_singleton; + +Item* +Create_func_cot::create(THD *thd, Item *arg1) { - return new Item_func_locate(a,b); + Item *i1= new (thd->mem_root) Item_int((char*) "1", 1, 1); + Item *i2= new (thd->mem_root) Item_func_tan(arg1); + return new (thd->mem_root) Item_func_div(i1, i2); } -Item *create_func_isnull(Item* a) + +Create_func_crc32 Create_func_crc32::s_singleton; + +Item* +Create_func_crc32::create(THD *thd, Item *arg1) { - return new Item_func_isnull(a); + return new (thd->mem_root) Item_func_crc32(arg1); } -Item *create_func_lcase(Item* a) + +#ifdef HAVE_SPATIAL +Create_func_crosses Create_func_crosses::s_singleton; + +Item* +Create_func_crosses::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_lcase(a); + return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, + Item_func::SP_CROSSES_FUNC); +} +#endif + + +Create_func_date_format Create_func_date_format::s_singleton; + +Item* +Create_func_date_format::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_date_format(arg1, arg2, 0); } -Item *create_func_length(Item* a) + +Create_func_datediff Create_func_datediff::s_singleton; + +Item* +Create_func_datediff::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_length(a); + Item *i1= new (thd->mem_root) Item_func_to_days(arg1); + Item *i2= new (thd->mem_root) Item_func_to_days(arg2); + + return new (thd->mem_root) Item_func_minus(i1, i2); } -Item *create_func_bit_length(Item* a) + +Create_func_dayname Create_func_dayname::s_singleton; + +Item* +Create_func_dayname::create(THD *thd, Item *arg1) { - return new Item_func_bit_length(a); + return new (thd->mem_root) Item_func_dayname(arg1); } -Item *create_func_coercibility(Item* a) + +Create_func_dayofmonth Create_func_dayofmonth::s_singleton; + +Item* +Create_func_dayofmonth::create(THD *thd, Item *arg1) { - return new Item_func_coercibility(a); + return new (thd->mem_root) Item_func_dayofmonth(arg1); } -Item *create_func_char_length(Item* a) + +Create_func_dayofweek Create_func_dayofweek::s_singleton; + +Item* +Create_func_dayofweek::create(THD *thd, Item *arg1) { - return new Item_func_char_length(a); + return new (thd->mem_root) Item_func_weekday(arg1, 1); } -Item *create_func_ln(Item* a) + +Create_func_dayofyear Create_func_dayofyear::s_singleton; + +Item* +Create_func_dayofyear::create(THD *thd, Item *arg1) { - return new Item_func_ln(a); + return new (thd->mem_root) Item_func_dayofyear(arg1); } -Item *create_func_log2(Item* a) + +Create_func_decode Create_func_decode::s_singleton; + +Item* +Create_func_decode::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_log2(a); + /* TODO: Known limitation, see Bug#22684 */ + if ((arg2->type() != Item::STRING_ITEM) || ! arg2->basic_const_item()) + { + my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), "DECODE"); + return NULL; + } + + String dummy; + String *val = arg2->val_str(& dummy); + DBUG_ASSERT(val); + return new (thd->mem_root) Item_func_decode(arg1, val->c_ptr()); } -Item *create_func_log10(Item* a) + +Create_func_degrees Create_func_degrees::s_singleton; + +Item* +Create_func_degrees::create(THD *thd, Item *arg1) { - return new Item_func_log10(a); + return new (thd->mem_root) Item_func_units((char*) "degrees", arg1, + 180/M_PI, 0.0); } -Item *create_func_lpad(Item* a, Item *b, Item *c) + +Create_func_des_decrypt Create_func_des_decrypt::s_singleton; + +Item* +Create_func_des_decrypt::create(THD *thd, LEX_STRING name, + List *item_list) { - return new Item_func_lpad(a,b,c); + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *param_1= item_list->pop(); + func= new (thd->mem_root) Item_func_des_decrypt(param_1); + break; + } + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_des_decrypt(param_1, param_2); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; } -Item *create_func_ltrim(Item* a) + +Create_func_des_encrypt Create_func_des_encrypt::s_singleton; + +Item* +Create_func_des_encrypt::create(THD *thd, LEX_STRING name, + List *item_list) { - return new Item_func_ltrim(a); + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *param_1= item_list->pop(); + func= new (thd->mem_root) Item_func_des_encrypt(param_1); + break; + } + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_des_encrypt(param_1, param_2); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; } -Item *create_func_md5(Item* a) + +#ifdef HAVE_SPATIAL +Create_func_dimension Create_func_dimension::s_singleton; + +Item* +Create_func_dimension::create(THD *thd, Item *arg1) { - return new Item_func_md5(a); + return new (thd->mem_root) Item_func_dimension(arg1); +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_disjoint Create_func_disjoint::s_singleton; + +Item* +Create_func_disjoint::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, + Item_func::SP_DISJOINT_FUNC); +} +#endif + + +Create_func_elt Create_func_elt::s_singleton; + +Item* +Create_func_elt::create(THD *thd, LEX_STRING name, List *item_list) +{ + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + if (arg_count < 2) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + return NULL; + } + + return new (thd->mem_root) Item_func_elt(*item_list); } -Item *create_func_mod(Item* a, Item *b) + +Create_func_encode Create_func_encode::s_singleton; + +Item* +Create_func_encode::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_mod(a,b); + /* TODO: Known limitation, see Bug#22684 */ + if ((arg2->type() != Item::STRING_ITEM) || ! arg2->basic_const_item()) + { + my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), "ENCODE"); + return NULL; + } + + String dummy; + String *val = arg2->val_str(& dummy); + DBUG_ASSERT(val); + return new (thd->mem_root) Item_func_encode(arg1, val->c_ptr()); } -Item *create_func_name_const(Item *a, Item *b) + +Create_func_encrypt Create_func_encrypt::s_singleton; + +Item* +Create_func_encrypt::create(THD *thd, LEX_STRING name, List *item_list) { - return new Item_name_const(a,b); + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *param_1= item_list->pop(); + func= new (thd->mem_root) Item_func_encrypt(param_1); + thd->lex->uncacheable(UNCACHEABLE_RAND); + break; + } + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_encrypt(param_1, param_2); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; } -Item *create_func_monthname(Item* a) + +#ifdef HAVE_SPATIAL +Create_func_endpoint Create_func_endpoint::s_singleton; + +Item* +Create_func_endpoint::create(THD *thd, Item *arg1) { - return new Item_func_monthname(a); + return new (thd->mem_root) Item_func_spatial_decomp(arg1, + Item_func::SP_ENDPOINT); +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_envelope Create_func_envelope::s_singleton; + +Item* +Create_func_envelope::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_envelope(arg1); +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_equals Create_func_equals::s_singleton; + +Item* +Create_func_equals::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, + Item_func::SP_EQUALS_FUNC); +} +#endif + + +Create_func_exp Create_func_exp::s_singleton; + +Item* +Create_func_exp::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_exp(arg1); } -Item *create_func_month(Item* a) + +Create_func_export_set Create_func_export_set::s_singleton; + +Item* +Create_func_export_set::create(THD *thd, LEX_STRING name, List *item_list) { - return new Item_func_month(a); + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 3: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + Item *param_3= item_list->pop(); + func= new (thd->mem_root) Item_func_export_set(param_1, param_2, param_3); + break; + } + case 4: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + Item *param_3= item_list->pop(); + Item *param_4= item_list->pop(); + func= new (thd->mem_root) Item_func_export_set(param_1, param_2, param_3, + param_4); + break; + } + case 5: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + Item *param_3= item_list->pop(); + Item *param_4= item_list->pop(); + Item *param_5= item_list->pop(); + func= new (thd->mem_root) Item_func_export_set(param_1, param_2, param_3, + param_4, param_5); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; } -Item *create_func_oct(Item *a) + +#ifdef HAVE_SPATIAL +Create_func_exteriorring Create_func_exteriorring::s_singleton; + +Item* +Create_func_exteriorring::create(THD *thd, Item *arg1) { - return new Item_func_conv(a,new Item_int((int32) 10,2), - new Item_int((int32) 8,1)); + return new (thd->mem_root) Item_func_spatial_decomp(arg1, + Item_func::SP_EXTERIORRING); +} +#endif + + +Create_func_field Create_func_field::s_singleton; + +Item* +Create_func_field::create(THD *thd, LEX_STRING name, List *item_list) +{ + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + if (arg_count < 2) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + return NULL; + } + + return new (thd->mem_root) Item_func_field(*item_list); } -Item *create_func_period_add(Item* a, Item *b) + +Create_func_find_in_set Create_func_find_in_set::s_singleton; + +Item* +Create_func_find_in_set::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_period_add(a,b); + return new (thd->mem_root) Item_func_find_in_set(arg1, arg2); } -Item *create_func_period_diff(Item* a, Item *b) + +Create_func_floor Create_func_floor::s_singleton; + +Item* +Create_func_floor::create(THD *thd, Item *arg1) { - return new Item_func_period_diff(a,b); + return new (thd->mem_root) Item_func_floor(arg1); } -Item *create_func_pi(void) + +Create_func_format Create_func_format::s_singleton; + +Item* +Create_func_format::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_static_float_func("pi()", M_PI, 6, 8); + /* TODO: Known limitation, see Bug#22684 */ + if ((arg2->type() != Item::INT_ITEM) || ! arg2->basic_const_item()) + { + my_error(ER_WRONG_PARAMETERS_TO_NATIVE_FCT, MYF(0), "FORMAT"); + return NULL; + } + + return new (thd->mem_root) Item_func_format(arg1, arg2->val_int()); } -Item *create_func_pow(Item* a, Item *b) + +Create_func_found_rows Create_func_found_rows::s_singleton; + +Item* +Create_func_found_rows::create(THD *thd) { - return new Item_func_pow(a,b); + thd->lex->safe_to_cache_query= 0; + return new (thd->mem_root) Item_func_found_rows(); } -Item *create_func_radians(Item *a) + +Create_func_from_days Create_func_from_days::s_singleton; + +Item* +Create_func_from_days::create(THD *thd, Item *arg1) { - return new Item_func_units((char*) "radians",a,M_PI/180,0.0); + return new (thd->mem_root) Item_func_from_days(arg1); } -Item *create_func_release_lock(Item* a) + +Create_func_from_unixtime Create_func_from_unixtime::s_singleton; + +Item* +Create_func_from_unixtime::create(THD *thd, LEX_STRING name, + List *item_list) { - current_thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - return new Item_func_release_lock(a); + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *param_1= item_list->pop(); + func= new (thd->mem_root) Item_func_from_unixtime(param_1); + break; + } + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + Item *ut= new (thd->mem_root) Item_func_from_unixtime(param_1); + func= new (thd->mem_root) Item_func_date_format(ut, param_2, 0); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; } -Item *create_func_repeat(Item* a, Item *b) + +#ifdef HAVE_SPATIAL +Create_func_geometry_from_text Create_func_geometry_from_text::s_singleton; + +Item* +Create_func_geometry_from_text::create(THD *thd, LEX_STRING name, + List *item_list) { - return new Item_func_repeat(a,b); + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *param_1= item_list->pop(); + func= new (thd->mem_root) Item_func_geometry_from_text(param_1); + thd->lex->uncacheable(UNCACHEABLE_RAND); + break; + } + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_geometry_from_text(param_1, param_2); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_geometry_from_wkb Create_func_geometry_from_wkb::s_singleton; + +Item* +Create_func_geometry_from_wkb::create(THD *thd, LEX_STRING name, + List *item_list) +{ + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *param_1= item_list->pop(); + func= new (thd->mem_root) Item_func_geometry_from_wkb(param_1); + thd->lex->uncacheable(UNCACHEABLE_RAND); + break; + } + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_geometry_from_wkb(param_1, param_2); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_geometry_type Create_func_geometry_type::s_singleton; + +Item* +Create_func_geometry_type::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_geometry_type(arg1); +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_geometryn Create_func_geometryn::s_singleton; + +Item* +Create_func_geometryn::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_spatial_decomp_n(arg1, arg2, + Item_func::SP_GEOMETRYN); +} +#endif + + +Create_func_get_lock Create_func_get_lock::s_singleton; + +Item* +Create_func_get_lock::create(THD *thd, Item *arg1, Item *arg2) +{ + thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); + return new (thd->mem_root) Item_func_get_lock(arg1, arg2); } -Item *create_func_reverse(Item* a) + +#ifdef HAVE_SPATIAL +Create_func_glength Create_func_glength::s_singleton; + +Item* +Create_func_glength::create(THD *thd, Item *arg1) { - return new Item_func_reverse(a); + return new (thd->mem_root) Item_func_glength(arg1); +} +#endif + + +Create_func_greatest Create_func_greatest::s_singleton; + +Item* +Create_func_greatest::create(THD *thd, LEX_STRING name, List *item_list) +{ + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + if (arg_count < 2) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + return NULL; + } + + return new (thd->mem_root) Item_func_max(*item_list); } -Item *create_func_rpad(Item* a, Item *b, Item *c) + +Create_func_hex Create_func_hex::s_singleton; + +Item* +Create_func_hex::create(THD *thd, Item *arg1) { - return new Item_func_rpad(a,b,c); + return new (thd->mem_root) Item_func_hex(arg1); } -Item *create_func_rtrim(Item* a) + +Create_func_ifnull Create_func_ifnull::s_singleton; + +Item* +Create_func_ifnull::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_rtrim(a); + return new (thd->mem_root) Item_func_ifnull(arg1, arg2); } -Item *create_func_sec_to_time(Item* a) + +Create_func_inet_ntoa Create_func_inet_ntoa::s_singleton; + +Item* +Create_func_inet_ntoa::create(THD *thd, Item *arg1) { - return new Item_func_sec_to_time(a); + return new (thd->mem_root) Item_func_inet_ntoa(arg1); } -Item *create_func_sign(Item* a) + +Create_func_inet_aton Create_func_inet_aton::s_singleton; + +Item* +Create_func_inet_aton::create(THD *thd, Item *arg1) { - return new Item_func_sign(a); + return new (thd->mem_root) Item_func_inet_aton(arg1); } -Item *create_func_sin(Item* a) + +Create_func_instr Create_func_instr::s_singleton; + +Item* +Create_func_instr::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_sin(a); + return new (thd->mem_root) Item_func_locate(arg1, arg2); } -Item *create_func_sha(Item* a) + +#ifdef HAVE_SPATIAL +Create_func_interiorringn Create_func_interiorringn::s_singleton; + +Item* +Create_func_interiorringn::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_sha(a); + return new (thd->mem_root) Item_func_spatial_decomp_n(arg1, arg2, + Item_func::SP_INTERIORRINGN); +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_intersects Create_func_intersects::s_singleton; + +Item* +Create_func_intersects::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, + Item_func::SP_INTERSECTS_FUNC); +} +#endif + + +Create_func_is_free_lock Create_func_is_free_lock::s_singleton; + +Item* +Create_func_is_free_lock::create(THD *thd, Item *arg1) +{ + thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); + return new (thd->mem_root) Item_func_is_free_lock(arg1); } -Item *create_func_sleep(Item* a) + +Create_func_is_used_lock Create_func_is_used_lock::s_singleton; + +Item* +Create_func_is_used_lock::create(THD *thd, Item *arg1) { - current_thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - return new Item_func_sleep(a); + thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); + return new (thd->mem_root) Item_func_is_used_lock(arg1); } -Item *create_func_space(Item *a) + +#ifdef HAVE_SPATIAL +Create_func_isclosed Create_func_isclosed::s_singleton; + +Item* +Create_func_isclosed::create(THD *thd, Item *arg1) { - CHARSET_INFO *cs= current_thd->variables.collation_connection; + return new (thd->mem_root) Item_func_isclosed(arg1); +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_isempty Create_func_isempty::s_singleton; + +Item* +Create_func_isempty::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_isempty(arg1); +} +#endif + + +Create_func_isnull Create_func_isnull::s_singleton; + +Item* +Create_func_isnull::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_isnull(arg1); +} + + +#ifdef HAVE_SPATIAL +Create_func_issimple Create_func_issimple::s_singleton; + +Item* +Create_func_issimple::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_issimple(arg1); +} +#endif + + +Create_func_last_day Create_func_last_day::s_singleton; + +Item* +Create_func_last_day::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_last_day(arg1); +} + + +Create_func_last_insert_id Create_func_last_insert_id::s_singleton; + +Item* +Create_func_last_insert_id::create(THD *thd, LEX_STRING name, + List *item_list) +{ + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 0: + { + func= new (thd->mem_root) Item_func_last_insert_id(); + thd->lex->safe_to_cache_query= 0; + break; + } + case 1: + { + Item *param_1= item_list->pop(); + func= new (thd->mem_root) Item_func_last_insert_id(param_1); + thd->lex->safe_to_cache_query= 0; + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; +} + + +Create_func_lcase Create_func_lcase::s_singleton; + +Item* +Create_func_lcase::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_lcase(arg1); +} + + +Create_func_least Create_func_least::s_singleton; + +Item* +Create_func_least::create(THD *thd, LEX_STRING name, List *item_list) +{ + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + if (arg_count < 2) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + return NULL; + } + + return new (thd->mem_root) Item_func_min(*item_list); +} + + +Create_func_length Create_func_length::s_singleton; + +Item* +Create_func_length::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_length(arg1); +} + + +Create_func_ln Create_func_ln::s_singleton; + +Item* +Create_func_ln::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_ln(arg1); +} + + +Create_func_load_file Create_func_load_file::s_singleton; + +Item* +Create_func_load_file::create(THD *thd, Item *arg1) +{ + thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); + return new (thd->mem_root) Item_load_file(arg1); +} + + +Create_func_locate Create_func_locate::s_singleton; + +Item* +Create_func_locate::create(THD *thd, LEX_STRING name, List *item_list) +{ + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + /* Yes, parameters in that order : 2, 1 */ + func= new (thd->mem_root) Item_func_locate(param_2, param_1); + break; + } + case 3: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + Item *param_3= item_list->pop(); + /* Yes, parameters in that order : 2, 1, 3 */ + func= new (thd->mem_root) Item_func_locate(param_2, param_1, param_3); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; +} + + +Create_func_log Create_func_log::s_singleton; + +Item* +Create_func_log::create(THD *thd, LEX_STRING name, List *item_list) +{ + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *param_1= item_list->pop(); + func= new (thd->mem_root) Item_func_log(param_1); + break; + } + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_log(param_1, param_2); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; +} + + +Create_func_log10 Create_func_log10::s_singleton; + +Item* +Create_func_log10::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_log10(arg1); +} + + +Create_func_log2 Create_func_log2::s_singleton; + +Item* +Create_func_log2::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_log2(arg1); +} + + +Create_func_lpad Create_func_lpad::s_singleton; + +Item* +Create_func_lpad::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) +{ + return new (thd->mem_root) Item_func_lpad(arg1, arg2, arg3); +} + + +Create_func_ltrim Create_func_ltrim::s_singleton; + +Item* +Create_func_ltrim::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_ltrim(arg1); +} + + +Create_func_makedate Create_func_makedate::s_singleton; + +Item* +Create_func_makedate::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_makedate(arg1, arg2); +} + + +Create_func_maketime Create_func_maketime::s_singleton; + +Item* +Create_func_maketime::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) +{ + return new (thd->mem_root) Item_func_maketime(arg1, arg2, arg3); +} + + +Create_func_make_set Create_func_make_set::s_singleton; + +Item* +Create_func_make_set::create(THD *thd, LEX_STRING name, List *item_list) +{ + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + if (arg_count < 2) + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + return NULL; + } + + Item *param_1= item_list->pop(); + return new (thd->mem_root) Item_func_make_set(param_1, *item_list); +} + + +Create_func_master_pos_wait Create_func_master_pos_wait::s_singleton; + +Item* +Create_func_master_pos_wait::create(THD *thd, LEX_STRING name, + List *item_list) +{ + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_master_pos_wait(param_1, param_2); + thd->lex->safe_to_cache_query= 0; + break; + } + case 3: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + Item *param_3= item_list->pop(); + func= new (thd->mem_root) Item_master_pos_wait(param_1, param_2, param_3); + thd->lex->safe_to_cache_query= 0; + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; +} + + +Create_func_md5 Create_func_md5::s_singleton; + +Item* +Create_func_md5::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_md5(arg1); +} + + +Create_func_monthname Create_func_monthname::s_singleton; + +Item* +Create_func_monthname::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_monthname(arg1); +} + + +Create_func_name_const Create_func_name_const::s_singleton; + +Item* +Create_func_name_const::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_name_const(arg1, arg2); +} + + +Create_func_nullif Create_func_nullif::s_singleton; + +Item* +Create_func_nullif::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_nullif(arg1, arg2); +} + + +#ifdef HAVE_SPATIAL +Create_func_numgeometries Create_func_numgeometries::s_singleton; + +Item* +Create_func_numgeometries::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_numgeometries(arg1); +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_numinteriorring Create_func_numinteriorring::s_singleton; + +Item* +Create_func_numinteriorring::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_numinteriorring(arg1); +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_numpoints Create_func_numpoints::s_singleton; + +Item* +Create_func_numpoints::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_numpoints(arg1); +} +#endif + + +Create_func_oct Create_func_oct::s_singleton; + +Item* +Create_func_oct::create(THD *thd, Item *arg1) +{ + Item *i10= new (thd->mem_root) Item_int((int32) 10,2); + Item *i8= new (thd->mem_root) Item_int((int32) 8,1); + return new (thd->mem_root) Item_func_conv(arg1, i10, i8); +} + + +Create_func_ord Create_func_ord::s_singleton; + +Item* +Create_func_ord::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_ord(arg1); +} + + +#ifdef HAVE_SPATIAL +Create_func_overlaps Create_func_overlaps::s_singleton; + +Item* +Create_func_overlaps::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, + Item_func::SP_OVERLAPS_FUNC); +} +#endif + + +Create_func_period_add Create_func_period_add::s_singleton; + +Item* +Create_func_period_add::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_period_add(arg1, arg2); +} + + +Create_func_period_diff Create_func_period_diff::s_singleton; + +Item* +Create_func_period_diff::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_period_diff(arg1, arg2); +} + + +Create_func_pi Create_func_pi::s_singleton; + +Item* +Create_func_pi::create(THD *thd) +{ + return new (thd->mem_root) Item_static_float_func("pi()", M_PI, 6, 8); +} + + +#ifdef HAVE_SPATIAL +Create_func_pointn Create_func_pointn::s_singleton; + +Item* +Create_func_pointn::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_spatial_decomp_n(arg1, arg2, + Item_func::SP_POINTN); +} +#endif + + +Create_func_pow Create_func_pow::s_singleton; + +Item* +Create_func_pow::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_pow(arg1, arg2); +} + + +Create_func_quote Create_func_quote::s_singleton; + +Item* +Create_func_quote::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_quote(arg1); +} + + +Create_func_radians Create_func_radians::s_singleton; + +Item* +Create_func_radians::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_units((char*) "radians", arg1, + M_PI/180, 0.0); +} + + +Create_func_rand Create_func_rand::s_singleton; + +Item* +Create_func_rand::create(THD *thd, LEX_STRING name, List *item_list) +{ + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 0: + { + func= new (thd->mem_root) Item_func_rand(); + thd->lex->uncacheable(UNCACHEABLE_RAND); + break; + } + case 1: + { + Item *param_1= item_list->pop(); + func= new (thd->mem_root) Item_func_rand(param_1); + thd->lex->uncacheable(UNCACHEABLE_RAND); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; +} + + +Create_func_release_lock Create_func_release_lock::s_singleton; + +Item* +Create_func_release_lock::create(THD *thd, Item *arg1) +{ + thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); + return new (thd->mem_root) Item_func_release_lock(arg1); +} + + +Create_func_reverse Create_func_reverse::s_singleton; + +Item* +Create_func_reverse::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_reverse(arg1); +} + + +Create_func_round Create_func_round::s_singleton; + +Item* +Create_func_round::create(THD *thd, LEX_STRING name, List *item_list) +{ + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *param_1= item_list->pop(); + Item *i0 = new (thd->mem_root) Item_int((char*)"0", 0, 1); + func= new (thd->mem_root) Item_func_round(param_1, i0, 0); + break; + } + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_round(param_1, param_2, 0); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; +} + + +Create_func_row_count Create_func_row_count::s_singleton; + +Item* +Create_func_row_count::create(THD *thd) +{ + thd->lex->safe_to_cache_query= 0; + return new (thd->mem_root) Item_func_row_count(); +} + + +Create_func_rpad Create_func_rpad::s_singleton; + +Item* +Create_func_rpad::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) +{ + return new (thd->mem_root) Item_func_rpad(arg1, arg2, arg3); +} + + +Create_func_rtrim Create_func_rtrim::s_singleton; + +Item* +Create_func_rtrim::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_rtrim(arg1); +} + + +Create_func_sec_to_time Create_func_sec_to_time::s_singleton; + +Item* +Create_func_sec_to_time::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_sec_to_time(arg1); +} + + +Create_func_sha Create_func_sha::s_singleton; + +Item* +Create_func_sha::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_sha(arg1); +} + + +Create_func_sign Create_func_sign::s_singleton; + +Item* +Create_func_sign::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_sign(arg1); +} + + +Create_func_sin Create_func_sin::s_singleton; + +Item* +Create_func_sin::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_sin(arg1); +} + + +Create_func_sleep Create_func_sleep::s_singleton; + +Item* +Create_func_sleep::create(THD *thd, Item *arg1) +{ + thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); + return new (thd->mem_root) Item_func_sleep(arg1); +} + + +Create_func_soundex Create_func_soundex::s_singleton; + +Item* +Create_func_soundex::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_soundex(arg1); +} + + +Create_func_space Create_func_space::s_singleton; + +Item* +Create_func_space::create(THD *thd, Item *arg1) +{ + /** + TODO: Fix Bug#23637 + The parsed item tree should not depend on + thd->variables.collation_connection. + */ + CHARSET_INFO *cs= thd->variables.collation_connection; Item *sp; if (cs->mbminlen > 1) { uint dummy_errors; - sp= new Item_string("",0,cs); - if (sp) - sp->str_value.copy(" ", 1, &my_charset_latin1, cs, &dummy_errors); + sp= new (thd->mem_root) Item_string("", 0, cs); + sp->str_value.copy(" ", 1, &my_charset_latin1, cs, &dummy_errors); } else { - sp= new Item_string(" ",1,cs); + sp= new (thd->mem_root) Item_string(" ", 1, cs); } - return sp ? new Item_func_repeat(sp, a) : 0; + + return new (thd->mem_root) Item_func_repeat(sp, arg1); } -Item *create_func_soundex(Item* a) + +Create_func_sqrt Create_func_sqrt::s_singleton; + +Item* +Create_func_sqrt::create(THD *thd, Item *arg1) { - return new Item_func_soundex(a); + return new (thd->mem_root) Item_func_sqrt(arg1); } -Item *create_func_sqrt(Item* a) + +#ifdef HAVE_SPATIAL +Create_func_srid Create_func_srid::s_singleton; + +Item* +Create_func_srid::create(THD *thd, Item *arg1) { - return new Item_func_sqrt(a); + return new (thd->mem_root) Item_func_srid(arg1); +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_startpoint Create_func_startpoint::s_singleton; + +Item* +Create_func_startpoint::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_spatial_decomp(arg1, + Item_func::SP_STARTPOINT); +} +#endif + + +Create_func_str_to_date Create_func_str_to_date::s_singleton; + +Item* +Create_func_str_to_date::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_str_to_date(arg1, arg2); } -Item *create_func_strcmp(Item* a, Item *b) + +Create_func_strcmp Create_func_strcmp::s_singleton; + +Item* +Create_func_strcmp::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_strcmp(a,b); + return new (thd->mem_root) Item_func_strcmp(arg1, arg2); } -Item *create_func_tan(Item* a) + +Create_func_substr_index Create_func_substr_index::s_singleton; + +Item* +Create_func_substr_index::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) { - return new Item_func_tan(a); + return new (thd->mem_root) Item_func_substr_index(arg1, arg2, arg3); } -Item *create_func_time_format(Item *a, Item *b) + +Create_func_subtime Create_func_subtime::s_singleton; + +Item* +Create_func_subtime::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_date_format(a,b,1); + return new (thd->mem_root) Item_func_add_time(arg1, arg2, 0, 1); } -Item *create_func_time_to_sec(Item* a) + +Create_func_tan Create_func_tan::s_singleton; + +Item* +Create_func_tan::create(THD *thd, Item *arg1) { - return new Item_func_time_to_sec(a); + return new (thd->mem_root) Item_func_tan(arg1); } -Item *create_func_to_days(Item* a) + +Create_func_time_format Create_func_time_format::s_singleton; + +Item* +Create_func_time_format::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_to_days(a); + return new (thd->mem_root) Item_func_date_format(arg1, arg2, 1); } -Item *create_func_ucase(Item* a) + +Create_func_time_to_sec Create_func_time_to_sec::s_singleton; + +Item* +Create_func_time_to_sec::create(THD *thd, Item *arg1) { - return new Item_func_ucase(a); + return new (thd->mem_root) Item_func_time_to_sec(arg1); } -Item *create_func_unhex(Item* a) + +Create_func_timediff Create_func_timediff::s_singleton; + +Item* +Create_func_timediff::create(THD *thd, Item *arg1, Item *arg2) { - return new Item_func_unhex(a); + return new (thd->mem_root) Item_func_timediff(arg1, arg2); } -Item *create_func_uuid(void) + +Create_func_to_days Create_func_to_days::s_singleton; + +Item* +Create_func_to_days::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_to_days(arg1); +} + + +#ifdef HAVE_SPATIAL +Create_func_touches Create_func_touches::s_singleton; + +Item* +Create_func_touches::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, + Item_func::SP_TOUCHES_FUNC); +} +#endif + + +Create_func_ucase Create_func_ucase::s_singleton; + +Item* +Create_func_ucase::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_ucase(arg1); +} + + +Create_func_uncompress Create_func_uncompress::s_singleton; + +Item* +Create_func_uncompress::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_uncompress(arg1); +} + + +Create_func_uncompressed_length Create_func_uncompressed_length::s_singleton; + +Item* +Create_func_uncompressed_length::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_uncompressed_length(arg1); +} + + +Create_func_unhex Create_func_unhex::s_singleton; + +Item* +Create_func_unhex::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_unhex(arg1); +} + + +Create_func_unix_timestamp Create_func_unix_timestamp::s_singleton; + +Item* +Create_func_unix_timestamp::create(THD *thd, LEX_STRING name, + List *item_list) +{ + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 0: + { + func= new (thd->mem_root) Item_func_unix_timestamp(); + thd->lex->safe_to_cache_query= 0; + break; + } + case 1: + { + Item *param_1= item_list->pop(); + func= new (thd->mem_root) Item_func_unix_timestamp(param_1); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; +} + + +Create_func_uuid Create_func_uuid::s_singleton; + +Item* +Create_func_uuid::create(THD *thd) { - THD *thd= current_thd; #ifdef HAVE_ROW_BASED_REPLICATION thd->lex->binlog_row_based_if_mixed= TRUE; #endif - return new(thd->mem_root) Item_func_uuid(); + return new (thd->mem_root) Item_func_uuid(); } -Item *create_func_version(void) + +Create_func_version Create_func_version::s_singleton; + +Item* +Create_func_version::create(THD *thd) { - return new Item_static_string_func("version()", server_version, - (uint) strlen(server_version), - system_charset_info, DERIVATION_SYSCONST); + return new (thd->mem_root) Item_static_string_func("version()", + server_version, + (uint) strlen(server_version), + system_charset_info, + DERIVATION_SYSCONST); } -Item *create_func_weekday(Item* a) + +Create_func_weekday Create_func_weekday::s_singleton; + +Item* +Create_func_weekday::create(THD *thd, Item *arg1) { - return new Item_func_weekday(a, 0); + return new (thd->mem_root) Item_func_weekday(arg1, 0); } -Item *create_func_year(Item* a) + +Create_func_weekofyear Create_func_weekofyear::s_singleton; + +Item* +Create_func_weekofyear::create(THD *thd, Item *arg1) { - return new Item_func_year(a); + Item *i1= new (thd->mem_root) Item_int((char*) "0", 3, 1); + return new (thd->mem_root) Item_func_week(arg1, i1); } -Item *create_load_file(Item* a) + +#ifdef HAVE_SPATIAL +Create_func_within Create_func_within::s_singleton; + +Item* +Create_func_within::create(THD *thd, Item *arg1, Item *arg2) { - current_thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - return new Item_load_file(a); + return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2, + Item_func::SP_WITHIN_FUNC); +} +#endif + + +#ifdef HAVE_SPATIAL +Create_func_x Create_func_x::s_singleton; + +Item* +Create_func_x::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_x(arg1); +} +#endif + + +Create_func_xml_extractvalue Create_func_xml_extractvalue::s_singleton; + +Item* +Create_func_xml_extractvalue::create(THD *thd, Item *arg1, Item *arg2) +{ + return new (thd->mem_root) Item_func_xml_extractvalue(arg1, arg2); } -Item *create_func_cast(Item *a, Cast_target cast_type, int len, int dec, - CHARSET_INFO *cs) +Create_func_xml_update Create_func_xml_update::s_singleton; + +Item* +Create_func_xml_update::create(THD *thd, Item *arg1, Item *arg2, Item *arg3) +{ + return new (thd->mem_root) Item_func_xml_update(arg1, arg2, arg3); +} + + +#ifdef HAVE_SPATIAL +Create_func_y Create_func_y::s_singleton; + +Item* +Create_func_y::create(THD *thd, Item *arg1) +{ + return new (thd->mem_root) Item_func_y(arg1); +} +#endif + + +Create_func_year_week Create_func_year_week::s_singleton; + +Item* +Create_func_year_week::create(THD *thd, LEX_STRING name, List *item_list) +{ + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *param_1= item_list->pop(); + Item *i0= new (thd->mem_root) Item_int((char*) "0", 0, 1); + func= new (thd->mem_root) Item_func_yearweek(param_1, i0); + break; + } + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_yearweek(param_1, param_2); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; +} + + +struct Native_func_registry +{ + LEX_STRING name; + Create_func *builder; +}; + +#define BUILDER(F) & F::s_singleton + +#ifdef HAVE_SPATIAL + #define GEOM_BUILDER(F) & F::s_singleton +#else + #define GEOM_BUILDER(F) & Create_func_no_geom::s_singleton +#endif + +/* + MySQL native functions. + MAINTAINER: + - Keep sorted for human lookup. At runtime, a hash table is used. + - do **NOT** conditionally (#ifdef, #ifndef) define a function *NAME*: + doing so will cause user code that works against a --without-XYZ binary + to fail with name collisions against a --with-XYZ binary. + Use something similar to GEOM_BUILDER instead. + - keep 1 line per entry, it makes grep | sort easier +*/ + +static Native_func_registry func_array[] = +{ + { C_STRING_WITH_LEN("ABS"), BUILDER(Create_func_abs)}, + { C_STRING_WITH_LEN("ACOS"), BUILDER(Create_func_acos)}, + { C_STRING_WITH_LEN("ADDTIME"), BUILDER(Create_func_addtime)}, + { C_STRING_WITH_LEN("AES_DECRYPT"), BUILDER(Create_func_aes_decrypt)}, + { C_STRING_WITH_LEN("AES_ENCRYPT"), BUILDER(Create_func_aes_encrypt)}, + { C_STRING_WITH_LEN("AREA"), GEOM_BUILDER(Create_func_area)}, + { C_STRING_WITH_LEN("ASBINARY"), GEOM_BUILDER(Create_func_as_wkb)}, + { C_STRING_WITH_LEN("ASIN"), BUILDER(Create_func_asin)}, + { C_STRING_WITH_LEN("ASTEXT"), GEOM_BUILDER(Create_func_as_wkt)}, + { C_STRING_WITH_LEN("ASWKB"), GEOM_BUILDER(Create_func_as_wkb)}, + { C_STRING_WITH_LEN("ASWKT"), GEOM_BUILDER(Create_func_as_wkt)}, + { C_STRING_WITH_LEN("ATAN"), BUILDER(Create_func_atan)}, + { C_STRING_WITH_LEN("ATAN2"), BUILDER(Create_func_atan)}, + { C_STRING_WITH_LEN("BENCHMARK"), BUILDER(Create_func_benchmark)}, + { C_STRING_WITH_LEN("BIN"), BUILDER(Create_func_bin)}, + { C_STRING_WITH_LEN("BIT_COUNT"), BUILDER(Create_func_bit_count)}, + { C_STRING_WITH_LEN("BIT_LENGTH"), BUILDER(Create_func_bit_length)}, + { C_STRING_WITH_LEN("CEIL"), BUILDER(Create_func_ceiling)}, + { C_STRING_WITH_LEN("CEILING"), BUILDER(Create_func_ceiling)}, + { C_STRING_WITH_LEN("CENTROID"), GEOM_BUILDER(Create_func_centroid)}, + { C_STRING_WITH_LEN("CHARACTER_LENGTH"), BUILDER(Create_func_char_length)}, + { C_STRING_WITH_LEN("CHAR_LENGTH"), BUILDER(Create_func_char_length)}, + { C_STRING_WITH_LEN("COERCIBILITY"), BUILDER(Create_func_coercibility)}, + { C_STRING_WITH_LEN("COMPRESS"), BUILDER(Create_func_compress)}, + { C_STRING_WITH_LEN("CONCAT"), BUILDER(Create_func_concat)}, + { C_STRING_WITH_LEN("CONCAT_WS"), BUILDER(Create_func_concat_ws)}, + { C_STRING_WITH_LEN("CONNECTION_ID"), BUILDER(Create_func_connection_id)}, + { C_STRING_WITH_LEN("CONV"), BUILDER(Create_func_conv)}, + { C_STRING_WITH_LEN("CONVERT_TZ"), BUILDER(Create_func_convert_tz)}, + { C_STRING_WITH_LEN("COS"), BUILDER(Create_func_cos)}, + { C_STRING_WITH_LEN("COT"), BUILDER(Create_func_cot)}, + { C_STRING_WITH_LEN("CRC32"), BUILDER(Create_func_crc32)}, + { C_STRING_WITH_LEN("CROSSES"), GEOM_BUILDER(Create_func_crosses)}, + { C_STRING_WITH_LEN("DATEDIFF"), BUILDER(Create_func_datediff)}, + { C_STRING_WITH_LEN("DATE_FORMAT"), BUILDER(Create_func_date_format)}, + { C_STRING_WITH_LEN("DAYNAME"), BUILDER(Create_func_dayname)}, + { C_STRING_WITH_LEN("DAYOFMONTH"), BUILDER(Create_func_dayofmonth)}, + { C_STRING_WITH_LEN("DAYOFWEEK"), BUILDER(Create_func_dayofweek)}, + { C_STRING_WITH_LEN("DAYOFYEAR"), BUILDER(Create_func_dayofyear)}, + { C_STRING_WITH_LEN("DECODE"), BUILDER(Create_func_decode)}, + { C_STRING_WITH_LEN("DEGREES"), BUILDER(Create_func_degrees)}, + { C_STRING_WITH_LEN("DES_DECRYPT"), BUILDER(Create_func_des_decrypt)}, + { C_STRING_WITH_LEN("DES_ENCRYPT"), BUILDER(Create_func_des_encrypt)}, + { C_STRING_WITH_LEN("DIMENSION"), GEOM_BUILDER(Create_func_dimension)}, + { C_STRING_WITH_LEN("DISJOINT"), GEOM_BUILDER(Create_func_disjoint)}, + { C_STRING_WITH_LEN("ELT"), BUILDER(Create_func_elt)}, + { C_STRING_WITH_LEN("ENCODE"), BUILDER(Create_func_encode)}, + { C_STRING_WITH_LEN("ENCRYPT"), BUILDER(Create_func_encrypt)}, + { C_STRING_WITH_LEN("ENDPOINT"), GEOM_BUILDER(Create_func_endpoint)}, + { C_STRING_WITH_LEN("ENVELOPE"), GEOM_BUILDER(Create_func_envelope)}, + { C_STRING_WITH_LEN("EQUALS"), GEOM_BUILDER(Create_func_equals)}, + { C_STRING_WITH_LEN("EXP"), BUILDER(Create_func_exp)}, + { C_STRING_WITH_LEN("EXPORT_SET"), BUILDER(Create_func_export_set)}, + { C_STRING_WITH_LEN("EXTERIORRING"), GEOM_BUILDER(Create_func_exteriorring)}, + { C_STRING_WITH_LEN("EXTRACTVALUE"), BUILDER(Create_func_xml_extractvalue)}, + { C_STRING_WITH_LEN("FIELD"), BUILDER(Create_func_field)}, + { C_STRING_WITH_LEN("FIND_IN_SET"), BUILDER(Create_func_find_in_set)}, + { C_STRING_WITH_LEN("FLOOR"), BUILDER(Create_func_floor)}, + { C_STRING_WITH_LEN("FORMAT"), BUILDER(Create_func_format)}, + { C_STRING_WITH_LEN("FOUND_ROWS"), BUILDER(Create_func_found_rows)}, + { C_STRING_WITH_LEN("FROM_DAYS"), BUILDER(Create_func_from_days)}, + { C_STRING_WITH_LEN("FROM_UNIXTIME"), BUILDER(Create_func_from_unixtime)}, + { C_STRING_WITH_LEN("GEOMCOLLFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("GEOMCOLLFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("GEOMETRYCOLLECTIONFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("GEOMETRYCOLLECTIONFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("GEOMETRYFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("GEOMETRYFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("GEOMETRYN"), GEOM_BUILDER(Create_func_geometryn)}, + { C_STRING_WITH_LEN("GEOMETRYTYPE"), GEOM_BUILDER(Create_func_geometry_type)}, + { C_STRING_WITH_LEN("GEOMFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("GEOMFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("GET_LOCK"), BUILDER(Create_func_get_lock)}, + { C_STRING_WITH_LEN("GLENGTH"), GEOM_BUILDER(Create_func_glength)}, + { C_STRING_WITH_LEN("GREATEST"), BUILDER(Create_func_greatest)}, + { C_STRING_WITH_LEN("HEX"), BUILDER(Create_func_hex)}, + { C_STRING_WITH_LEN("IFNULL"), BUILDER(Create_func_ifnull)}, + { C_STRING_WITH_LEN("INET_ATON"), BUILDER(Create_func_inet_aton)}, + { C_STRING_WITH_LEN("INET_NTOA"), BUILDER(Create_func_inet_ntoa)}, + { C_STRING_WITH_LEN("INSTR"), BUILDER(Create_func_instr)}, + { C_STRING_WITH_LEN("INTERIORRINGN"), GEOM_BUILDER(Create_func_interiorringn)}, + { C_STRING_WITH_LEN("INTERSECTS"), GEOM_BUILDER(Create_func_intersects)}, + { C_STRING_WITH_LEN("ISCLOSED"), GEOM_BUILDER(Create_func_isclosed)}, + { C_STRING_WITH_LEN("ISEMPTY"), GEOM_BUILDER(Create_func_isempty)}, + { C_STRING_WITH_LEN("ISNULL"), BUILDER(Create_func_isnull)}, + { C_STRING_WITH_LEN("ISSIMPLE"), GEOM_BUILDER(Create_func_issimple)}, + { C_STRING_WITH_LEN("IS_FREE_LOCK"), BUILDER(Create_func_is_free_lock)}, + { C_STRING_WITH_LEN("IS_USED_LOCK"), BUILDER(Create_func_is_used_lock)}, + { C_STRING_WITH_LEN("LAST_DAY"), BUILDER(Create_func_last_day)}, + { C_STRING_WITH_LEN("LAST_INSERT_ID"), BUILDER(Create_func_last_insert_id)}, + { C_STRING_WITH_LEN("LCASE"), BUILDER(Create_func_lcase)}, + { C_STRING_WITH_LEN("LEAST"), BUILDER(Create_func_least)}, + { C_STRING_WITH_LEN("LENGTH"), BUILDER(Create_func_length)}, + { C_STRING_WITH_LEN("LINEFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("LINEFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("LINESTRINGFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("LINESTRINGFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("LN"), BUILDER(Create_func_ln)}, + { C_STRING_WITH_LEN("LOAD_FILE"), BUILDER(Create_func_load_file)}, + { C_STRING_WITH_LEN("LOCATE"), BUILDER(Create_func_locate)}, + { C_STRING_WITH_LEN("LOG"), BUILDER(Create_func_log)}, + { C_STRING_WITH_LEN("LOG10"), BUILDER(Create_func_log10)}, + { C_STRING_WITH_LEN("LOG2"), BUILDER(Create_func_log2)}, + { C_STRING_WITH_LEN("LOWER"), BUILDER(Create_func_lcase)}, + { C_STRING_WITH_LEN("LPAD"), BUILDER(Create_func_lpad)}, + { C_STRING_WITH_LEN("LTRIM"), BUILDER(Create_func_ltrim)}, + { C_STRING_WITH_LEN("MAKEDATE"), BUILDER(Create_func_makedate)}, + { C_STRING_WITH_LEN("MAKETIME"), BUILDER(Create_func_maketime)}, + { C_STRING_WITH_LEN("MAKE_SET"), BUILDER(Create_func_make_set)}, + { C_STRING_WITH_LEN("MASTER_POS_WAIT"), BUILDER(Create_func_master_pos_wait)}, + { C_STRING_WITH_LEN("MBRCONTAINS"), GEOM_BUILDER(Create_func_contains)}, + { C_STRING_WITH_LEN("MD5"), BUILDER(Create_func_md5)}, + { C_STRING_WITH_LEN("MLINEFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("MLINEFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("MONTHNAME"), BUILDER(Create_func_monthname)}, + { C_STRING_WITH_LEN("MPOINTFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("MPOINTFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("MPOLYFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("MPOLYFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("MULTILINESTRINGFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("MULTILINESTRINGFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("MULTIPOINTFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("MULTIPOINTFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("MULTIPOLYGONFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("MULTIPOLYGONFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("NAME_CONST"), BUILDER(Create_func_name_const)}, + { C_STRING_WITH_LEN("NULLIF"), BUILDER(Create_func_nullif)}, + { C_STRING_WITH_LEN("NUMGEOMETRIES"), GEOM_BUILDER(Create_func_numgeometries)}, + { C_STRING_WITH_LEN("NUMINTERIORRINGS"), GEOM_BUILDER(Create_func_numinteriorring)}, + { C_STRING_WITH_LEN("NUMPOINTS"), GEOM_BUILDER(Create_func_numpoints)}, + { C_STRING_WITH_LEN("OCT"), BUILDER(Create_func_oct)}, + { C_STRING_WITH_LEN("OCTET_LENGTH"), BUILDER(Create_func_length)}, + { C_STRING_WITH_LEN("ORD"), BUILDER(Create_func_ord)}, + { C_STRING_WITH_LEN("OVERLAPS"), GEOM_BUILDER(Create_func_overlaps)}, + { C_STRING_WITH_LEN("PERIOD_ADD"), BUILDER(Create_func_period_add)}, + { C_STRING_WITH_LEN("PERIOD_DIFF"), BUILDER(Create_func_period_diff)}, + { C_STRING_WITH_LEN("PI"), BUILDER(Create_func_pi)}, + { C_STRING_WITH_LEN("POINTFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("POINTFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("POINTN"), GEOM_BUILDER(Create_func_pointn)}, + { C_STRING_WITH_LEN("POLYFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("POLYFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("POLYGONFROMTEXT"), GEOM_BUILDER(Create_func_geometry_from_text)}, + { C_STRING_WITH_LEN("POLYGONFROMWKB"), GEOM_BUILDER(Create_func_geometry_from_wkb)}, + { C_STRING_WITH_LEN("POW"), BUILDER(Create_func_pow)}, + { C_STRING_WITH_LEN("POWER"), BUILDER(Create_func_pow)}, + { C_STRING_WITH_LEN("QUOTE"), BUILDER(Create_func_quote)}, + { C_STRING_WITH_LEN("RADIANS"), BUILDER(Create_func_radians)}, + { C_STRING_WITH_LEN("RAND"), BUILDER(Create_func_rand)}, + { C_STRING_WITH_LEN("RELEASE_LOCK"), BUILDER(Create_func_release_lock)}, + { C_STRING_WITH_LEN("REVERSE"), BUILDER(Create_func_reverse)}, + { C_STRING_WITH_LEN("ROUND"), BUILDER(Create_func_round)}, + { C_STRING_WITH_LEN("ROW_COUNT"), BUILDER(Create_func_row_count)}, + { C_STRING_WITH_LEN("RPAD"), BUILDER(Create_func_rpad)}, + { C_STRING_WITH_LEN("RTRIM"), BUILDER(Create_func_rtrim)}, + { C_STRING_WITH_LEN("SEC_TO_TIME"), BUILDER(Create_func_sec_to_time)}, + { C_STRING_WITH_LEN("SHA"), BUILDER(Create_func_sha)}, + { C_STRING_WITH_LEN("SHA1"), BUILDER(Create_func_sha)}, + { C_STRING_WITH_LEN("SIGN"), BUILDER(Create_func_sign)}, + { C_STRING_WITH_LEN("SIN"), BUILDER(Create_func_sin)}, + { C_STRING_WITH_LEN("SLEEP"), BUILDER(Create_func_sleep)}, + { C_STRING_WITH_LEN("SOUNDEX"), BUILDER(Create_func_soundex)}, + { C_STRING_WITH_LEN("SPACE"), BUILDER(Create_func_space)}, + { C_STRING_WITH_LEN("SQRT"), BUILDER(Create_func_sqrt)}, + { C_STRING_WITH_LEN("SRID"), GEOM_BUILDER(Create_func_srid)}, + { C_STRING_WITH_LEN("STARTPOINT"), GEOM_BUILDER(Create_func_startpoint)}, + { C_STRING_WITH_LEN("STRCMP"), BUILDER(Create_func_strcmp)}, + { C_STRING_WITH_LEN("STR_TO_DATE"), BUILDER(Create_func_str_to_date)}, + { C_STRING_WITH_LEN("SUBSTRING_INDEX"), BUILDER(Create_func_substr_index)}, + { C_STRING_WITH_LEN("SUBTIME"), BUILDER(Create_func_subtime)}, + { C_STRING_WITH_LEN("TAN"), BUILDER(Create_func_tan)}, + { C_STRING_WITH_LEN("TIMEDIFF"), BUILDER(Create_func_timediff)}, + { C_STRING_WITH_LEN("TIME_FORMAT"), BUILDER(Create_func_time_format)}, + { C_STRING_WITH_LEN("TIME_TO_SEC"), BUILDER(Create_func_time_to_sec)}, + { C_STRING_WITH_LEN("TOUCHES"), GEOM_BUILDER(Create_func_touches)}, + { C_STRING_WITH_LEN("TO_DAYS"), BUILDER(Create_func_to_days)}, + { C_STRING_WITH_LEN("UCASE"), BUILDER(Create_func_ucase)}, + { C_STRING_WITH_LEN("UNCOMPRESS"), BUILDER(Create_func_uncompress)}, + { C_STRING_WITH_LEN("UNCOMPRESSED_LENGTH"), BUILDER(Create_func_uncompressed_length)}, + { C_STRING_WITH_LEN("UNHEX"), BUILDER(Create_func_unhex)}, + { C_STRING_WITH_LEN("UNIX_TIMESTAMP"), BUILDER(Create_func_unix_timestamp)}, + { C_STRING_WITH_LEN("UPDATEXML"), BUILDER(Create_func_xml_update)}, + { C_STRING_WITH_LEN("UPPER"), BUILDER(Create_func_ucase)}, + { C_STRING_WITH_LEN("UUID"), BUILDER(Create_func_uuid)}, + { C_STRING_WITH_LEN("VERSION"), BUILDER(Create_func_version)}, + { C_STRING_WITH_LEN("WEEKDAY"), BUILDER(Create_func_weekday)}, + { C_STRING_WITH_LEN("WEEKOFYEAR"), BUILDER(Create_func_weekofyear)}, + { C_STRING_WITH_LEN("WITHIN"), GEOM_BUILDER(Create_func_within)}, + { C_STRING_WITH_LEN("X"), GEOM_BUILDER(Create_func_x)}, + { C_STRING_WITH_LEN("Y"), GEOM_BUILDER(Create_func_y)}, + { C_STRING_WITH_LEN("YEARWEEK"), BUILDER(Create_func_year_week)}, + + { {0, 0}, NULL} +}; + +static HASH native_functions_hash; + +extern "C" byte* +get_native_fct_hash_key(const byte *buff, uint *length, my_bool /* unused */) +{ + Native_func_registry *func= (Native_func_registry*) buff; + *length= func->name.length; + return (byte*) func->name.str; +} + +/* + Load the hash table for native functions. + Note: this code is not thread safe, and is intended to be used at server + startup only (before going multi-threaded) +*/ + +int item_create_init() +{ + Native_func_registry *func; + + DBUG_ENTER("item_create_init"); + + if (hash_init(& native_functions_hash, + system_charset_info, + array_elements(func_array), + 0, + 0, + (hash_get_key) get_native_fct_hash_key, + NULL, /* Nothing to free */ + MYF(0))) + DBUG_RETURN(1); + + for (func= func_array; func->builder != NULL; func++) + { + if (my_hash_insert(& native_functions_hash, (byte*) func)) + DBUG_RETURN(1); + } + +#ifndef DBUG_OFF + for (uint i=0 ; i < native_functions_hash.records ; i++) + { + func= (Native_func_registry*) hash_element(& native_functions_hash, i); + DBUG_PRINT("info", ("native function %s, length %d", + func->name.str, func->name.length)); + } +#endif + + DBUG_RETURN(0); +} + +/* + Empty the hash table for native functions. + Note: this code is not thread safe, and is intended to be used at server + shutdown only (after thread requests have been executed). +*/ + +void item_create_cleanup() +{ + DBUG_ENTER("item_create_cleanup"); + hash_free(& native_functions_hash); + DBUG_VOID_RETURN; +} + +Create_func * +find_native_function_builder(THD *thd, LEX_STRING name) +{ + Native_func_registry *func; + Create_func *builder= NULL; + + /* Thread safe */ + func= (Native_func_registry*) hash_search(& native_functions_hash, + (byte*) name.str, + name.length); + + if (func) + { + builder= func->builder; + } + + return builder; +} + +Create_qfunc * +find_qualified_function_builder(THD *thd) +{ + return & Create_sp_func::s_singleton; +} + +Item* +create_func_cast(THD *thd, Item *a, Cast_target cast_type, int len, int dec, + CHARSET_INFO *cs) { Item *res; - int tmp_len; LINT_INIT(res); switch (cast_type) { - case ITEM_CAST_BINARY: res= new Item_func_binary(a); break; - case ITEM_CAST_SIGNED_INT: res= new Item_func_signed(a); break; - case ITEM_CAST_UNSIGNED_INT: res= new Item_func_unsigned(a); break; - case ITEM_CAST_DATE: res= new Item_date_typecast(a); break; - case ITEM_CAST_TIME: res= new Item_time_typecast(a); break; - case ITEM_CAST_DATETIME: res= new Item_datetime_typecast(a); break; + case ITEM_CAST_BINARY: + res= new (thd->mem_root) Item_func_binary(a); + break; + case ITEM_CAST_SIGNED_INT: + res= new (thd->mem_root) Item_func_signed(a); + break; + case ITEM_CAST_UNSIGNED_INT: + res= new (thd->mem_root) Item_func_unsigned(a); + break; + case ITEM_CAST_DATE: + res= new (thd->mem_root) Item_date_typecast(a); + break; + case ITEM_CAST_TIME: + res= new (thd->mem_root) Item_time_typecast(a); + break; + case ITEM_CAST_DATETIME: + res= new (thd->mem_root) Item_datetime_typecast(a); + break; case ITEM_CAST_DECIMAL: - tmp_len= (len>0) ? len : 10; + { + int tmp_len= (len>0) ? len : 10; if (tmp_len < dec) { my_error(ER_M_BIGGER_THAN_D, MYF(0), ""); return 0; } - res= new Item_decimal_typecast(a, tmp_len, dec); + res= new (thd->mem_root) Item_decimal_typecast(a, tmp_len, dec); break; + } case ITEM_CAST_CHAR: - res= new Item_char_typecast(a, len, cs ? cs : - current_thd->variables.collation_connection); + { + CHARSET_INFO *real_cs= (cs ? cs : thd->variables.collation_connection); + res= new (thd->mem_root) Item_char_typecast(a, len, real_cs); break; + } default: + { DBUG_ASSERT(0); res= 0; break; } + } return res; } -Item *create_func_is_free_lock(Item* a) -{ - current_thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - return new Item_func_is_free_lock(a); -} - -Item *create_func_is_used_lock(Item* a) -{ - current_thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - return new Item_func_is_used_lock(a); -} - -Item *create_func_quote(Item* a) -{ - return new Item_func_quote(a); -} - -Item *create_func_xml_extractvalue(Item *a, Item *b) -{ - return new Item_func_xml_extractvalue(a, b); -} - -Item *create_func_xml_update(Item *a, Item *b, Item *c) -{ - return new Item_func_xml_update(a, b, c); -} - -#ifdef HAVE_SPATIAL -Item *create_func_as_wkt(Item *a) -{ - return new Item_func_as_wkt(a); -} - -Item *create_func_as_wkb(Item *a) -{ - return new Item_func_as_wkb(a); -} - -Item *create_func_srid(Item *a) -{ - return new Item_func_srid(a); -} - -Item *create_func_startpoint(Item *a) -{ - return new Item_func_spatial_decomp(a, Item_func::SP_STARTPOINT); -} - -Item *create_func_endpoint(Item *a) -{ - return new Item_func_spatial_decomp(a, Item_func::SP_ENDPOINT); -} - -Item *create_func_exteriorring(Item *a) -{ - return new Item_func_spatial_decomp(a, Item_func::SP_EXTERIORRING); -} - -Item *create_func_pointn(Item *a, Item *b) -{ - return new Item_func_spatial_decomp_n(a, b, Item_func::SP_POINTN); -} - -Item *create_func_interiorringn(Item *a, Item *b) -{ - return new Item_func_spatial_decomp_n(a, b, Item_func::SP_INTERIORRINGN); -} - -Item *create_func_geometryn(Item *a, Item *b) -{ - return new Item_func_spatial_decomp_n(a, b, Item_func::SP_GEOMETRYN); -} - -Item *create_func_centroid(Item *a) -{ - return new Item_func_centroid(a); -} - -Item *create_func_envelope(Item *a) -{ - return new Item_func_envelope(a); -} - -Item *create_func_equals(Item *a, Item *b) -{ - return new Item_func_spatial_rel(a, b, Item_func::SP_EQUALS_FUNC); -} - -Item *create_func_disjoint(Item *a, Item *b) -{ - return new Item_func_spatial_rel(a, b, Item_func::SP_DISJOINT_FUNC); -} - -Item *create_func_intersects(Item *a, Item *b) -{ - return new Item_func_spatial_rel(a, b, Item_func::SP_INTERSECTS_FUNC); -} - -Item *create_func_touches(Item *a, Item *b) -{ - return new Item_func_spatial_rel(a, b, Item_func::SP_TOUCHES_FUNC); -} - -Item *create_func_crosses(Item *a, Item *b) -{ - return new Item_func_spatial_rel(a, b, Item_func::SP_CROSSES_FUNC); -} - -Item *create_func_within(Item *a, Item *b) -{ - return new Item_func_spatial_rel(a, b, Item_func::SP_WITHIN_FUNC); -} - -Item *create_func_contains(Item *a, Item *b) -{ - return new Item_func_spatial_rel(a, b, Item_func::SP_CONTAINS_FUNC); -} - -Item *create_func_overlaps(Item *a, Item *b) -{ - return new Item_func_spatial_rel(a, b, Item_func::SP_OVERLAPS_FUNC); -} - -Item *create_func_isempty(Item *a) -{ - return new Item_func_isempty(a); -} - -Item *create_func_issimple(Item *a) -{ - return new Item_func_issimple(a); -} - -Item *create_func_isclosed(Item *a) -{ - return new Item_func_isclosed(a); -} - -Item *create_func_geometry_type(Item *a) -{ - return new Item_func_geometry_type(a); -} - -Item *create_func_dimension(Item *a) -{ - return new Item_func_dimension(a); -} - -Item *create_func_x(Item *a) -{ - return new Item_func_x(a); -} - -Item *create_func_y(Item *a) -{ - return new Item_func_y(a); -} - -Item *create_func_numpoints(Item *a) -{ - return new Item_func_numpoints(a); -} - -Item *create_func_numinteriorring(Item *a) -{ - return new Item_func_numinteriorring(a); -} - -Item *create_func_numgeometries(Item *a) -{ - return new Item_func_numgeometries(a); -} - -Item *create_func_area(Item *a) -{ - return new Item_func_area(a); -} - -Item *create_func_glength(Item *a) -{ - return new Item_func_glength(a); -} - -Item *create_func_point(Item *a, Item *b) -{ - return new Item_func_point(a, b); -} -#endif /*HAVE_SPATIAL*/ - -Item *create_func_crc32(Item* a) -{ - return new Item_func_crc32(a); -} - -Item *create_func_compress(Item* a) -{ - return new Item_func_compress(a); -} - -Item *create_func_uncompress(Item* a) -{ - return new Item_func_uncompress(a); -} - -Item *create_func_uncompressed_length(Item* a) -{ - return new Item_func_uncompressed_length(a); -} - -Item *create_func_datediff(Item *a, Item *b) -{ - return new Item_func_minus(new Item_func_to_days(a), - new Item_func_to_days(b)); -} - -Item *create_func_weekofyear(Item *a) -{ - return new Item_func_week(a, new Item_int((char*) "0", 3, 1)); -} - -Item *create_func_makedate(Item* a,Item* b) -{ - return new Item_func_makedate(a, b); -} - -Item *create_func_addtime(Item* a,Item* b) -{ - return new Item_func_add_time(a, b, 0, 0); -} - -Item *create_func_subtime(Item* a,Item* b) -{ - return new Item_func_add_time(a, b, 0, 1); -} - -Item *create_func_timediff(Item* a,Item* b) -{ - return new Item_func_timediff(a, b); -} - -Item *create_func_maketime(Item* a,Item* b,Item* c) -{ - return new Item_func_maketime(a, b, c); -} - -Item *create_func_str_to_date(Item* a,Item* b) -{ - return new Item_func_str_to_date(a, b); -} - -Item *create_func_last_day(Item *a) -{ - return new Item_func_last_day(a); -} diff --git a/sql/item_create.h b/sql/item_create.h index 9b6a74b5bdd..c20e36af04f 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -14,148 +14,154 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Functions to create an item. Used by lex.h */ +/* Functions to create an item. Used by sql/sql_yacc.yy */ -Item *create_func_abs(Item* a); -Item *create_func_acos(Item* a); -Item *create_func_aes_encrypt(Item* a, Item* b); -Item *create_func_aes_decrypt(Item* a, Item* b); -Item *create_func_ascii(Item* a); -Item *create_func_asin(Item* a); -Item *create_func_bin(Item* a); -Item *create_func_bit_count(Item* a); -Item *create_func_bit_length(Item* a); -Item *create_func_coercibility(Item* a); -Item *create_func_ceiling(Item* a); -Item *create_func_char_length(Item* a); -Item *create_func_cast(Item *a, Cast_target cast_type, int len, int dec, - CHARSET_INFO *cs); -Item *create_func_connection_id(void); -Item *create_func_conv(Item* a, Item *b, Item *c); -Item *create_func_cos(Item* a); -Item *create_func_cot(Item* a); -Item *create_func_crc32(Item* a); -Item *create_func_date_format(Item* a,Item *b); -Item *create_func_dayname(Item* a); -Item *create_func_dayofmonth(Item* a); -Item *create_func_dayofweek(Item* a); -Item *create_func_dayofyear(Item* a); -Item *create_func_degrees(Item *); -Item *create_func_exp(Item* a); -Item *create_func_find_in_set(Item* a, Item *b); -Item *create_func_floor(Item* a); -Item *create_func_found_rows(void); -Item *create_func_from_days(Item* a); -Item *create_func_get_lock(Item* a, Item *b); -Item *create_func_hex(Item *a); -Item *create_func_inet_aton(Item* a); -Item *create_func_inet_ntoa(Item* a); +#ifndef ITEM_CREATE_H +#define ITEM_CREATE_H -Item *create_func_ifnull(Item* a, Item *b); -Item *create_func_instr(Item* a, Item *b); -Item *create_func_isnull(Item* a); -Item *create_func_lcase(Item* a); -Item *create_func_length(Item* a); -Item *create_func_ln(Item* a); -Item *create_func_locate(Item* a, Item *b); -Item *create_func_log2(Item* a); -Item *create_func_log10(Item* a); -Item *create_func_lpad(Item* a, Item *b, Item *c); -Item *create_func_ltrim(Item* a); -Item *create_func_md5(Item* a); -Item *create_func_mod(Item* a, Item *b); -Item *create_func_monthname(Item* a); -Item *create_func_name_const(Item *a, Item *b); -Item *create_func_nullif(Item* a, Item *b); -Item *create_func_oct(Item *); -Item *create_func_ord(Item* a); -Item *create_func_period_add(Item* a, Item *b); -Item *create_func_period_diff(Item* a, Item *b); -Item *create_func_pi(void); -Item *create_func_pow(Item* a, Item *b); -Item *create_func_radians(Item *a); -Item *create_func_release_lock(Item* a); -Item *create_func_repeat(Item* a, Item *b); -Item *create_func_reverse(Item* a); -Item *create_func_rpad(Item* a, Item *b, Item *c); -Item *create_func_rtrim(Item* a); -Item *create_func_sec_to_time(Item* a); -Item *create_func_sign(Item* a); -Item *create_func_sin(Item* a); -Item *create_func_sha(Item* a); -Item *create_func_sleep(Item* a); -Item *create_func_soundex(Item* a); -Item *create_func_space(Item *); -Item *create_func_sqrt(Item* a); -Item *create_func_strcmp(Item* a, Item *b); -Item *create_func_tan(Item* a); -Item *create_func_time_format(Item *a, Item *b); -Item *create_func_time_to_sec(Item* a); -Item *create_func_to_days(Item* a); -Item *create_func_ucase(Item* a); -Item *create_func_unhex(Item* a); -Item *create_func_uuid(void); -Item *create_func_version(void); -Item *create_func_weekday(Item* a); -Item *create_load_file(Item* a); -Item *create_func_is_free_lock(Item* a); -Item *create_func_is_used_lock(Item* a); -Item *create_func_quote(Item* a); -Item *create_func_xml_extractvalue(Item *a, Item *b); -Item *create_func_xml_update(Item *a, Item *b, Item *c); -#ifdef HAVE_SPATIAL +/** + Public function builder interface. + The parser (sql/sql_yacc.yy) uses a factory / builder pattern to + construct an Item object for each function call. + All the concrete function builders implements this interface, + either directly or indirectly with some adapter helpers. + Keeping the function creation separated from the bison grammar allows + to simplify the parser, and avoid the need to introduce a new token + for each function, which has undesirable side effects in the grammar. +*/ -Item *create_func_geometry_from_text(Item *a); -Item *create_func_as_wkt(Item *a); -Item *create_func_as_wkb(Item *a); -Item *create_func_srid(Item *a); -Item *create_func_startpoint(Item *a); -Item *create_func_endpoint(Item *a); -Item *create_func_exteriorring(Item *a); -Item *create_func_centroid(Item *a); -Item *create_func_envelope(Item *a); -Item *create_func_pointn(Item *a, Item *b); -Item *create_func_interiorringn(Item *a, Item *b); -Item *create_func_geometryn(Item *a, Item *b); +class Create_func +{ +public: + /** + The builder create method. + Given the function name and list or arguments, this method creates + an Item that represents the function call. + In case or errors, a NULL item is returned, and an error is reported. + Note that the thd object may be modified by the builder. + In particular, the following members/methods can be set/called, + depending on the function called and the function possible side effects. +
    +
  • thd->lex->binlog_row_based_if_mixed
  • +
  • thd->lex->current_context()
  • +
  • thd->lex->safe_to_cache_query
  • +
  • thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT)
  • +
  • thd->lex->uncacheable(UNCACHEABLE_RAND)
  • +
  • thd->lex->add_time_zone_tables_to_query_tables(thd)
  • +
+ @param thd The current thread + @param name The function name + @param item_list The list of arguments to the function, can be NULL + @return An item representing the parsed function call, or NULL + */ + virtual Item* create(THD *thd, LEX_STRING name, List *item_list) = 0; -Item *create_func_equals(Item *a, Item *b); -Item *create_func_disjoint(Item *a, Item *b); -Item *create_func_intersects(Item *a, Item *b); -Item *create_func_touches(Item *a, Item *b); -Item *create_func_crosses(Item *a, Item *b); -Item *create_func_within(Item *a, Item *b); -Item *create_func_contains(Item *a, Item *b); -Item *create_func_overlaps(Item *a, Item *b); +protected: + /** Constructor */ + Create_func() {} + /** Destructor */ + virtual ~Create_func() {} +}; -Item *create_func_isempty(Item *a); -Item *create_func_issimple(Item *a); -Item *create_func_isclosed(Item *a); -Item *create_func_geometry_type(Item *a); -Item *create_func_dimension(Item *a); -Item *create_func_x(Item *a); -Item *create_func_y(Item *a); -Item *create_func_area(Item *a); -Item *create_func_glength(Item *a); +/** + Function builder for qualified functions. + This builder is used with functions call using a qualified function name + syntax, as in db.func(expr, expr, ...). +*/ -Item *create_func_numpoints(Item *a); -Item *create_func_numinteriorring(Item *a); -Item *create_func_numgeometries(Item *a); +class Create_qfunc : public Create_func +{ +public: + /** + The builder create method, for unqualified functions. + This builder will use the current database for the database name. + @param thd The current thread + @param name The function name + @param item_list The list of arguments to the function, can be NULL + @return An item representing the parsed function call + */ + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); -Item *create_func_point(Item *a, Item *b); + /** + The builder create method, for qualified functions. + @param thd The current thread + @param db The database name + @param name The function name + @param item_list The list of arguments to the function, can be NULL + @return An item representing the parsed function call + */ + virtual Item* create(THD *thd, LEX_STRING db, LEX_STRING name, + List *item_list) = 0; -#endif /*HAVE_SPATIAL*/ +protected: + /** Constructor. */ + Create_qfunc() {} + /** Destructor. */ + virtual ~Create_qfunc() {} +}; -Item *create_func_compress(Item *a); -Item *create_func_uncompress(Item *a); -Item *create_func_uncompressed_length(Item *a); -Item *create_func_datediff(Item *a, Item *b); -Item *create_func_weekofyear(Item *a); -Item *create_func_makedate(Item* a,Item* b); -Item *create_func_addtime(Item* a,Item* b); -Item *create_func_subtime(Item* a,Item* b); -Item *create_func_timediff(Item* a,Item* b); -Item *create_func_maketime(Item* a,Item* b,Item* c); -Item *create_func_str_to_date(Item* a,Item* b); -Item *create_func_last_day(Item *a); +/** + Find the native function builder associated with a given function name. + @param thd The current thread + @param name The native function name + @return The native function builder associated with the name, or NULL +*/ +extern Create_func * find_native_function_builder(THD *thd, LEX_STRING name); + + +/** + Find the function builder for qualified functions. + @param thd The current thread + @return A function builder for qualified functions +*/ +extern Create_qfunc * find_qualified_function_builder(THD *thd); + + +#ifdef HAVE_DLOPEN +/** + Function builder for User Defined Functions. +*/ + +class Create_udf_func : public Create_func +{ +public: + virtual Item* create(THD *thd, LEX_STRING name, List *item_list); + + /** + The builder create method, for User Defined Functions. + @param thd The current thread + @param fct The User Defined Function metadata + @param item_list The list of arguments to the function, can be NULL + @return An item representing the parsed function call + */ + Item* create(THD *thd, udf_func *fct, List *item_list); + + /** Singleton. */ + static Create_udf_func s_singleton; + +protected: + /** Constructor. */ + Create_udf_func() {} + /** Destructor. */ + virtual ~Create_udf_func() {} +}; +#endif + + +/** + Builder for cast expressions. + @param thd The current thread + @param a The item to cast + @param cast_type the type casted into + @param len TODO + @param dec TODO + @param cs The character set +*/ +Item* +create_func_cast(THD *thd, Item *a, Cast_target cast_type, int len, int dec, + CHARSET_INFO *cs); + +#endif + diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 4848f59301d..42f11820869 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -348,11 +348,11 @@ public: void fix_length_and_dec() { max_length= 10; } }; -#define GEOM_NEW(obj_constructor) new obj_constructor +#define GEOM_NEW(thd, obj_constructor) new (thd->mem_root) obj_constructor #else /*HAVE_SPATIAL*/ -#define GEOM_NEW(obj_constructor) NULL +#define GEOM_NEW(thd, obj_constructor) NULL #endif diff --git a/sql/lex.h b/sql/lex.h index f19c9413e0e..97b097148aa 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -30,16 +30,7 @@ SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"}; #define SYM_OR_NULL(A) A #endif -#define SYM(A) SYM_OR_NULL(A),0,0,&sym_group_common -#define F_SYM(A) SYM_OR_NULL(A) - -#define CREATE_FUNC(A) (void *)(SYM_OR_NULL(A)), &sym_group_common - -#ifdef HAVE_SPATIAL -#define CREATE_FUNC_GEOM(A) (void *)(SYM_OR_NULL(A)), &sym_group_geom -#else -#define CREATE_FUNC_GEOM(A) 0, &sym_group_geom -#endif +#define SYM(A) SYM_OR_NULL(A),0,&sym_group_common /* Symbols are broken into separated arrays to allow field names with @@ -588,235 +579,38 @@ static SYMBOL symbols[] = { static SYMBOL sql_functions[] = { - { "ABS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_abs)}, - { "ACOS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_acos)}, { "ADDDATE", SYM(ADDDATE_SYM)}, - { "ADDTIME", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_addtime)}, - { "AES_ENCRYPT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_encrypt)}, - { "AES_DECRYPT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_aes_decrypt)}, - { "AREA", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_area)}, - { "ASIN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_asin)}, - { "ASBINARY", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_as_wkb)}, - { "ASTEXT", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_as_wkt)}, - { "ASWKB", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_as_wkb)}, - { "ASWKT", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_as_wkt)}, - { "ATAN", SYM(ATAN)}, - { "ATAN2", SYM(ATAN)}, - { "BENCHMARK", SYM(BENCHMARK_SYM)}, - { "BIN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bin)}, - { "BIT_COUNT", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_count)}, - { "BIT_OR", SYM(BIT_OR)}, { "BIT_AND", SYM(BIT_AND)}, + { "BIT_OR", SYM(BIT_OR)}, { "BIT_XOR", SYM(BIT_XOR)}, { "CAST", SYM(CAST_SYM)}, - { "CEIL", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)}, - { "CEILING", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)}, - { "BIT_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_length)}, - { "CENTROID", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_centroid)}, - { "CHAR_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)}, - { "CHARACTER_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)}, - { "COERCIBILITY", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_coercibility)}, - { "COMPRESS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_compress)}, - { "CONCAT", SYM(CONCAT)}, - { "CONCAT_WS", SYM(CONCAT_WS)}, - { "CONNECTION_ID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_connection_id)}, - { "CONV", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_conv)}, - { "CONVERT_TZ", SYM(CONVERT_TZ_SYM)}, { "COUNT", SYM(COUNT_SYM)}, - { "COS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cos)}, - { "COT", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_cot)}, - { "CRC32", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_crc32)}, - { "CROSSES", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_crosses)}, { "CURDATE", SYM(CURDATE)}, { "CURTIME", SYM(CURTIME)}, { "DATE_ADD", SYM(DATE_ADD_INTERVAL)}, - { "DATEDIFF", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_datediff)}, - { "DATE_FORMAT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_date_format)}, { "DATE_SUB", SYM(DATE_SUB_INTERVAL)}, - { "DAYNAME", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayname)}, - { "DAYOFMONTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofmonth)}, - { "DAYOFWEEK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofweek)}, - { "DAYOFYEAR", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_dayofyear)}, - { "DECODE", SYM(DECODE_SYM)}, - { "DEGREES", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_degrees)}, - { "DES_ENCRYPT", SYM(DES_ENCRYPT_SYM)}, - { "DES_DECRYPT", SYM(DES_DECRYPT_SYM)}, - { "DIMENSION", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_dimension)}, - { "DISJOINT", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_disjoint)}, - { "ELT", SYM(ELT_FUNC)}, - { "ENCODE", SYM(ENCODE_SYM)}, - { "ENCRYPT", SYM(ENCRYPT)}, - { "ENDPOINT", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_endpoint)}, - { "ENVELOPE", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_envelope)}, - { "EQUALS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_equals)}, - { "EXTERIORRING", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_exteriorring)}, { "EXTRACT", SYM(EXTRACT_SYM)}, - { "EXTRACTVALUE", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_xml_extractvalue)}, - { "EXP", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_exp)}, - { "EXPORT_SET", SYM(EXPORT_SET)}, - { "FIELD", SYM(FIELD_FUNC)}, /* For compability */ - { "FIND_IN_SET", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_find_in_set)}, - { "FLOOR", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_floor)}, - { "FORMAT", SYM(FORMAT_SYM)}, - { "FOUND_ROWS", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_found_rows)}, - { "FROM_DAYS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_from_days)}, - { "FROM_UNIXTIME", SYM(FROM_UNIXTIME)}, - { "GET_LOCK", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_get_lock)}, - { "GEOMETRYN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_geometryn)}, - { "GEOMETRYTYPE", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_geometry_type)}, - { "GEOMCOLLFROMTEXT", SYM(GEOMCOLLFROMTEXT)}, - { "GEOMCOLLFROMWKB", SYM(GEOMFROMWKB)}, - { "GEOMETRYCOLLECTIONFROMTEXT",SYM(GEOMCOLLFROMTEXT)}, - { "GEOMETRYCOLLECTIONFROMWKB",SYM(GEOMFROMWKB)}, - { "GEOMETRYFROMTEXT", SYM(GEOMFROMTEXT)}, - { "GEOMETRYFROMWKB", SYM(GEOMFROMWKB)}, - { "GEOMFROMTEXT", SYM(GEOMFROMTEXT)}, - { "GEOMFROMWKB", SYM(GEOMFROMWKB)}, - { "GLENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_glength)}, - { "GREATEST", SYM(GREATEST_SYM)}, { "GROUP_CONCAT", SYM(GROUP_CONCAT_SYM)}, { "GROUP_UNIQUE_USERS", SYM(GROUP_UNIQUE_USERS)}, - { "HEX", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_hex)}, - { "IFNULL", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_ifnull)}, - { "INET_ATON", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_aton)}, - { "INET_NTOA", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_inet_ntoa)}, - { "INSTR", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_instr)}, - { "INTERIORRINGN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_interiorringn)}, - { "INTERSECTS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_intersects)}, - { "ISCLOSED", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_isclosed)}, - { "ISEMPTY", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_isempty)}, - { "ISNULL", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_isnull)}, - { "IS_FREE_LOCK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_is_free_lock)}, - { "IS_USED_LOCK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_is_used_lock)}, - { "LAST_INSERT_ID", SYM(LAST_INSERT_ID)}, - { "ISSIMPLE", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_issimple)}, - { "LAST_DAY", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_last_day)}, - { "LCASE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)}, - { "LEAST", SYM(LEAST_SYM)}, - { "LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)}, - { "LN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ln)}, - { "LINEFROMTEXT", SYM(LINEFROMTEXT)}, - { "LINEFROMWKB", SYM(GEOMFROMWKB)}, - { "LINESTRINGFROMTEXT",SYM(LINEFROMTEXT)}, - { "LINESTRINGFROMWKB",SYM(GEOMFROMWKB)}, - { "LOAD_FILE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_load_file)}, - { "LOCATE", SYM(LOCATE)}, - { "LOG", SYM(LOG_SYM)}, - { "LOG2", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log2)}, - { "LOG10", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_log10)}, - { "LOWER", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)}, - { "LPAD", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_lpad)}, - { "LTRIM", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ltrim)}, - { "MAKE_SET", SYM(MAKE_SET_SYM)}, - { "MAKEDATE", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_makedate)}, - { "MAKETIME", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_maketime)}, - { "MASTER_POS_WAIT", SYM(MASTER_POS_WAIT)}, { "MAX", SYM(MAX_SYM)}, - { "MBRCONTAINS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_contains)}, - { "MBRDISJOINT", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_disjoint)}, - { "MBREQUAL", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_equals)}, - { "MBRINTERSECTS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_intersects)}, - { "MBROVERLAPS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_overlaps)}, - { "MBRTOUCHES", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_touches)}, - { "MBRWITHIN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_within)}, - { "MD5", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_md5)}, { "MID", SYM(SUBSTRING)}, /* unireg function */ { "MIN", SYM(MIN_SYM)}, - { "MLINEFROMTEXT", SYM(MLINEFROMTEXT)}, - { "MLINEFROMWKB", SYM(GEOMFROMWKB)}, - { "MPOINTFROMTEXT", SYM(MPOINTFROMTEXT)}, - { "MPOINTFROMWKB", SYM(GEOMFROMWKB)}, - { "MPOLYFROMTEXT", SYM(MPOLYFROMTEXT)}, - { "MPOLYFROMWKB", SYM(GEOMFROMWKB)}, - { "MONTHNAME", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_monthname)}, - { "MULTILINESTRINGFROMTEXT",SYM(MLINEFROMTEXT)}, - { "MULTILINESTRINGFROMWKB",SYM(GEOMFROMWKB)}, - { "MULTIPOINTFROMTEXT",SYM(MPOINTFROMTEXT)}, - { "MULTIPOINTFROMWKB",SYM(GEOMFROMWKB)}, - { "MULTIPOLYGONFROMTEXT",SYM(MPOLYFROMTEXT)}, - { "MULTIPOLYGONFROMWKB",SYM(GEOMFROMWKB)}, - { "NAME_CONST", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_name_const)}, { "NOW", SYM(NOW_SYM)}, - { "NULLIF", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_nullif)}, - { "NUMGEOMETRIES", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_numgeometries)}, - { "NUMINTERIORRINGS", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_numinteriorring)}, - { "NUMPOINTS", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_numpoints)}, - { "OCTET_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)}, - { "OCT", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_oct)}, - { "ORD", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ord)}, - { "OVERLAPS", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_overlaps)}, - { "PERIOD_ADD", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_add)}, - { "PERIOD_DIFF", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_diff)}, - { "PI", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_pi)}, - { "POINTFROMTEXT", SYM(POINTFROMTEXT)}, - { "POINTFROMWKB", SYM(GEOMFROMWKB)}, - { "POINTN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_pointn)}, - { "POLYFROMTEXT", SYM(POLYFROMTEXT)}, - { "POLYFROMWKB", SYM(GEOMFROMWKB)}, - { "POLYGONFROMTEXT", SYM(POLYFROMTEXT)}, - { "POLYGONFROMWKB", SYM(GEOMFROMWKB)}, { "POSITION", SYM(POSITION_SYM)}, - { "POW", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, - { "POWER", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_pow)}, - { "QUOTE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_quote)}, - { "RADIANS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_radians)}, - { "RAND", SYM(RAND)}, - { "RELEASE_LOCK", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_release_lock)}, - { "REVERSE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_reverse)}, - { "ROUND", SYM(ROUND)}, - { "ROW_COUNT", SYM(ROW_COUNT_SYM)}, - { "RPAD", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_rpad)}, - { "RTRIM", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_rtrim)}, - { "SEC_TO_TIME", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sec_to_time)}, - { "SESSION_USER", SYM(USER)}, - { "SUBDATE", SYM(SUBDATE_SYM)}, - { "SIGN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sign)}, - { "SIN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sin)}, - { "SHA", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)}, - { "SHA1", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)}, - { "SLEEP", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sleep)}, - { "SOUNDEX", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_soundex)}, - { "SPACE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_space)}, - { "SQRT", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sqrt)}, - { "SRID", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_srid)}, - { "STARTPOINT", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_startpoint)}, + { "SESSION_USER", SYM(USER)}, { "STD", SYM(STD_SYM)}, { "STDDEV", SYM(STD_SYM)}, { "STDDEV_POP", SYM(STD_SYM)}, { "STDDEV_SAMP", SYM(STDDEV_SAMP_SYM)}, - { "STR_TO_DATE", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_str_to_date)}, - { "STRCMP", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)}, + { "SUBDATE", SYM(SUBDATE_SYM)}, { "SUBSTR", SYM(SUBSTRING)}, { "SUBSTRING", SYM(SUBSTRING)}, - { "SUBSTRING_INDEX", SYM(SUBSTRING_INDEX)}, - { "SUBTIME", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)}, { "SUM", SYM(SUM_SYM)}, { "SYSDATE", SYM(SYSDATE)}, - { "SYSTEM_USER", SYM(USER)}, - { "TAN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_tan)}, - { "TIME_FORMAT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_time_format)}, - { "TIME_TO_SEC", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_time_to_sec)}, - { "TIMEDIFF", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_timediff)}, - { "TO_DAYS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_to_days)}, - { "TOUCHES", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_touches)}, + { "SYSTEM_USER", SYM(USER)}, { "TRIM", SYM(TRIM)}, - { "UCASE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)}, - { "UNCOMPRESS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_uncompress)}, - { "UNCOMPRESSED_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_uncompressed_length)}, - { "UNHEX", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_unhex)}, { "UNIQUE_USERS", SYM(UNIQUE_USERS)}, - { "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP)}, - { "UPDATEXML", F_SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_xml_update)}, - { "UPPER", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)}, - { "UUID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_uuid)}, { "VARIANCE", SYM(VARIANCE_SYM)}, { "VAR_POP", SYM(VARIANCE_SYM)}, { "VAR_SAMP", SYM(VAR_SAMP_SYM)}, - { "VERSION", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)}, - { "WEEKDAY", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)}, - { "WEEKOFYEAR", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekofyear)}, - { "WITHIN", F_SYM(FUNC_ARG2),0,CREATE_FUNC_GEOM(create_func_within)}, - { "X", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_x)}, - { "Y", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_y)}, - { "YEARWEEK", SYM(YEARWEEK)} }; diff --git a/sql/lex_symbol.h b/sql/lex_symbol.h index 3074a489b6a..5ba785d16f3 100644 --- a/sql/lex_symbol.h +++ b/sql/lex_symbol.h @@ -26,7 +26,6 @@ typedef struct st_symbol { const char *name; uint tok; uint length; - void *create_func; struct st_sym_group *group; } SYMBOL; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6ddec155edb..ba69a574b55 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -2011,6 +2011,10 @@ inline void kill_delayed_threads(void) {} /* Used by handlers to store things in schema tables */ bool schema_table_store_record(THD *thd, TABLE *table); +/* sql/item_create.cc */ +int item_create_init(); +void item_create_cleanup(); + #endif /* MYSQL_SERVER */ #endif /* MYSQL_CLIENT */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6674dd87757..745c837c01b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1184,6 +1184,7 @@ void clean_up(bool print_message) hostname_cache_free(); item_user_lock_free(); lex_free(); /* Free some memory */ + item_create_cleanup(); set_var_free(); free_charsets(); (void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */ @@ -2693,6 +2694,8 @@ static int init_common_variables(const char *conf_file_name, int argc, return 1; init_client_errs(); lex_init(); + if (item_create_init()) + return 1; item_init(); set_var_init(); mysys_uses_curses=0; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 3b64684b5da..3022967eeeb 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6006,4 +6006,8 @@ ER_NON_INSERTABLE_TABLE eng "The target table %-.100s of the %s is not insertable-into" ER_CANT_RENAME_LOG_TABLE eng "Cannot rename '%s'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to '%s'" +ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT 42000 + eng "Incorrect parameter count in the call to native function '%-.64s'" +ER_WRONG_PARAMETERS_TO_NATIVE_FCT 42000 + eng "Incorrect parameters in the call to native function '%-.64s'" diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a6ae102fa0c..8062381e813 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -56,12 +56,17 @@ const LEX_STRING null_lex_str={0,0}; } /* Helper for parsing "IS [NOT] truth_value" */ -inline Item *is_truth_value(Item *A, bool v1, bool v2) +inline Item *is_truth_value(THD *thd, Item *A, bool v1, bool v2) { - return new Item_func_if(create_func_ifnull(A, - new Item_int((char *) (v2 ? "TRUE" : "FALSE"), v2, 1)), - new Item_int((char *) (v1 ? "TRUE" : "FALSE"), v1, 1), - new Item_int((char *) (v1 ? "FALSE" : "TRUE"),!v1, 1)); + Item *v1_t= new (thd->mem_root) Item_int((char *) (v1 ? "TRUE" : "FALSE"), + v1, 1); + Item *v1_f= new (thd->mem_root) Item_int((char *) (v1 ? "FALSE" : "TRUE"), + !v1, 1); + Item *v2_t= new (thd->mem_root) Item_int((char *) (v2 ? "TRUE" : "FALSE"), + v2, 1); + Item *ifnull= new (thd->mem_root) Item_func_ifnull(A, v2_t); + + return new (thd->mem_root) Item_func_if(ifnull, v1_t, v1_f); } #ifndef DBUG_OFF @@ -142,213 +147,209 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %pure_parser /* We have threads */ -%token END_OF_INPUT +/* + Comments for TOKENS. + For each token, please include in the same line a comment that contains + the following tags: + SQL-2003-R : Reserved keyword as per SQL-2003 + SQL-2003-N : Non Reserved keyword as per SQL-2003 + SQL-1999-R : Reserved keyword as per SQL-1999 + SQL-1999-N : Non Reserved keyword as per SQL-1999 + MYSQL : MySQL extention (unspecified) + MYSQL-FUNC : MySQL extention, function + INTERNAL : Not a real token, lex optimization + OPERATOR : SQL operator + FUTURE-USE : Reserved for futur use -%token ABORT_SYM + This makes the code grep-able, and helps maintenance. +*/ + +%token ABORT_SYM /* INTERNAL (used in lex) */ %token ACCESSIBLE_SYM -%token ACTION -%token ADD -%token ADDDATE_SYM -%token AFTER_SYM +%token ACTION /* SQL-2003-N */ +%token ADD /* SQL-2003-R */ +%token ADDDATE_SYM /* MYSQL-FUNC */ +%token AFTER_SYM /* SQL-2003-N */ %token AGAINST %token AGGREGATE_SYM %token ALGORITHM_SYM -%token ALL -%token ALTER +%token ALL /* SQL-2003-R */ +%token ALTER /* SQL-2003-R */ %token ANALYZE_SYM -%token AND_AND_SYM -%token AND_SYM -%token ANY_SYM -%token AS -%token ASC -%token ASCII_SYM -%token ASENSITIVE_SYM -%token AT_SYM -%token ATAN +%token AND_AND_SYM /* OPERATOR */ +%token AND_SYM /* SQL-2003-R */ +%token ANY_SYM /* SQL-2003-R */ +%token AS /* SQL-2003-R */ +%token ASC /* SQL-2003-N */ +%token ASCII_SYM /* MYSQL-FUNC */ +%token ASENSITIVE_SYM /* FUTURE-USE */ +%token AT_SYM /* SQL-2003-R */ %token AUTHORS_SYM -%token AUTO_INC %token AUTOEXTEND_SIZE_SYM +%token AUTO_INC %token AVG_ROW_LENGTH -%token AVG_SYM +%token AVG_SYM /* SQL-2003-N */ %token BACKUP_SYM -%token BEFORE_SYM -%token BEGIN_SYM -%token BENCHMARK_SYM -%token BIGINT -%token BINARY +%token BEFORE_SYM /* SQL-2003-N */ +%token BEGIN_SYM /* SQL-2003-R */ +%token BETWEEN_SYM /* SQL-2003-R */ +%token BIGINT /* SQL-2003-R */ +%token BINARY /* SQL-2003-R */ %token BINLOG_SYM %token BIN_NUM -%token BIT_AND -%token BIT_OR -%token BIT_SYM -%token BIT_XOR -%token BLOB_SYM -%token BOOLEAN_SYM +%token BIT_AND /* MYSQL-FUNC */ +%token BIT_OR /* MYSQL-FUNC */ +%token BIT_SYM /* MYSQL-FUNC */ +%token BIT_XOR /* MYSQL-FUNC */ +%token BLOB_SYM /* SQL-2003-R */ +%token BOOLEAN_SYM /* SQL-2003-R */ %token BOOL_SYM -%token BOTH +%token BOTH /* SQL-2003-R */ %token BTREE_SYM -%token BY +%token BY /* SQL-2003-R */ %token BYTE_SYM %token CACHE_SYM -%token CALL_SYM -%token CASCADE -%token CASCADED -%token CAST_SYM -%token CHAIN_SYM +%token CALL_SYM /* SQL-2003-R */ +%token CASCADE /* SQL-2003-N */ +%token CASCADED /* SQL-2003-R */ +%token CASE_SYM /* SQL-2003-R */ +%token CAST_SYM /* SQL-2003-R */ +%token CHAIN_SYM /* SQL-2003-N */ %token CHANGE %token CHANGED %token CHARSET -%token CHAR_SYM +%token CHAR_SYM /* SQL-2003-R */ %token CHECKSUM_SYM -%token CHECK_SYM +%token CHECK_SYM /* SQL-2003-R */ %token CIPHER_SYM %token CLIENT_SYM -%token CLOSE_SYM -%token COALESCE +%token CLOSE_SYM /* SQL-2003-R */ +%token COALESCE /* SQL-2003-N */ %token CODE_SYM -%token COLLATE_SYM -%token COLLATION_SYM +%token COLLATE_SYM /* SQL-2003-R */ +%token COLLATION_SYM /* SQL-2003-N */ %token COLUMNS -%token COLUMN_SYM +%token COLUMN_SYM /* SQL-2003-R */ %token COMMENT_SYM -%token COMMITTED_SYM -%token COMMIT_SYM +%token COMMITTED_SYM /* SQL-2003-N */ +%token COMMIT_SYM /* SQL-2003-R */ %token COMPACT_SYM %token COMPLETION_SYM %token COMPRESSED_SYM -%token CONCAT -%token CONCAT_WS %token CONCURRENT -%token CONDITION_SYM +%token CONDITION_SYM /* SQL-2003-N */ %token CONNECTION_SYM %token CONSISTENT_SYM -%token CONSTRAINT -%token CONTAINS_SYM -%token CONTINUE_SYM +%token CONSTRAINT /* SQL-2003-R */ +%token CONTAINS_SYM /* SQL-2003-N */ +%token CONTINUE_SYM /* SQL-2003-R */ %token CONTRIBUTORS_SYM -%token CONVERT_SYM -%token CONVERT_TZ_SYM -%token COUNT_SYM -%token CREATE -%token CROSS -%token CUBE_SYM -%token CURDATE -%token CURRENT_USER -%token CURSOR_SYM -%token CURTIME +%token CONVERT_SYM /* SQL-2003-N */ +%token COUNT_SYM /* SQL-2003-N */ +%token CREATE /* SQL-2003-R */ +%token CROSS /* SQL-2003-R */ +%token CUBE_SYM /* SQL-2003-R */ +%token CURDATE /* MYSQL-FUNC */ +%token CURRENT_USER /* SQL-2003-R */ +%token CURSOR_SYM /* SQL-2003-R */ +%token CURTIME /* MYSQL-FUNC */ %token DATABASE %token DATABASES %token DATAFILE_SYM -%token DATA_SYM +%token DATA_SYM /* SQL-2003-N */ %token DATETIME -%token DATE_ADD_INTERVAL -%token DATE_SUB_INTERVAL -%token DATE_SYM +%token DATE_ADD_INTERVAL /* MYSQL-FUNC */ +%token DATE_SUB_INTERVAL /* MYSQL-FUNC */ +%token DATE_SYM /* SQL-2003-R */ %token DAY_HOUR_SYM %token DAY_MICROSECOND_SYM %token DAY_MINUTE_SYM %token DAY_SECOND_SYM -%token DAY_SYM -%token DEALLOCATE_SYM +%token DAY_SYM /* SQL-2003-R */ +%token DEALLOCATE_SYM /* SQL-2003-R */ %token DECIMAL_NUM -%token DECIMAL_SYM -%token DECLARE_SYM -%token DECODE_SYM -%token DEFAULT +%token DECIMAL_SYM /* SQL-2003-R */ +%token DECLARE_SYM /* SQL-2003-R */ +%token DEFAULT /* SQL-2003-R */ %token DEFINER_SYM %token DELAYED_SYM %token DELAY_KEY_WRITE_SYM -%token DELETE_SYM -%token DESC -%token DESCRIBE -%token DES_DECRYPT_SYM -%token DES_ENCRYPT_SYM +%token DELETE_SYM /* SQL-2003-R */ +%token DESC /* SQL-2003-N */ +%token DESCRIBE /* SQL-2003-R */ %token DES_KEY_FILE -%token DETERMINISTIC_SYM +%token DETERMINISTIC_SYM /* SQL-2003-R */ %token DIRECTORY_SYM %token DISABLE_SYM %token DISCARD %token DISK_SYM -%token DISTINCT +%token DISTINCT /* SQL-2003-R */ %token DIV_SYM -%token DOUBLE_SYM +%token DOUBLE_SYM /* SQL-2003-R */ %token DO_SYM -%token DROP +%token DROP /* SQL-2003-R */ %token DUAL_SYM %token DUMPFILE %token DUPLICATE_SYM -%token DYNAMIC_SYM -%token EACH_SYM +%token DYNAMIC_SYM /* SQL-2003-R */ +%token EACH_SYM /* SQL-2003-R */ +%token ELSE /* SQL-2003-R */ %token ELSEIF_SYM -%token ELT_FUNC %token ENABLE_SYM %token ENCLOSED -%token ENCODE_SYM -%token ENCRYPT -%token END +%token END /* SQL-2003-R */ %token ENDS_SYM +%token END_OF_INPUT /* INTERNAL */ %token ENGINES_SYM %token ENGINE_SYM %token ENUM -%token EQ -%token EQUAL_SYM +%token EQ /* OPERATOR */ +%token EQUAL_SYM /* OPERATOR */ %token ERRORS %token ESCAPED -%token ESCAPE_SYM -%token EVENT_SYM +%token ESCAPE_SYM /* SQL-2003-R */ %token EVENTS_SYM -%token EVERY_SYM -%token EXECUTE_SYM -%token EXISTS +%token EVENT_SYM +%token EVERY_SYM /* SQL-2003-N */ +%token EXECUTE_SYM /* SQL-2003-R */ +%token EXISTS /* SQL-2003-R */ %token EXIT_SYM %token EXPANSION_SYM -%token EXPORT_SET %token EXTENDED_SYM %token EXTENT_SIZE_SYM -%token EXTRACT_SYM -%token FALSE_SYM +%token EXTRACT_SYM /* SQL-2003-N */ +%token FALSE_SYM /* SQL-2003-R */ %token FAST_SYM -%token FETCH_SYM -%token FIELD_FUNC +%token FETCH_SYM /* SQL-2003-R */ %token FILE_SYM -%token FIRST_SYM +%token FIRST_SYM /* SQL-2003-N */ %token FIXED_SYM %token FLOAT_NUM -%token FLOAT_SYM +%token FLOAT_SYM /* SQL-2003-R */ %token FLUSH_SYM %token FORCE_SYM -%token FOREIGN -%token FORMAT_SYM -%token FOR_SYM -%token FOUND_SYM +%token FOREIGN /* SQL-2003-R */ +%token FOR_SYM /* SQL-2003-R */ +%token FOUND_SYM /* SQL-2003-R */ %token FRAC_SECOND_SYM %token FROM -%token FROM_UNIXTIME -%token FULL +%token FULL /* SQL-2003-R */ %token FULLTEXT_SYM -%token FUNCTION_SYM -%token FUNC_ARG0 -%token FUNC_ARG1 -%token FUNC_ARG2 -%token FUNC_ARG3 +%token FUNCTION_SYM /* SQL-2003-R */ %token GE -%token GEOMCOLLFROMTEXT %token GEOMETRYCOLLECTION %token GEOMETRY_SYM -%token GEOMFROMTEXT -%token GEOMFROMWKB -%token GET_FORMAT -%token GLOBAL_SYM -%token GRANT +%token GET_FORMAT /* MYSQL-FUNC */ +%token GLOBAL_SYM /* SQL-2003-R */ +%token GRANT /* SQL-2003-R */ %token GRANTS -%token GREATEST_SYM -%token GROUP +%token GROUP /* SQL-2003-R */ %token GROUP_CONCAT_SYM %token GROUP_UNIQUE_USERS -%token GT_SYM +%token GT_SYM /* OPERATOR */ %token HANDLER_SYM %token HASH_SYM -%token HAVING +%token HAVING /* SQL-2003-R */ %token HELP_SYM %token HEX_NUM %token HIGH_PRIORITY @@ -356,7 +357,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token HOUR_MICROSECOND_SYM %token HOUR_MINUTE_SYM %token HOUR_SECOND_SYM -%token HOUR_SYM +%token HOUR_SYM /* SQL-2003-R */ %token IDENT %token IDENTIFIED_SYM %token IDENT_QUOTED @@ -367,70 +368,63 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token INDEX_SYM %token INFILE %token INITIAL_SIZE_SYM -%token INNER_SYM +%token INNER_SYM /* SQL-2003-R */ %token INNOBASE_SYM -%token INOUT_SYM -%token INSENSITIVE_SYM -%token INSERT +%token INOUT_SYM /* SQL-2003-R */ +%token INSENSITIVE_SYM /* SQL-2003-R */ +%token INSERT /* SQL-2003-R */ %token INSERT_METHOD %token INSTALL_SYM -%token INTERVAL_SYM -%token INTO -%token INT_SYM +%token INTERVAL_SYM /* SQL-2003-R */ +%token INTO /* SQL-2003-R */ +%token INT_SYM /* SQL-2003-R */ %token INVOKER_SYM -%token IN_SYM -%token IS -%token ISOLATION +%token IN_SYM /* SQL-2003-R */ +%token IS /* SQL-2003-R */ +%token ISOLATION /* SQL-2003-R */ %token ISSUER_SYM %token ITERATE_SYM -%token JOIN_SYM +%token JOIN_SYM /* SQL-2003-R */ %token KEYS -%token KEY_SYM %token KEY_BLOCK_SIZE +%token KEY_SYM /* SQL-2003-N */ %token KILL_SYM -%token LANGUAGE_SYM -%token LAST_INSERT_ID -%token LAST_SYM -%token LE -%token LEADING -%token LEAST_SYM +%token LANGUAGE_SYM /* SQL-2003-R */ +%token LAST_SYM /* SQL-2003-N */ +%token LE /* OPERATOR */ +%token LEADING /* SQL-2003-R */ %token LEAVES %token LEAVE_SYM -%token LEFT +%token LEFT /* SQL-2003-R */ %token LESS_SYM %token LEVEL_SYM %token LEX_HOSTNAME -%token LIKE +%token LIKE /* SQL-2003-R */ %token LIMIT %token LINEAR_SYM -%token LINEFROMTEXT %token LINES %token LINESTRING %token LIST_SYM %token LOAD -%token LOCAL_SYM -%token LOCATE -%token LOCATOR_SYM +%token LOCAL_SYM /* SQL-2003-R */ +%token LOCATOR_SYM /* SQL-2003-N */ %token LOCKS_SYM %token LOCK_SYM %token LOGFILE_SYM %token LOGS_SYM -%token LOG_SYM %token LONGBLOB %token LONGTEXT %token LONG_NUM %token LONG_SYM %token LOOP_SYM %token LOW_PRIORITY -%token LT -%token MAKE_SET_SYM +%token LT /* OPERATOR */ %token MASTER_CONNECT_RETRY_SYM %token MASTER_HOST_SYM %token MASTER_LOG_FILE_SYM %token MASTER_LOG_POS_SYM %token MASTER_PASSWORD_SYM %token MASTER_PORT_SYM -%token MASTER_POS_WAIT %token MASTER_SERVER_ID_SYM %token MASTER_SSL_CAPATH_SYM %token MASTER_SSL_CA_SYM @@ -440,134 +434,128 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token MASTER_SSL_SYM %token MASTER_SYM %token MASTER_USER_SYM -%token MATCH +%token MATCH /* SQL-2003-R */ %token MAX_CONNECTIONS_PER_HOUR %token MAX_QUERIES_PER_HOUR %token MAX_ROWS %token MAX_SIZE_SYM -%token MAX_SYM +%token MAX_SYM /* SQL-2003-N */ %token MAX_UPDATES_PER_HOUR %token MAX_USER_CONNECTIONS_SYM -%token MAX_VALUE_SYM +%token MAX_VALUE_SYM /* SQL-2003-N */ %token MEDIUMBLOB %token MEDIUMINT %token MEDIUMTEXT %token MEDIUM_SYM %token MEMORY_SYM -%token MERGE_SYM -%token MICROSECOND_SYM +%token MERGE_SYM /* SQL-2003-R */ +%token MICROSECOND_SYM /* MYSQL-FUNC */ %token MIGRATE_SYM %token MINUTE_MICROSECOND_SYM %token MINUTE_SECOND_SYM -%token MINUTE_SYM +%token MINUTE_SYM /* SQL-2003-R */ %token MIN_ROWS -%token MIN_SYM -%token MLINEFROMTEXT +%token MIN_SYM /* SQL-2003-N */ %token MODE_SYM -%token MODIFIES_SYM +%token MODIFIES_SYM /* SQL-2003-R */ %token MODIFY_SYM -%token MOD_SYM -%token MONTH_SYM -%token MPOINTFROMTEXT -%token MPOLYFROMTEXT +%token MOD_SYM /* SQL-2003-N */ +%token MONTH_SYM /* SQL-2003-R */ %token MULTILINESTRING %token MULTIPOINT %token MULTIPOLYGON %token MUTEX_SYM -%token NAMES_SYM -%token NAME_SYM -%token NATIONAL_SYM -%token NATURAL +%token NAMES_SYM /* SQL-2003-N */ +%token NAME_SYM /* SQL-2003-N */ +%token NATIONAL_SYM /* SQL-2003-R */ +%token NATURAL /* SQL-2003-R */ %token NCHAR_STRING -%token NCHAR_SYM +%token NCHAR_SYM /* SQL-2003-R */ %token NDBCLUSTER_SYM -%token NE -%token NEW_SYM -%token NEXT_SYM +%token NE /* OPERATOR */ +%token NEG +%token NEW_SYM /* SQL-2003-R */ +%token NEXT_SYM /* SQL-2003-N */ %token NODEGROUP_SYM -%token NONE_SYM +%token NONE_SYM /* SQL-2003-R */ %token NOT2_SYM -%token NOT_SYM +%token NOT_SYM /* SQL-2003-R */ %token NOW_SYM -%token NO_SYM +%token NO_SYM /* SQL-2003-R */ %token NO_WAIT_SYM %token NO_WRITE_TO_BINLOG -%token NULL_SYM +%token NULL_SYM /* SQL-2003-R */ %token NUM -%token NUMERIC_SYM +%token NUMERIC_SYM /* SQL-2003-R */ %token NVARCHAR_SYM %token OFFSET_SYM -%token OJ_SYM %token OLD_PASSWORD -%token ON +%token ON /* SQL-2003-R */ %token ONE_SHOT_SYM %token ONE_SYM -%token OPEN_SYM +%token OPEN_SYM /* SQL-2003-R */ %token OPTIMIZE -%token OPTION +%token OPTION /* SQL-2003-N */ %token OPTIONALLY %token OR2_SYM -%token ORDER_SYM -%token OR_OR_SYM -%token OR_SYM +%token ORDER_SYM /* SQL-2003-R */ +%token OR_OR_SYM /* OPERATOR */ +%token OR_SYM /* SQL-2003-R */ %token OUTER %token OUTFILE -%token OUT_SYM +%token OUT_SYM /* SQL-2003-R */ %token PACK_KEYS_SYM +%token PARAM_MARKER %token PARSER_SYM -%token PARTIAL -%token PARTITION_SYM +%token PARTIAL /* SQL-2003-N */ %token PARTITIONING_SYM %token PARTITIONS_SYM +%token PARTITION_SYM /* SQL-2003-R */ %token PASSWORD -%token PARAM_MARKER %token PHASE_SYM -%token PLUGIN_SYM %token PLUGINS_SYM -%token POINTFROMTEXT +%token PLUGIN_SYM %token POINT_SYM -%token POLYFROMTEXT %token POLYGON -%token POSITION_SYM -%token PRECISION -%token PREPARE_SYM +%token POSITION_SYM /* SQL-2003-N */ +%token PRECISION /* SQL-2003-R */ +%token PREPARE_SYM /* SQL-2003-R */ %token PRESERVE_SYM %token PREV_SYM -%token PRIMARY_SYM -%token PRIVILEGES -%token PROCEDURE +%token PRIMARY_SYM /* SQL-2003-R */ +%token PRIVILEGES /* SQL-2003-N */ +%token PROCEDURE /* SQL-2003-R */ %token PROCESS %token PROCESSLIST_SYM %token PURGE %token QUARTER_SYM %token QUERY_SYM %token QUICK -%token RAND -%token RANGE_SYM -%token READS_SYM +%token RANGE_SYM /* SQL-2003-R */ +%token READS_SYM /* SQL-2003-R */ %token READ_ONLY_SYM -%token READ_SYM +%token READ_SYM /* SQL-2003-N */ %token READ_WRITE_SYM -%token REAL +%token REAL /* SQL-2003-R */ %token REBUILD_SYM %token RECOVER_SYM -%token REDO_BUFFER_SIZE_SYM %token REDOFILE_SYM +%token REDO_BUFFER_SIZE_SYM %token REDUNDANT_SYM -%token REFERENCES +%token REFERENCES /* SQL-2003-R */ %token REGEXP %token RELAY_LOG_FILE_SYM %token RELAY_LOG_POS_SYM %token RELAY_THREAD -%token RELEASE_SYM +%token RELEASE_SYM /* SQL-2003-R */ %token RELOAD %token REMOVE_SYM %token RENAME %token REORGANIZE_SYM %token REPAIR -%token REPEATABLE_SYM -%token REPEAT_SYM -%token REPLACE +%token REPEATABLE_SYM /* SQL-2003-N */ +%token REPEAT_SYM /* MYSQL-FUNC */ +%token REPLACE /* MYSQL-FUNC */ %token REPLICATION %token REQUIRE_SYM %token RESET_SYM @@ -575,159 +563,155 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token RESTORE_SYM %token RESTRICT %token RESUME_SYM -%token RETURNS_SYM -%token RETURN_SYM -%token REVOKE -%token RIGHT -%token ROLLBACK_SYM -%token ROLLUP_SYM -%token ROUND -%token ROUTINE_SYM -%token ROWS_SYM -%token ROW_COUNT_SYM +%token RETURNS_SYM /* SQL-2003-R */ +%token RETURN_SYM /* SQL-2003-R */ +%token REVOKE /* SQL-2003-R */ +%token RIGHT /* SQL-2003-R */ +%token ROLLBACK_SYM /* SQL-2003-R */ +%token ROLLUP_SYM /* SQL-2003-R */ +%token ROUTINE_SYM /* SQL-2003-N */ +%token ROWS_SYM /* SQL-2003-R */ %token ROW_FORMAT_SYM -%token ROW_SYM +%token ROW_SYM /* SQL-2003-R */ %token RTREE_SYM -%token SAVEPOINT_SYM +%token SAVEPOINT_SYM /* SQL-2003-R */ %token SCHEDULE_SYM %token SECOND_MICROSECOND_SYM -%token SECOND_SYM -%token SECURITY_SYM -%token SELECT_SYM -%token SENSITIVE_SYM +%token SECOND_SYM /* SQL-2003-R */ +%token SECURITY_SYM /* SQL-2003-N */ +%token SELECT_SYM /* SQL-2003-R */ +%token SENSITIVE_SYM /* FUTURE-USE */ %token SEPARATOR_SYM -%token SERIALIZABLE_SYM +%token SERIALIZABLE_SYM /* SQL-2003-N */ %token SERIAL_SYM -%token SESSION_SYM -%token SET +%token SESSION_SYM /* SQL-2003-N */ +%token SET /* SQL-2003-R */ %token SET_VAR %token SHARE_SYM -%token SHIFT_LEFT -%token SHIFT_RIGHT +%token SHIFT_LEFT /* OPERATOR */ +%token SHIFT_RIGHT /* OPERATOR */ %token SHOW %token SHUTDOWN %token SIGNED_SYM -%token SIMPLE_SYM +%token SIMPLE_SYM /* SQL-2003-N */ %token SLAVE -%token SMALLINT +%token SMALLINT /* SQL-2003-R */ %token SNAPSHOT_SYM %token SONAME_SYM %token SOUNDS_SYM %token SPATIAL_SYM -%token SPECIFIC_SYM -%token SQLEXCEPTION_SYM -%token SQLSTATE_SYM -%token SQLWARNING_SYM +%token SPECIFIC_SYM /* SQL-2003-R */ +%token SQLEXCEPTION_SYM /* SQL-2003-R */ +%token SQLSTATE_SYM /* SQL-2003-R */ +%token SQLWARNING_SYM /* SQL-2003-R */ %token SQL_BIG_RESULT %token SQL_BUFFER_RESULT %token SQL_CACHE_SYM %token SQL_CALC_FOUND_ROWS %token SQL_NO_CACHE_SYM %token SQL_SMALL_RESULT -%token SQL_SYM +%token SQL_SYM /* SQL-2003-R */ %token SQL_THREAD %token SSL_SYM %token STARTING -%token START_SYM %token STARTS_SYM +%token START_SYM /* SQL-2003-R */ %token STATUS_SYM +%token STDDEV_SAMP_SYM /* SQL-2003-N */ %token STD_SYM -%token STDDEV_SAMP_SYM %token STOP_SYM %token STORAGE_SYM %token STRAIGHT_JOIN %token STRING_SYM %token SUBDATE_SYM %token SUBJECT_SYM -%token SUBPARTITION_SYM %token SUBPARTITIONS_SYM -%token SUBSTRING -%token SUBSTRING_INDEX -%token SUM_SYM +%token SUBPARTITION_SYM +%token SUBSTRING /* SQL-2003-N */ +%token SUM_SYM /* SQL-2003-N */ %token SUPER_SYM %token SUSPEND_SYM %token SYSDATE %token TABLES %token TABLESPACE -%token TABLE_SYM -%token TEMPORARY +%token TABLE_REF_PRIORITY +%token TABLE_SYM /* SQL-2003-R */ +%token TEMPORARY /* SQL-2003-N */ %token TEMPTABLE_SYM %token TERMINATED %token TEXT_STRING %token TEXT_SYM -%token TIMESTAMP +%token THAN_SYM +%token THEN_SYM /* SQL-2003-R */ +%token TIMESTAMP /* SQL-2003-R */ %token TIMESTAMP_ADD %token TIMESTAMP_DIFF -%token TIME_SYM +%token TIME_SYM /* SQL-2003-R */ %token TINYBLOB %token TINYINT %token TINYTEXT -%token THAN_SYM -%token TO_SYM -%token TRAILING +%token TO_SYM /* SQL-2003-R */ +%token TRAILING /* SQL-2003-R */ %token TRANSACTION_SYM -%token TRIGGER_SYM %token TRIGGERS_SYM -%token TRIM -%token TRUE_SYM +%token TRIGGER_SYM /* SQL-2003-R */ +%token TRIM /* SQL-2003-N */ +%token TRUE_SYM /* SQL-2003-R */ %token TRUNCATE_SYM %token TYPES_SYM -%token TYPE_SYM +%token TYPE_SYM /* SQL-2003-N */ %token UDF_RETURNS_SYM %token ULONGLONG_NUM -%token UNCOMMITTED_SYM +%token UNCOMMITTED_SYM /* SQL-2003-N */ %token UNDEFINED_SYM -%token UNDO_BUFFER_SIZE_SYM -%token UNDOFILE_SYM %token UNDERSCORE_CHARSET -%token UNDO_SYM +%token UNDOFILE_SYM +%token UNDO_BUFFER_SIZE_SYM +%token UNDO_SYM /* FUTURE-USE */ %token UNICODE_SYM %token UNINSTALL_SYM -%token UNION_SYM +%token UNION_SYM /* SQL-2003-R */ %token UNIQUE_SYM %token UNIQUE_USERS -%token UNIX_TIMESTAMP -%token UNKNOWN_SYM +%token UNKNOWN_SYM /* SQL-2003-R */ %token UNLOCK_SYM %token UNSIGNED %token UNTIL_SYM -%token UPDATE_SYM +%token UPDATE_SYM /* SQL-2003-R */ %token UPGRADE_SYM -%token USAGE -%token USER +%token USAGE /* SQL-2003-N */ +%token USER /* SQL-2003-R */ %token USE_FRM %token USE_SYM -%token USING +%token USING /* SQL-2003-R */ %token UTC_DATE_SYM %token UTC_TIMESTAMP_SYM %token UTC_TIME_SYM -%token VAR_SAMP_SYM -%token VALUES -%token VALUE_SYM +%token VALUES /* SQL-2003-R */ +%token VALUE_SYM /* SQL-2003-R */ %token VARBINARY -%token VARCHAR +%token VARCHAR /* SQL-2003-R */ %token VARIABLES %token VARIANCE_SYM -%token VARYING -%token VIEW_SYM +%token VARYING /* SQL-2003-R */ +%token VAR_SAMP_SYM +%token VIEW_SYM /* SQL-2003-N */ %token WAIT_SYM %token WARNINGS %token WEEK_SYM -%token WHEN_SYM -%token WHERE +%token WHEN_SYM /* SQL-2003-R */ +%token WHERE /* SQL-2003-R */ %token WHILE_SYM -%token WITH -%token WORK_SYM -%token WRITE_SYM +%token WITH /* SQL-2003-R */ +%token WORK_SYM /* SQL-2003-N */ +%token WRITE_SYM /* SQL-2003-N */ %token X509_SYM %token XA_SYM %token XOR -%token YEARWEEK %token YEAR_MONTH_SYM -%token YEAR_SYM +%token YEAR_SYM /* SQL-2003-R */ %token ZEROFILL - %left JOIN_SYM INNER_SYM STRAIGHT_JOIN CROSS LEFT RIGHT /* A dummy token to force the priority of table_ref production in a join. */ %left TABLE_REF_PRIORITY @@ -803,6 +787,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); simple_ident_nospvar simple_ident_q field_or_var limit_option part_func_expr + function_call_keyword + function_call_nonkeyword + function_call_generic + function_call_conflict %type NUM_literal @@ -810,6 +798,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type expr_list udf_expr_list udf_expr_list2 when_list ident_list ident_list_arg + expr_list_opt %type option_type opt_var_type opt_var_ident_type @@ -848,7 +837,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type udf_func_type -%type FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp +%type keyword keyword_sp %type user grant_user @@ -5825,10 +5814,10 @@ bool_factor: | bool_test ; bool_test: - bool_pri IS TRUE_SYM { $$= is_truth_value($1,1,0); } - | bool_pri IS not TRUE_SYM { $$= is_truth_value($1,0,0); } - | bool_pri IS FALSE_SYM { $$= is_truth_value($1,0,1); } - | bool_pri IS not FALSE_SYM { $$= is_truth_value($1,1,1); } + bool_pri IS TRUE_SYM { $$= is_truth_value(YYTHD, $1,1,0); } + | bool_pri IS not TRUE_SYM { $$= is_truth_value(YYTHD, $1,0,0); } + | bool_pri IS FALSE_SYM { $$= is_truth_value(YYTHD, $1,0,1); } + | bool_pri IS not FALSE_SYM { $$= is_truth_value(YYTHD, $1,1,1); } | bool_pri IS UNKNOWN_SYM { $$= new Item_func_isnull($1); } | bool_pri IS not UNKNOWN_SYM { $$= new Item_func_isnotnull($1); } | bool_pri ; @@ -5949,56 +5938,67 @@ interval_expr: simple_expr: simple_ident + | function_call_keyword + | function_call_nonkeyword + | function_call_generic + | function_call_conflict | simple_expr COLLATE_SYM ident_or_text %prec NEG { - $$= new Item_func_set_collation($1, - new Item_string($3.str, - $3.length, - YYTHD->charset())); + THD *thd= YYTHD; + Item *i1= new (thd->mem_root) Item_string($3.str, + $3.length, + thd->charset()); + $$= new (thd->mem_root) Item_func_set_collation($1, i1); } | literal | param_marker | variable | sum_expr | simple_expr OR_OR_SYM simple_expr - { $$= new Item_func_concat($1, $3); } + { $$= new (YYTHD->mem_root) Item_func_concat($1, $3); } | '+' simple_expr %prec NEG { $$= $2; } - | '-' simple_expr %prec NEG { $$= new Item_func_neg($2); } - | '~' simple_expr %prec NEG { $$= new Item_func_bit_neg($2); } - | not2 simple_expr %prec NEG { $$= negate_expression(YYTHD, $2); } + | '-' simple_expr %prec NEG + { $$= new (YYTHD->mem_root) Item_func_neg($2); } + | '~' simple_expr %prec NEG + { $$= new (YYTHD->mem_root) Item_func_bit_neg($2); } + | not2 simple_expr %prec NEG + { $$= negate_expression(YYTHD, $2); } | '(' subselect ')' { - $$= new Item_singlerow_subselect($2); + $$= new (YYTHD->mem_root) Item_singlerow_subselect($2); } | '(' expr ')' { $$= $2; } | '(' expr ',' expr_list ')' { $4->push_front($2); - $$= new Item_row(*$4); + $$= new (YYTHD->mem_root) Item_row(*$4); } | ROW_SYM '(' expr ',' expr_list ')' { $5->push_front($3); - $$= new Item_row(*$5); + $$= new (YYTHD->mem_root) Item_row(*$5); } | EXISTS '(' subselect ')' { - $$= new Item_exists_subselect($3); + $$= new (YYTHD->mem_root) Item_exists_subselect($3); } | '{' ident expr '}' { $$= $3; } | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')' - { $2->push_front($5); - Select->add_ftfunc_to_list((Item_func_match*) - ($$=new Item_func_match(*$2,$6))); } - | ASCII_SYM '(' expr ')' { $$= new Item_func_ascii($3); } + { + $2->push_front($5); + Item_func_match *i1= new (YYTHD->mem_root) Item_func_match(*$2, $6); + Select->add_ftfunc_to_list(i1); + $$= i1; + } | BINARY simple_expr %prec NEG { - $$= create_func_cast($2, ITEM_CAST_CHAR, -1, 0, &my_charset_bin); + $$= create_func_cast(YYTHD, $2, ITEM_CAST_CHAR, -1, 0, + &my_charset_bin); } | CAST_SYM '(' expr AS cast_type ')' { LEX *lex= Lex; - $$= create_func_cast($3, $5, + $$= create_func_cast(YYTHD, $3, $5, lex->length ? atoi(lex->length) : -1, lex->dec ? atoi(lex->dec) : 0, lex->charset); @@ -6006,10 +6006,10 @@ simple_expr: YYABORT; } | CASE_SYM opt_expr WHEN_SYM when_list opt_else END - { $$= new Item_func_case(* $4, $2, $5 ); } + { $$= new (YYTHD->mem_root) Item_func_case(* $4, $2, $5 ); } | CONVERT_SYM '(' expr ',' cast_type ')' { - $$= create_func_cast($3, $5, + $$= create_func_cast(YYTHD, $3, $5, Lex->length ? atoi(Lex->length) : -1, Lex->dec ? atoi(Lex->dec) : 0, Lex->charset); @@ -6017,7 +6017,7 @@ simple_expr: YYABORT; } | CONVERT_SYM '(' expr USING charset_name ')' - { $$= new Item_func_conv_charset($3,$5); } + { $$= new (YYTHD->mem_root) Item_func_conv_charset($3,$5); } | DEFAULT '(' simple_ident ')' { if ($3->is_splocal()) @@ -6027,170 +6027,15 @@ simple_expr: my_error(ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str); YYABORT; } - $$= new Item_default_value(Lex->current_context(), $3); + $$= new (YYTHD->mem_root) Item_default_value(Lex->current_context(), + $3); } | VALUES '(' simple_ident_nospvar ')' - { $$= new Item_insert_value(Lex->current_context(), $3); } - | FUNC_ARG0 '(' ')' - { - if (!$1.symbol->create_func) - { - my_error(ER_FEATURE_DISABLED, MYF(0), - $1.symbol->group->name, - $1.symbol->group->needed_define); - YYABORT; - } - $$= ((Item*(*)(void))($1.symbol->create_func))(); - } - | FUNC_ARG1 '(' expr ')' - { - if (!$1.symbol->create_func) - { - my_error(ER_FEATURE_DISABLED, MYF(0), - $1.symbol->group->name, - $1.symbol->group->needed_define); - YYABORT; - } - $$= ((Item*(*)(Item*))($1.symbol->create_func))($3); - } - | FUNC_ARG2 '(' expr ',' expr ')' - { - if (!$1.symbol->create_func) - { - my_error(ER_FEATURE_DISABLED, MYF(0), - $1.symbol->group->name, - $1.symbol->group->needed_define); - YYABORT; - } - $$= ((Item*(*)(Item*,Item*))($1.symbol->create_func))($3,$5); - } - | FUNC_ARG3 '(' expr ',' expr ',' expr ')' - { - if (!$1.symbol->create_func) - { - my_error(ER_FEATURE_DISABLED, MYF(0), - $1.symbol->group->name, - $1.symbol->group->needed_define); - YYABORT; - } - $$= ((Item*(*)(Item*,Item*,Item*))($1.symbol->create_func))($3,$5,$7); - } - | ADDDATE_SYM '(' expr ',' expr ')' - { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 0);} - | ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')' - { $$= new Item_date_add_interval($3, $6, $7, 0); } - | REPEAT_SYM '(' expr ',' expr ')' - { $$= new Item_func_repeat($3,$5); } - | ATAN '(' expr ')' - { $$= new Item_func_atan($3); } - | ATAN '(' expr ',' expr ')' - { $$= new Item_func_atan($3,$5); } - | CHAR_SYM '(' expr_list ')' - { $$= new Item_func_char(*$3); } - | CHAR_SYM '(' expr_list USING charset_name ')' - { $$= new Item_func_char(*$3, $5); } - | CHARSET '(' expr ')' - { $$= new Item_func_charset($3); } - | COALESCE '(' expr_list ')' - { $$= new Item_func_coalesce(* $3); } - | COLLATION_SYM '(' expr ')' - { $$= new Item_func_collation($3); } - | CONCAT '(' expr_list ')' - { $$= new Item_func_concat(* $3); } - | CONCAT_WS '(' expr ',' expr_list ')' - { $5->push_front($3); $$= new Item_func_concat_ws(*$5); } - | CONVERT_TZ_SYM '(' expr ',' expr ',' expr ')' - { - if (Lex->add_time_zone_tables_to_query_tables(YYTHD)) - YYABORT; - $$= new Item_func_convert_tz($3, $5, $7); - } - | CURDATE optional_braces - { $$= new Item_func_curdate_local(); Lex->safe_to_cache_query=0; } - | CURTIME optional_braces - { $$= new Item_func_curtime_local(); Lex->safe_to_cache_query=0; } - | CURTIME '(' expr ')' - { - $$= new Item_func_curtime_local($3); - Lex->safe_to_cache_query=0; - } - | CURRENT_USER optional_braces - { - $$= new Item_func_current_user(Lex->current_context()); - Lex->safe_to_cache_query= 0; - } - | DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')' - { $$= new Item_date_add_interval($3,$5,$6,0); } - | DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')' - { $$= new Item_date_add_interval($3,$5,$6,1); } - | DATABASE '(' ')' - { - $$= new Item_func_database(); - Lex->safe_to_cache_query=0; - } - | DATE_SYM '(' expr ')' - { $$= new Item_date_typecast($3); } - | DAY_SYM '(' expr ')' - { $$= new Item_func_dayofmonth($3); } - | ELT_FUNC '(' expr ',' expr_list ')' - { $5->push_front($3); $$= new Item_func_elt(*$5); } - | MAKE_SET_SYM '(' expr ',' expr_list ')' - { $$= new Item_func_make_set($3, *$5); } - | ENCRYPT '(' expr ')' - { - $$= new Item_func_encrypt($3); - Lex->uncacheable(UNCACHEABLE_RAND); - } - | ENCRYPT '(' expr ',' expr ')' { $$= new Item_func_encrypt($3,$5); } - | DECODE_SYM '(' expr ',' TEXT_STRING_literal ')' - { $$= new Item_func_decode($3,$5.str); } - | ENCODE_SYM '(' expr ',' TEXT_STRING_literal ')' - { $$= new Item_func_encode($3,$5.str); } - | DES_DECRYPT_SYM '(' expr ')' - { $$= new Item_func_des_decrypt($3); } - | DES_DECRYPT_SYM '(' expr ',' expr ')' - { $$= new Item_func_des_decrypt($3,$5); } - | DES_ENCRYPT_SYM '(' expr ')' - { $$= new Item_func_des_encrypt($3); } - | DES_ENCRYPT_SYM '(' expr ',' expr ')' - { $$= new Item_func_des_encrypt($3,$5); } - | EXPORT_SET '(' expr ',' expr ',' expr ')' - { $$= new Item_func_export_set($3, $5, $7); } - | EXPORT_SET '(' expr ',' expr ',' expr ',' expr ')' - { $$= new Item_func_export_set($3, $5, $7, $9); } - | EXPORT_SET '(' expr ',' expr ',' expr ',' expr ',' expr ')' - { $$= new Item_func_export_set($3, $5, $7, $9, $11); } - | FORMAT_SYM '(' expr ',' NUM ')' - { $$= new Item_func_format($3,atoi($5.str)); } - | FROM_UNIXTIME '(' expr ')' - { $$= new Item_func_from_unixtime($3); } - | FROM_UNIXTIME '(' expr ',' expr ')' - { - $$= new Item_func_date_format (new Item_func_from_unixtime($3),$5,0); - } - | FIELD_FUNC '(' expr ',' expr_list ')' - { $5->push_front($3); $$= new Item_func_field(*$5); } - | geometry_function - { -#ifdef HAVE_SPATIAL - $$= $1; -#else - my_error(ER_FEATURE_DISABLED, MYF(0), - sym_group_geom.name, sym_group_geom.needed_define); - YYABORT; -#endif - } - | GET_FORMAT '(' date_time_type ',' expr ')' - { $$= new Item_func_get_format($3, $5); } - | HOUR_SYM '(' expr ')' - { $$= new Item_func_hour($3); } - | IF '(' expr ',' expr ',' expr ')' - { $$= new Item_func_if($3,$5,$7); } - | INSERT '(' expr ',' expr ',' expr ',' expr ')' - { $$= new Item_func_insert($3,$5,$7,$9); } + { $$= new (YYTHD->mem_root) Item_insert_value(Lex->current_context(), + $3); } | interval_expr interval '+' expr /* we cannot put interval before - */ - { $$= new Item_date_add_interval($4,$1,$2,0); } + { $$= new (YYTHD->mem_root) Item_date_add_interval($4,$1,$2,0); } | interval_expr { if ($1->type() != Item::ROW_ITEM) @@ -6198,374 +6043,416 @@ simple_expr: yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; } - $$= new Item_func_interval((Item_row *)$1); - } - | LAST_INSERT_ID '(' ')' - { - $$= new Item_func_last_insert_id(); - Lex->safe_to_cache_query= 0; - } - | LAST_INSERT_ID '(' expr ')' - { - $$= new Item_func_last_insert_id($3); - Lex->safe_to_cache_query= 0; - } - | LEFT '(' expr ',' expr ')' - { $$= new Item_func_left($3,$5); } - | LOCATE '(' expr ',' expr ')' - { $$= new Item_func_locate($5,$3); } - | LOCATE '(' expr ',' expr ',' expr ')' - { $$= new Item_func_locate($5,$3,$7); } - | GREATEST_SYM '(' expr ',' expr_list ')' - { $5->push_front($3); $$= new Item_func_max(*$5); } - | LEAST_SYM '(' expr ',' expr_list ')' - { $5->push_front($3); $$= new Item_func_min(*$5); } - | LOG_SYM '(' expr ')' - { $$= new Item_func_log($3); } - | LOG_SYM '(' expr ',' expr ')' - { $$= new Item_func_log($3, $5); } - | MASTER_POS_WAIT '(' expr ',' expr ')' - { - $$= new Item_master_pos_wait($3, $5); - Lex->safe_to_cache_query=0; - } - | MASTER_POS_WAIT '(' expr ',' expr ',' expr ')' - { - $$= new Item_master_pos_wait($3, $5, $7); - Lex->safe_to_cache_query=0; - } - | MICROSECOND_SYM '(' expr ')' - { $$= new Item_func_microsecond($3); } - | MINUTE_SYM '(' expr ')' - { $$= new Item_func_minute($3); } - | MOD_SYM '(' expr ',' expr ')' - { $$ = new Item_func_mod( $3, $5); } - | MONTH_SYM '(' expr ')' - { $$= new Item_func_month($3); } - | NOW_SYM optional_braces - { $$= new Item_func_now_local(); Lex->safe_to_cache_query=0;} - | NOW_SYM '(' expr ')' - { $$= new Item_func_now_local($3); Lex->safe_to_cache_query=0;} - | PASSWORD '(' expr ')' - { - $$= YYTHD->variables.old_passwords ? - (Item *) new Item_func_old_password($3) : - (Item *) new Item_func_password($3); - } - | OLD_PASSWORD '(' expr ')' - { $$= new Item_func_old_password($3); } - | POSITION_SYM '(' bit_expr IN_SYM expr ')' - { $$ = new Item_func_locate($5,$3); } - | QUARTER_SYM '(' expr ')' - { $$ = new Item_func_quarter($3); } - | RAND '(' expr ')' - { $$= new Item_func_rand($3); Lex->uncacheable(UNCACHEABLE_RAND);} - | RAND '(' ')' - { $$= new Item_func_rand(); Lex->uncacheable(UNCACHEABLE_RAND);} - | REPLACE '(' expr ',' expr ',' expr ')' - { $$= new Item_func_replace($3,$5,$7); } - | RIGHT '(' expr ',' expr ')' - { $$= new Item_func_right($3,$5); } - | ROUND '(' expr ')' - { $$= new Item_func_round($3, new Item_int((char*)"0",0,1),0); } - | ROUND '(' expr ',' expr ')' { $$= new Item_func_round($3,$5,0); } - | ROW_COUNT_SYM '(' ')' - { - $$= new Item_func_row_count(); - Lex->safe_to_cache_query= 0; - } - | SUBDATE_SYM '(' expr ',' expr ')' - { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 1);} - | SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')' - { $$= new Item_date_add_interval($3, $6, $7, 1); } - | SECOND_SYM '(' expr ')' - { $$= new Item_func_second($3); } - | SUBSTRING '(' expr ',' expr ',' expr ')' - { $$= new Item_func_substr($3,$5,$7); } - | SUBSTRING '(' expr ',' expr ')' - { $$= new Item_func_substr($3,$5); } - | SUBSTRING '(' expr FROM expr FOR_SYM expr ')' - { $$= new Item_func_substr($3,$5,$7); } - | SUBSTRING '(' expr FROM expr ')' - { $$= new Item_func_substr($3,$5); } - | SUBSTRING_INDEX '(' expr ',' expr ',' expr ')' - { $$= new Item_func_substr_index($3,$5,$7); } - | SYSDATE optional_braces - { - if (global_system_variables.sysdate_is_now == 0) - $$= new Item_func_sysdate_local(); - else $$= new Item_func_now_local(); - Lex->safe_to_cache_query=0; - } - | SYSDATE '(' expr ')' - { - if (global_system_variables.sysdate_is_now == 0) - $$= new Item_func_sysdate_local($3); - else $$= new Item_func_now_local($3); - Lex->safe_to_cache_query=0; - } - | TIME_SYM '(' expr ')' - { $$= new Item_time_typecast($3); } - | TIMESTAMP '(' expr ')' - { $$= new Item_datetime_typecast($3); } - | TIMESTAMP '(' expr ',' expr ')' - { $$= new Item_func_add_time($3, $5, 1, 0); } - | TIMESTAMP_ADD '(' interval_time_st ',' expr ',' expr ')' - { $$= new Item_date_add_interval($7,$5,$3,0); } - | TIMESTAMP_DIFF '(' interval_time_st ',' expr ',' expr ')' - { $$= new Item_func_timestamp_diff($5,$7,$3); } - | TRIM '(' expr ')' - { $$= new Item_func_trim($3); } - | TRIM '(' LEADING expr FROM expr ')' - { $$= new Item_func_ltrim($6,$4); } - | TRIM '(' TRAILING expr FROM expr ')' - { $$= new Item_func_rtrim($6,$4); } - | TRIM '(' BOTH expr FROM expr ')' - { $$= new Item_func_trim($6,$4); } - | TRIM '(' LEADING FROM expr ')' - { $$= new Item_func_ltrim($5); } - | TRIM '(' TRAILING FROM expr ')' - { $$= new Item_func_rtrim($5); } - | TRIM '(' BOTH FROM expr ')' - { $$= new Item_func_trim($5); } - | TRIM '(' expr FROM expr ')' - { $$= new Item_func_trim($5,$3); } - | TRUNCATE_SYM '(' expr ',' expr ')' - { $$= new Item_func_round($3,$5,1); } - | ident '.' ident '(' udf_expr_list ')' - { - LEX *lex= Lex; - sp_name *name= new sp_name($1, $3); - - name->init_qname(YYTHD); - sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION); - if ($5) - $$= new Item_func_sp(Lex->current_context(), name, *$5); - else - $$= new Item_func_sp(Lex->current_context(), name); - lex->safe_to_cache_query=0; - } - | IDENT_sys '(' - { -#ifdef HAVE_DLOPEN - udf_func *udf= 0; - if (using_udf_functions && - (udf= find_udf($1.str, $1.length)) && - udf->type == UDFTYPE_AGGREGATE) - { - LEX *lex= Lex; - if (lex->current_select->inc_in_sum_expr()) - { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; - } - } - $$= udf; -#endif - } - udf_expr_list ')' - { -#ifdef HAVE_DLOPEN - udf_func *udf= $3; - SELECT_LEX *sel= Select; - - if (udf) - { - if (udf->type == UDFTYPE_AGGREGATE) - Select->in_sum_expr--; - - Lex->binlog_row_based_if_mixed= TRUE; - - switch (udf->returns) { - case STRING_RESULT: - if (udf->type == UDFTYPE_FUNCTION) - { - if ($4 != NULL) - $$ = new Item_func_udf_str(udf, *$4); - else - $$ = new Item_func_udf_str(udf); - } - else - { - if ($4 != NULL) - $$ = new Item_sum_udf_str(udf, *$4); - else - $$ = new Item_sum_udf_str(udf); - } - break; - case REAL_RESULT: - if (udf->type == UDFTYPE_FUNCTION) - { - if ($4 != NULL) - $$ = new Item_func_udf_float(udf, *$4); - else - $$ = new Item_func_udf_float(udf); - } - else - { - if ($4 != NULL) - $$ = new Item_sum_udf_float(udf, *$4); - else - $$ = new Item_sum_udf_float(udf); - } - break; - case INT_RESULT: - if (udf->type == UDFTYPE_FUNCTION) - { - if ($4 != NULL) - $$ = new Item_func_udf_int(udf, *$4); - else - $$ = new Item_func_udf_int(udf); - } - else - { - if ($4 != NULL) - $$ = new Item_sum_udf_int(udf, *$4); - else - $$ = new Item_sum_udf_int(udf); - } - break; - case DECIMAL_RESULT: - if (udf->type == UDFTYPE_FUNCTION) - { - if ($4 != NULL) - $$ = new Item_func_udf_decimal(udf, *$4); - else - $$ = new Item_func_udf_decimal(udf); - } - else - { - if ($4 != NULL) - $$ = new Item_sum_udf_decimal(udf, *$4); - else - $$ = new Item_sum_udf_decimal(udf); - } - break; - default: - YYABORT; - } - } - else -#endif /* HAVE_DLOPEN */ - { - LEX *lex= Lex; - THD *thd= lex->thd; - LEX_STRING db; - if (thd->copy_db_to(&db.str, &db.length)) - YYABORT; - sp_name *name= new sp_name(db, $1); - if (name) - name->init_qname(thd); - - sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION); - if ($4) - $$= new Item_func_sp(Lex->current_context(), name, *$4); - else - $$= new Item_func_sp(Lex->current_context(), name); - lex->safe_to_cache_query=0; - } + $$= new (YYTHD->mem_root) Item_func_interval((Item_row *)$1); } | UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' expr_list ')' { $$= new Item_func_unique_users($3,atoi($5.str),atoi($7.str), * $9); } - | UNIX_TIMESTAMP '(' ')' + ; + +/* + Function call syntax using official SQL 2003 keywords. + Because the function name is an official token, + a dedicated grammar rule is needed in the parser. + There is no potential for conflicts +*/ +function_call_keyword: + CHAR_SYM '(' expr_list ')' + { $$= new (YYTHD->mem_root) Item_func_char(*$3); } + | CHAR_SYM '(' expr_list USING charset_name ')' + { $$= new (YYTHD->mem_root) Item_func_char(*$3, $5); } + | CURRENT_USER optional_braces + { + $$= new (YYTHD->mem_root) Item_func_current_user(Lex->current_context()); + Lex->safe_to_cache_query= 0; + } + | DATE_SYM '(' expr ')' + { $$= new (YYTHD->mem_root) Item_date_typecast($3); } + | DAY_SYM '(' expr ')' + { $$= new (YYTHD->mem_root) Item_func_dayofmonth($3); } + | HOUR_SYM '(' expr ')' + { $$= new (YYTHD->mem_root) Item_func_hour($3); } + | INSERT '(' expr ',' expr ',' expr ',' expr ')' + { $$= new (YYTHD->mem_root) Item_func_insert($3,$5,$7,$9); } + | LEFT '(' expr ',' expr ')' + { $$= new (YYTHD->mem_root) Item_func_left($3,$5); } + | MINUTE_SYM '(' expr ')' + { $$= new (YYTHD->mem_root) Item_func_minute($3); } + | MONTH_SYM '(' expr ')' + { $$= new (YYTHD->mem_root) Item_func_month($3); } + | RIGHT '(' expr ',' expr ')' + { $$= new (YYTHD->mem_root) Item_func_right($3,$5); } + | SECOND_SYM '(' expr ')' + { $$= new (YYTHD->mem_root) Item_func_second($3); } + | TIME_SYM '(' expr ')' + { $$= new (YYTHD->mem_root) Item_time_typecast($3); } + | TIMESTAMP '(' expr ')' + { $$= new (YYTHD->mem_root) Item_datetime_typecast($3); } + | TIMESTAMP '(' expr ',' expr ')' + { $$= new (YYTHD->mem_root) Item_func_add_time($3, $5, 1, 0); } + | TRIM '(' expr ')' + { $$= new (YYTHD->mem_root) Item_func_trim($3); } + | TRIM '(' LEADING expr FROM expr ')' + { $$= new (YYTHD->mem_root) Item_func_ltrim($6,$4); } + | TRIM '(' TRAILING expr FROM expr ')' + { $$= new (YYTHD->mem_root) Item_func_rtrim($6,$4); } + | TRIM '(' BOTH expr FROM expr ')' + { $$= new (YYTHD->mem_root) Item_func_trim($6,$4); } + | TRIM '(' LEADING FROM expr ')' + { $$= new (YYTHD->mem_root) Item_func_ltrim($5); } + | TRIM '(' TRAILING FROM expr ')' + { $$= new (YYTHD->mem_root) Item_func_rtrim($5); } + | TRIM '(' BOTH FROM expr ')' + { $$= new (YYTHD->mem_root) Item_func_trim($5); } + | TRIM '(' expr FROM expr ')' + { $$= new (YYTHD->mem_root) Item_func_trim($5,$3); } + | USER '(' ')' { - $$= new Item_func_unix_timestamp(); + $$= new (YYTHD->mem_root) Item_func_user(); + Lex->safe_to_cache_query=0; + } + | YEAR_SYM '(' expr ')' + { $$= new (YYTHD->mem_root) Item_func_year($3); } + ; + +/* + Function calls using non reserved keywords, with special syntaxic forms. + Dedicated grammar rules are needed because of the syntax, + but also have the potential to cause incompatibilities with other + parts of the language. + MAINTAINER: + The only reasons a function should be added here are: + - for compatibility reasons with another SQL syntax (CURDATE), + - for typing reasons (GET_FORMAT) + Any other 'Syntaxic sugar' enhancements should be *STRONGLY* + discouraged. +*/ +function_call_nonkeyword: + ADDDATE_SYM '(' expr ',' expr ')' + { + $$= new (YYTHD->mem_root) Item_date_add_interval($3, $5, + INTERVAL_DAY, 0); + } + | ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')' + { $$= new (YYTHD->mem_root) Item_date_add_interval($3, $6, $7, 0); } + | CURDATE optional_braces + { + $$= new (YYTHD->mem_root) Item_func_curdate_local(); + Lex->safe_to_cache_query=0; + } + | CURTIME optional_braces + { + $$= new (YYTHD->mem_root) Item_func_curtime_local(); + Lex->safe_to_cache_query=0; + } + | CURTIME '(' expr ')' + { + $$= new (YYTHD->mem_root) Item_func_curtime_local($3); Lex->safe_to_cache_query=0; } - | UNIX_TIMESTAMP '(' expr ')' - { $$= new Item_func_unix_timestamp($3); } - | USER '(' ')' - { $$= new Item_func_user(); Lex->safe_to_cache_query=0; } + | DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')' + { $$= new (YYTHD->mem_root) Item_date_add_interval($3,$5,$6,0); } + | DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')' + { $$= new (YYTHD->mem_root) Item_date_add_interval($3,$5,$6,1); } + | EXTRACT_SYM '(' interval FROM expr ')' + { $$=new (YYTHD->mem_root) Item_extract( $3, $5); } + | GET_FORMAT '(' date_time_type ',' expr ')' + { $$= new (YYTHD->mem_root) Item_func_get_format($3, $5); } + | NOW_SYM optional_braces + { + $$= new (YYTHD->mem_root) Item_func_now_local(); + Lex->safe_to_cache_query=0; + } + | NOW_SYM '(' expr ')' + { + $$= new (YYTHD->mem_root) Item_func_now_local($3); + Lex->safe_to_cache_query=0; + } + | POSITION_SYM '(' bit_expr IN_SYM expr ')' + { $$ = new (YYTHD->mem_root) Item_func_locate($5,$3); } + | SUBDATE_SYM '(' expr ',' expr ')' + { + $$= new (YYTHD->mem_root) Item_date_add_interval($3, $5, + INTERVAL_DAY, 1); + } + | SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')' + { $$= new (YYTHD->mem_root) Item_date_add_interval($3, $6, $7, 1); } + | SUBSTRING '(' expr ',' expr ',' expr ')' + { $$= new (YYTHD->mem_root) Item_func_substr($3,$5,$7); } + | SUBSTRING '(' expr ',' expr ')' + { $$= new (YYTHD->mem_root) Item_func_substr($3,$5); } + | SUBSTRING '(' expr FROM expr FOR_SYM expr ')' + { $$= new (YYTHD->mem_root) Item_func_substr($3,$5,$7); } + | SUBSTRING '(' expr FROM expr ')' + { $$= new (YYTHD->mem_root) Item_func_substr($3,$5); } + | SYSDATE optional_braces + { + if (global_system_variables.sysdate_is_now == 0) + $$= new (YYTHD->mem_root) Item_func_sysdate_local(); + else + $$= new (YYTHD->mem_root) Item_func_now_local(); + Lex->safe_to_cache_query=0; + } + | SYSDATE '(' expr ')' + { + if (global_system_variables.sysdate_is_now == 0) + $$= new (YYTHD->mem_root) Item_func_sysdate_local($3); + else + $$= new (YYTHD->mem_root) Item_func_now_local($3); + Lex->safe_to_cache_query=0; + } + | TIMESTAMP_ADD '(' interval_time_st ',' expr ',' expr ')' + { $$= new (YYTHD->mem_root) Item_date_add_interval($7,$5,$3,0); } + | TIMESTAMP_DIFF '(' interval_time_st ',' expr ',' expr ')' + { $$= new (YYTHD->mem_root) Item_func_timestamp_diff($5,$7,$3); } | UTC_DATE_SYM optional_braces - { $$= new Item_func_curdate_utc(); Lex->safe_to_cache_query=0;} + { + $$= new (YYTHD->mem_root) Item_func_curdate_utc(); + Lex->safe_to_cache_query=0; + } | UTC_TIME_SYM optional_braces - { $$= new Item_func_curtime_utc(); Lex->safe_to_cache_query=0;} + { + $$= new (YYTHD->mem_root) Item_func_curtime_utc(); + Lex->safe_to_cache_query=0; + } | UTC_TIMESTAMP_SYM optional_braces - { $$= new Item_func_now_utc(); Lex->safe_to_cache_query=0;} + { + $$= new (YYTHD->mem_root) Item_func_now_utc(); + Lex->safe_to_cache_query=0; + } + ; + +/* + Functions calls using a non reserved keywork, and using a regular syntax. + Because the non reserved keyword is used in another part of the grammar, + a dedicated rule is needed here. +*/ +function_call_conflict: + ASCII_SYM '(' expr ')' + { $$= new (YYTHD->mem_root) Item_func_ascii($3); } + | CHARSET '(' expr ')' + { $$= new (YYTHD->mem_root) Item_func_charset($3); } + | COALESCE '(' expr_list ')' + { $$= new (YYTHD->mem_root) Item_func_coalesce(* $3); } + | COLLATION_SYM '(' expr ')' + { $$= new (YYTHD->mem_root) Item_func_collation($3); } + | DATABASE '(' ')' + { + $$= new (YYTHD->mem_root) Item_func_database(); + Lex->safe_to_cache_query=0; + } + | IF '(' expr ',' expr ',' expr ')' + { $$= new (YYTHD->mem_root) Item_func_if($3,$5,$7); } + | MICROSECOND_SYM '(' expr ')' + { $$= new (YYTHD->mem_root) Item_func_microsecond($3); } + | MOD_SYM '(' expr ',' expr ')' + { $$ = new (YYTHD->mem_root) Item_func_mod( $3, $5); } + | OLD_PASSWORD '(' expr ')' + { $$= new (YYTHD->mem_root) Item_func_old_password($3); } + | PASSWORD '(' expr ')' + { + THD *thd= YYTHD; + Item* i1; + if (thd->variables.old_passwords) + i1= new (thd->mem_root) Item_func_old_password($3); + else + i1= new (thd->mem_root) Item_func_password($3); + $$= i1; + } + | QUARTER_SYM '(' expr ')' + { $$ = new (YYTHD->mem_root) Item_func_quarter($3); } + | REPEAT_SYM '(' expr ',' expr ')' + { $$= new (YYTHD->mem_root) Item_func_repeat($3,$5); } + | REPLACE '(' expr ',' expr ',' expr ')' + { $$= new (YYTHD->mem_root) Item_func_replace($3,$5,$7); } + | TRUNCATE_SYM '(' expr ',' expr ')' + { $$= new (YYTHD->mem_root) Item_func_round($3,$5,1); } | WEEK_SYM '(' expr ')' { - $$= new Item_func_week($3,new Item_int((char*) "0", - YYTHD->variables.default_week_format,1)); + THD *thd= YYTHD; + Item *i1= new (thd->mem_root) Item_int((char*) "0", + thd->variables.default_week_format, + 1); + + $$= new (thd->mem_root) Item_func_week($3, i1); } | WEEK_SYM '(' expr ',' expr ')' - { $$= new Item_func_week($3,$5); } - | YEAR_SYM '(' expr ')' - { $$= new Item_func_year($3); } - | YEARWEEK '(' expr ')' - { $$= new Item_func_yearweek($3,new Item_int((char*) "0",0,1)); } - | YEARWEEK '(' expr ',' expr ')' - { $$= new Item_func_yearweek($3, $5); } - | BENCHMARK_SYM '(' ulong_num ',' expr ')' - { - $$=new Item_func_benchmark($3,$5); - Lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - } - | EXTRACT_SYM '(' interval FROM expr ')' - { $$=new Item_extract( $3, $5); }; + { $$= new (YYTHD->mem_root) Item_func_week($3,$5); } + | geometry_function + { +#ifdef HAVE_SPATIAL + $$= $1; +#else + my_error(ER_FEATURE_DISABLED, MYF(0), + sym_group_geom.name, sym_group_geom.needed_define); + YYABORT; +#endif + } + ; geometry_function: CONTAINS_SYM '(' expr ',' expr ')' - { $$= GEOM_NEW(Item_func_spatial_rel($3, $5, Item_func::SP_CONTAINS_FUNC)); } - | GEOMFROMTEXT '(' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } - | GEOMFROMTEXT '(' expr ',' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } - | GEOMFROMWKB '(' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_wkb($3)); } - | GEOMFROMWKB '(' expr ',' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_wkb($3, $5)); } + { + $$= GEOM_NEW(YYTHD, + Item_func_spatial_rel($3, $5, + Item_func::SP_CONTAINS_FUNC)); + } | GEOMETRYCOLLECTION '(' expr_list ')' - { $$= GEOM_NEW(Item_func_spatial_collection(* $3, + { + $$= GEOM_NEW(YYTHD, + Item_func_spatial_collection(* $3, Geometry::wkb_geometrycollection, - Geometry::wkb_point)); } + Geometry::wkb_point)); + } | LINESTRING '(' expr_list ')' - { $$= GEOM_NEW(Item_func_spatial_collection(* $3, - Geometry::wkb_linestring, Geometry::wkb_point)); } + { + $$= GEOM_NEW(YYTHD, + Item_func_spatial_collection(* $3, + Geometry::wkb_linestring, + Geometry::wkb_point)); + } | MULTILINESTRING '(' expr_list ')' - { $$= GEOM_NEW( Item_func_spatial_collection(* $3, - Geometry::wkb_multilinestring, Geometry::wkb_linestring)); } - | MLINEFROMTEXT '(' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } - | MLINEFROMTEXT '(' expr ',' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } - | MPOINTFROMTEXT '(' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } - | MPOINTFROMTEXT '(' expr ',' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } - | MPOLYFROMTEXT '(' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } - | MPOLYFROMTEXT '(' expr ',' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } + { + $$= GEOM_NEW(YYTHD, + Item_func_spatial_collection(* $3, + Geometry::wkb_multilinestring, + Geometry::wkb_linestring)); + } | MULTIPOINT '(' expr_list ')' - { $$= GEOM_NEW(Item_func_spatial_collection(* $3, - Geometry::wkb_multipoint, Geometry::wkb_point)); } + { + $$= GEOM_NEW(YYTHD, + Item_func_spatial_collection(* $3, + Geometry::wkb_multipoint, + Geometry::wkb_point)); + } | MULTIPOLYGON '(' expr_list ')' - { $$= GEOM_NEW(Item_func_spatial_collection(* $3, - Geometry::wkb_multipolygon, Geometry::wkb_polygon)); } + { + $$= GEOM_NEW(YYTHD, + Item_func_spatial_collection(* $3, + Geometry::wkb_multipolygon, + Geometry::wkb_polygon)); + } | POINT_SYM '(' expr ',' expr ')' - { $$= GEOM_NEW(Item_func_point($3,$5)); } - | POINTFROMTEXT '(' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } - | POINTFROMTEXT '(' expr ',' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } - | POLYFROMTEXT '(' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } - | POLYFROMTEXT '(' expr ',' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } + { $$= GEOM_NEW(YYTHD, Item_func_point($3,$5)); } | POLYGON '(' expr_list ')' - { $$= GEOM_NEW(Item_func_spatial_collection(* $3, - Geometry::wkb_polygon, Geometry::wkb_linestring)); } - | GEOMCOLLFROMTEXT '(' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } - | GEOMCOLLFROMTEXT '(' expr ',' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } - | LINEFROMTEXT '(' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3)); } - | LINEFROMTEXT '(' expr ',' expr ')' - { $$= GEOM_NEW(Item_func_geometry_from_text($3, $5)); } - ; + { + $$= GEOM_NEW(YYTHD, + Item_func_spatial_collection(* $3, + Geometry::wkb_polygon, + Geometry::wkb_linestring)); + } + ; + +/* + Regular function calls. + The function name is *not* a token, and therefore is guaranteed to not + introduce side effects to the language in general. + MAINTAINER: + All the new functions implemented for new features should fit into + this category. The place to implement the function itself is + in sql/item_create.cc +*/ +function_call_generic: + IDENT_sys '(' + { +#ifdef HAVE_DLOPEN + udf_func *udf= 0; + if (using_udf_functions && + (udf= find_udf($1.str, $1.length)) && + udf->type == UDFTYPE_AGGREGATE) + { + LEX *lex= Lex; + if (lex->current_select->inc_in_sum_expr()) + { + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } + } + /* Temporary placing the result of find_udf in $3 */ + $$= udf; +#endif + } + expr_list_opt ')' + { + THD *thd= YYTHD; + LEX *lex= Lex; + Create_func *builder; + Item *item= NULL; + + /* + Implementation note: + names are resolved with the following order: + - MySQL native functions, + - User Defined Functions, + - Stored Functions (assuming the current database) + + This will be revised with WL#2128 (SQL PATH) + */ + builder= find_native_function_builder(thd, $1); + if (builder) + { + item= builder->create(thd, $1, $4); + } + else + { +#ifdef HAVE_DLOPEN + /* Retrieving the result of find_udf */ + udf_func *udf= $3; + + if (udf) + { + if (udf->type == UDFTYPE_AGGREGATE) + { + Select->in_sum_expr--; + } + + item= Create_udf_func::s_singleton.create(thd, udf, $4); + } + else +#endif + { + builder= find_qualified_function_builder(thd); + DBUG_ASSERT(builder); + item= builder->create(thd, $1, $4); + } + } + + if (! ($$= item)) + { + YYABORT; + } + } + | ident '.' ident '(' udf_expr_list ')' + { + THD *thd= YYTHD; + Create_qfunc *builder; + Item *item= NULL; + + /* + The following in practice calls: + Create_sp_func::create() + and builds a stored function. + + However, it's important to maintain the interface between the + parser and the implementation in item_create.cc clean, + since this will change with WL#2128 (SQL PATH): + - INFORMATION_SCHEMA.version() is the SQL 99 syntax for the native + funtion version(), + - MySQL.version() is the SQL 2003 syntax for the native function + version() (a vendor can specify any schema). + */ + + builder= find_qualified_function_builder(thd); + DBUG_ASSERT(builder); + item= builder->create(thd, $1, $3, $5); + + if (! ($$= item)) + { + YYABORT; + } + } + ; fulltext_options: opt_natural_language_mode opt_query_expansion @@ -6775,6 +6662,13 @@ cast_type: | DECIMAL_SYM float_options { $$=ITEM_CAST_DECIMAL; Lex->charset= NULL; } ; +expr_list_opt: + /* empty */ + { $$ = NULL; } + | expr_list + { $$ = $1;} + ; + expr_list: { Select->expr_list.push_front(new List); } expr_list2 diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 148295398f4..d16eec1e3cc 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -8685,7 +8685,7 @@ static void test_sqlmode() if (!opt_silent) fprintf(stdout, "\n query: %s", query); stmt= mysql_simple_prepare(mysql, query); - check_stmt_r(stmt); + check_stmt(stmt); /* ANSI */ strmov(query, "SET SQL_MODE= \"ANSI\""); From 0af0c4432913bedeeaf274d2712c88876ab9c58b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 2 Nov 2006 14:02:07 -0700 Subject: [PATCH 46/47] Post merge fix --- mysql-test/r/ps.result | 6 ++++-- mysql-test/t/ps.test | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 36b69497e89..58bcc2b4d8d 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -502,7 +502,8 @@ deallocate prepare stmt; create table t1 (a varchar(20)); insert into t1 values ('foo'); prepare stmt FROM 'SELECT char_length (a) FROM t1'; -ERROR 42000: FUNCTION test.char_length does not exist +prepare stmt2 FROM 'SELECT not_a_function (a) FROM t1'; +ERROR 42000: FUNCTION test.not_a_function does not exist drop table t1; prepare stmt from "SELECT SQL_CALC_FOUND_ROWS 'foo' UNION SELECT 'bar' LIMIT 0"; execute stmt; @@ -1056,7 +1057,8 @@ End of 4.1 tests. create table t1 (a varchar(20)); insert into t1 values ('foo'); prepare stmt FROM 'SELECT char_length (a) FROM t1'; -ERROR 42000: FUNCTION test.char_length does not exist +prepare stmt2 FROM 'SELECT not_a_function (a) FROM t1'; +ERROR 42000: FUNCTION test.not_a_function does not exist drop table t1; create table t1 (a char(3) not null, b char(3) not null, c char(3) not null, primary key (a, b, c)); diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index c6839a8c93d..9048a3b2a56 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -523,8 +523,9 @@ deallocate prepare stmt; # create table t1 (a varchar(20)); insert into t1 values ('foo'); ---error 1305 prepare stmt FROM 'SELECT char_length (a) FROM t1'; +-- error ER_SP_DOES_NOT_EXIST +prepare stmt2 FROM 'SELECT not_a_function (a) FROM t1'; drop table t1; # @@ -1126,8 +1127,9 @@ DROP TABLE t1; # create table t1 (a varchar(20)); insert into t1 values ('foo'); ---error 1305 prepare stmt FROM 'SELECT char_length (a) FROM t1'; +-- error ER_SP_DOES_NOT_EXIST +prepare stmt2 FROM 'SELECT not_a_function (a) FROM t1'; drop table t1; # From 0d92b17851f8a42f25bcb44695a5a653b85750a5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 3 Nov 2006 12:16:31 +0300 Subject: [PATCH 47/47] Cleanup: fix race in rename.test. mysql-test/r/rename.result: Update result. mysql-test/t/rename.test: Remove the race by replacing sleep with a reap. --- mysql-test/r/rename.result | 1 + mysql-test/t/rename.test | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/rename.result b/mysql-test/r/rename.result index 76c0f4422fe..505af2d5d1a 100644 --- a/mysql-test/r/rename.result +++ b/mysql-test/r/rename.result @@ -54,3 +54,4 @@ Tables_in_test t2 t4 drop table t2, t4; +End of 4.1 tests diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test index 5caecef176e..caba0b87061 100644 --- a/mysql-test/t/rename.test +++ b/mysql-test/t/rename.test @@ -61,9 +61,15 @@ connection con2; sleep 1; show tables; UNLOCK TABLES; -sleep 1; +connection con1; +reap; +connection con2; show tables; drop table t2, t4; -# End of 4.1 tests +disconnect con2; +disconnect con1; +connection default; + +--echo End of 4.1 tests
Nr Varsized Attributes
Row Overhead16
Varsized Overhead
Column TypeVARSIZE Size Key
YES