summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomas@poseidon.ndb.mysql.com <>2006-05-16 12:33:24 +0200
committertomas@poseidon.ndb.mysql.com <>2006-05-16 12:33:24 +0200
commitb467bdfcdb3045b4821d4de1c2cc772761a62faa (patch)
tree020b3c31436110dbce578dff1d4ac042f8bdd5f6
parentea3067a50d0d444906ffd39f2eaba89b70e25212 (diff)
parenta29504cbcb30d3a6fb446294a82ece8f676e774a (diff)
downloadmariadb-git-b467bdfcdb3045b4821d4de1c2cc772761a62faa.tar.gz
Merge poseidon.ndb.mysql.com:/home/tomas/mysql-5.0
into poseidon.ndb.mysql.com:/home/tomas/mysql-5.0-main
-rw-r--r--innobase/os/os0file.c63
-rw-r--r--mysql-test/lib/mtr_process.pl20
-rwxr-xr-xmysql-test/mysql-test-run.pl86
-rw-r--r--mysql-test/r/case.result8
-rw-r--r--mysql-test/r/explain.result4
-rw-r--r--mysql-test/r/im_options_set.result6
-rw-r--r--mysql-test/r/im_options_unset.result6
-rw-r--r--mysql-test/r/join_outer.result22
-rw-r--r--mysql-test/r/metadata.result2
-rw-r--r--mysql-test/r/mysqlbinlog.result1
-rw-r--r--mysql-test/r/ps_2myisam.result4
-rw-r--r--mysql-test/r/ps_3innodb.result4
-rw-r--r--mysql-test/r/ps_4heap.result4
-rw-r--r--mysql-test/r/ps_5merge.result8
-rw-r--r--mysql-test/r/ps_6bdb.result4
-rw-r--r--mysql-test/r/ps_7ndb.result4
-rw-r--r--mysql-test/r/rpl_temporary.result15
-rw-r--r--mysql-test/r/rpl_until.result148
-rw-r--r--mysql-test/r/sp-error.result4
-rw-r--r--mysql-test/r/sp.result56
-rw-r--r--mysql-test/r/subselect.result8
-rw-r--r--mysql-test/r/trigger-grant.result84
-rw-r--r--mysql-test/r/trigger.result92
-rw-r--r--mysql-test/r/type_float.result8
-rw-r--r--mysql-test/r/type_newdecimal.result14
-rw-r--r--mysql-test/r/view.result13
-rw-r--r--mysql-test/t/explain.test9
-rw-r--r--mysql-test/t/join_outer.test26
-rw-r--r--mysql-test/t/mysqlbinlog.test15
-rw-r--r--mysql-test/t/rename.test8
-rw-r--r--mysql-test/t/rpl_temporary.test37
-rw-r--r--mysql-test/t/rpl_until.test8
-rw-r--r--mysql-test/t/sp.test70
-rw-r--r--mysql-test/t/subselect.test15
-rw-r--r--mysql-test/t/trigger-grant.test173
-rw-r--r--mysql-test/t/trigger.test122
-rw-r--r--mysql-test/t/view.test16
-rw-r--r--server-tools/instance-manager/manager.cc13
-rw-r--r--server-tools/instance-manager/manager.h2
-rw-r--r--server-tools/instance-manager/mysqlmanager.cc8
-rw-r--r--server-tools/instance-manager/options.cc59
-rw-r--r--server-tools/instance-manager/options.h1
-rw-r--r--sql/field_conv.cc3
-rw-r--r--sql/ha_innodb.cc3
-rw-r--r--sql/item.cc35
-rw-r--r--sql/item.h101
-rw-r--r--sql/item_func.cc13
-rw-r--r--sql/item_func.h12
-rw-r--r--sql/item_subselect.cc11
-rw-r--r--sql/item_subselect.h1
-rw-r--r--sql/item_timefunc.cc9
-rw-r--r--sql/mysql_priv.h19
-rw-r--r--sql/share/errmsg.txt2
-rw-r--r--sql/sp_head.cc241
-rw-r--r--sql/sp_head.h2
-rw-r--r--sql/sp_rcontext.cc13
-rw-r--r--sql/sp_rcontext.h8
-rw-r--r--sql/sql_base.cc163
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_insert.cc147
-rw-r--r--sql/sql_parse.cc3
-rw-r--r--sql/sql_table.cc99
-rw-r--r--sql/sql_yacc.yy38
63 files changed, 1723 insertions, 472 deletions
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 3b8f7576049..df819b73ea6 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -3700,6 +3700,37 @@ os_aio_posix_handle(
#endif
/**************************************************************************
+Do a 'last millisecond' check that the page end is sensible;
+reported page checksum errors from Linux seem to wipe over the page end. */
+static
+void
+os_file_check_page_trailers(
+/*========================*/
+ byte* combined_buf, /* in: combined write buffer */
+ ulint total_len) /* in: size of combined_buf, in bytes
+ (a multiple of UNIV_PAGE_SIZE) */
+{
+ ulint len;
+
+ for (len = 0; len + UNIV_PAGE_SIZE <= total_len;
+ len += UNIV_PAGE_SIZE) {
+ byte* buf = combined_buf + len;
+
+ if (memcmp(buf + (FIL_PAGE_LSN + 4), buf + (UNIV_PAGE_SIZE
+ - FIL_PAGE_END_LSN_OLD_CHKSUM + 4), 4)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: ERROR: The page to be written seems corrupt!\n"
+"InnoDB: Writing a block of %lu bytes, currently at offset %lu\n",
+ (ulong)total_len, (ulong)len);
+ buf_page_print(buf);
+ fprintf(stderr,
+"InnoDB: ERROR: The page to be written seems corrupt!\n");
+ }
+ }
+}
+
+/**************************************************************************
Does simulated aio. This function should be called by an i/o-handler
thread. */
@@ -3736,7 +3767,6 @@ os_aio_simulated_handle(
ibool ret;
ulint n;
ulint i;
- ulint len2;
segment = os_aio_get_array_and_local_segment(&array, global_segment);
@@ -3943,33 +3973,16 @@ consecutive_loop:
(ulong) total_len);
ut_error;
}
-
- /* Do a 'last millisecond' check that the page end
- is sensible; reported page checksum errors from
- Linux seem to wipe over the page end */
-
- for (len2 = 0; len2 + UNIV_PAGE_SIZE <= total_len;
- len2 += UNIV_PAGE_SIZE) {
- if (mach_read_from_4(combined_buf + len2
- + FIL_PAGE_LSN + 4)
- != mach_read_from_4(combined_buf + len2
- + UNIV_PAGE_SIZE
- - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: ERROR: The page to be written seems corrupt!\n");
- fprintf(stderr,
-"InnoDB: Writing a block of %lu bytes, currently writing at offset %lu\n",
- (ulong)total_len, (ulong)len2);
- buf_page_print(combined_buf + len2);
- fprintf(stderr,
-"InnoDB: ERROR: The page to be written seems corrupt!\n");
- }
- }
+
+ os_file_check_page_trailers(combined_buf, total_len);
}
-
+
ret = os_file_write(slot->name, slot->file, combined_buf,
slot->offset, slot->offset_high, total_len);
+
+ if (array == os_aio_write_array) {
+ os_file_check_page_trailers(combined_buf, total_len);
+ }
} else {
ret = os_file_read(slot->file, combined_buf,
slot->offset, slot->offset_high, total_len);
diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl
index 973655a3eb6..6fa6bc73bdb 100644
--- a/mysql-test/lib/mtr_process.pl
+++ b/mysql-test/lib/mtr_process.pl
@@ -20,6 +20,7 @@ sub mtr_record_dead_children ();
sub mtr_exit ($);
sub sleep_until_file_created ($$$);
sub mtr_kill_processes ($);
+sub mtr_kill_process ($$$$);
# static in C
sub spawn_impl ($$$$$$$$);
@@ -885,6 +886,25 @@ sub mtr_kill_processes ($) {
}
}
+
+sub mtr_kill_process ($$$$) {
+ my $pid= shift;
+ my $signal= shift;
+ my $retries= shift;
+ my $timeout= shift;
+
+ while (1)
+ {
+ kill($signal, $pid);
+
+ last unless kill (0, $pid) and $retries--;
+
+ mtr_debug("Sleep $timeout second waiting for processes to die");
+
+ sleep($timeout);
+ }
+}
+
##############################################################################
#
# When we exit, we kill off all children
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index e57a5da2c79..4a9628c0721 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -918,6 +918,7 @@ sub command_line_setup () {
path_err => "$opt_vardir/log/im.err",
path_log => "$opt_vardir/log/im.log",
path_pid => "$opt_vardir/run/im.pid",
+ path_angel_pid => "$opt_vardir/run/im.angel.pid",
path_sock => "$sockdir/im.sock",
port => $im_port,
start_timeout => $master->[0]->{'start_timeout'},
@@ -1188,6 +1189,7 @@ sub environment_setup () {
$ENV{'NDB_STATUS_OK'}= "YES";
$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_MYSQLD1_SOCK'}= $instance_manager->{instances}->[0]->{path_sock};
@@ -1813,6 +1815,7 @@ sub im_create_defaults_file($) {
[manager]
pid-file = $instance_manager->{path_pid}
+angel-pid-file = $instance_manager->{path_angel_pid}
socket = $instance_manager->{path_sock}
port = $instance_manager->{port}
password-file = $instance_manager->{password_file}
@@ -1837,7 +1840,7 @@ log-slow-queries = $instance->{path_datadir}/mysqld$server_id.slow.log
language = $path_language
character-sets-dir = $path_charsetsdir
basedir = $path_my_basedir
-server_id =$server_id
+server_id = $server_id
skip-stack-trace
skip-innodb
skip-bdb
@@ -2805,6 +2808,18 @@ sub im_start($$) {
sub im_stop($) {
my $instance_manager = shift;
+ # Obtain mysqld-process pids before we start stopping IM (it can delete pid
+ # files).
+
+ my @mysqld_pids = ();
+ my $instances = $instance_manager->{'instances'};
+
+ push(@mysqld_pids, mtr_get_pid_from_file($instances->[0]->{'path_pid'}))
+ if -r $instances->[0]->{'path_pid'};
+
+ push(@mysqld_pids, mtr_get_pid_from_file($instances->[1]->{'path_pid'}))
+ if -r $instances->[1]->{'path_pid'};
+
# Re-read pid from the file, since during tests Instance Manager could have
# been restarted, so its pid could have been changed.
@@ -2812,34 +2827,79 @@ sub im_stop($) {
mtr_get_pid_from_file($instance_manager->{'path_pid'})
if -f $instance_manager->{'path_pid'};
+ if (-f $instance_manager->{'path_angel_pid'})
+ {
+ $instance_manager->{'angel_pid'} =
+ mtr_get_pid_from_file($instance_manager->{'path_angel_pid'})
+ }
+ else
+ {
+ $instance_manager->{'angel_pid'} = undef;
+ }
+
# Inspired from mtr_stop_mysqld_servers().
start_reap_all();
- # Create list of pids. We should stop Instance Manager and all started
- # mysqld-instances. Some of them may be nonguarded, so IM will not stop them
- # on shutdown.
+ # Try graceful shutdown.
- my @pids = ( $instance_manager->{'pid'} );
- my $instances = $instance_manager->{'instances'};
+ mtr_kill_process($instance_manager->{'pid'}, 'TERM', 10, 1);
+
+ # Check that all processes died.
+
+ my $clean_shutdown= 0;
- if ( -r $instances->[0]->{'path_pid'} )
+ while (1)
{
- push(@pids, mtr_get_pid_from_file($instances->[0]->{'path_pid'}));
+ last if kill (0, $instance_manager->{'pid'});
+
+ last if (defined $instance_manager->{'angel_pid'}) &&
+ kill (0, $instance_manager->{'angel_pid'});
+
+ foreach my $pid (@mysqld_pids)
+ {
+ last if kill (0, $pid);
+ }
+
+ $clean_shutdown= 1;
+ last;
}
- if ( -r $instances->[1]->{'path_pid'} )
+ # Kill leftovers (the order is important).
+
+ unless ($clean_shutdown)
{
- push(@pids, mtr_get_pid_from_file($instances->[1]->{'path_pid'}));
- }
+ mtr_kill_process($instance_manager->{'angel_pid'}, 'KILL', 10, 1)
+ if defined $instance_manager->{'angel_pid'};
+
+ mtr_kill_process($instance_manager->{'pid'}, 'KILL', 10, 1);
- # Kill processes.
+ # Shutdown managed mysqld-processes. Some of them may be nonguarded, so IM
+ # will not stop them on shutdown. So, we should firstly try to end them
+ # legally.
+
+ mtr_kill_processes(\@mysqld_pids);
+
+ # Complain in error log so that a warning will be shown.
+
+ my $errlog= "$opt_vardir/log/mysql-test-run.pl.err";
+
+ open (ERRLOG, ">>$errlog") ||
+ mtr_error("Can not open error log ($errlog)");
+
+ my $ts= localtime();
+ print ERRLOG
+ "Warning: [$ts] Instance Manager did not shutdown gracefully.\n";
+
+ close ERRLOG;
+ }
- mtr_kill_processes(\@pids);
+ # That's all.
stop_reap_all();
$instance_manager->{'pid'} = undef;
+ $instance_manager->{'angel_pid'} = undef;
}
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index 8349d6e9338..cf358e6a404 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -103,8 +103,8 @@ t1 CREATE TABLE `t1` (
`c2` varchar(1) character set latin1 collate latin1_danish_ci NOT NULL default '',
`c3` varbinary(1) NOT NULL default '',
`c4` varbinary(1) NOT NULL default '',
- `c5` varbinary(3) NOT NULL default '',
- `c6` varbinary(3) NOT NULL default '',
+ `c5` varbinary(4) NOT NULL default '',
+ `c6` varbinary(4) NOT NULL default '',
`c7` decimal(2,1) NOT NULL default '0.0',
`c8` decimal(2,1) NOT NULL default '0.0',
`c9` decimal(2,1) default NULL,
@@ -152,11 +152,11 @@ SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`COALESCE(1)` int(1) NOT NULL default '0',
- `COALESCE(1.0)` decimal(2,1) unsigned NOT NULL default '0.0',
+ `COALESCE(1.0)` decimal(2,1) NOT NULL default '0.0',
`COALESCE('a')` varchar(1) NOT NULL default '',
`COALESCE(1,1.0)` decimal(2,1) NOT NULL default '0.0',
`COALESCE(1,'1')` varbinary(1) NOT NULL default '',
- `COALESCE(1.1,'1')` varbinary(3) NOT NULL default '',
+ `COALESCE(1.1,'1')` varbinary(4) NOT NULL default '',
`COALESCE('a' COLLATE latin1_bin,'b')` varchar(1) character set latin1 collate latin1_bin NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result
index d66dec741bd..75e1548cdee 100644
--- a/mysql-test/r/explain.result
+++ b/mysql-test/r/explain.result
@@ -53,3 +53,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ÔÁÂ ref ÉÎÄ0,ÉÎÄ01 ÉÎÄ0 5 const 1 Using where; Using index
drop table ÔÁÂ;
set names latin1;
+select 3 into @v1;
+explain select 3 into @v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
diff --git a/mysql-test/r/im_options_set.result b/mysql-test/r/im_options_set.result
index 0d2fa699fc7..5e6c740624e 100644
--- a/mysql-test/r/im_options_set.result
+++ b/mysql-test/r/im_options_set.result
@@ -1,11 +1,11 @@
-server_id =1
-server_id =2
+server_id = 1
+server_id = 2
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
SET mysqld1.server_id = 11;
server_id =11
-server_id =2
+server_id = 2
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
diff --git a/mysql-test/r/im_options_unset.result b/mysql-test/r/im_options_unset.result
index 834152c35d2..bf54025edb7 100644
--- a/mysql-test/r/im_options_unset.result
+++ b/mysql-test/r/im_options_unset.result
@@ -1,10 +1,10 @@
-server_id =1
-server_id =2
+server_id = 1
+server_id = 2
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
UNSET mysqld1.server_id;
-server_id =2
+server_id = 2
SHOW VARIABLES LIKE 'server_id';
Variable_name Value
server_id 1
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index 694bab2597c..712a60828f7 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -1154,3 +1154,25 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index PRIMARY,name name 23 NULL 3 Using where; Using index
1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using where; Using index
DROP TABLE t1,t2;
+DROP VIEW IF EXISTS v1,v2;
+DROP TABLE IF EXISTS t1,t2;
+CREATE TABLE t1 (a int);
+CREATE table t2 (b int);
+INSERT INTO t1 VALUES (1), (2), (3), (4), (1), (1), (3);
+INSERT INTO t2 VALUES (2), (3);
+CREATE VIEW v1 AS SELECT a FROM t1 JOIN t2 ON t1.a=t2.b;
+CREATE VIEW v2 AS SELECT b FROM t2 JOIN t1 ON t2.b=t1.a;
+SELECT v1.a, v2. b
+FROM v1 LEFT OUTER JOIN v2 ON (v1.a=v2.b) AND (v1.a >= 3)
+GROUP BY v1.a;
+a b
+2 NULL
+3 3
+SELECT v1.a, v2. b
+FROM { OJ v1 LEFT OUTER JOIN v2 ON (v1.a=v2.b) AND (v1.a >= 3) }
+GROUP BY v1.a;
+a b
+2 NULL
+3 3
+DROP VIEW v1,v2;
+DROP TABLE t1,t2;
diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result
index 0a170e16188..50b0b6ae294 100644
--- a/mysql-test/r/metadata.result
+++ b/mysql-test/r/metadata.result
@@ -2,7 +2,7 @@ drop table if exists t1,t2;
select 1, 1.0, -1, "hello", NULL;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def 1 8 1 1 N 32897 0 63
-def 1.0 246 3 3 N 161 1 63
+def 1.0 246 4 3 N 129 1 63
def -1 8 2 2 N 32897 0 63
def hello 253 5 5 N 1 31 8
def NULL 6 0 0 Y 32896 0 63
diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result
index 50e4cc28d93..664833fab2a 100644
--- a/mysql-test/r/mysqlbinlog.result
+++ b/mysql-test/r/mysqlbinlog.result
@@ -189,4 +189,5 @@ HEX(f)
select HEX(f) from t4;
HEX(f)
835C
+flush logs;
drop table t1, t2, t03, t04, t3, t4;
diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result
index 603de2afe4e..207d9ea7475 100644
--- a/mysql-test/r/ps_2myisam.result
+++ b/mysql-test/r/ps_2myisam.result
@@ -1777,7 +1777,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(2,1) unsigned NOT NULL default '0.0',
+ `const02` decimal(2,1) NOT NULL default '0.0',
`param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
@@ -1807,7 +1807,7 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 33 1 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result
index 9e635f60f14..13aa549949c 100644
--- a/mysql-test/r/ps_3innodb.result
+++ b/mysql-test/r/ps_3innodb.result
@@ -1760,7 +1760,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(2,1) unsigned NOT NULL default '0.0',
+ `const02` decimal(2,1) NOT NULL default '0.0',
`param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
@@ -1790,7 +1790,7 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 33 1 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result
index fd51c71cad6..a08dae945bd 100644
--- a/mysql-test/r/ps_4heap.result
+++ b/mysql-test/r/ps_4heap.result
@@ -1761,7 +1761,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(2,1) unsigned NOT NULL default '0.0',
+ `const02` decimal(2,1) NOT NULL default '0.0',
`param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
@@ -1791,7 +1791,7 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 33 1 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result
index 876f7615672..6682b085097 100644
--- a/mysql-test/r/ps_5merge.result
+++ b/mysql-test/r/ps_5merge.result
@@ -1697,7 +1697,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(2,1) unsigned NOT NULL default '0.0',
+ `const02` decimal(2,1) NOT NULL default '0.0',
`param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
@@ -1727,7 +1727,7 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 33 1 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
@@ -4711,7 +4711,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(2,1) unsigned NOT NULL default '0.0',
+ `const02` decimal(2,1) NOT NULL default '0.0',
`param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
@@ -4741,7 +4741,7 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 33 1 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result
index c39621d184f..dc3b984949d 100644
--- a/mysql-test/r/ps_6bdb.result
+++ b/mysql-test/r/ps_6bdb.result
@@ -1760,7 +1760,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(2,1) unsigned NOT NULL default '0.0',
+ `const02` decimal(2,1) NOT NULL default '0.0',
`param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
@@ -1790,7 +1790,7 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 33 1 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result
index 7c83099311e..000a20da655 100644
--- a/mysql-test/r/ps_7ndb.result
+++ b/mysql-test/r/ps_7ndb.result
@@ -1760,7 +1760,7 @@ Table Create Table
t5 CREATE TABLE `t5` (
`const01` bigint(1) NOT NULL default '0',
`param01` bigint(20) default NULL,
- `const02` decimal(2,1) unsigned NOT NULL default '0.0',
+ `const02` decimal(2,1) NOT NULL default '0.0',
`param02` decimal(65,30) default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
@@ -1790,7 +1790,7 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 8 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 3 3 N 33 1 63
+def test t5 t5 const02 const02 246 4 3 N 1 1 63
def test t5 t5 param02 param02 246 67 32 Y 0 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result
index da85ef5104d..751dc7754f7 100644
--- a/mysql-test/r/rpl_temporary.result
+++ b/mysql-test/r/rpl_temporary.result
@@ -103,15 +103,24 @@ f
1
drop temporary table t4;
drop table t5;
-set @session.pseudo_thread_id=100;
+set @@session.pseudo_thread_id=100;
create temporary table t101 (id int);
create temporary table t102 (id int);
-set @session.pseudo_thread_id=200;
+set @@session.pseudo_thread_id=200;
create temporary table t201 (id int);
-create temporary table `#not_user_table_prefixed_with_hash_sign_no_harm` (id int);
+create temporary table `t``201` (id int);
+create temporary table `#sql_not_user_table202` (id int);
+set @@session.pseudo_thread_id=300;
+create temporary table t301 (id int);
+create temporary table t302 (id int);
+create temporary table `#sql_not_user_table303` (id int);
create table t1(f int);
insert into t1 values (1);
select * from t1 /* must be 1 */;
f
1
drop table t1;
+select * from t1;
+a
+1
+drop table t1;
diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result
index b584e04ed57..60b956785ba 100644
--- a/mysql-test/r/rpl_until.result
+++ b/mysql-test/r/rpl_until.result
@@ -29,9 +29,40 @@ n
2
3
4
-show slave status;
-Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 319 # Master master-bin.000001 319 No #
+SHOW SLAVE STATUS;
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 776
+Relay_Log_File slave-relay-bin.000004
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running #
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 319
+Relay_Log_Space #
+Until_Condition Master
+Until_Log_File master-bin.000001
+Until_Log_Pos 319
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291;
select * from t1;
n
@@ -39,23 +70,116 @@ n
2
3
4
-show slave status;
-Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 319 # Master master-no-such-bin.000001 291 No #
+SHOW SLAVE STATUS;
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 776
+Relay_Log_File slave-relay-bin.000004
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running #
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 319
+Relay_Log_Space #
+Until_Condition Master
+Until_Log_File master-no-such-bin.000001
+Until_Log_Pos 291
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746;
select * from t2;
n
1
2
-show slave status;
-Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 608 # Relay slave-relay-bin.000004 746 No #
+SHOW SLAVE STATUS;
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 776
+Relay_Log_File slave-relay-bin.000004
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running #
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 608
+Relay_Log_Space #
+Until_Condition Relay
+Until_Log_File slave-relay-bin.000004
+Until_Log_Pos 746
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
start slave;
stop slave;
start slave until master_log_file='master-bin.000001', master_log_pos=776;
-show slave status;
-Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
-# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 776 # Master master-bin.000001 776 No #
+SHOW SLAVE STATUS;
+Slave_IO_State #
+Master_Host 127.0.0.1
+Master_User root
+Master_Port MASTER_MYPORT
+Connect_Retry 1
+Master_Log_File master-bin.000001
+Read_Master_Log_Pos 776
+Relay_Log_File slave-relay-bin.000004
+Relay_Log_Pos #
+Relay_Master_Log_File master-bin.000001
+Slave_IO_Running Yes
+Slave_SQL_Running No
+Replicate_Do_DB
+Replicate_Ignore_DB
+Replicate_Do_Table
+Replicate_Ignore_Table
+Replicate_Wild_Do_Table
+Replicate_Wild_Ignore_Table
+Last_Errno 0
+Last_Error
+Skip_Counter 0
+Exec_Master_Log_Pos 776
+Relay_Log_Space #
+Until_Condition Master
+Until_Log_File master-bin.000001
+Until_Log_Pos 776
+Master_SSL_Allowed No
+Master_SSL_CA_File
+Master_SSL_CA_Path
+Master_SSL_Cert
+Master_SSL_Cipher
+Master_SSL_Key
+Seconds_Behind_Master #
start slave until master_log_file='master-bin', master_log_pos=561;
ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL
start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12;
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index a49b282ddb7..924963017eb 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -282,9 +282,9 @@ select @tmp_x, @tmp_y, @tmp_z|
@tmp_x @tmp_y @tmp_z
42 45 87
call p(42, 43, @tmp_z)|
-ERROR 42000: OUT or INOUT argument 2 for routine test.p is not a variable
+ERROR 42000: OUT or INOUT argument 2 for routine test.p is not a variable or NEW pseudo-variable in BEFORE trigger
call p(42, @tmp_y, 43)|
-ERROR 42000: OUT or INOUT argument 3 for routine test.p is not a variable
+ERROR 42000: OUT or INOUT argument 3 for routine test.p is not a variable or NEW pseudo-variable in BEFORE trigger
drop procedure p|
create procedure p() begin end|
lock table t1 read|
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 59ce1d13d2b..746cd8f00d4 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -4904,4 +4904,60 @@ schema_name
select routine_name,routine_schema from information_schema.routines where
routine_schema like 'bug18344%'|
routine_name routine_schema
+drop function if exists bug12472|
+create function bug12472() returns int return (select count(*) from t1)|
+create table t3 as select bug12472() as i|
+show create table t3|
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `i` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t3|
+i
+0
+drop table t3|
+create view v1 as select bug12472() as j|
+create table t3 as select * from v1|
+show create table t3|
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `j` bigint(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t3|
+j
+0
+drop table t3|
+drop view v1|
+drop function bug12472|
+DROP FUNCTION IF EXISTS bug18589_f1|
+DROP PROCEDURE IF EXISTS bug18589_p1|
+DROP PROCEDURE IF EXISTS bug18589_p2|
+CREATE FUNCTION bug18589_f1(arg TEXT) RETURNS TEXT
+BEGIN
+RETURN CONCAT(arg, "");
+END|
+CREATE PROCEDURE bug18589_p1(arg TEXT, OUT ret TEXT)
+BEGIN
+SET ret = CONCAT(arg, "");
+END|
+CREATE PROCEDURE bug18589_p2(arg TEXT)
+BEGIN
+DECLARE v TEXT;
+CALL bug18589_p1(arg, v);
+SELECT v;
+END|
+SELECT bug18589_f1(REPEAT("a", 767))|
+bug18589_f1(REPEAT("a", 767))
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+SET @bug18589_v1 = ""|
+CALL bug18589_p1(REPEAT("a", 767), @bug18589_v1)|
+SELECT @bug18589_v1|
+@bug18589_v1
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+CALL bug18589_p2(REPEAT("a", 767))|
+v
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+DROP FUNCTION bug18589_f1|
+DROP PROCEDURE bug18589_p1|
+DROP PROCEDURE bug18589_p2|
drop table t1,t2;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index e3d65882f81..39cb95be9e1 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -3169,3 +3169,11 @@ create table t2 (a int, b int);
insert into t2 values (2, 1), (1, 0);
delete from t1 where c <= 1140006215 and (select b from t2 where a = 2) = 1;
drop table t1, t2;
+CREATE TABLE t1 (a INT);
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE no_such_column = ANY (SELECT 1);
+ERROR 42S22: Unknown column 'no_such_column' in 'where clause'
+CREATE VIEW v2 AS SELECT * FROM t1 WHERE no_such_column = (SELECT 1);
+ERROR 42S22: Unknown column 'no_such_column' in 'where clause'
+SELECT * FROM t1 WHERE no_such_column = ANY (SELECT 1);
+ERROR 42S22: Unknown column 'no_such_column' in 'IN/ALL/ANY subquery'
+DROP TABLE t1;
diff --git a/mysql-test/r/trigger-grant.result b/mysql-test/r/trigger-grant.result
index 87e5e11d779..f6384d479b7 100644
--- a/mysql-test/r/trigger-grant.result
+++ b/mysql-test/r/trigger-grant.result
@@ -310,3 +310,87 @@ SELECT @mysqltest_var;
Hello, world!
DROP USER mysqltest_u1@localhost;
DROP DATABASE mysqltest_db1;
+DELETE FROM mysql.user WHERE User LIKE 'mysqltest_%';
+DELETE FROM mysql.db WHERE User LIKE 'mysqltest_%';
+DELETE FROM mysql.tables_priv WHERE User LIKE 'mysqltest_%';
+DELETE FROM mysql.columns_priv WHERE User LIKE 'mysqltest_%';
+FLUSH PRIVILEGES;
+DROP DATABASE IF EXISTS mysqltest_db1;
+CREATE DATABASE mysqltest_db1;
+USE mysqltest_db1;
+CREATE TABLE t1 (i1 INT);
+CREATE TABLE t2 (i1 INT);
+CREATE USER mysqltest_dfn@localhost;
+CREATE USER mysqltest_inv@localhost;
+GRANT EXECUTE, CREATE ROUTINE, SUPER ON *.* TO mysqltest_dfn@localhost;
+GRANT INSERT ON mysqltest_db1.* TO mysqltest_inv@localhost;
+CREATE PROCEDURE p1(OUT i INT) DETERMINISTIC NO SQL SET i = 3;
+CREATE PROCEDURE p2(INOUT i INT) DETERMINISTIC NO SQL SET i = i * 5;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+CALL p2(NEW.i1);
+INSERT INTO t1 VALUES (7);
+ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't1'
+INSERT INTO t2 VALUES (11);
+ERROR 42000: SELECT,UPDATE command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't2'
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+GRANT SELECT ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+CALL p2(NEW.i1);
+INSERT INTO t1 VALUES (13);
+ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't1'
+INSERT INTO t2 VALUES (17);
+ERROR 42000: UPDATE command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't2'
+REVOKE SELECT ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+GRANT UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+CALL p2(NEW.i1);
+INSERT INTO t1 VALUES (19);
+INSERT INTO t2 VALUES (23);
+ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't2'
+REVOKE UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+GRANT SELECT, UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+CALL p2(NEW.i1);
+INSERT INTO t1 VALUES (29);
+INSERT INTO t2 VALUES (31);
+REVOKE SELECT, UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+GRANT UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+CREATE PROCEDURE p1(OUT i INT) DETERMINISTIC NO SQL SET i = 37;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+INSERT INTO t1 VALUES (41);
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1(IN i INT) DETERMINISTIC NO SQL SET @v1 = i + 43;
+INSERT INTO t1 VALUES (47);
+ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't1'
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1(INOUT i INT) DETERMINISTIC NO SQL SET i = i + 51;
+INSERT INTO t1 VALUES (53);
+ERROR 42000: SELECT command denied to user 'mysqltest_dfn'@'localhost' for column 'i1' in table 't1'
+DROP PROCEDURE p1;
+REVOKE UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+DROP TRIGGER t1_bi;
+DROP USER mysqltest_inv@localhost;
+DROP USER mysqltest_dfn@localhost;
+DROP TABLE t2;
+DROP TABLE t1;
+DROP DATABASE mysqltest_db1;
+USE test;
+End of 5.0 tests.
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 6a689437482..8b4aba367fb 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -998,3 +998,95 @@ SELECT * FROM t1 WHERE conn_id != trigger_conn_id;
conn_id trigger_conn_id
DROP TRIGGER t1_bi;
DROP TABLE t1;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (i1 INT);
+SET @save_sql_mode=@@sql_mode;
+SET SQL_MODE='';
+CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW
+SET @x = 5/0;
+SET SQL_MODE='traditional';
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW
+SET @x = 5/0;
+SET @x=1;
+INSERT INTO t1 VALUES (@x);
+SELECT @x;
+@x
+NULL
+SET @x=2;
+UPDATE t1 SET i1 = @x;
+ERROR 22012: Division by 0
+SELECT @x;
+@x
+2
+SET SQL_MODE='';
+SET @x=3;
+INSERT INTO t1 VALUES (@x);
+SELECT @x;
+@x
+NULL
+SET @x=4;
+UPDATE t1 SET i1 = @x;
+ERROR 22012: Division by 0
+SELECT @x;
+@x
+4
+SET @@sql_mode=@save_sql_mode;
+DROP TRIGGER t1_ai;
+DROP TRIGGER t1_au;
+DROP TABLE t1;
+DROP TABLE IF EXISTS t1;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+CREATE TABLE t1 (i1 INT);
+INSERT INTO t1 VALUES (3);
+CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET i1 = 5;
+CREATE PROCEDURE p2(INOUT i1 INT) DETERMINISTIC NO SQL SET i1 = i1 * 7;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+BEGIN
+CALL p1(NEW.i1);
+CALL p2(NEW.i1);
+END//
+UPDATE t1 SET i1 = 11 WHERE i1 = 3;
+DROP TRIGGER t1_bu;
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+INSERT INTO t1 VALUES (13);
+CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 17;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+CALL p1(OLD.i1);
+UPDATE t1 SET i1 = 19 WHERE i1 = 13;
+ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger
+DROP TRIGGER t1_bu;
+DROP PROCEDURE p1;
+INSERT INTO t1 VALUES (23);
+CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 29;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+CALL p1(OLD.i1);
+UPDATE t1 SET i1 = 31 WHERE i1 = 23;
+ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger
+DROP TRIGGER t1_bu;
+DROP PROCEDURE p1;
+INSERT INTO t1 VALUES (37);
+CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 41;
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+UPDATE t1 SET i1 = 43 WHERE i1 = 37;
+ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger
+DROP TRIGGER t1_au;
+DROP PROCEDURE p1;
+INSERT INTO t1 VALUES (47);
+CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 49;
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW
+CALL p1(NEW.i1);
+UPDATE t1 SET i1 = 51 WHERE i1 = 47;
+ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger
+DROP TRIGGER t1_au;
+DROP PROCEDURE p1;
+SELECT * FROM t1;
+i1
+35
+13
+23
+43
+51
+DROP TABLE t1;
diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result
index e941e740fcb..61482ab282c 100644
--- a/mysql-test/r/type_float.result
+++ b/mysql-test/r/type_float.result
@@ -245,22 +245,22 @@ show warnings;
Level Code Message
desc t1;
Field Type Null Key Default Extra
-x decimal(21,2) unsigned NO 0.00
+x decimal(21,2) NO 0.00
drop table t1;
create table t1 select 0.0 x;
desc t1;
Field Type Null Key Default Extra
-x decimal(2,1) unsigned NO 0.0
+x decimal(2,1) NO 0.0
create table t2 select 105213674794682365.00 y;
desc t2;
Field Type Null Key Default Extra
-y decimal(20,2) unsigned NO 0.00
+y decimal(20,2) NO 0.00
create table t3 select x+y a from t1,t2;
show warnings;
Level Code Message
desc t3;
Field Type Null Key Default Extra
-a decimal(21,2) unsigned NO 0.00
+a decimal(21,2) NO 0.00
drop table t1,t2,t3;
create table t1 (s1 float(0,2));
ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1').
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
index 938dccc864c..968c6d3ec6f 100644
--- a/mysql-test/r/type_newdecimal.result
+++ b/mysql-test/r/type_newdecimal.result
@@ -68,10 +68,10 @@ NULL 1.1 NULL NULL NULL 1
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `nullif(1.1, 1.1)` decimal(2,1) unsigned default NULL,
- `nullif(1.1, 1.2)` decimal(2,1) unsigned default NULL,
- `nullif(1.1, 0.11e1)` decimal(2,1) unsigned default NULL,
- `nullif(1.0, 1)` decimal(2,1) unsigned default NULL,
+ `nullif(1.1, 1.1)` decimal(2,1) default NULL,
+ `nullif(1.1, 1.2)` decimal(2,1) default NULL,
+ `nullif(1.1, 0.11e1)` decimal(2,1) default NULL,
+ `nullif(1.0, 1)` decimal(2,1) default NULL,
`nullif(1, 1.0)` int(1) default NULL,
`nullif(1, 1.1)` int(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@@ -174,9 +174,9 @@ create table t1 select round(15.4,-1), truncate(-5678.123451,-3), abs(-1.1), -(-
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `round(15.4,-1)` decimal(3,0) unsigned NOT NULL default '0',
+ `round(15.4,-1)` decimal(3,0) NOT NULL default '0',
`truncate(-5678.123451,-3)` decimal(4,0) NOT NULL default '0',
- `abs(-1.1)` decimal(2,1) NOT NULL default '0.0',
+ `abs(-1.1)` decimal(3,1) NOT NULL default '0.0',
`-(-1.1)` decimal(2,1) NOT NULL default '0.0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
@@ -771,7 +771,7 @@ create table t1 as select 0.5;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `0.5` decimal(2,1) unsigned NOT NULL default '0.0'
+ `0.5` decimal(2,1) NOT NULL default '0.0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select round(1.5),round(2.5);
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 667d10cd145..4baa56070b7 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -706,7 +706,7 @@ create view v1 as select a from t1;
create view v2 as select a from t2 where a in (select a from v1);
show create view v2;
View Create View
-v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a` from `t2` where `a` in (select `v1`.`a` AS `a` from `v1`)
+v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `t2`.`a` AS `a` from `t2` where `t2`.`a` in (select `v1`.`a` AS `a` from `v1`)
drop view v2, v1;
drop table t1, t2;
CREATE VIEW `v 1` AS select 5 AS `5`;
@@ -2649,3 +2649,14 @@ ldt
2006-01-01 03:00:00
drop view v1, v2;
drop table t1;
+CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, d datetime);
+CREATE VIEW v1 AS
+SELECT id, date(d) + INTERVAL TIME_TO_SEC(d) SECOND AS t, COUNT(*)
+FROM t1 GROUP BY id, t;
+SHOW CREATE VIEW v1;
+View Create View
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`id` AS `id`,(cast(`t1`.`d` as date) + interval time_to_sec(`t1`.`d`) second) AS `t`,count(0) AS `COUNT(*)` from `t1` group by `t1`.`id`,(cast(`t1`.`d` as date) + interval time_to_sec(`t1`.`d`) second)
+SELECT * FROM v1;
+id t COUNT(*)
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/t/explain.test b/mysql-test/t/explain.test
index 2a3a23c5f96..a38771db233 100644
--- a/mysql-test/t/explain.test
+++ b/mysql-test/t/explain.test
@@ -43,3 +43,12 @@ drop table ÔÁÂ;
set names latin1;
# End of 4.1 tests
+
+
+#
+# Bug#15463: EXPLAIN SELECT..INTO hangs the client (QB, command line)
+#
+select 3 into @v1;
+explain select 3 into @v1;
+
+# End of 5.0 tests.
diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test
index c194213e0c9..7134137a430 100644
--- a/mysql-test/t/join_outer.test
+++ b/mysql-test/t/join_outer.test
@@ -779,3 +779,29 @@ SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id
WHERE t1.name LIKE 'A%' OR FALSE;
DROP TABLE t1,t2;
+
+#
+# Bug 19396: LEFT OUTER JOIN over views in curly braces
+#
+--disable_warnings
+DROP VIEW IF EXISTS v1,v2;
+DROP TABLE IF EXISTS t1,t2;
+--enable_warnings
+
+CREATE TABLE t1 (a int);
+CREATE table t2 (b int);
+INSERT INTO t1 VALUES (1), (2), (3), (4), (1), (1), (3);
+INSERT INTO t2 VALUES (2), (3);
+
+CREATE VIEW v1 AS SELECT a FROM t1 JOIN t2 ON t1.a=t2.b;
+CREATE VIEW v2 AS SELECT b FROM t2 JOIN t1 ON t2.b=t1.a;
+
+SELECT v1.a, v2. b
+ FROM v1 LEFT OUTER JOIN v2 ON (v1.a=v2.b) AND (v1.a >= 3)
+ GROUP BY v1.a;
+SELECT v1.a, v2. b
+ FROM { OJ v1 LEFT OUTER JOIN v2 ON (v1.a=v2.b) AND (v1.a >= 3) }
+ GROUP BY v1.a;
+
+DROP VIEW v1,v2;
+DROP TABLE t1,t2;
diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test
index 28074fba7e4..d74bb1c3a80 100644
--- a/mysql-test/t/mysqlbinlog.test
+++ b/mysql-test/t/mysqlbinlog.test
@@ -122,9 +122,22 @@ select HEX(f) from t3;
select HEX(f) from t04;
select HEX(f) from t4;
+#
+# BUG#14157: utf8 encoding in binlog without set character_set_client
+#
+# BUG:
+# This test only works on the MySQL-internal rpl machines.
+# Needs to be fixed. Problem is that koi8r is not installed
+# on many machines.
+#
+flush logs;
+# --exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table if not exists t5 (a int); set names koi8r; create temporary table `ÑÝÉË` (a int); insert into `ÑÝÉË` values (1); insert into t5 select * from `ÑÝÉË`'
+# resulted log is client charset insensitive (latin1 not koi8r) as it must be
+# --exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000006 | $MYSQL --default-character-set=latin1
+#select * from t5 /* must be (1),(1) */;
# clean up
drop table t1, t2, t03, t04, t3, t4;
-# End of 4.1 tests
+# End of 5.0 tests
diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test
index 5caecef176e..86e4b6eed0a 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;
+disconnect con2;
+disconnect con1;
+connection default;
+
# End of 4.1 tests
diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test
index 7d2222ea79a..51a195e3d0e 100644
--- a/mysql-test/t/rpl_temporary.test
+++ b/mysql-test/t/rpl_temporary.test
@@ -163,24 +163,19 @@ drop table t5;
# value was set up at the moment of temp table creation
#
connection con1;
-set @session.pseudo_thread_id=100;
+set @@session.pseudo_thread_id=100;
create temporary table t101 (id int);
create temporary table t102 (id int);
-set @session.pseudo_thread_id=200;
+set @@session.pseudo_thread_id=200;
create temporary table t201 (id int);
-create temporary table `#not_user_table_prefixed_with_hash_sign_no_harm` (id int);
-
-#
-# Don't kill our own connection to the server as
-# the result code differs depending on platform.
-#
-# Select the id to kill into a variable of mysqltest
-let $con1_id= `select connection_id()`;
-# Switch connection to avoid killing our own connection
-connection master;
---disable_query_log
-eval kill $con1_id;
---enable_query_log
+create temporary table `t``201` (id int);
+# emulate internal temp table not to come to binlog
+create temporary table `#sql_not_user_table202` (id int);
+set @@session.pseudo_thread_id=300;
+create temporary table t301 (id int);
+create temporary table t302 (id int);
+create temporary table `#sql_not_user_table303` (id int);
+disconnect con1;
#now do something to show that slave is ok after DROP temp tables
connection master;
@@ -194,4 +189,16 @@ select * from t1 /* must be 1 */;
connection master;
drop table t1;
+#
+#14157: utf8 encoding in binlog without set character_set_client
+#
+--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table t1 (a int); set names koi8r; create temporary table `ÑÝÉË` (a int); insert into `ÑÝÉË` values (1); insert into t1 select * from `ÑÝÉË`'
+
+sync_slave_with_master;
+#connection slave;
+select * from t1;
+
+connection master;
+drop table t1;
+
# End of 5.0 tests
diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test
index e0ecf981fea..c404ea7e58b 100644
--- a/mysql-test/t/rpl_until.test
+++ b/mysql-test/t/rpl_until.test
@@ -31,7 +31,7 @@ wait_for_slave_to_stop;
select * from t1;
--replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 11 # 23 # 33 #
-show slave status;
+--query_vertical SHOW SLAVE STATUS
# this should fail right after start
start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291;
@@ -41,7 +41,7 @@ sleep 2;
wait_for_slave_to_stop;
--replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 11 # 23 # 33 #
-show slave status;
+--query_vertical SHOW SLAVE STATUS
# try replicate all until second insert to t2;
start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746;
@@ -50,7 +50,7 @@ wait_for_slave_to_stop;
select * from t2;
--replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 11 # 23 # 33 #
-show slave status;
+--query_vertical SHOW SLAVE STATUS
# clean up
start slave;
@@ -67,7 +67,7 @@ wait_for_slave_to_stop;
# here the sql slave thread should be stopped
--replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004
--replace_column 1 # 9 # 23 # 33 #
-show slave status;
+--query_vertical SHOW SLAVE STATUS
#testing various error conditions
--error 1277
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 22500bbd280..9995ff5a9ad 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -5774,6 +5774,76 @@ select routine_name,routine_schema from information_schema.routines where
#
+# BUG#12472/BUG#15137 'CREATE TABLE ... SELECT ... which explicitly or
+# implicitly uses stored function gives "Table not locked" error'.
+#
+--disable_warnings
+drop function if exists bug12472|
+--enable_warnings
+create function bug12472() returns int return (select count(*) from t1)|
+# Check case when function is used directly
+create table t3 as select bug12472() as i|
+show create table t3|
+select * from t3|
+drop table t3|
+# Check case when function is used indirectly through view
+create view v1 as select bug12472() as j|
+create table t3 as select * from v1|
+show create table t3|
+select * from t3|
+drop table t3|
+drop view v1|
+drop function bug12472|
+
+
+#
+# BUG#18587: Function that accepts and returns TEXT garbles data if longer than
+# 766 chars
+#
+
+# Prepare.
+
+--disable_warnings
+DROP FUNCTION IF EXISTS bug18589_f1|
+DROP PROCEDURE IF EXISTS bug18589_p1|
+DROP PROCEDURE IF EXISTS bug18589_p2|
+--enable_warnings
+
+CREATE FUNCTION bug18589_f1(arg TEXT) RETURNS TEXT
+BEGIN
+ RETURN CONCAT(arg, "");
+END|
+
+CREATE PROCEDURE bug18589_p1(arg TEXT, OUT ret TEXT)
+BEGIN
+ SET ret = CONCAT(arg, "");
+END|
+
+CREATE PROCEDURE bug18589_p2(arg TEXT)
+BEGIN
+ DECLARE v TEXT;
+ CALL bug18589_p1(arg, v);
+ SELECT v;
+END|
+
+# Test case.
+
+SELECT bug18589_f1(REPEAT("a", 767))|
+
+SET @bug18589_v1 = ""|
+CALL bug18589_p1(REPEAT("a", 767), @bug18589_v1)|
+SELECT @bug18589_v1|
+
+CALL bug18589_p2(REPEAT("a", 767))|
+
+# Cleanup.
+
+DROP FUNCTION bug18589_f1|
+DROP PROCEDURE bug18589_p1|
+DROP PROCEDURE bug18589_p2|
+
+
+#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 1ef80bdd7ac..9f4d89a7e50 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -2085,3 +2085,18 @@ create table t2 (a int, b int);
insert into t2 values (2, 1), (1, 0);
delete from t1 where c <= 1140006215 and (select b from t2 where a = 2) = 1;
drop table t1, t2;
+
+#
+# Bug #7549: Missing error message for invalid view selection with subquery
+#
+
+CREATE TABLE t1 (a INT);
+
+--error 1054
+CREATE VIEW v1 AS SELECT * FROM t1 WHERE no_such_column = ANY (SELECT 1);
+--error 1054
+CREATE VIEW v2 AS SELECT * FROM t1 WHERE no_such_column = (SELECT 1);
+--error 1054
+SELECT * FROM t1 WHERE no_such_column = ANY (SELECT 1);
+
+DROP TABLE t1;
diff --git a/mysql-test/t/trigger-grant.test b/mysql-test/t/trigger-grant.test
index 7a3f7a9fa94..12b929898a8 100644
--- a/mysql-test/t/trigger-grant.test
+++ b/mysql-test/t/trigger-grant.test
@@ -564,3 +564,176 @@ SELECT @mysqltest_var;
DROP USER mysqltest_u1@localhost;
DROP DATABASE mysqltest_db1;
+
+
+#
+# Test for bug #14635 Accept NEW.x as INOUT parameters to stored
+# procedures from within triggers
+#
+# We require UPDATE privilege when NEW.x passed as OUT parameter, and
+# SELECT and UPDATE when NEW.x passed as INOUT parameter.
+#
+DELETE FROM mysql.user WHERE User LIKE 'mysqltest_%';
+DELETE FROM mysql.db WHERE User LIKE 'mysqltest_%';
+DELETE FROM mysql.tables_priv WHERE User LIKE 'mysqltest_%';
+DELETE FROM mysql.columns_priv WHERE User LIKE 'mysqltest_%';
+FLUSH PRIVILEGES;
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest_db1;
+--enable_warnings
+
+CREATE DATABASE mysqltest_db1;
+USE mysqltest_db1;
+
+CREATE TABLE t1 (i1 INT);
+CREATE TABLE t2 (i1 INT);
+
+CREATE USER mysqltest_dfn@localhost;
+CREATE USER mysqltest_inv@localhost;
+
+GRANT EXECUTE, CREATE ROUTINE, SUPER ON *.* TO mysqltest_dfn@localhost;
+GRANT INSERT ON mysqltest_db1.* TO mysqltest_inv@localhost;
+
+connect (definer,localhost,mysqltest_dfn,,mysqltest_db1);
+connect (invoker,localhost,mysqltest_inv,,mysqltest_db1);
+
+connection definer;
+CREATE PROCEDURE p1(OUT i INT) DETERMINISTIC NO SQL SET i = 3;
+CREATE PROCEDURE p2(INOUT i INT) DETERMINISTIC NO SQL SET i = i * 5;
+
+# Check that having no privilege won't work.
+connection definer;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+ CALL p2(NEW.i1);
+
+connection invoker;
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t1 VALUES (7);
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t2 VALUES (11);
+
+connection definer;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+
+# Check that having only SELECT privilege is not enough.
+connection default;
+GRANT SELECT ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+
+connection definer;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+ CALL p2(NEW.i1);
+
+connection invoker;
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t1 VALUES (13);
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t2 VALUES (17);
+
+connection default;
+REVOKE SELECT ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+
+connection definer;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+
+# Check that having only UPDATE privilege is enough for OUT parameter,
+# but not for INOUT parameter.
+connection default;
+GRANT UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+
+connection definer;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+ CALL p2(NEW.i1);
+
+connection invoker;
+INSERT INTO t1 VALUES (19);
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t2 VALUES (23);
+
+connection default;
+REVOKE UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+
+connection definer;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+
+# Check that having SELECT and UPDATE privileges is enough.
+connection default;
+GRANT SELECT, UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+
+connection definer;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+CREATE TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW
+ CALL p2(NEW.i1);
+
+connection invoker;
+INSERT INTO t1 VALUES (29);
+INSERT INTO t2 VALUES (31);
+
+connection default;
+REVOKE SELECT, UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+
+connection definer;
+DROP TRIGGER t2_bi;
+DROP TRIGGER t1_bi;
+
+connection default;
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+
+# Check that late procedure redefining won't open a security hole.
+connection default;
+GRANT UPDATE ON mysqltest_db1.* TO mysqltest_dfn@localhost;
+
+connection definer;
+CREATE PROCEDURE p1(OUT i INT) DETERMINISTIC NO SQL SET i = 37;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+
+connection invoker;
+INSERT INTO t1 VALUES (41);
+
+connection definer;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1(IN i INT) DETERMINISTIC NO SQL SET @v1 = i + 43;
+
+connection invoker;
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t1 VALUES (47);
+
+connection definer;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1(INOUT i INT) DETERMINISTIC NO SQL SET i = i + 51;
+
+connection invoker;
+--error ER_COLUMNACCESS_DENIED_ERROR
+INSERT INTO t1 VALUES (53);
+
+connection default;
+DROP PROCEDURE p1;
+REVOKE UPDATE ON mysqltest_db1.* FROM mysqltest_dfn@localhost;
+
+connection definer;
+DROP TRIGGER t1_bi;
+
+# Cleanup.
+disconnect definer;
+disconnect invoker;
+connection default;
+DROP USER mysqltest_inv@localhost;
+DROP USER mysqltest_dfn@localhost;
+DROP TABLE t2;
+DROP TABLE t1;
+DROP DATABASE mysqltest_db1;
+USE test;
+
+--echo End of 5.0 tests.
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index 00c85a650d1..a5bd2ba0b38 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -1165,4 +1165,126 @@ SELECT * FROM t1 WHERE conn_id != trigger_conn_id;
DROP TRIGGER t1_bi;
DROP TABLE t1;
+
+#
+# Bug#6951: Triggers/Traditional: SET @ result wrong
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (i1 INT);
+
+SET @save_sql_mode=@@sql_mode;
+
+SET SQL_MODE='';
+
+CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW
+ SET @x = 5/0;
+
+SET SQL_MODE='traditional';
+
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW
+ SET @x = 5/0;
+
+SET @x=1;
+INSERT INTO t1 VALUES (@x);
+SELECT @x;
+
+SET @x=2;
+--error 1365
+UPDATE t1 SET i1 = @x;
+SELECT @x;
+
+SET SQL_MODE='';
+
+SET @x=3;
+INSERT INTO t1 VALUES (@x);
+SELECT @x;
+
+SET @x=4;
+--error 1365
+UPDATE t1 SET i1 = @x;
+SELECT @x;
+
+SET @@sql_mode=@save_sql_mode;
+
+DROP TRIGGER t1_ai;
+DROP TRIGGER t1_au;
+DROP TABLE t1;
+
+
+#
+# Test for bug #14635 Accept NEW.x as INOUT parameters to stored
+# procedures from within triggers
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+--enable_warnings
+
+CREATE TABLE t1 (i1 INT);
+
+# Check that NEW.x pseudo variable is accepted as INOUT and OUT
+# parameter to stored routine.
+INSERT INTO t1 VALUES (3);
+CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET i1 = 5;
+CREATE PROCEDURE p2(INOUT i1 INT) DETERMINISTIC NO SQL SET i1 = i1 * 7;
+delimiter //;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+BEGIN
+ CALL p1(NEW.i1);
+ CALL p2(NEW.i1);
+END//
+delimiter ;//
+UPDATE t1 SET i1 = 11 WHERE i1 = 3;
+DROP TRIGGER t1_bu;
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+
+# Check that OLD.x pseudo variable is not accepted as INOUT and OUT
+# parameter to stored routine.
+INSERT INTO t1 VALUES (13);
+CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 17;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+ CALL p1(OLD.i1);
+--error ER_SP_NOT_VAR_ARG
+UPDATE t1 SET i1 = 19 WHERE i1 = 13;
+DROP TRIGGER t1_bu;
+DROP PROCEDURE p1;
+
+INSERT INTO t1 VALUES (23);
+CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 29;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+ CALL p1(OLD.i1);
+--error ER_SP_NOT_VAR_ARG
+UPDATE t1 SET i1 = 31 WHERE i1 = 23;
+DROP TRIGGER t1_bu;
+DROP PROCEDURE p1;
+
+# Check that NEW.x pseudo variable is read-only in the AFTER TRIGGER.
+INSERT INTO t1 VALUES (37);
+CREATE PROCEDURE p1(OUT i1 INT) DETERMINISTIC NO SQL SET @a = 41;
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+--error ER_SP_NOT_VAR_ARG
+UPDATE t1 SET i1 = 43 WHERE i1 = 37;
+DROP TRIGGER t1_au;
+DROP PROCEDURE p1;
+
+INSERT INTO t1 VALUES (47);
+CREATE PROCEDURE p1(INOUT i1 INT) DETERMINISTIC NO SQL SET @a = i1 * 49;
+CREATE TRIGGER t1_au AFTER UPDATE ON t1 FOR EACH ROW
+ CALL p1(NEW.i1);
+--error ER_SP_NOT_VAR_ARG
+UPDATE t1 SET i1 = 51 WHERE i1 = 47;
+DROP TRIGGER t1_au;
+DROP PROCEDURE p1;
+
+# Post requisite.
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
# End of 5.0 tests
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index 8f759c2d43e..ea22ada900a 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -2512,3 +2512,19 @@ create view v2 as select convert_tz(dt, 'UTC', 'Europe/Moscow') as ldt from v1;
select * from v2;
drop view v1, v2;
drop table t1;
+
+#
+# Bug #19490: usage of view specified by a query with GROUP BY
+# an expression containing non-constant interval
+
+CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, d datetime);
+
+CREATE VIEW v1 AS
+SELECT id, date(d) + INTERVAL TIME_TO_SEC(d) SECOND AS t, COUNT(*)
+ FROM t1 GROUP BY id, t;
+
+SHOW CREATE VIEW v1;
+SELECT * FROM v1;
+
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc
index 95f9029f648..90d9d04cd36 100644
--- a/server-tools/instance-manager/manager.cc
+++ b/server-tools/instance-manager/manager.cc
@@ -35,12 +35,12 @@
#endif
-static int create_pid_file(const char *pid_file_name)
+int create_pid_file(const char *pid_file_name, int pid)
{
if (FILE *pid_file= my_fopen(pid_file_name,
O_WRONLY | O_CREAT | O_BINARY, MYF(0)))
{
- fprintf(pid_file, "%d\n", (int) getpid());
+ fprintf(pid_file, "%d\n", (int) pid);
my_fclose(pid_file, MYF(0));
return 0;
}
@@ -138,8 +138,13 @@ void manager(const Options &options)
if (user_map.load(options.password_file_name))
return;
- /* write pid file */
- if (create_pid_file(options.pid_file_name))
+ /* write Instance Manager pid file */
+
+ log_info("IM pid file: '%s'; PID: %d.",
+ (const char *) options.pid_file_name,
+ (int) manager_pid);
+
+ if (create_pid_file(options.pid_file_name, manager_pid))
return;
sigset_t mask;
diff --git a/server-tools/instance-manager/manager.h b/server-tools/instance-manager/manager.h
index 12ed6b3b1ff..3ddf292132e 100644
--- a/server-tools/instance-manager/manager.h
+++ b/server-tools/instance-manager/manager.h
@@ -20,4 +20,6 @@ struct Options;
void manager(const Options &options);
+int create_pid_file(const char *pid_file_name, int pid);
+
#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H
diff --git a/server-tools/instance-manager/mysqlmanager.cc b/server-tools/instance-manager/mysqlmanager.cc
index d0b2cf2666c..ef714099de7 100644
--- a/server-tools/instance-manager/mysqlmanager.cc
+++ b/server-tools/instance-manager/mysqlmanager.cc
@@ -338,6 +338,14 @@ spawn:
/* Here we return to main, and fall into manager */
break;
default: // parent, success
+ pid= getpid(); /* Get our pid. */
+
+ log_info("Angel pid file: '%s'; PID: %d.",
+ (const char *) options.angel_pid_file_name,
+ (int) pid);
+
+ create_pid_file(Options::angel_pid_file_name, pid);
+
while (child_status == CHILD_OK && is_terminated == 0)
sigsuspend(&zeromask);
diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc
index e7d366e7457..a98c0e291be 100644
--- a/server-tools/instance-manager/options.cc
+++ b/server-tools/instance-manager/options.cc
@@ -44,6 +44,7 @@ const char *Options::user= 0; /* No default value */
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;
#endif
const char *Options::log_file_name= default_log_file_name;
const char *Options::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME);
@@ -58,6 +59,9 @@ char **Options::saved_argv= NULL;
/* Remember if the config file was forced */
bool Options::is_forced_default_file= 0;
+static const char * const ANGEL_PID_FILE_SUFFIX= ".angel.pid";
+static const int ANGEL_PID_FILE_SUFFIX_LEN= strlen(ANGEL_PID_FILE_SUFFIX);
+
/*
List of options, accepted by the instance manager.
List must be closed with empty option.
@@ -72,6 +76,7 @@ enum options {
#ifndef __WIN__
OPT_RUN_AS_SERVICE,
OPT_USER,
+ OPT_ANGEL_PID_FILE,
#else
OPT_INSTALL_SERVICE,
OPT_REMOVE_SERVICE,
@@ -94,7 +99,14 @@ static struct my_option my_long_options[] =
{ "pid-file", OPT_PID_FILE, "Pid file to use.",
(gptr *) &Options::pid_file_name, (gptr *) &Options::pid_file_name,
- 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+
+#ifndef __WIN__
+ { "angel-pid-file", OPT_ANGEL_PID_FILE, "Pid file for angel process.",
+ (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,
@@ -290,6 +302,46 @@ int Options::load(int argc, char **argv)
get_one_option)) != 0)
goto err;
+#ifndef __WIN__
+ if (Options::run_as_service)
+ {
+ if (Options::angel_pid_file_name == NULL)
+ {
+ /*
+ Calculate angel pid file on the IM pid file basis: replace the
+ extension (everything after the last dot) of the pid file basename to
+ '.angel.pid'.
+ */
+
+ char *angel_pid_file_name;
+ char *base_name_ptr;
+ char *ext_ptr;
+
+ angel_pid_file_name= (char *) malloc(strlen(Options::pid_file_name) +
+ ANGEL_PID_FILE_SUFFIX_LEN);
+
+ strcpy(angel_pid_file_name, Options::pid_file_name);
+
+ base_name_ptr= strrchr(angel_pid_file_name, '/');
+
+ if (!base_name_ptr)
+ base_name_ptr= angel_pid_file_name + 1;
+
+ ext_ptr= strrchr(base_name_ptr, '.');
+ if (ext_ptr)
+ *ext_ptr= 0;
+
+ strcat(angel_pid_file_name, ANGEL_PID_FILE_SUFFIX);
+
+ Options::angel_pid_file_name= angel_pid_file_name;
+ }
+ else
+ {
+ Options::angel_pid_file_name= strdup(Options::angel_pid_file_name);
+ }
+ }
+#endif
+
return 0;
err:
@@ -301,6 +353,11 @@ void Options::cleanup()
/* free_defaults returns nothing */
if (Options::saved_argv != NULL)
free_defaults(Options::saved_argv);
+
+#ifndef __WIN__
+ if (Options::run_as_service)
+ free((void *) Options::angel_pid_file_name);
+#endif
}
#ifdef __WIN__
diff --git a/server-tools/instance-manager/options.h b/server-tools/instance-manager/options.h
index abb094eac93..ad3458869b6 100644
--- a/server-tools/instance-manager/options.h
+++ b/server-tools/instance-manager/options.h
@@ -35,6 +35,7 @@ struct Options
#else
static char run_as_service; /* handle_options doesn't support bool */
static const char *user;
+ static const char *angel_pid_file_name;
#endif
static bool is_forced_default_file;
static const char *log_file_name;
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 895f022624c..4e977c06180 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -642,7 +642,8 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
void field_conv(Field *to,Field *from)
{
- if (to->real_type() == from->real_type())
+ if (to->real_type() == from->real_type() &&
+ !(to->type() == FIELD_TYPE_BLOB && to->table->copy_blobs))
{
if (to->pack_length() == from->pack_length() &&
!(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) &&
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 934437e0c91..28cdfd23b6a 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -4048,6 +4048,9 @@ ha_innobase::index_prev(
mysql_byte* buf) /* in/out: buffer for previous row in MySQL
format */
{
+ statistic_increment(current_thd->status_var.ha_read_prev_count,
+ &LOCK_status);
+
return(general_fetch(buf, ROW_SEL_PREV, 0));
}
diff --git a/sql/item.cc b/sql/item.cc
index 31fbef0f053..ba378e56cb0 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -958,6 +958,12 @@ void Item_splocal::print(String *str)
}
+bool Item_splocal::set_value(THD *thd, sp_rcontext *ctx, Item **it)
+{
+ return ctx->set_variable(thd, get_var_idx(), it);
+}
+
+
/*****************************************************************************
Item_case_expr methods
*****************************************************************************/
@@ -1883,7 +1889,6 @@ Item_decimal::Item_decimal(const char *str_arg, uint length,
name= (char*) str_arg;
decimals= (uint8) decimal_value.frac;
fixed= 1;
- unsigned_flag= !decimal_value.sign();
max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
decimals, unsigned_flag);
}
@@ -1893,7 +1898,6 @@ Item_decimal::Item_decimal(longlong val, bool unsig)
int2my_decimal(E_DEC_FATAL_ERROR, val, unsig, &decimal_value);
decimals= (uint8) decimal_value.frac;
fixed= 1;
- unsigned_flag= !decimal_value.sign();
max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
decimals, unsigned_flag);
}
@@ -1904,7 +1908,6 @@ Item_decimal::Item_decimal(double val, int precision, int scale)
double2my_decimal(E_DEC_FATAL_ERROR, val, &decimal_value);
decimals= (uint8) decimal_value.frac;
fixed= 1;
- unsigned_flag= !decimal_value.sign();
max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
decimals, unsigned_flag);
}
@@ -1917,7 +1920,6 @@ Item_decimal::Item_decimal(const char *str, const my_decimal *val_arg,
name= (char*) str;
decimals= (uint8) decimal_par;
max_length= length;
- unsigned_flag= !decimal_value.sign();
fixed= 1;
}
@@ -1927,7 +1929,6 @@ Item_decimal::Item_decimal(my_decimal *value_par)
my_decimal2decimal(value_par, &decimal_value);
decimals= (uint8) decimal_value.frac;
fixed= 1;
- unsigned_flag= !decimal_value.sign();
max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
decimals, unsigned_flag);
}
@@ -1939,7 +1940,6 @@ Item_decimal::Item_decimal(const char *bin, int precision, int scale)
&decimal_value, precision, scale);
decimals= (uint8) decimal_value.frac;
fixed= 1;
- unsigned_flag= !decimal_value.sign();
max_length= my_decimal_precision_to_length(precision, decimals,
unsigned_flag);
}
@@ -5365,6 +5365,25 @@ bool Item_trigger_field::eq(const Item *item, bool binary_cmp) const
}
+void Item_trigger_field::set_required_privilege(const bool rw)
+{
+ /*
+ Require SELECT and UPDATE privilege if this field will be read and
+ set, and only UPDATE privilege for setting the field.
+ */
+ want_privilege= (rw ? SELECT_ACL | UPDATE_ACL : UPDATE_ACL);
+}
+
+
+bool Item_trigger_field::set_value(THD *thd, sp_rcontext */*ctx*/, Item **it)
+{
+ Item *item= sp_prepare_func_item(thd, it);
+
+ return (!item || (!fixed && fix_fields(thd, 0)) ||
+ (item->save_in_field(field, 0) < 0));
+}
+
+
bool Item_trigger_field::fix_fields(THD *thd, Item **items)
{
/*
@@ -5387,8 +5406,7 @@ bool Item_trigger_field::fix_fields(THD *thd, Item **items)
if (table_grants)
{
- table_grants->want_privilege=
- access_type == AT_READ ? SELECT_ACL : UPDATE_ACL;
+ table_grants->want_privilege= want_privilege;
if (check_grant_column(thd, table_grants, triggers->table->s->db,
triggers->table->s->table_name, field_name,
@@ -5420,6 +5438,7 @@ void Item_trigger_field::print(String *str)
void Item_trigger_field::cleanup()
{
+ want_privilege= original_privilege;
/*
Since special nature of Item_trigger_field we should not do most of
things from Item_field::cleanup() or Item_ident::cleanup() here.
diff --git a/sql/item.h b/sql/item.h
index 24aca4a86d1..cfc2306f15d 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -372,6 +372,42 @@ public:
/*************************************************************************/
+class sp_rcontext;
+
+
+class Settable_routine_parameter
+{
+public:
+ /*
+ Set required privileges for accessing the parameter.
+
+ SYNOPSIS
+ set_required_privilege()
+ rw if 'rw' is true then we are going to read and set the
+ parameter, so SELECT and UPDATE privileges might be
+ required, otherwise we only reading it and SELECT
+ privilege might be required.
+ */
+ virtual void set_required_privilege(bool rw) {};
+
+ /*
+ Set parameter value.
+
+ SYNOPSIS
+ set_value()
+ thd thread handle
+ ctx context to which parameter belongs (if it is local
+ variable).
+ it item which represents new value
+
+ RETURN
+ FALSE if parameter value has been set,
+ TRUE if error has occured.
+ */
+ virtual bool set_value(THD *thd, sp_rcontext *ctx, Item **it)= 0;
+};
+
+
typedef bool (Item::*Item_processor)(byte *arg);
typedef Item* (Item::*Item_transformer) (byte *arg);
typedef void (*Cond_traverser) (const Item *item, void *arg);
@@ -744,6 +780,15 @@ public:
}
virtual bool is_splocal() { return 0; } /* Needed for error checking */
+
+ /*
+ Return Settable_routine_parameter interface of the Item. Return 0
+ if this Item is not Settable_routine_parameter.
+ */
+ virtual Settable_routine_parameter *get_settable_routine_parameter()
+ {
+ return 0;
+ }
};
@@ -842,7 +887,8 @@ inline bool Item_sp_variable::send(Protocol *protocol, String *str)
runtime.
*****************************************************************************/
-class Item_splocal :public Item_sp_variable
+class Item_splocal :public Item_sp_variable,
+ private Settable_routine_parameter
{
uint m_var_idx;
@@ -880,6 +926,15 @@ public:
inline enum Type type() const;
inline Item_result result_type() const;
+
+private:
+ bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
+
+public:
+ Settable_routine_parameter *get_settable_routine_parameter()
+ {
+ return this;
+ }
};
/*****************************************************************************
@@ -2100,14 +2155,13 @@ class Table_triggers_list;
two Field instances representing either OLD or NEW version of this
field.
*/
-class Item_trigger_field : public Item_field
+class Item_trigger_field : public Item_field,
+ private Settable_routine_parameter
{
public:
/* Is this item represents row from NEW or OLD row ? */
enum row_version_type {OLD_ROW, NEW_ROW};
row_version_type row_version;
- /* Is this item used for reading or updating the value? */
- enum access_types { AT_READ = 0x1, AT_UPDATE = 0x2 };
/* Next in list of all Item_trigger_field's in trigger */
Item_trigger_field *next_trg_field;
/* Index of the field in the TABLE::field array */
@@ -2118,11 +2172,11 @@ public:
Item_trigger_field(Name_resolution_context *context_arg,
row_version_type row_ver_arg,
const char *field_name_arg,
- access_types access_type_arg)
+ ulong priv, const bool ro)
:Item_field(context_arg,
(const char *)NULL, (const char *)NULL, field_name_arg),
- row_version(row_ver_arg), field_idx((uint)-1),
- access_type(access_type_arg), table_grants(NULL)
+ row_version(row_ver_arg), field_idx((uint)-1), original_privilege(priv),
+ want_privilege(priv), table_grants(NULL), read_only (ro)
{}
void setup_field(THD *thd, TABLE *table, GRANT_INFO *table_grant_info);
enum Type type() const { return TRIGGER_FIELD_ITEM; }
@@ -2133,8 +2187,39 @@ public:
void cleanup();
private:
- access_types access_type;
+ void set_required_privilege(const bool rw);
+ bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
+
+public:
+ Settable_routine_parameter *get_settable_routine_parameter()
+ {
+ return (read_only ? 0 : this);
+ }
+
+ bool set_value(THD *thd, Item **it)
+ {
+ return set_value(thd, NULL, it);
+ }
+
+private:
+ /*
+ 'want_privilege' holds privileges required to perform operation on
+ this trigger field (SELECT_ACL if we are going to read it and
+ UPDATE_ACL if we are going to update it). It is initialized at
+ parse time but can be updated later if this trigger field is used
+ as OUT or INOUT parameter of stored routine (in this case
+ set_required_privilege() is called to appropriately update
+ want_privilege and cleanup() is responsible for restoring of
+ original want_privilege once parameter's value is updated).
+ */
+ ulong original_privilege;
+ ulong want_privilege;
GRANT_INFO *table_grants;
+ /*
+ Trigger field is read-only unless it belongs to the NEW row in a
+ BEFORE INSERT of BEFORE UPDATE trigger.
+ */
+ bool read_only;
};
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 6ec74560b91..5ef9db6f52b 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -4120,6 +4120,18 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
}
+bool Item_func_get_user_var::set_value(THD *thd,
+ sp_rcontext */*ctx*/, Item **it)
+{
+ Item_func_set_user_var *suv= new Item_func_set_user_var(get_name(), *it);
+ /*
+ Item_func_set_user_var is not fixed after construction, call
+ fix_fields().
+ */
+ return (!suv || suv->fix_fields(thd, it) || suv->check() || suv->update());
+}
+
+
bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
@@ -4752,6 +4764,7 @@ Item_func_sp::sp_result_field(void) const
dummy_table->alias = empty_name;
dummy_table->maybe_null = maybe_null;
dummy_table->in_use= current_thd;
+ dummy_table->copy_blobs= TRUE;
share->table_cache_key = empty_name;
share->table_name = empty_name;
}
diff --git a/sql/item_func.h b/sql/item_func.h
index a91d93be8c6..1d8a1bd5e22 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1179,7 +1179,8 @@ public:
};
-class Item_func_get_user_var :public Item_func
+class Item_func_get_user_var :public Item_func,
+ private Settable_routine_parameter
{
user_var_entry *var_entry;
@@ -1206,6 +1207,15 @@ public:
table_map used_tables() const
{ return const_item() ? 0 : RAND_TABLE_BIT; }
bool eq(const Item *item, bool binary_cmp) const;
+
+private:
+ bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
+
+public:
+ Settable_routine_parameter *get_settable_routine_parameter()
+ {
+ return this;
+ }
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index d93f6501ebb..4b304725927 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1351,6 +1351,17 @@ void Item_in_subselect::print(String *str)
}
+bool Item_in_subselect::fix_fields(THD *thd, Item **ref)
+{
+ bool result = 0;
+
+ if(thd->lex->view_prepare_mode && left_expr && !left_expr->fixed)
+ result = left_expr->fix_fields(thd, &left_expr);
+
+ return result || Item_subselect::fix_fields(thd, ref);
+}
+
+
Item_subselect::trans_res
Item_allany_subselect::select_transformer(JOIN *join)
{
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index a4dac5bda87..293408dc09e 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -258,6 +258,7 @@ public:
void top_level_item() { abort_on_null=1; }
bool test_limit(st_select_lex_unit *unit);
void print(String *str);
+ bool fix_fields(THD *thd, Item **ref);
friend class Item_ref_null_helper;
friend class Item_is_not_null_test;
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index e997d4ae70c..72c53272e0c 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2144,8 +2144,13 @@ bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const
Item_date_add_interval *other= (Item_date_add_interval*) item;
if ((int_type != other->int_type) ||
- (!args[0]->eq(other->args[0], binary_cmp)) ||
- (get_interval_value(args[1], int_type, &val, &interval)))
+ (!args[0]->eq(other->args[0], binary_cmp)))
+ return FALSE;
+
+ if (!args[1]->const_item() || !other->args[1]->const_item())
+ return (args[1]->eq(other->args[1], binary_cmp));
+
+ if (get_interval_value(args[1], int_type, &val, &interval))
return FALSE;
val= other->value;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 1ce9dd78d2c..815876688fb 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -718,12 +718,6 @@ bool mysql_create_table(THD *thd,const char *db, const char *table_name,
List<create_field> &fields, List<Key> &keys,
bool tmp_table, uint select_field_count);
-TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
- TABLE_LIST *create_table,
- List<create_field> *extra_fields,
- List<Key> *keys,
- List<Item> *items,
- MYSQL_LOCK **lock);
bool mysql_alter_table(THD *thd, char *new_db, char *new_name,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
@@ -1315,10 +1309,11 @@ extern struct st_VioSSLFd * ssl_acceptor_fd;
MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count,
uint flags, bool *need_reopen);
-/* mysql_lock_tables() flags bits */
+/* mysql_lock_tables() and open_table() flags bits */
#define MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK 0x0001
#define MYSQL_LOCK_IGNORE_FLUSH 0x0002
#define MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN 0x0004
+#define MYSQL_OPEN_IGNORE_LOCKED_TABLES 0x0008
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
@@ -1582,6 +1577,16 @@ inline int hexchar_to_int(char c)
return -1;
}
+/*
+ is_user_table()
+ return true if the table was created explicitly
+*/
+
+inline bool is_user_table(TABLE * table)
+{
+ const char *name= table->s->table_name;
+ return strncmp(name, tmp_file_prefix, tmp_file_prefix_length);
+}
/*
Some functions that are different in the embedded library and the normal
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 2892c5c8b01..4e7b9200d88 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -5475,7 +5475,7 @@ ER_SP_DUP_HANDLER 42000
eng "Duplicate handler declared in the same block"
ger "Doppelter Handler im selben Block deklariert"
ER_SP_NOT_VAR_ARG 42000
- eng "OUT or INOUT argument %d for routine %s is not a variable"
+ eng "OUT or INOUT argument %d for routine %s is not a variable or NEW pseudo-variable in BEFORE trigger"
ger "OUT- oder INOUT-Argument %d für Routine %s ist keine Variable"
ER_SP_NO_RETSET 0A000
eng "Not allowed to return a result set from a %s"
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 6a7676c7bf2..174f62c9497 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -310,11 +310,13 @@ sp_prepare_func_item(THD* thd, Item **it_addr)
*/
bool
-sp_eval_expr(THD *thd, Field *result_field, Item *expr_item)
+sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
{
+ Item *expr_item;
+
DBUG_ENTER("sp_eval_expr");
- if (!(expr_item= sp_prepare_func_item(thd, &expr_item)))
+ if (!(expr_item= sp_prepare_func_item(thd, expr_item_ptr)))
DBUG_RETURN(TRUE);
bool err_status= FALSE;
@@ -936,6 +938,7 @@ sp_head::execute(THD *thd)
bool err_status= FALSE;
uint ip= 0;
ulong save_sql_mode;
+ bool save_abort_on_warning;
Query_arena *old_arena;
/* per-instruction arena */
MEM_ROOT execute_mem_root;
@@ -996,6 +999,10 @@ sp_head::execute(THD *thd)
thd->derived_tables= 0;
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));
+
/*
It is also more efficient to save/restore current thd->lex once when
do it in each instruction
@@ -1128,6 +1135,7 @@ sp_head::execute(THD *thd)
DBUG_ASSERT(!thd->derived_tables);
thd->derived_tables= old_derived_tables;
thd->variables.sql_mode= save_sql_mode;
+ thd->abort_on_warning= save_abort_on_warning;
thd->stmt_arena= old_arena;
state= EXECUTED;
@@ -1204,130 +1212,144 @@ bool
sp_head::execute_function(THD *thd, Item **argp, uint argcount,
Field *return_value_fld)
{
- Item_cache **param_values;
ulonglong binlog_save_options;
bool need_binlog_call;
- uint params;
+ uint arg_no;
sp_rcontext *octx = thd->spcont;
sp_rcontext *nctx = NULL;
+ char buf[STRING_BUFFER_USUAL_SIZE];
+ String binlog_buf(buf, sizeof(buf), &my_charset_bin);
bool err_status= FALSE;
+ MEM_ROOT call_mem_root;
+ Query_arena call_arena(&call_mem_root, Query_arena::INITIALIZED_FOR_SP);
+ Query_arena backup_arena;
DBUG_ENTER("sp_head::execute_function");
DBUG_PRINT("info", ("function %s", m_name.str));
- params = m_pcont->context_var_count();
-
/*
Check that the function is called with all specified arguments.
If it is not, use my_error() to report an error, or it will not terminate
the invoking query properly.
*/
-
- if (argcount != params)
+ if (argcount != m_pcont->context_var_count())
{
/*
Need to use my_error here, or it will not terminate the
invoking query properly.
*/
my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0),
- "FUNCTION", m_qname.str, params, argcount);
+ "FUNCTION", m_qname.str, m_pcont->context_var_count(), argcount);
DBUG_RETURN(TRUE);
}
-
- /* Allocate param_values to be used for dumping the call into binlog. */
-
- if (!(param_values= (Item_cache**)thd->alloc(sizeof(Item_cache*)*argcount)))
- DBUG_RETURN(TRUE);
-
- // QQ Should have some error checking here? (types, etc...)
+ /*
+ Prepare arena and memroot for objects which lifetime is whole
+ duration of function call (sp_rcontext, it's tables and items,
+ sp_cursor and Item_cache holders for case expressions).
+ We can't use caller's arena/memroot for those objects because
+ in this case some fixed amount of memory will be consumed for
+ each function/trigger invocation and so statements which involve
+ lot of them will hog memory.
+ TODO: we should create sp_rcontext once per command and reuse
+ it on subsequent executions of a function/trigger.
+ */
+ init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
+ thd->set_n_backup_active_arena(&call_arena, &backup_arena);
if (!(nctx= new sp_rcontext(m_pcont, return_value_fld, octx)) ||
nctx->init(thd))
{
- delete nctx; /* Delete nctx if it was init() that failed. */
- DBUG_RETURN(TRUE);
+ thd->restore_active_arena(&call_arena, &backup_arena);
+ err_status= TRUE;
+ goto err_with_cleanup;
}
+ /*
+ We have to switch temporarily back to callers arena/memroot.
+ Function arguments belong to the caller and so the may reference
+ memory which they will allocate during calculation long after
+ this function call will be finished (e.g. in Item::cleanup()).
+ */
+ thd->restore_active_arena(&call_arena, &backup_arena);
+
#ifndef DBUG_OFF
nctx->sp= this;
#endif
/* Pass arguments. */
+ for (arg_no= 0; arg_no < argcount; arg_no++)
+ {
+ /* Arguments must be fixed in Item_func_sp::fix_fields */
+ DBUG_ASSERT(argp[arg_no]->fixed);
+
+ if ((err_status= nctx->set_variable(thd, arg_no, &(argp[arg_no]))))
+ goto err_with_cleanup;
+ }
+
+ need_binlog_call= mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG);
+ /*
+ Remember the original arguments for unrolled replication of functions
+ before they are changed by execution.
+ */
+ if (need_binlog_call)
{
- uint i;
-
- for (i= 0 ; i < argcount ; i++)
+ binlog_buf.length(0);
+ binlog_buf.append(STRING_WITH_LEN("SELECT "));
+ append_identifier(thd, &binlog_buf, m_name.str, m_name.length);
+ binlog_buf.append('(');
+ for (arg_no= 0; arg_no < argcount; arg_no++)
{
- if (!argp[i]->fixed && argp[i]->fix_fields(thd, &argp[i]))
- {
- err_status= TRUE;
- break;
- }
+ String str_value_holder;
+ String *str_value;
- param_values[i]= Item_cache::get_cache(argp[i]->result_type());
- param_values[i]->store(argp[i]);
+ if (arg_no)
+ binlog_buf.append(',');
- if (nctx->set_variable(thd, i, param_values[i]))
- {
- err_status= TRUE;
- break;
- }
- }
- }
+ str_value= sp_get_item_value(nctx->get_item(arg_no),
+ &str_value_holder);
- if (err_status)
- {
- delete nctx;
- DBUG_RETURN(TRUE);
+ if (str_value)
+ binlog_buf.append(*str_value);
+ else
+ binlog_buf.append(STRING_WITH_LEN("NULL"));
+ }
+ binlog_buf.append(')');
}
-
thd->spcont= nctx;
binlog_save_options= thd->options;
- need_binlog_call= mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG);
if (need_binlog_call)
{
reset_dynamic(&thd->user_var_events);
mysql_bin_log.start_union_events(thd);
}
-
+
+ /*
+ Switch to call arena/mem_root so objects like sp_cursor or
+ Item_cache holders for case expressions can be allocated on it.
+
+ TODO: In future we should associate call arena/mem_root with
+ sp_rcontext and allocate all these objects (and sp_rcontext
+ itself) on it directly rather than juggle with arenas.
+ */
+ thd->set_n_backup_active_arena(&call_arena, &backup_arena);
+
thd->options&= ~OPTION_BIN_LOG;
err_status= execute(thd);
thd->options= binlog_save_options;
-
+
+ thd->restore_active_arena(&call_arena, &backup_arena);
+
if (need_binlog_call)
mysql_bin_log.stop_union_events(thd);
if (need_binlog_call && thd->binlog_evt_union.unioned_events)
{
- char buf[256];
- String bufstr(buf, sizeof(buf), &my_charset_bin);
- bufstr.length(0);
- bufstr.append(STRING_WITH_LEN("SELECT "));
- append_identifier(thd, &bufstr, m_name.str, m_name.length);
- bufstr.append('(');
- for (uint i=0; i < argcount; i++)
- {
- String str_value_holder;
- String *str_value;
-
- if (i)
- bufstr.append(',');
-
- str_value= sp_get_item_value(param_values[i], &str_value_holder);
-
- if (str_value)
- bufstr.append(*str_value);
- else
- bufstr.append(STRING_WITH_LEN("NULL"));
- }
- bufstr.append(')');
-
- Query_log_event qinfo(thd, bufstr.ptr(), bufstr.length(),
+ Query_log_event qinfo(thd, binlog_buf.ptr(), binlog_buf.length(),
thd->binlog_evt_union.unioned_events_trans, FALSE);
- if (mysql_bin_log.write(&qinfo) &&
+ if (mysql_bin_log.write(&qinfo) &&
thd->binlog_evt_union.unioned_events_trans)
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
@@ -1348,27 +1370,19 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
}
}
+
nctx->pop_all_cursors(); // To avoid memory leaks after an error
+
+err_with_cleanup:
delete nctx;
+ call_arena.free_items();
+ free_root(&call_mem_root, MYF(0));
thd->spcont= octx;
DBUG_RETURN(err_status);
}
-static Item_func_get_user_var *item_is_user_var(Item *it)
-{
- if (it->type() == Item::FUNC_ITEM)
- {
- Item_func *fi= static_cast<Item_func*>(it);
-
- if (fi->functype() == Item_func::GUSERVAR_FUNC)
- return static_cast<Item_func_get_user_var*>(fi);
- }
- return NULL;
-}
-
-
/*
Execute a procedure.
SYNOPSIS
@@ -1444,22 +1458,28 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
for (uint i= 0 ; i < params ; i++)
{
Item *arg_item= it_args++;
- sp_variable_t *spvar= m_pcont->find_variable(i);
if (!arg_item)
break;
+ sp_variable_t *spvar= m_pcont->find_variable(i);
+
if (!spvar)
continue;
if (spvar->mode != sp_param_in)
{
- if (!arg_item->is_splocal() && !item_is_user_var(arg_item))
+ Settable_routine_parameter *srp=
+ arg_item->get_settable_routine_parameter();
+
+ if (!srp)
{
my_error(ER_SP_NOT_VAR_ARG, MYF(0), i+1, m_qname.str);
err_status= TRUE;
break;
}
+
+ srp->set_required_privilege(spvar->mode == sp_param_inout);
}
if (spvar->mode == sp_param_out)
@@ -1467,7 +1487,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
Item_null *null_item= new Item_null();
if (!null_item ||
- nctx->set_variable(thd, i, null_item))
+ nctx->set_variable(thd, i, (struct Item **)&null_item))
{
err_status= TRUE;
break;
@@ -1475,7 +1495,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
}
else
{
- if (nctx->set_variable(thd, i, *it_args.ref()))
+ if (nctx->set_variable(thd, i, it_args.ref()))
{
err_status= TRUE;
break;
@@ -1527,36 +1547,16 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (spvar->mode == sp_param_in)
continue;
- if (arg_item->is_splocal())
- {
- if (octx->set_variable(thd,
- ((Item_splocal*) arg_item)->get_var_idx(),
- nctx->get_item(i)))
- {
- err_status= TRUE;
- break;
- }
- }
- else
+ Settable_routine_parameter *srp=
+ arg_item->get_settable_routine_parameter();
+
+ DBUG_ASSERT(srp);
+
+ if (srp->set_value(thd, octx, nctx->get_item_addr(i)))
{
- Item_func_get_user_var *guv= item_is_user_var(arg_item);
-
- if (guv)
- {
- Item *item= nctx->get_item(i);
- Item_func_set_user_var *suv;
-
- suv= new Item_func_set_user_var(guv->get_name(), item);
- /*
- Item_func_set_user_var is not fixed after construction,
- call fix_fields().
- */
- if ((err_status= test(!suv || suv->fix_fields(thd, &item) ||
- suv->check() || suv->update())))
- break;
- }
+ err_status= TRUE;
+ break;
}
-
}
}
@@ -2328,7 +2328,7 @@ sp_instr_set::execute(THD *thd, uint *nextp)
int
sp_instr_set::exec_core(THD *thd, uint *nextp)
{
- int res= thd->spcont->set_variable(thd, m_offset, m_value);
+ int res= thd->spcont->set_variable(thd, m_offset, &m_value);
if (res && thd->spcont->found_handler_here())
{
@@ -2393,12 +2393,7 @@ sp_instr_set_trigger_field::execute(THD *thd, uint *nextp)
int
sp_instr_set_trigger_field::exec_core(THD *thd, uint *nextp)
{
- int res= 0;
- Item *it= sp_prepare_func_item(thd, &value);
- if (!it ||
- !trigger_field->fixed && trigger_field->fix_fields(thd, 0) ||
- (it->save_in_field(trigger_field->field, 0) < 0))
- res= -1;
+ const int res= (trigger_field->set_value(thd, &value) ? -1 : 0);
*nextp = m_ip+1;
return res;
}
@@ -2603,7 +2598,7 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp)
do it in scope of execution the current context/block.
*/
- return thd->spcont->set_return_value(thd, m_value);
+ return thd->spcont->set_return_value(thd, &m_value);
}
void
@@ -3047,7 +3042,7 @@ sp_instr_set_case_expr::execute(THD *thd, uint *nextp)
int
sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp)
{
- int res= thd->spcont->set_case_expr(thd, m_case_expr_id, m_case_expr);
+ int res= thd->spcont->set_case_expr(thd, m_case_expr_id, &m_case_expr);
if (res &&
!thd->spcont->get_case_expr(m_case_expr_id) &&
@@ -3061,7 +3056,7 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp)
Item *null_item= new Item_null();
if (!null_item ||
- thd->spcont->set_case_expr(thd, m_case_expr_id, null_item))
+ thd->spcont->set_case_expr(thd, m_case_expr_id, &null_item))
{
/* If this also failed, we have to abort. */
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 6a9cf97d739..d5f49d8a964 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -1169,6 +1169,6 @@ Item *
sp_prepare_func_item(THD* thd, Item **it_addr);
bool
-sp_eval_expr(THD *thd, Field *result_field, Item *expr_item);
+sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr);
#endif /* _SP_HEAD_H_ */
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 38b6de0e75a..3bc27a029d0 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -150,7 +150,7 @@ sp_rcontext::init_var_items()
bool
-sp_rcontext::set_return_value(THD *thd, Item *return_value_item)
+sp_rcontext::set_return_value(THD *thd, Item **return_value_item)
{
DBUG_ASSERT(m_return_value_fld);
@@ -279,14 +279,14 @@ sp_rcontext::pop_cursors(uint count)
int
-sp_rcontext::set_variable(THD *thd, uint var_idx, Item *value)
+sp_rcontext::set_variable(THD *thd, uint var_idx, Item **value)
{
return set_variable(thd, m_var_table->field[var_idx], value);
}
int
-sp_rcontext::set_variable(THD *thd, Field *field, Item *value)
+sp_rcontext::set_variable(THD *thd, Field *field, Item **value)
{
if (!value)
{
@@ -478,9 +478,10 @@ sp_rcontext::create_case_expr_holder(THD *thd, Item_result result_type)
*/
int
-sp_rcontext::set_case_expr(THD *thd, int case_expr_id, Item *case_expr_item)
+sp_rcontext::set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr)
{
- if (!(case_expr_item= sp_prepare_func_item(thd, &case_expr_item)))
+ Item *case_expr_item= sp_prepare_func_item(thd, case_expr_item_ptr);
+ if (!case_expr_item)
return TRUE;
if (!m_case_expr_holders[case_expr_id] ||
@@ -542,7 +543,7 @@ bool Select_fetch_into_spvars::send_data(List<Item> &items)
*/
for (; spvar= spvar_iter++, item= item_iter++; )
{
- if (thd->spcont->set_variable(thd, spvar->offset, item))
+ if (thd->spcont->set_variable(thd, spvar->offset, &item))
return TRUE;
}
return FALSE;
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index 20aaea3b7c1..30521f6da84 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -91,7 +91,7 @@ class sp_rcontext : public Sql_alloc
~sp_rcontext();
int
- set_variable(THD *thd, uint var_idx, Item *value);
+ set_variable(THD *thd, uint var_idx, Item **value);
Item *
get_item(uint var_idx);
@@ -100,7 +100,7 @@ class sp_rcontext : public Sql_alloc
get_item_addr(uint var_idx);
bool
- set_return_value(THD *thd, Item *return_value_item);
+ set_return_value(THD *thd, Item **return_value_item);
inline bool
is_return_value_set() const
@@ -200,7 +200,7 @@ class sp_rcontext : public Sql_alloc
*/
int
- set_case_expr(THD *thd, int case_expr_id, Item *case_expr_item);
+ set_case_expr(THD *thd, int case_expr_id, Item **case_expr_item_ptr);
Item *
get_case_expr(int case_expr_id);
@@ -254,7 +254,7 @@ private:
Item_cache *create_case_expr_holder(THD *thd, Item_result result_type);
- int set_variable(THD *thd, Field *field, Item *value);
+ int set_variable(THD *thd, Field *field, Item **value);
}; // class sp_rcontext : public Sql_alloc
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 482a25acbd2..1f3b9e14631 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -617,118 +617,110 @@ static inline uint tmpkeyval(THD *thd, TABLE *table)
void close_temporary_tables(THD *thd)
{
- TABLE *next,
- *prev_table /* prev link is not maintained in TABLE's double-linked list */,
- *table;
- char *query= (gptr) 0, *end;
- uint query_buf_size, max_names_len;
- bool found_user_tables;
-
+ TABLE *table;
if (!thd->temporary_tables)
return;
-
- LINT_INIT(end);
- query_buf_size= 50; // Enough for DROP ... TABLE IF EXISTS
- /*
- insertion sort of temp tables by pseudo_thread_id to build ordered list
+ if (!mysql_bin_log.is_open())
+ {
+ for (table= thd->temporary_tables; table; table= table->next)
+ {
+ close_temporary(table, 1);
+ }
+ thd->temporary_tables= 0;
+ return;
+ }
+
+ TABLE *next,
+ *prev_table /* prev link is not maintained in TABLE's double-linked list */;
+ bool was_quote_show= true; /* to assume thd->options has OPTION_QUOTE_SHOW_CREATE */
+ // Better add "if exists", in case a RESET MASTER has been done
+ const char stub[]= "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ";
+ uint stub_len= sizeof(stub) - 1;
+ char buf[256];
+ memcpy(buf, stub, stub_len);
+ String s_query= String(buf, sizeof(buf), system_charset_info);
+ bool found_user_tables= false;
+ LINT_INIT(next);
+
+ /*
+ insertion sort of temp tables by pseudo_thread_id to build ordered list
of sublists of equal pseudo_thread_id
*/
- for (prev_table= thd->temporary_tables,
- table= prev_table->next,
- found_user_tables= (prev_table->s->table_name[0] != '#');
+
+ for (prev_table= thd->temporary_tables, table= prev_table->next;
table;
prev_table= table, table= table->next)
{
- TABLE *prev_sorted /* same as for prev_table */,
- *sorted;
- /*
- table not created directly by the user is moved to the tail.
- Fixme/todo: nothing (I checked the manual) prevents user to create temp
- with `#'
- */
- if (table->s->table_name[0] == '#')
- continue;
- else
- {
- found_user_tables = 1;
- }
- for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table;
- prev_sorted= sorted, sorted= sorted->next)
+ TABLE *prev_sorted /* same as for prev_table */, *sorted;
+ if (is_user_table(table))
{
- if (sorted->s->table_name[0] == '#' || tmpkeyval(thd, sorted) > tmpkeyval(thd, table))
+ if (!found_user_tables)
+ found_user_tables= true;
+ for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table;
+ prev_sorted= sorted, sorted= sorted->next)
{
- /* move into the sorted part of the list from the unsorted */
- prev_table->next= table->next;
- table->next= sorted;
- if (prev_sorted)
+ if (!is_user_table(sorted) ||
+ tmpkeyval(thd, sorted) > tmpkeyval(thd, table))
{
- prev_sorted->next= table;
- }
- else
- {
- thd->temporary_tables= table;
+ /* move into the sorted part of the list from the unsorted */
+ prev_table->next= table->next;
+ table->next= sorted;
+ if (prev_sorted)
+ {
+ prev_sorted->next= table;
+ }
+ else
+ {
+ thd->temporary_tables= table;
+ }
+ table= prev_table;
+ break;
}
- table= prev_table;
- break;
}
}
- }
- /*
- calc query_buf_size as max per sublists, one sublist per pseudo thread id.
- Also stop at first occurence of `#'-named table that starts
- all implicitly created temp tables
- */
- for (max_names_len= 0, table=thd->temporary_tables;
- table && table->s->table_name[0] != '#';
- table=table->next)
+ }
+
+ /* We always quote db,table names though it is slight overkill */
+ if (found_user_tables &&
+ !(was_quote_show= (thd->options & OPTION_QUOTE_SHOW_CREATE)))
{
- uint tmp_names_len;
- for (tmp_names_len= table->s->key_length + 1;
- table->next && table->s->table_name[0] != '#' &&
- tmpkeyval(thd, table) == tmpkeyval(thd, table->next);
- table=table->next)
- {
- /*
- We are going to add 4 ` around the db/table names, so 1 might not look
- enough; indeed it is enough, because table->key_length is greater (by 8,
- because of server_id and thread_id) than db||table.
- */
- tmp_names_len += table->next->s->key_length + 1;
- }
- if (tmp_names_len > max_names_len) max_names_len= tmp_names_len;
+ thd->options |= OPTION_QUOTE_SHOW_CREATE;
}
-
- /* allocate */
- if (found_user_tables && mysql_bin_log.is_open() &&
- (query = alloc_root(thd->mem_root, query_buf_size+= max_names_len)))
- // Better add "if exists", in case a RESET MASTER has been done
- end= strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ");
/* scan sorted tmps to generate sequence of DROP */
- for (table=thd->temporary_tables; table; table= next)
+ for (table= thd->temporary_tables; table; table= next)
{
- if (query // we might be out of memory, but this is not fatal
- && table->s->table_name[0] != '#')
+ if (is_user_table(table))
{
- char *end_cur;
/* Set pseudo_thread_id to be that of the processed table */
thd->variables.pseudo_thread_id= tmpkeyval(thd, table);
/* Loop forward through all tables within the sublist of
common pseudo_thread_id to create single DROP query */
- for (end_cur= end;
- table && table->s->table_name[0] != '#' &&
+ for (s_query.length(stub_len);
+ table && is_user_table(table) &&
tmpkeyval(thd, table) == thd->variables.pseudo_thread_id;
table= next)
{
- end_cur= strxmov(end_cur, "`", table->s->db, "`.`",
- table->s->table_name, "`,", NullS);
+ /*
+ We are going to add 4 ` around the db/table names and possible more
+ due to special characters in the names
+ */
+ append_identifier(thd, &s_query, table->s->db, strlen(table->s->db));
+ s_query.q_append('.');
+ append_identifier(thd, &s_query, table->s->table_name,
+ strlen(table->s->table_name));
+ s_query.q_append(',');
next= table->next;
close_temporary(table, 1);
}
thd->clear_error();
- /* The -1 is to remove last ',' */
- Query_log_event qinfo(thd, query, (ulong)(end_cur - query) - 1, 0, FALSE);
+ CHARSET_INFO *cs_save= thd->variables.character_set_client;
+ thd->variables.character_set_client= system_charset_info;
+ Query_log_event qinfo(thd, s_query.ptr(),
+ s_query.length() - 1 /* to remove trailing ',' */,
+ 0, FALSE);
+ thd->variables.character_set_client= cs_save;
/*
Imagine the thread had created a temp table, then was doing a SELECT, and
the SELECT was killed. Then it's not clever to mark the statement above as
@@ -741,12 +733,14 @@ void close_temporary_tables(THD *thd)
qinfo.error_code= 0;
mysql_bin_log.write(&qinfo);
}
- else
+ else
{
next= table->next;
close_temporary(table, 1);
}
}
+ if (!was_quote_show)
+ thd->options &= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */
thd->temporary_tables=0;
}
@@ -1160,6 +1154,8 @@ bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
MYSQL_LOCK_IGNORE_FLUSH - Open table even if
someone has done a flush or namelock on it.
No version number checking is done.
+ MYSQL_OPEN_IGNORE_LOCKED_TABLES - Open table
+ ignoring set of locked tables and prelocked mode.
IMPLEMENTATION
Uses a cache of open tables to find a table not in use.
@@ -1219,7 +1215,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
}
}
- if (thd->locked_tables || thd->prelocked_mode)
+ if (!(flags & MYSQL_OPEN_IGNORE_LOCKED_TABLES) &&
+ (thd->locked_tables || thd->prelocked_mode))
{ // Using table locks
TABLE *best_table= 0;
int best_distance= INT_MIN;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 026c3e0d515..65fd4d3ac19 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1877,7 +1877,7 @@ bool select_dumpvar::send_data(List<Item> &items)
if ((yy=var_li++))
{
if (thd->spcont->set_variable(current_thd, yy->get_var_idx(),
- *it.ref()))
+ it.ref()))
DBUG_RETURN(1);
}
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 320b8e1df9d..c054499ecd8 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2437,6 +2437,153 @@ bool select_insert::send_eof()
CREATE TABLE (SELECT) ...
***************************************************************************/
+/*
+ Create table from lists of fields and items (or open existing table
+ with same name).
+
+ SYNOPSIS
+ create_table_from_items()
+ thd in Thread object
+ create_info in Create information (like MAX_ROWS, ENGINE or
+ temporary table flag)
+ create_table in Pointer to TABLE_LIST object providing database
+ and name for table to be created or to be open
+ extra_fields in/out Initial list of fields for table to be created
+ keys in List of keys for table to be created
+ items in List of items which should be used to produce rest
+ of fields for the table (corresponding fields will
+ be added to the end of 'extra_fields' list)
+ lock out Pointer to the MYSQL_LOCK object for table created
+ (open) will be returned in this parameter. Since
+ this table is not included in THD::lock caller is
+ responsible for explicitly unlocking this table.
+
+ NOTES
+ If 'create_info->options' bitmask has HA_LEX_CREATE_IF_NOT_EXISTS
+ flag and table with name provided already exists then this function will
+ simply open existing table.
+ Also note that create, open and lock sequence in this function is not
+ atomic and thus contains gap for deadlock and can cause other troubles.
+ Since this function contains some logic specific to CREATE TABLE ... SELECT
+ it should be changed before it can be used in other contexts.
+
+ RETURN VALUES
+ non-zero Pointer to TABLE object for table created or opened
+ 0 Error
+*/
+
+static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
+ TABLE_LIST *create_table,
+ List<create_field> *extra_fields,
+ List<Key> *keys, List<Item> *items,
+ MYSQL_LOCK **lock)
+{
+ TABLE tmp_table; // Used during 'create_field()'
+ TABLE *table= 0;
+ uint select_field_count= items->elements;
+ /* Add selected items to field list */
+ List_iterator_fast<Item> it(*items);
+ Item *item;
+ Field *tmp_field;
+ bool not_used;
+ DBUG_ENTER("create_table_from_items");
+
+ tmp_table.alias= 0;
+ tmp_table.timestamp_field= 0;
+ tmp_table.s= &tmp_table.share_not_to_be_used;
+ tmp_table.s->db_create_options=0;
+ tmp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
+ tmp_table.s->db_low_byte_first= test(create_info->db_type == DB_TYPE_MYISAM ||
+ create_info->db_type == DB_TYPE_HEAP);
+ tmp_table.null_row=tmp_table.maybe_null=0;
+
+ while ((item=it++))
+ {
+ create_field *cr_field;
+ Field *field;
+ if (item->type() == Item::FUNC_ITEM)
+ field=item->tmp_table_field(&tmp_table);
+ else
+ field=create_tmp_field(thd, &tmp_table, item, item->type(),
+ (Item ***) 0, &tmp_field, 0, 0, 0, 0, 0);
+ if (!field ||
+ !(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ?
+ ((Item_field *)item)->field :
+ (Field*) 0))))
+ DBUG_RETURN(0);
+ if (item->maybe_null)
+ cr_field->flags &= ~NOT_NULL_FLAG;
+ extra_fields->push_back(cr_field);
+ }
+ /*
+ create and lock table
+
+ We don't log the statement, it will be logged later.
+
+ If this is a HEAP table, the automatic DELETE FROM which is written to the
+ binlog when a HEAP table is opened for the first time since startup, must
+ not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we
+ don't want to delete from it) 2) it would be written before the CREATE
+ TABLE, which is a wrong order. So we keep binary logging disabled when we
+ open_table().
+ NOTE: By locking table which we just have created (or for which we just have
+ have found that it already exists) separately from other tables used by the
+ statement we create potential window for deadlock.
+ TODO: create and open should be done atomic !
+ */
+ {
+ tmp_disable_binlog(thd);
+ if (!mysql_create_table(thd, create_table->db, create_table->table_name,
+ create_info, *extra_fields, *keys, 0,
+ select_field_count))
+ {
+ /*
+ If we are here in prelocked mode we either create temporary table
+ or prelocked mode is caused by the SELECT part of this statement.
+ */
+ DBUG_ASSERT(!thd->prelocked_mode ||
+ create_info->options & HA_LEX_CREATE_TMP_TABLE ||
+ thd->lex->requires_prelocking());
+
+ /*
+ NOTE: We don't want to ignore set of locked tables here if we are
+ under explicit LOCK TABLES since it will open gap for deadlock
+ too wide (and also is not backward compatible).
+ */
+ if (! (table= open_table(thd, create_table, thd->mem_root, (bool*) 0,
+ (MYSQL_LOCK_IGNORE_FLUSH |
+ ((thd->prelocked_mode == PRELOCKED) ?
+ MYSQL_OPEN_IGNORE_LOCKED_TABLES:0)))))
+ quick_rm_table(create_info->db_type, create_table->db,
+ table_case_name(create_info, create_table->table_name));
+ }
+ reenable_binlog(thd);
+ if (!table) // open failed
+ DBUG_RETURN(0);
+ }
+
+ /*
+ FIXME: What happens if trigger manages to be created while we are
+ obtaining this lock ? May be it is sensible just to disable
+ trigger execution in this case ? Or will MYSQL_LOCK_IGNORE_FLUSH
+ save us from that ?
+ */
+ table->reginfo.lock_type=TL_WRITE;
+ if (! ((*lock)= mysql_lock_tables(thd, &table, 1,
+ MYSQL_LOCK_IGNORE_FLUSH, &not_used)))
+ {
+ VOID(pthread_mutex_lock(&LOCK_open));
+ hash_delete(&open_cache,(byte*) table);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ quick_rm_table(create_info->db_type, create_table->db,
+ table_case_name(create_info, create_table->table_name));
+ DBUG_RETURN(0);
+ }
+ table->file->extra(HA_EXTRA_WRITE_CACHE);
+ DBUG_RETURN(table);
+}
+
+
int
select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index a8de7ff0154..7d62e5bb405 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -5709,6 +5709,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
}
else
{
+ DBUG_ASSERT(thd->net.report_error);
DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
thd->is_fatal_error));
query_cache_abort(&thd->net);
@@ -7226,7 +7227,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
lex->create_info.merge_list.first))
goto err;
if (grant_option && want_priv != CREATE_TMP_ACL &&
- check_grant(thd, want_priv, create_table, 0, UINT_MAX, 0))
+ check_grant(thd, want_priv, create_table, 0, 1, 0))
goto err;
if (select_lex->item_list.elements)
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 9eaadc58cb0..32a86b0f39a 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1796,105 +1796,6 @@ make_unique_key_name(const char *field_name,KEY *start,KEY *end)
/****************************************************************************
-** Create table from a list of fields and items
-****************************************************************************/
-
-TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
- TABLE_LIST *create_table,
- List<create_field> *extra_fields,
- List<Key> *keys,
- List<Item> *items,
- MYSQL_LOCK **lock)
-{
- TABLE tmp_table; // Used during 'create_field()'
- TABLE *table= 0;
- uint select_field_count= items->elements;
- /* Add selected items to field list */
- List_iterator_fast<Item> it(*items);
- Item *item;
- Field *tmp_field;
- bool not_used;
- DBUG_ENTER("create_table_from_items");
-
- tmp_table.alias= 0;
- tmp_table.timestamp_field= 0;
- tmp_table.s= &tmp_table.share_not_to_be_used;
- tmp_table.s->db_create_options=0;
- tmp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
- tmp_table.s->db_low_byte_first= test(create_info->db_type == DB_TYPE_MYISAM ||
- create_info->db_type == DB_TYPE_HEAP);
- tmp_table.null_row=tmp_table.maybe_null=0;
-
- while ((item=it++))
- {
- create_field *cr_field;
- Field *field;
- if (item->type() == Item::FUNC_ITEM)
- field=item->tmp_table_field(&tmp_table);
- else
- field=create_tmp_field(thd, &tmp_table, item, item->type(),
- (Item ***) 0, &tmp_field, 0, 0, 0, 0, 0);
- if (!field ||
- !(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ?
- ((Item_field *)item)->field :
- (Field*) 0))))
- DBUG_RETURN(0);
- if (item->maybe_null)
- cr_field->flags &= ~NOT_NULL_FLAG;
- extra_fields->push_back(cr_field);
- }
- /*
- create and lock table
-
- We don't log the statement, it will be logged later.
-
- If this is a HEAP table, the automatic DELETE FROM which is written to the
- binlog when a HEAP table is opened for the first time since startup, must
- not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we
- don't want to delete from it) 2) it would be written before the CREATE
- TABLE, which is a wrong order. So we keep binary logging disabled when we
- open_table().
- TODO: create and open should be done atomic !
- */
- {
- tmp_disable_binlog(thd);
- if (!mysql_create_table(thd, create_table->db, create_table->table_name,
- create_info, *extra_fields, *keys, 0,
- select_field_count))
- {
- if (! (table= open_table(thd, create_table, thd->mem_root, (bool*) 0,
- MYSQL_LOCK_IGNORE_FLUSH)))
- quick_rm_table(create_info->db_type, create_table->db,
- table_case_name(create_info, create_table->table_name));
- }
- reenable_binlog(thd);
- if (!table) // open failed
- DBUG_RETURN(0);
- }
-
- /*
- FIXME: What happens if trigger manages to be created while we are
- obtaining this lock ? May be it is sensible just to disable
- trigger execution in this case ? Or will MYSQL_LOCK_IGNORE_FLUSH
- save us from that ?
- */
- table->reginfo.lock_type=TL_WRITE;
- if (! ((*lock)= mysql_lock_tables(thd, &table, 1,
- MYSQL_LOCK_IGNORE_FLUSH, &not_used)))
- {
- VOID(pthread_mutex_lock(&LOCK_open));
- hash_delete(&open_cache,(byte*) table);
- VOID(pthread_mutex_unlock(&LOCK_open));
- quick_rm_table(create_info->db_type, create_table->db,
- table_case_name(create_info, create_table->table_name));
- DBUG_RETURN(0);
- }
- table->file->extra(HA_EXTRA_WRITE_CACHE);
- DBUG_RETURN(table);
-}
-
-
-/****************************************************************************
** Alter a table definition
****************************************************************************/
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 6473163a6ec..b2dbc517fa4 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -448,6 +448,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token NUMERIC_SYM
%token NVARCHAR_SYM
%token OFFSET_SYM
+%token OJ_SYM
%token OLD_PASSWORD
%token ON
%token ONE_SHOT_SYM
@@ -5246,11 +5247,14 @@ table_factor:
}
expr '}'
{
+ LEX *lex= Lex;
YYERROR_UNLESS($3 && $7);
add_join_on($7,$10);
Lex->pop_context();
$7->outer_join|=JOIN_TYPE_LEFT;
$$=$7;
+ if (!($$= lex->current_select->nest_last_join(lex->thd)))
+ YYABORT;
}
| select_derived_init get_select_lex select_derived2
{
@@ -5795,7 +5799,11 @@ select_var_ident:
if (lex->result)
((select_dumpvar *)lex->result)->var_list.push_back( new my_var($2,0,0,(enum_field_types)0));
else
- YYABORT;
+ /*
+ The parser won't create select_result instance only
+ if it's an EXPLAIN.
+ */
+ DBUG_ASSERT(lex->describe);
}
| ident_or_text
{
@@ -5807,10 +5815,8 @@ select_var_ident:
my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
YYABORT;
}
- if (! lex->result)
- YYABORT;
- else
- {
+ if (lex->result)
+ {
my_var *var;
((select_dumpvar *)lex->result)->
var_list.push_back(var= new my_var($1,1,t->offset,t->type));
@@ -5818,6 +5824,14 @@ select_var_ident:
if (var)
var->sp= lex->sphead;
#endif
+ }
+ else
+ {
+ /*
+ The parser won't create select_result instance only
+ if it's an EXPLAIN.
+ */
+ DBUG_ASSERT(lex->describe);
}
}
;
@@ -7206,12 +7220,18 @@ simple_ident_q:
YYABORT;
}
+ DBUG_ASSERT(!new_row ||
+ (lex->trg_chistics.event == TRG_EVENT_INSERT ||
+ lex->trg_chistics.event == TRG_EVENT_UPDATE));
+ const bool read_only=
+ !(new_row && lex->trg_chistics.action_time == TRG_ACTION_BEFORE);
if (!(trg_fld= new Item_trigger_field(Lex->current_context(),
new_row ?
Item_trigger_field::NEW_ROW:
Item_trigger_field::OLD_ROW,
$3.str,
- Item_trigger_field::AT_READ)))
+ SELECT_ACL,
+ read_only)))
YYABORT;
/*
@@ -7847,11 +7867,13 @@ sys_option_value:
it= new Item_null();
}
+ DBUG_ASSERT(lex->trg_chistics.action_time == TRG_ACTION_BEFORE &&
+ (lex->trg_chistics.event == TRG_EVENT_INSERT ||
+ lex->trg_chistics.event == TRG_EVENT_UPDATE));
if (!(trg_fld= new Item_trigger_field(Lex->current_context(),
Item_trigger_field::NEW_ROW,
$2.base_name.str,
- Item_trigger_field::AT_UPDATE)
- ) ||
+ UPDATE_ACL, FALSE)) ||
!(sp_fld= new sp_instr_set_trigger_field(lex->sphead->
instructions(),
lex->spcont,