summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2006-02-09 13:35:59 +0300
committerunknown <konstantin@mysql.com>2006-02-09 13:35:59 +0300
commitd7becbc2c8af24dd236ecdbb511a6a88745b9117 (patch)
tree5cb0dfc9bfbaf2c7fe5b62e6e2c4eb3240c19f9a
parent1b09a63e0785c549c9b801c74255d21f6c4934df (diff)
parent5ffc2dc202e49607b91851f3e44f60f49f175294 (diff)
downloadmariadb-git-d7becbc2c8af24dd236ecdbb511a6a88745b9117.tar.gz
Merge mysql.com:/home/kostja/mysql/mysql-5.0-root
into mysql.com:/home/kostja/mysql/mysql-5.1-merge BitKeeper/deleted/.del-ndb_load.result: Delete: mysql-test/r/ndb_load.result BitKeeper/deleted/.del-ndb_load.test: Delete: mysql-test/t/ndb_load.test extra/perror.c: Auto merged mysql-test/r/fulltext.result: Auto merged mysql-test/r/ndb_blob.result: Auto merged mysql-test/r/sp-code.result: Auto merged mysql-test/r/sp.result: Auto merged mysql-test/r/view.result: Auto merged mysql-test/t/fulltext.test: Auto merged mysql-test/t/sp-destruct.test: Auto merged mysql-test/t/sp.test: Auto merged mysql-test/t/view.test: Auto merged sql/ha_ndbcluster.cc: Auto merged sql/ha_ndbcluster.h: Auto merged sql/item_func.cc: Auto merged sql/opt_range.cc: Auto merged sql/sp.cc: Auto merged sql/sp.h: Auto merged sql/sp_head.cc: Auto merged sql/sp_head.h: Auto merged sql/sql_acl.cc: Auto merged sql/sql_base.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_load.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_prepare.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_yacc.yy: Auto merged storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp: Auto merged storage/ndb/src/kernel/main.cpp: Auto merged storage/ndb/src/kernel/vm/Configuration.cpp: Auto merged storage/ndb/src/kernel/vm/Configuration.hpp: Auto merged storage/ndb/src/ndbapi/NdbBlob.cpp: Auto merged storage/ndb/test/ndbapi/testBlobs.cpp: Auto merged storage/ndb/tools/delete_all.cpp: Auto merged mysql-test/t/disabled.def: Manual merge.
-rw-r--r--extra/perror.c16
-rw-r--r--mysql-test/r/fulltext.result11
-rw-r--r--mysql-test/r/func_math.result15
-rw-r--r--mysql-test/r/group_min_max.result27
-rw-r--r--mysql-test/r/having.result17
-rw-r--r--mysql-test/r/ndb_blob.result7
-rw-r--r--mysql-test/r/ndb_index_unique.result9
-rw-r--r--mysql-test/r/sp-code.result2
-rw-r--r--mysql-test/r/sp-destruct.result8
-rw-r--r--mysql-test/r/sp.result7
-rw-r--r--mysql-test/r/view.result34
-rw-r--r--mysql-test/t/disabled.def2
-rw-r--r--mysql-test/t/fulltext.test12
-rw-r--r--mysql-test/t/func_math.test14
-rw-r--r--mysql-test/t/group_min_max.test21
-rw-r--r--mysql-test/t/having.test16
-rw-r--r--mysql-test/t/ndb_blob.test6
-rw-r--r--mysql-test/t/ndb_index_unique.test14
-rw-r--r--mysql-test/t/sp-destruct.test11
-rw-r--r--mysql-test/t/sp.test5
-rw-r--r--mysql-test/t/view.test17
-rw-r--r--sql/ha_ndbcluster.cc4
-rw-r--r--sql/ha_ndbcluster.h1
-rw-r--r--sql/item_func.cc34
-rw-r--r--sql/item_func.h4
-rw-r--r--sql/opt_range.cc1
-rw-r--r--sql/sp.cc53
-rw-r--r--sql/sp.h5
-rw-r--r--sql/sp_head.cc85
-rw-r--r--sql/sp_head.h96
-rw-r--r--sql/sql_acl.cc2
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h1
-rw-r--r--sql/sql_parse.cc20
-rw-r--r--sql/sql_prepare.cc19
-rw-r--r--sql/sql_select.cc31
-rw-r--r--sql/sql_yacc.yy17
-rw-r--r--storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp2
-rw-r--r--storage/ndb/src/kernel/main.cpp24
-rw-r--r--storage/ndb/src/kernel/vm/Configuration.cpp17
-rw-r--r--storage/ndb/src/kernel/vm/Configuration.hpp10
-rw-r--r--storage/ndb/test/ndbapi/testBlobs.cpp84
-rw-r--r--storage/ndb/tools/delete_all.cpp31
43 files changed, 651 insertions, 163 deletions
diff --git a/extra/perror.c b/extra/perror.c
index e82ff08ad5d..3b7560837b9 100644
--- a/extra/perror.c
+++ b/extra/perror.c
@@ -239,10 +239,24 @@ int main(int argc,char *argv[])
if ((ndb_error_string(code, ndb_string, sizeof(ndb_string)) < 0) &&
(ndbd_exit_string(code, ndb_string, sizeof(ndb_string)) < 0))
{
- msg= 0;
+ msg= 0;
}
else
msg= ndb_string;
+ if (msg)
+ {
+ if (verbose)
+ printf("NDB error code %3d: %s\n",code,msg);
+ else
+ puts(msg);
+ }
+ else
+ {
+ fprintf(stderr,"Illegal ndb error code: %d\n",code);
+ error= 1;
+ }
+ found= 1;
+ msg= 0;
}
else
#endif
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index 4ee95cffb00..b5084fff165 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -449,3 +449,14 @@ t1 CREATE TABLE `t1` (
FULLTEXT KEY `a` (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
+CREATE TABLE t1 (a TEXT, FULLTEXT KEY(a));
+INSERT INTO t1 VALUES('test'),('test1'),('test');
+PREPARE stmt from "SELECT a, MATCH(a) AGAINST('test1 test') FROM t1 WHERE MATCH(a) AGAINST('test1 test')";
+EXECUTE stmt;
+a MATCH(a) AGAINST('test1 test')
+test1 0.68526661396027
+EXECUTE stmt;
+a MATCH(a) AGAINST('test1 test')
+test1 0.68526661396027
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index fba274b9bb1..1507f959ae6 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -203,3 +203,18 @@ NULL
Warnings:
Error 1365 Division by 0
set sql_mode='';
+select round(111,-10);
+round(111,-10)
+0
+select round(-5000111000111000155,-1);
+round(-5000111000111000155,-1)
+-5000111000111000160
+select round(15000111000111000155,-1);
+round(15000111000111000155,-1)
+15000111000111000160
+select truncate(-5000111000111000155,-1);
+truncate(-5000111000111000155,-1)
+-5000111000111000150
+select truncate(15000111000111000155,-1);
+truncate(15000111000111000155,-1)
+15000111000111000150
diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result
index 91579a7ea42..b1703c51f4e 100644
--- a/mysql-test/r/group_min_max.result
+++ b/mysql-test/r/group_min_max.result
@@ -2043,3 +2043,30 @@ c1 c2
30 8
30 9
drop table t1;
+CREATE TABLE t1 (a varchar(5), b int(11), PRIMARY KEY (a,b));
+INSERT INTO t1 VALUES ('AA',1), ('AA',2), ('AA',3), ('BB',1), ('AA',4);
+OPTIMIZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+SELECT a FROM t1 WHERE a='AA' GROUP BY a;
+a
+AA
+SELECT a FROM t1 WHERE a='BB' GROUP BY a;
+a
+BB
+EXPLAIN SELECT a FROM t1 WHERE a='AA' GROUP BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref PRIMARY PRIMARY 7 const 3 Using where; Using index
+EXPLAIN SELECT a FROM t1 WHERE a='BB' GROUP BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref PRIMARY PRIMARY 7 const 1 Using where; Using index
+SELECT DISTINCT a FROM t1 WHERE a='BB';
+a
+BB
+SELECT DISTINCT a FROM t1 WHERE a LIKE 'B%';
+a
+BB
+SELECT a FROM t1 WHERE a LIKE 'B%' GROUP BY a;
+a
+BB
+DROP TABLE t1;
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index 379c2f83c78..e54f6d7f2a4 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -141,6 +141,23 @@ SUM(a)
6
4
DROP TABLE t1;
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (1), (2), (1), (3), (2), (1);
+SELECT a FROM t1 GROUP BY a HAVING a > 1;
+a
+2
+3
+SELECT a FROM t1 GROUP BY a HAVING 1 != 1 AND a > 1;
+a
+SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1;
+x a
+EXPLAIN SELECT a FROM t1 GROUP BY a HAVING 1 != 1 AND a > 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible HAVING
+EXPLAIN SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible HAVING
+DROP table t1;
create table t1 (col1 int, col2 varchar(5), col_t1 int);
create table t2 (col1 int, col2 varchar(5), col_t2 int);
create table t3 (col1 int, col2 varchar(5), col_t3 int);
diff --git a/mysql-test/r/ndb_blob.result b/mysql-test/r/ndb_blob.result
index f28cb865962..9c76d46f4f0 100644
--- a/mysql-test/r/ndb_blob.result
+++ b/mysql-test/r/ndb_blob.result
@@ -428,6 +428,13 @@ delete from t1;
select * from t1;
a b
commit;
+replace t1 set a=2, b='y';
+select * from t1;
+a b
+2 y
+delete from t1;
+select * from t1;
+a b
drop table t1;
set autocommit=0;
create table t1 (
diff --git a/mysql-test/r/ndb_index_unique.result b/mysql-test/r/ndb_index_unique.result
index 1401ae26ddb..7864a5d1354 100644
--- a/mysql-test/r/ndb_index_unique.result
+++ b/mysql-test/r/ndb_index_unique.result
@@ -626,3 +626,12 @@ select * from t1 where code = '12' and month = 4 and year = 2004 ;
id month year code
1 4 2004 12
drop table t1;
+create table t1 (a int primary key, b varchar(1000) not null, unique key (b))
+engine=ndb charset=utf8;
+insert into t1 values (1, repeat(_utf8 0xe288ab6474, 200));
+insert into t1 values (2, repeat(_utf8 0xe288ab6474, 200));
+ERROR 23000: Duplicate entry '2' for key 1
+select a, sha1(b) from t1;
+a sha1(b)
+1 08f5d02c8b8bc244f275bdfc22c42c5cab0d9d7d
+drop table t1;
diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result
index bb0adae6bab..4156b351281 100644
--- a/mysql-test/r/sp-code.result
+++ b/mysql-test/r/sp-code.result
@@ -172,7 +172,7 @@ Pos Instruction
17 set v_col@8 NULL
18 stmt 0 "select row,col into v_row,v_col from ..."
19 stmt 0 "select dig into v_dig from sudoku_wor..."
-20 set_case_expr 0 v_dig@4
+20 set_case_expr (34) 0 v_dig@4
21 jump_if_not 25(34) (case_expr@0 = 0)
22 set v_dig@4 1
23 stmt 4 "update sudoku_work set dig = 1 where ..."
diff --git a/mysql-test/r/sp-destruct.result b/mysql-test/r/sp-destruct.result
index 1b720be9403..4df8086c84e 100644
--- a/mysql-test/r/sp-destruct.result
+++ b/mysql-test/r/sp-destruct.result
@@ -72,6 +72,12 @@ drop trigger t1_ai;
create trigger t1_ai after insert on t1 for each row call bug14233_3();
insert into t1 values (0);
ERROR HY000: Failed to load routine test.bug14233_3. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
-delete from mysql.proc where name like 'bug14233%';
drop trigger t1_ai;
drop table t1;
+drop function bug14233_1;
+drop function bug14233_2;
+drop procedure bug14233_3;
+show procedure status;
+Db Name Type Definer Modified Created Security_type Comment
+show function status;
+Db Name Type Definer Modified Created Security_type Comment
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 761d4b83a39..fd0913d3961 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -4011,8 +4011,6 @@ NULL 1
call bug14643_2()|
Handler
boo
-2
-2
Handler
boo
drop procedure bug14643_1|
@@ -4360,6 +4358,11 @@ Handler
error
End
done
+call bug14498_4()|
+Handler
+error
+End
+done
call bug14498_5()|
Handler
error
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index af49099836f..5396db82965 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -2495,3 +2495,37 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
DROP VIEW v1;
DROP TABLE t1;
+CREATE TABLE t1 (x varchar(10));
+INSERT INTO t1 VALUES (null), ('foo'), ('bar'), (null);
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT IF(x IS NULL, 'blank', 'not blank') FROM v1 GROUP BY x;
+IF(x IS NULL, 'blank', 'not blank')
+blank
+not blank
+not blank
+SELECT IF(x IS NULL, 'blank', 'not blank') AS x FROM t1 GROUP BY x;
+x
+blank
+not blank
+not blank
+Warnings:
+Warning 1052 Column 'x' in group statement is ambiguous
+SELECT IF(x IS NULL, 'blank', 'not blank') AS x FROM v1;
+x
+blank
+not blank
+not blank
+blank
+SELECT IF(x IS NULL, 'blank', 'not blank') AS y FROM v1 GROUP BY y;
+y
+blank
+not blank
+SELECT IF(x IS NULL, 'blank', 'not blank') AS x FROM v1 GROUP BY x;
+x
+blank
+not blank
+not blank
+Warnings:
+Warning 1052 Column 'x' in group statement is ambiguous
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
index 5010e8afb81..a3d00ae73fe 100644
--- a/mysql-test/t/disabled.def
+++ b/mysql-test/t/disabled.def
@@ -33,3 +33,5 @@ rpl_ndb_auto_inc : MySQL Bugs:17086
rpl_ndb_relay_space : Bug 16993
ndb_binlog_ddl_multi : Bug #17038
rpl_ndb_log : MySQL Bugs: #17158
+subselect : Bug#15706
+ndb_load : Bug #17233
diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test
index 7974b74081a..590a7dc495b 100644
--- a/mysql-test/t/fulltext.test
+++ b/mysql-test/t/fulltext.test
@@ -371,4 +371,16 @@ CREATE TABLE t1 (a VARCHAR(10000), FULLTEXT(a));
SHOW CREATE TABLE t1;
DROP TABLE t1;
+#
+# BUG#14496: Crash or strange results with prepared statement,
+# MATCH and FULLTEXT
+#
+CREATE TABLE t1 (a TEXT, FULLTEXT KEY(a));
+INSERT INTO t1 VALUES('test'),('test1'),('test');
+PREPARE stmt from "SELECT a, MATCH(a) AGAINST('test1 test') FROM t1 WHERE MATCH(a) AGAINST('test1 test')";
+EXECUTE stmt;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test
index 9cf0ee452cd..8dc4eb215c7 100644
--- a/mysql-test/t/func_math.test
+++ b/mysql-test/t/func_math.test
@@ -141,3 +141,17 @@ select log(2,-1);
select log(-2,1);
set sql_mode='';
+#
+# Bug #8461 truncate() and round() return false results 2nd argument negative.
+#
+# round(a,-b) log_10(b) > a
+select round(111,-10);
+# round on bigint
+select round(-5000111000111000155,-1);
+# round on unsigned bigint
+select round(15000111000111000155,-1);
+# truncate on bigint
+select truncate(-5000111000111000155,-1);
+# truncate on unsigned bigint
+select truncate(15000111000111000155,-1);
+
diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test
index e15ef92116c..8dc55532bbf 100644
--- a/mysql-test/t/group_min_max.test
+++ b/mysql-test/t/group_min_max.test
@@ -715,3 +715,24 @@ select distinct c1, c2 from t1 order by c2;
select c1,min(c2) as c2 from t1 group by c1 order by c2;
select c1,c2 from t1 group by c1,c2 order by c2;
drop table t1;
+
+#
+# Bug #16203: Analysis for possible min/max optimization erroneously
+# returns impossible range
+#
+
+CREATE TABLE t1 (a varchar(5), b int(11), PRIMARY KEY (a,b));
+INSERT INTO t1 VALUES ('AA',1), ('AA',2), ('AA',3), ('BB',1), ('AA',4);
+OPTIMIZE TABLE t1;
+
+SELECT a FROM t1 WHERE a='AA' GROUP BY a;
+SELECT a FROM t1 WHERE a='BB' GROUP BY a;
+
+EXPLAIN SELECT a FROM t1 WHERE a='AA' GROUP BY a;
+EXPLAIN SELECT a FROM t1 WHERE a='BB' GROUP BY a;
+
+SELECT DISTINCT a FROM t1 WHERE a='BB';
+SELECT DISTINCT a FROM t1 WHERE a LIKE 'B%';
+SELECT a FROM t1 WHERE a LIKE 'B%' GROUP BY a;
+
+DROP TABLE t1;
diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test
index 1cc894697f9..78628bef198 100644
--- a/mysql-test/t/having.test
+++ b/mysql-test/t/having.test
@@ -135,6 +135,22 @@ SELECT SUM(a) FROM t1 GROUP BY a HAVING SUM(a);
DROP TABLE t1;
+#
+# Bug #14927: HAVING clause containing constant false conjunct
+#
+
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (1), (2), (1), (3), (2), (1);
+
+SELECT a FROM t1 GROUP BY a HAVING a > 1;
+SELECT a FROM t1 GROUP BY a HAVING 1 != 1 AND a > 1;
+SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1;
+
+EXPLAIN SELECT a FROM t1 GROUP BY a HAVING 1 != 1 AND a > 1;
+EXPLAIN SELECT 0 AS x, a FROM t1 GROUP BY x,a HAVING x=1 AND a > 1;
+
+DROP table t1;
+
# End of 4.1 tests
#
diff --git a/mysql-test/t/ndb_blob.test b/mysql-test/t/ndb_blob.test
index a12ebee2f0d..f80b7f71281 100644
--- a/mysql-test/t/ndb_blob.test
+++ b/mysql-test/t/ndb_blob.test
@@ -338,7 +338,7 @@ select * from t1 order by a;
drop table t1;
drop database test2;
-# -- bug-5252 tinytext crashes plus no-commit result --
+# -- bug-5252 tinytext crashes + no-commit result + replace --
set autocommit=0;
create table t1 (
@@ -352,6 +352,10 @@ select * from t1;
delete from t1;
select * from t1;
commit;
+replace t1 set a=2, b='y';
+select * from t1;
+delete from t1;
+select * from t1;
drop table t1;
# -- bug-5013 insert empty string to text --
diff --git a/mysql-test/t/ndb_index_unique.test b/mysql-test/t/ndb_index_unique.test
index 2185276c2c6..8561b3794c4 100644
--- a/mysql-test/t/ndb_index_unique.test
+++ b/mysql-test/t/ndb_index_unique.test
@@ -309,4 +309,18 @@ select * from t1 where code = '12' and month = 4 and year = 2004 ;
drop table t1;
+# bug#15918 Unique Key Limit in NDB Engine
+
+create table t1 (a int primary key, b varchar(1000) not null, unique key (b))
+engine=ndb charset=utf8;
+
+insert into t1 values (1, repeat(_utf8 0xe288ab6474, 200));
+--error 1062
+insert into t1 values (2, repeat(_utf8 0xe288ab6474, 200));
+select a, sha1(b) from t1;
+
+# perl -e 'print pack("H2000","e288ab6474"x200)' | sha1sum
+
+drop table t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/sp-destruct.test b/mysql-test/t/sp-destruct.test
index 25f87f9e661..5fc81c338c6 100644
--- a/mysql-test/t/sp-destruct.test
+++ b/mysql-test/t/sp-destruct.test
@@ -127,6 +127,15 @@ create trigger t1_ai after insert on t1 for each row call bug14233_3();
insert into t1 values (0);
# Clean-up
-delete from mysql.proc where name like 'bug14233%';
drop trigger t1_ai;
drop table t1;
+
+#
+# BUG#16303: erroneus stored procedures and functions should be droppable
+#
+drop function bug14233_1;
+drop function bug14233_2;
+drop procedure bug14233_3;
+# Assert: These should show nothing.
+show procedure status;
+show function status;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 74585a0d3b7..45de4010535 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -5125,10 +5125,7 @@ end|
call bug14498_1()|
call bug14498_2()|
call bug14498_3()|
-# We couldn't call this before, due to a known bug (BUG#14643)
-# QQ We still can't since the new set_case_expr instruction breaks
-# the semantics of case; it won't crash, but will get the wrong result.
-#call bug14498_4()|
+call bug14498_4()|
call bug14498_5()|
drop procedure bug14498_1|
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index d5aff94e47c..5d1b5a80a9b 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -2358,3 +2358,20 @@ EXPLAIN SELECT MIN(a) FROM v1;
DROP VIEW v1;
DROP TABLE t1;
+
+#
+# Bug#16382: grouping name is resolved against a view column name
+# which coincides with a select column name
+
+CREATE TABLE t1 (x varchar(10));
+INSERT INTO t1 VALUES (null), ('foo'), ('bar'), (null);
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+SELECT IF(x IS NULL, 'blank', 'not blank') FROM v1 GROUP BY x;
+SELECT IF(x IS NULL, 'blank', 'not blank') AS x FROM t1 GROUP BY x;
+SELECT IF(x IS NULL, 'blank', 'not blank') AS x FROM v1;
+SELECT IF(x IS NULL, 'blank', 'not blank') AS y FROM v1 GROUP BY y;
+SELECT IF(x IS NULL, 'blank', 'not blank') AS x FROM v1 GROUP BY x;
+
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index f1fdfe86930..3ea9a53a61b 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -6199,6 +6199,10 @@ uint ha_ndbcluster::max_supported_key_length() const
{
return NDB_MAX_KEY_SIZE;
}
+uint ha_ndbcluster::max_supported_key_part_length() const
+{
+ return NDB_MAX_KEY_SIZE;
+}
bool ha_ndbcluster::low_byte_first() const
{
#ifdef WORDS_BIGENDIAN
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index f12b6198a68..65ec5956b27 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -604,6 +604,7 @@ class ha_ndbcluster: public handler
uint max_supported_keys() const;
uint max_supported_key_parts() const;
uint max_supported_key_length() const;
+ uint max_supported_key_part_length() const;
int rename_table(const char *from, const char *to);
int delete_table(const char *name);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 60b0dafefc5..22200732861 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1865,28 +1865,30 @@ longlong Item_func_round::int_op()
return value; // integer have not digits after point
abs_dec= -dec;
- double tmp;
- /*
- tmp2 is here to avoid return the value with 80 bit precision
- This will fix that the test round(0.1,1) = round(0.1,1) is true
- */
- volatile double tmp2;
-
- tmp= (abs_dec < array_elements(log_10) ?
- log_10[abs_dec] : pow(10.0, (double) abs_dec));
-
+ longlong tmp;
+
+ if(abs_dec >= array_elements(log_10_int))
+ return 0;
+
+ tmp= log_10_int[abs_dec];
+
if (truncate)
{
if (unsigned_flag)
- tmp2= floor(ulonglong2double(value)/tmp)*tmp;
- else if (value >= 0)
- tmp2= floor(((double)value)/tmp)*tmp;
+ value= (ulonglong(value)/tmp)*tmp;
else
- tmp2= ceil(((double)value)/tmp)*tmp;
+ value= (value/tmp)*tmp;
}
else
- tmp2= rint(((double)value)/tmp)*tmp;
- return (longlong)tmp2;
+ {
+ if (unsigned_flag)
+ value= ((ulonglong(value)+(tmp>>1))/tmp)*tmp;
+ else if ( value >= 0)
+ value= ((value+(tmp>>1))/tmp)*tmp;
+ else
+ value= ((value-(tmp>>1))/tmp)*tmp;
+ }
+ return value;
}
diff --git a/sql/item_func.h b/sql/item_func.h
index d81eb5f6ebf..d8fa45fb9c0 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1283,10 +1283,8 @@ public:
DBUG_ENTER("Item_func_match");
Item_real_func::cleanup();
if (!master && ft_handler)
- {
ft_handler->please->close_search(ft_handler);
- ft_handler=0;
- }
+ ft_handler= 0;
concat= 0;
DBUG_VOID_RETURN;
}
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 887690aecc1..c0f1abe597c 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -9068,6 +9068,7 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
quick_prefix_selectivity= (double) quick_prefix_records /
(double) table_records;
num_groups= (uint) rint(num_groups * quick_prefix_selectivity);
+ set_if_bigger(num_groups, 1);
}
if (used_key_parts > group_key_parts)
diff --git a/sql/sp.cc b/sql/sp.cc
index bf639b13a41..4838f839b4e 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -1003,22 +1003,26 @@ sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp,
}
+/*
+ This is used by sql_acl.cc:mysql_routine_grant() and is used to find
+ the routines in 'routines'.
+*/
int
-sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error)
+sp_exist_routines(THD *thd, TABLE_LIST *routines, bool any, bool no_error)
{
- TABLE_LIST *table;
+ TABLE_LIST *routine;
bool result= 0;
DBUG_ENTER("sp_exists_routine");
- for (table= tables; table; table= table->next_global)
+ for (routine= routines; routine; routine= routine->next_global)
{
sp_name *name;
LEX_STRING lex_db;
LEX_STRING lex_name;
- lex_db.length= strlen(table->db);
- lex_name.length= strlen(table->table_name);
- lex_db.str= thd->strmake(table->db, lex_db.length);
- lex_name.str= thd->strmake(table->table_name, lex_name.length);
+ lex_db.length= strlen(routine->db);
+ lex_name.length= strlen(routine->table_name);
+ lex_db.str= thd->strmake(routine->db, lex_db.length);
+ lex_name.str= thd->strmake(routine->table_name, lex_name.length);
name= new sp_name(lex_db, lex_name);
name->init_qname(thd);
if (sp_find_routine(thd, TYPE_ENUM_PROCEDURE, name,
@@ -1035,7 +1039,7 @@ sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error)
if (!no_error)
{
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION or PROCEDURE",
- table->table_name);
+ routine->table_name);
DBUG_RETURN(-1);
}
DBUG_RETURN(0);
@@ -1045,6 +1049,39 @@ sp_exists_routine(THD *thd, TABLE_LIST *tables, bool any, bool no_error)
}
+/*
+ Check if a routine exists in the mysql.proc table, without actually
+ parsing the definition. (Used for dropping)
+
+ SYNOPSIS
+ sp_routine_exists_in_table()
+ thd - thread context
+ name - name of procedure
+
+ RETURN VALUE
+ 0 - Success
+ non-0 - Error; SP_OPEN_TABLE_FAILED or SP_KEY_NOT_FOUND
+*/
+
+int
+sp_routine_exists_in_table(THD *thd, int type, sp_name *name)
+{
+ TABLE *table;
+ int ret;
+ Open_tables_state open_tables_state_backup;
+
+ if (!(table= open_proc_table_for_read(thd, &open_tables_state_backup)))
+ ret= SP_OPEN_TABLE_FAILED;
+ else
+ {
+ if ((ret= db_find_routine_aux(thd, type, name, table)) != SP_OK)
+ ret= SP_KEY_NOT_FOUND;
+ close_proc_table(thd, &open_tables_state_backup);
+ }
+ return ret;
+}
+
+
int
sp_create_procedure(THD *thd, sp_head *sp)
{
diff --git a/sql/sp.h b/sql/sp.h
index 53343e0fb25..2587a9b115a 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -40,7 +40,10 @@ sp_find_routine(THD *thd, int type, sp_name *name,
sp_cache **cp, bool cache_only);
int
-sp_exists_routine(THD *thd, TABLE_LIST *procs, bool any, bool no_error);
+sp_exist_routines(THD *thd, TABLE_LIST *procs, bool any, bool no_error);
+
+int
+sp_routine_exists_in_table(THD *thd, int type, sp_name *name);
int
sp_create_procedure(THD *thd, sp_head *sp);
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 62de35cc109..cf1097a28c6 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1776,7 +1776,7 @@ sp_head::fill_field_definition(THD *thd, LEX *lex,
void
-sp_head::new_cont_backpatch(sp_instr_jump_if_not *i)
+sp_head::new_cont_backpatch(sp_instr_opt_meta *i)
{
m_cont_level+= 1;
if (i)
@@ -1788,7 +1788,7 @@ sp_head::new_cont_backpatch(sp_instr_jump_if_not *i)
}
void
-sp_head::add_cont_backpatch(sp_instr_jump_if_not *i)
+sp_head::add_cont_backpatch(sp_instr_opt_meta *i)
{
i->m_cont_dest= m_cont_level;
(void)m_cont_backpatch.push_front(i);
@@ -1799,7 +1799,7 @@ sp_head::do_cont_backpatch()
{
uint dest= instructions();
uint lev= m_cont_level--;
- sp_instr_jump_if_not *i;
+ sp_instr_opt_meta *i;
while ((i= m_cont_backpatch.head()) && i->m_cont_dest == lev)
{
@@ -2063,10 +2063,10 @@ void sp_head::optimize()
set_dynamic(&m_instr, (gptr)&i, dst);
while ((ibp= li++))
- {
- sp_instr_jump *ji= static_cast<sp_instr_jump *>(ibp);
- ji->set_destination(src, dst);
- }
+ {
+ sp_instr_opt_meta *im= static_cast<sp_instr_opt_meta *>(ibp);
+ im->set_destination(src, dst);
+ }
}
i->opt_move(dst, &bp);
src+= 1;
@@ -2088,6 +2088,10 @@ sp_head::opt_mark(uint ip)
#ifndef DBUG_OFF
+/*
+ Return the routine instructions as a result set.
+ Returns 0 if ok, !=0 on error.
+*/
int
sp_head::show_routine_code(THD *thd)
{
@@ -2115,6 +2119,22 @@ sp_head::show_routine_code(THD *thd)
for (ip= 0; (i = get_instr(ip)) ; ip++)
{
+ /*
+ Consistency check. If these are different something went wrong
+ during optimization.
+ */
+ if (ip != i->m_ip)
+ {
+ const char *format= "Instruction at position %u has m_ip=%u";
+ char tmp[sizeof(format) + 2*SP_INSTR_UINT_MAXLEN + 1];
+
+ sprintf(tmp, format, ip, i->m_ip);
+ /*
+ Since this is for debugging purposes only, we don't bother to
+ introduce a special error code for it.
+ */
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, tmp);
+ }
protocol->prepare_for_resend();
protocol->store((longlong)ip);
@@ -2539,14 +2559,14 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp)
void
sp_instr_jump_if_not::print(String *str)
{
- /* jump_if_not dest ... */
+ /* jump_if_not dest(cont) ... */
if (str->reserve(2*SP_INSTR_UINT_MAXLEN+14+32)) // Add some for the expr. too
return;
str->qs_append(STRING_WITH_LEN("jump_if_not "));
str->qs_append(m_dest);
- str->append('(');
+ str->qs_append('(');
str->qs_append(m_cont_dest);
- str->append(") ");
+ str->qs_append(STRING_WITH_LEN(") "));
m_expr->print(str);
}
@@ -3092,30 +3112,53 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp)
spcont->clear_handler();
thd->spcont= spcont;
}
+ *nextp= m_cont_dest; /* For continue handler */
}
+ else
+ *nextp= m_ip+1;
- *nextp = m_ip+1;
-
- return res; /* no error */
+ return res;
}
void
sp_instr_set_case_expr::print(String *str)
{
- const char CASE_EXPR_TAG[]= "set_case_expr ";
- const int CASE_EXPR_TAG_LEN= sizeof(CASE_EXPR_TAG) - 1;
- const int INT_STRING_MAX_LEN= 10;
-
- /* We must call reserve(), because qs_append() doesn't care about memory. */
- str->reserve(CASE_EXPR_TAG_LEN + INT_STRING_MAX_LEN + 2);
-
- str->qs_append(CASE_EXPR_TAG, CASE_EXPR_TAG_LEN);
+ /* set_case_expr (cont) id ... */
+ str->reserve(2*SP_INSTR_UINT_MAXLEN+18+32); // Add some extra for expr too
+ str->qs_append(STRING_WITH_LEN("set_case_expr ("));
+ str->qs_append(m_cont_dest);
+ str->qs_append(STRING_WITH_LEN(") "));
str->qs_append(m_case_expr_id);
str->qs_append(' ');
m_case_expr->print(str);
}
+uint
+sp_instr_set_case_expr::opt_mark(sp_head *sp)
+{
+ sp_instr *i;
+
+ marked= 1;
+ if ((i= sp->get_instr(m_cont_dest)))
+ {
+ m_cont_dest= i->opt_shortcut_jump(sp, this);
+ m_cont_optdest= sp->get_instr(m_cont_dest);
+ }
+ sp->opt_mark(m_cont_dest);
+ return m_ip+1;
+}
+
+void
+sp_instr_set_case_expr::opt_move(uint dst, List<sp_instr> *bp)
+{
+ if (m_cont_dest > m_ip)
+ bp->push_back(this); // Forward
+ else if (m_cont_optdest)
+ m_cont_dest= m_cont_optdest->m_ip; // Backward
+ m_ip= dst;
+}
+
/* ------------------------------------------------------------------ */
diff --git a/sql/sp_head.h b/sql/sp_head.h
index f9c37090322..a637c466041 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -41,6 +41,7 @@ sp_get_flags_for_command(LEX *lex);
struct sp_label;
class sp_instr;
+class sp_instr_opt_meta;
class sp_instr_jump_if_not;
struct sp_cond_type;
struct sp_pvar;
@@ -270,11 +271,11 @@ public:
// Start a new cont. backpatch level. If 'i' is NULL, the level is just incr.
void
- new_cont_backpatch(sp_instr_jump_if_not *i);
+ new_cont_backpatch(sp_instr_opt_meta *i);
// Add an instruction to the current level
void
- add_cont_backpatch(sp_instr_jump_if_not *i);
+ add_cont_backpatch(sp_instr_opt_meta *i);
// Backpatch (and pop) the current level to the current position.
void
@@ -371,15 +372,15 @@ private:
} bp_t;
List<bp_t> m_backpatch; // Instructions needing backpatching
/*
- We need a special list for backpatching of conditional jump's continue
+ We need a special list for backpatching of instructions with a continue
destination (in the case of a continue handler catching an error in
the test), since it would otherwise interfere with the normal backpatch
- mechanism - jump_if_not instructions have two different destination
+ mechanism - e.g. jump_if_not instructions have two different destinations
which are to be patched differently.
Since these occur in a more restricted way (always the same "level" in
the code), we don't need the label.
*/
- List<sp_instr_jump_if_not> m_cont_backpatch;
+ List<sp_instr_opt_meta> m_cont_backpatch;
uint m_cont_level; // The current cont. backpatch level
/*
@@ -676,21 +677,55 @@ private:
}; // class sp_instr_trigger_field : public sp_instr
-class sp_instr_jump : public sp_instr
+/*
+ An abstract class for all instructions with destinations that
+ needs to be updated by the optimizer.
+ Even if not all subclasses will use both the normal destination and
+ the continuation destination, we put them both here for simplicity.
+ */
+class sp_instr_opt_meta : public sp_instr
+{
+public:
+
+ uint m_dest; // Where we will go
+ uint m_cont_dest; // Where continue handlers will go
+
+ sp_instr_opt_meta(uint ip, sp_pcontext *ctx)
+ : sp_instr(ip, ctx),
+ m_dest(0), m_cont_dest(0), m_optdest(0), m_cont_optdest(0)
+ {}
+
+ sp_instr_opt_meta(uint ip, sp_pcontext *ctx, uint dest)
+ : sp_instr(ip, ctx),
+ m_dest(dest), m_cont_dest(0), m_optdest(0), m_cont_optdest(0)
+ {}
+
+ virtual ~sp_instr_opt_meta()
+ {}
+
+ virtual void set_destination(uint old_dest, uint new_dest)
+ = 0;
+
+protected:
+
+ sp_instr *m_optdest; // Used during optimization
+ sp_instr *m_cont_optdest; // Used during optimization
+
+}; // class sp_instr_opt_meta : public sp_instr
+
+class sp_instr_jump : public sp_instr_opt_meta
{
sp_instr_jump(const sp_instr_jump &); /* Prevent use of these */
void operator=(sp_instr_jump &);
public:
- uint m_dest; // Where we will go
-
sp_instr_jump(uint ip, sp_pcontext *ctx)
- : sp_instr(ip, ctx), m_dest(0), m_optdest(0)
+ : sp_instr_opt_meta(ip, ctx)
{}
sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest)
- : sp_instr(ip, ctx), m_dest(dest), m_optdest(0)
+ : sp_instr_opt_meta(ip, ctx, dest)
{}
virtual ~sp_instr_jump()
@@ -721,11 +756,7 @@ public:
m_dest= new_dest;
}
-protected:
-
- sp_instr *m_optdest; // Used during optimization
-
-}; // class sp_instr_jump : public sp_instr
+}; // class sp_instr_jump : public sp_instr_opt_meta
class sp_instr_jump_if_not : public sp_instr_jump
@@ -735,16 +766,14 @@ class sp_instr_jump_if_not : public sp_instr_jump
public:
- uint m_cont_dest; // Where continue handlers will go
-
sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, LEX *lex)
- : sp_instr_jump(ip, ctx), m_cont_dest(0), m_expr(i),
- m_lex_keeper(lex, TRUE), m_cont_optdest(0)
+ : sp_instr_jump(ip, ctx), m_expr(i),
+ m_lex_keeper(lex, TRUE)
{}
sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex)
- : sp_instr_jump(ip, ctx, dest), m_cont_dest(0), m_expr(i),
- m_lex_keeper(lex, TRUE), m_cont_optdest(0)
+ : sp_instr_jump(ip, ctx, dest), m_expr(i),
+ m_lex_keeper(lex, TRUE)
{}
virtual ~sp_instr_jump_if_not()
@@ -777,7 +806,6 @@ private:
Item *m_expr; // The condition
sp_lex_keeper m_lex_keeper;
- sp_instr *m_cont_optdest; // Used during optimization
}; // class sp_instr_jump_if_not : public sp_instr_jump
@@ -911,7 +939,7 @@ private:
uint m_frame;
-}; // class sp_instr_hreturn : public sp_instr
+}; // class sp_instr_hreturn : public sp_instr_jump
/* This is DECLARE CURSOR */
@@ -1088,14 +1116,18 @@ private:
}; // class sp_instr_error : public sp_instr
-class sp_instr_set_case_expr :public sp_instr
+class sp_instr_set_case_expr : public sp_instr_opt_meta
{
public:
sp_instr_set_case_expr(uint ip, sp_pcontext *ctx, uint case_expr_id,
Item *case_expr, LEX *lex)
- :sp_instr(ip, ctx), m_case_expr_id(case_expr_id), m_case_expr(case_expr),
- m_lex_keeper(lex, TRUE)
+ : sp_instr_opt_meta(ip, ctx),
+ m_case_expr_id(case_expr_id), m_case_expr(case_expr),
+ m_lex_keeper(lex, TRUE)
+ {}
+
+ virtual ~sp_instr_set_case_expr()
{}
virtual int execute(THD *thd, uint *nextp);
@@ -1104,13 +1136,23 @@ public:
virtual void print(String *str);
+ virtual uint opt_mark(sp_head *sp);
+
+ virtual void opt_move(uint dst, List<sp_instr> *ibp);
+
+ virtual void set_destination(uint old_dest, uint new_dest)
+ {
+ if (m_cont_dest == old_dest)
+ m_cont_dest= new_dest;
+ }
+
private:
uint m_case_expr_id;
Item *m_case_expr;
sp_lex_keeper m_lex_keeper;
-}; // class sp_instr_set_case_expr : public sp_instr
+}; // class sp_instr_set_case_expr : public sp_instr_opt_meta
#ifndef NO_EMBEDDED_ACCESS_CHECKS
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index cfcdd6d9e61..49f05a29ef3 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3045,7 +3045,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
if (!revoke_grant)
{
- if (sp_exists_routine(thd, table_list, is_proc, no_error)<0)
+ if (sp_exist_routines(thd, table_list, is_proc, no_error)<0)
DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index a9050ddf277..20c71ae738b 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1128,7 +1128,7 @@ void st_select_lex::init_query()
embedding= leaf_tables= 0;
item_list.empty();
join= 0;
- having= where= prep_where= 0;
+ having= prep_having= where= prep_where= 0;
olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0;
context.select_lex= this;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 07a42f7af2c..6b83525ba18 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -493,6 +493,7 @@ public:
char *db;
Item *where, *having; /* WHERE & HAVING clauses */
Item *prep_where; /* saved WHERE clause for prepared statement processing */
+ Item *prep_having;/* saved HAVING clause for prepared statement processing */
/* point on lex in which it was created, used in view subquery detection */
st_lex *parent_lex;
enum olap_type olap;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 279a02fa1d1..03f3dc8649c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4490,21 +4490,17 @@ end_with_restore_list:
case SQLCOM_DROP_PROCEDURE:
case SQLCOM_DROP_FUNCTION:
{
- sp_head *sp;
int result;
- char *db, *name;
+ int type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ?
+ TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
- if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
- sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
- &thd->sp_proc_cache, FALSE);
- else
- sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
- &thd->sp_func_cache, FALSE);
+ result= sp_routine_exists_in_table(thd, type, lex->spname);
mysql_reset_errors(thd, 0);
- if (sp)
+ if (result == SP_OK)
{
- db= thd->strdup(sp->m_db.str);
- name= thd->strdup(sp->m_name.str);
+ char *db= lex->spname->m_db.str;
+ char *name= lex->spname->m_name.str;
+
if (check_routine_access(thd, ALTER_PROC_ACL, db, name,
lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
goto error;
@@ -4644,7 +4640,7 @@ end_with_restore_list:
else
sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
&thd->sp_func_cache, FALSE);
- if (!sp || !sp->show_routine_code(thd))
+ if (!sp || sp->show_routine_code(thd))
{
/* We don't distinguish between errors for now */
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index cb080ba68e0..010c1250756 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2075,14 +2075,19 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
sl->exclude_from_table_unique_test= FALSE;
/*
- Copy WHERE clause pointers to avoid damaging they by optimisation
+ Copy WHERE, HAVING clause pointers to avoid damaging them by optimisation
*/
- if (sl->prep_where)
- {
- sl->where= sl->prep_where->copy_andor_structure(thd);
- sl->where->cleanup();
- }
- DBUG_ASSERT(sl->join == 0);
+ if (sl->prep_where)
+ {
+ sl->where= sl->prep_where->copy_andor_structure(thd);
+ sl->where->cleanup();
+ }
+ if (sl->prep_having)
+ {
+ sl->having= sl->prep_having->copy_andor_structure(thd);
+ sl->having->cleanup();
+ }
+ DBUG_ASSERT(sl->join == 0);
ORDER *order;
/* Fix GROUP list */
for (order= (ORDER *)sl->group_list.first; order; order= order->next)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index c5aca91c9e9..cafcd94632a 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -612,6 +612,7 @@ JOIN::optimize()
build_bitmap_for_nested_joins(join_list, 0);
sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
+ sel->prep_having= having ? having->copy_andor_structure(thd) : 0;
if (arena)
thd->restore_active_arena(arena, &backup);
@@ -625,13 +626,26 @@ JOIN::optimize()
DBUG_RETURN(1);
}
- if (cond_value == Item::COND_FALSE ||
- (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
- { /* Impossible cond */
- DBUG_PRINT("info", ("Impossible WHERE"));
- zero_result_cause= "Impossible WHERE";
- error= 0;
- DBUG_RETURN(0);
+ {
+ Item::cond_result having_value;
+ having= optimize_cond(this, having, join_list, &having_value);
+ if (thd->net.report_error)
+ {
+ error= 1;
+ DBUG_PRINT("error",("Error from optimize_cond"));
+ DBUG_RETURN(1);
+ }
+
+ if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE ||
+ (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
+ { /* Impossible cond */
+ DBUG_PRINT("info", (having_value == Item::COND_FALSE ?
+ "Impossible HAVING" : "Impossible WHERE"));
+ zero_result_cause= having_value == Item::COND_FALSE ?
+ "Impossible HAVING" : "Impossible WHERE";
+ error= 0;
+ DBUG_RETURN(0);
+ }
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
@@ -12472,7 +12486,8 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
overshadows the column reference from the SELECT list.
*/
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR,
- ER(ER_NON_UNIQ_ERROR), from_field->field_name,
+ ER(ER_NON_UNIQ_ERROR),
+ ((Item_ident*) order_item)->field_name,
current_thd->where);
}
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 79651f2e49e..76b9b410611 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2400,17 +2400,18 @@ sp_proc_stmt_case:
sp_head *sp= lex->sphead;
sp_pcontext *parsing_ctx= lex->spcont;
int case_expr_id= parsing_ctx->register_case_expr();
+ sp_instr_set_case_expr *i;
if (parsing_ctx->push_case_expr_id(case_expr_id))
YYABORT;
-
- sp->add_instr(
- new sp_instr_set_case_expr(sp->instructions(),
- parsing_ctx,
- case_expr_id,
- $3,
- lex));
-
+
+ i= new sp_instr_set_case_expr(sp->instructions(),
+ parsing_ctx,
+ case_expr_id,
+ $3,
+ lex);
+ sp->add_cont_backpatch(i);
+ sp->add_instr(i);
sp->m_flags|= sp_head::IN_SIMPLE_CASE;
sp->restore_lex(YYTHD);
}
diff --git a/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp b/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
index 2794990d608..5b1f85f1dd6 100644
--- a/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
+++ b/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
@@ -1061,7 +1061,7 @@ private:
Uint32 cexcPrevforward;
Uint32 clocalkey[32];
union {
- Uint32 ckeys[2048];
+ Uint32 ckeys[2048 * MAX_XFRM_MULTIPLY];
Uint64 ckeys_align;
};
diff --git a/storage/ndb/src/kernel/main.cpp b/storage/ndb/src/kernel/main.cpp
index 4bc9fbf76e5..7c1763485ce 100644
--- a/storage/ndb/src/kernel/main.cpp
+++ b/storage/ndb/src/kernel/main.cpp
@@ -63,8 +63,10 @@ extern "C" void handler_sigusr1(int signum); // child signalling failed restart
void systemInfo(const Configuration & conf,
const LogLevel & ll);
-static FILE *child_info_file_r= 0;
-static FILE *child_info_file_w= 0;
+// These are used already before fork if fetch_configuration() fails
+// (e.g. Unable to alloc node id). Set them to something reasonable.
+static FILE *child_info_file_r= stdin;
+static FILE *child_info_file_w= stdout;
static void writeChildInfo(const char *token, int val)
{
@@ -270,8 +272,8 @@ int main(int argc, char** argv)
#ifndef NDB_WIN32
signal(SIGUSR1, handler_sigusr1);
- pid_t child;
- while (1)
+ pid_t child = -1;
+ while (! theConfig->getForegroundMode()) // the cond is const
{
// setup reporting between child and parent
int filedes[2];
@@ -393,8 +395,10 @@ int main(int argc, char** argv)
if (child >= 0)
g_eventLogger.info("Angel pid: %d ndb pid: %d", getppid(), getpid());
- else
+ else if (child > 0)
g_eventLogger.info("Ndb pid: %d", getpid());
+ else
+ g_eventLogger.info("Ndb started in foreground");
#else
g_eventLogger.info("Ndb started");
#endif
@@ -569,10 +573,7 @@ catchsigs(bool ignore){
#ifdef SIGPOLL
SIGPOLL,
#endif
- SIGSEGV,
-#ifdef SIGTRAP
- SIGTRAP
-#endif
+ SIGSEGV
};
static const int signals_ignore[] = {
@@ -586,6 +587,11 @@ catchsigs(bool ignore){
handler_register(signals_error[i], handler_error, ignore);
for(i = 0; i < sizeof(signals_ignore)/sizeof(signals_ignore[0]); i++)
handler_register(signals_ignore[i], SIG_IGN, ignore);
+#ifdef SIGTRAP
+ Configuration* theConfig = globalEmulatorData.theConfiguration;
+ if (! theConfig->getForegroundMode())
+ handler_register(SIGTRAP, handler_error, ignore);
+#endif
#endif
}
diff --git a/storage/ndb/src/kernel/vm/Configuration.cpp b/storage/ndb/src/kernel/vm/Configuration.cpp
index 771fa6f5fe4..5f3b601023f 100644
--- a/storage/ndb/src/kernel/vm/Configuration.cpp
+++ b/storage/ndb/src/kernel/vm/Configuration.cpp
@@ -48,11 +48,13 @@ extern EventLogger g_eventLogger;
enum ndbd_options {
OPT_INITIAL = NDB_STD_OPTIONS_LAST,
- OPT_NODAEMON
+ OPT_NODAEMON,
+ OPT_FOREGROUND
};
NDB_STD_OPTS_VARS;
-static int _daemon, _no_daemon, _initial, _no_start;
+// XXX should be my_bool ???
+static int _daemon, _no_daemon, _foreground, _initial, _no_start;
/**
* Arguments to NDB process
*/
@@ -75,6 +77,11 @@ static struct my_option my_long_options[] =
"Do not start ndbd as daemon, provided for testing purposes",
(gptr*) &_no_daemon, (gptr*) &_no_daemon, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "foreground", OPT_FOREGROUND,
+ "Run real ndbd in foreground, provided for debugging purposes"
+ " (implies --nodaemon)",
+ (gptr*) &_foreground, (gptr*) &_foreground, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
static void short_usage_sub(void)
@@ -103,13 +110,14 @@ Configuration::init(int argc, char** argv)
ndb_std_get_one_option)))
exit(ho_error);
- if (_no_daemon) {
+ if (_no_daemon || _foreground) {
_daemon= 0;
}
DBUG_PRINT("info", ("no_start=%d", _no_start));
DBUG_PRINT("info", ("initial=%d", _initial));
DBUG_PRINT("info", ("daemon=%d", _daemon));
+ DBUG_PRINT("info", ("foreground=%d", _foreground));
DBUG_PRINT("info", ("connect_str=%s", opt_connect_str));
ndbSetOwnVersion();
@@ -131,6 +139,8 @@ Configuration::init(int argc, char** argv)
// Check daemon flag
if (_daemon)
_daemonMode = true;
+ if (_foreground)
+ _foregroundMode = true;
// Save programname
if(argc > 0 && argv[0] != 0)
@@ -151,6 +161,7 @@ Configuration::Configuration()
_backupPath = 0;
_initialStart = false;
_daemonMode = false;
+ _foregroundMode = false;
m_config_retriever= 0;
m_clusterConfig= 0;
m_clusterConfigIter= 0;
diff --git a/storage/ndb/src/kernel/vm/Configuration.hpp b/storage/ndb/src/kernel/vm/Configuration.hpp
index 243ecbee4e7..6315209ddbb 100644
--- a/storage/ndb/src/kernel/vm/Configuration.hpp
+++ b/storage/ndb/src/kernel/vm/Configuration.hpp
@@ -64,6 +64,7 @@ public:
bool getInitialStart() const;
void setInitialStart(bool val);
bool getDaemonMode() const;
+ bool getForegroundMode() const;
const ndb_mgm_configuration_iterator * getOwnConfigIterator() const;
@@ -105,7 +106,8 @@ private:
char * _connectString;
Uint32 m_mgmd_port;
BaseString m_mgmd_host;
- bool _daemonMode;
+ bool _daemonMode; // if not, angel in foreground
+ bool _foregroundMode; // no angel, raw ndbd in foreground
void calcSizeAlt(class ConfigValues * );
};
@@ -140,4 +142,10 @@ Configuration::getDaemonMode() const {
return _daemonMode;
}
+inline
+bool
+Configuration::getForegroundMode() const {
+ return _foregroundMode;
+}
+
#endif
diff --git a/storage/ndb/test/ndbapi/testBlobs.cpp b/storage/ndb/test/ndbapi/testBlobs.cpp
index 506ff188ff6..fff5ac247df 100644
--- a/storage/ndb/test/ndbapi/testBlobs.cpp
+++ b/storage/ndb/test/ndbapi/testBlobs.cpp
@@ -839,9 +839,6 @@ insertPk(int style)
CHK(g_con->execute(NoCommit) == 0);
CHK(writeBlobData(tup) == 0);
}
- // just another trap
- if (urandom(10) == 0)
- CHK(g_con->execute(NoCommit) == 0);
if (++n == g_opt.m_batch) {
CHK(g_con->execute(Commit) == 0);
g_ndb->closeTransaction(g_con);
@@ -963,21 +960,31 @@ static int
deletePk()
{
DBG("--- deletePk ---");
+ unsigned n = 0;
+ CHK((g_con = g_ndb->startTransaction()) != 0);
for (unsigned k = 0; k < g_opt.m_rows; k++) {
Tup& tup = g_tups[k];
DBG("deletePk pk1=" << hex << tup.m_pk1);
- CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
CHK(g_opr->deleteTuple() == 0);
CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
if (g_opt.m_pk2len != 0)
CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
- CHK(g_con->execute(Commit) == 0);
- g_ndb->closeTransaction(g_con);
+ if (++n == g_opt.m_batch) {
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ n = 0;
+ }
g_opr = 0;
- g_con = 0;
tup.m_exists = false;
}
+ if (n != 0) {
+ CHK(g_con->execute(Commit) == 0);
+ n = 0;
+ }
+ g_ndb->closeTransaction(g_con);
+ g_con = 0;
return 0;
}
@@ -1080,19 +1087,27 @@ static int
deleteIdx()
{
DBG("--- deleteIdx ---");
+ unsigned n = 0;
+ CHK((g_con = g_ndb->startTransaction()) != 0);
for (unsigned k = 0; k < g_opt.m_rows; k++) {
Tup& tup = g_tups[k];
DBG("deleteIdx pk1=" << hex << tup.m_pk1);
- CHK((g_con = g_ndb->startTransaction()) != 0);
CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0);
CHK(g_opx->deleteTuple() == 0);
CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
- CHK(g_con->execute(Commit) == 0);
- g_ndb->closeTransaction(g_con);
+ if (++n == g_opt.m_batch) {
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ n = 0;
+ }
g_opx = 0;
- g_con = 0;
tup.m_exists = false;
}
+ if (n != 0) {
+ CHK(g_con->execute(Commit) == 0);
+ n = 0;
+ }
return 0;
}
@@ -1220,20 +1235,49 @@ deleteScan(bool idx)
CHK(g_ops->getValue("PK2", tup.m_pk2) != 0);
CHK(g_con->execute(NoCommit) == 0);
unsigned rows = 0;
+ unsigned n = 0;
while (1) {
int ret;
tup.m_pk1 = (Uint32)-1;
memset(tup.m_pk2, 'x', g_opt.m_pk2len);
- CHK((ret = g_ops->nextResult()) == 0 || ret == 1);
+ CHK((ret = g_ops->nextResult(true)) == 0 || ret == 1);
if (ret == 1)
break;
- DBG("deleteScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1);
- CHK(g_ops->deleteCurrentTuple() == 0);
- CHK(g_con->execute(NoCommit) == 0);
- Uint32 k = tup.m_pk1 - g_opt.m_pk1off;
- CHK(k < g_opt.m_rows && g_tups[k].m_exists);
- g_tups[k].m_exists = false;
- rows++;
+ while (1) {
+ DBG("deleteScan" << (idx ? "Idx" : "") << " pk1=" << hex << tup.m_pk1);
+ Uint32 k = tup.m_pk1 - g_opt.m_pk1off;
+ CHK(k < g_opt.m_rows && g_tups[k].m_exists);
+ g_tups[k].m_exists = false;
+ CHK(g_ops->deleteCurrentTuple() == 0);
+ rows++;
+ tup.m_pk1 = (Uint32)-1;
+ memset(tup.m_pk2, 'x', g_opt.m_pk2len);
+ CHK((ret = g_ops->nextResult(false)) == 0 || ret == 1 || ret == 2);
+ if (++n == g_opt.m_batch || ret == 2) {
+ DBG("execute batch: n=" << n << " ret=" << ret);
+ switch (0) {
+ case 0: // works normally
+ CHK(g_con->execute(NoCommit) == 0);
+ CHK(true || g_con->restart() == 0);
+ break;
+ case 1: // nonsense - g_con is invalid for 2nd batch
+ CHK(g_con->execute(Commit) == 0);
+ CHK(true || g_con->restart() == 0);
+ break;
+ case 2: // DBTC sendSignalErrorRefuseLab
+ CHK(g_con->execute(NoCommit) == 0);
+ CHK(g_con->restart() == 0);
+ break;
+ case 3: // 266 time-out
+ CHK(g_con->execute(Commit) == 0);
+ CHK(g_con->restart() == 0);
+ break;
+ }
+ n = 0;
+ }
+ if (ret == 2)
+ break;
+ }
}
CHK(g_con->execute(Commit) == 0);
g_ndb->closeTransaction(g_con);
@@ -1256,7 +1300,7 @@ static int
testmain()
{
g_ndb = new Ndb(g_ncc, "TEST_DB");
- CHK(g_ndb->init() == 0);
+ CHK(g_ndb->init(20) == 0);
CHK(g_ndb->waitUntilReady() == 0);
g_dic = g_ndb->getDictionary();
g_tups = new Tup [g_opt.m_rows];
diff --git a/storage/ndb/tools/delete_all.cpp b/storage/ndb/tools/delete_all.cpp
index 6b7453d4d55..feedded06ad 100644
--- a/storage/ndb/tools/delete_all.cpp
+++ b/storage/ndb/tools/delete_all.cpp
@@ -22,7 +22,8 @@
#include <NdbSleep.h>
#include <NDBT.hpp>
-static int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism=240);
+static int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
+ bool commit_across_open_cursor, int parallelism=240);
NDB_STD_OPTS_VARS;
@@ -83,8 +84,18 @@ int main(int argc, char** argv){
ndbout << " Table " << argv[i] << " does not exist!" << endl;
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
+ // Check if we have any blobs
+ bool commit_across_open_cursor = true;
+ for (int j = 0; j < pTab->getNoOfColumns(); j++) {
+ NdbDictionary::Column::Type t = pTab->getColumn(j)->getType();
+ if (t == NdbDictionary::Column::Blob ||
+ t == NdbDictionary::Column::Text) {
+ commit_across_open_cursor = false;
+ break;
+ }
+ }
ndbout << "Deleting all from " << argv[i] << "...";
- if(clear_table(&MyNdb, pTab) == NDBT_FAILED){
+ if(clear_table(&MyNdb, pTab, commit_across_open_cursor) == NDBT_FAILED){
res = NDBT_FAILED;
ndbout << "FAILED" << endl;
}
@@ -93,7 +104,8 @@ int main(int argc, char** argv){
}
-int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism)
+int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
+ bool commit_across_open_cursor, int parallelism)
{
// Scan all records exclusive and delete
// them one by one
@@ -155,8 +167,12 @@ int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism)
} while((check = pOp->nextResult(false)) == 0);
if(check != -1){
- check = pTrans->execute(NdbTransaction::Commit);
- pTrans->restart();
+ if (commit_across_open_cursor) {
+ check = pTrans->execute(NdbTransaction::Commit);
+ pTrans->restart(); // new tx id
+ } else {
+ check = pTrans->execute(NdbTransaction::NoCommit);
+ }
}
err = pTrans->getNdbError();
@@ -182,6 +198,11 @@ int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism)
}
goto failed;
}
+ if (! commit_across_open_cursor &&
+ pTrans->execute(NdbTransaction::Commit) != 0) {
+ err = pTrans->getNdbError();
+ goto failed;
+ }
pNdb->closeTransaction(pTrans);
return NDBT_OK;
}