summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BitKeeper/etc/logging_ok1
-rw-r--r--include/my_sys.h7
-rw-r--r--include/mysqld_error.h2
-rw-r--r--mysql-test/r/case.result2
-rw-r--r--mysql-test/r/func_if.result2
-rw-r--r--mysql-test/r/func_in.result2
-rw-r--r--mysql-test/r/func_test.result2
-rw-r--r--mysql-test/r/sp-error.result23
-rw-r--r--mysql-test/r/sp.result18
-rw-r--r--mysql-test/r/subselect.result4
-rw-r--r--mysql-test/r/view.result108
-rw-r--r--mysql-test/t/sp-error.test23
-rw-r--r--mysql-test/t/sp.test24
-rw-r--r--mysql-test/t/view.test126
-rw-r--r--mysys/default.c316
-rw-r--r--sql/item.cc57
-rw-r--r--sql/item.h8
-rw-r--r--sql/item_func.cc18
-rw-r--r--sql/item_strfunc.cc12
-rw-r--r--sql/item_strfunc.h2
-rw-r--r--sql/item_timefunc.cc2
-rw-r--r--sql/share/czech/errmsg.txt2
-rw-r--r--sql/share/danish/errmsg.txt2
-rw-r--r--sql/share/dutch/errmsg.txt2
-rw-r--r--sql/share/english/errmsg.txt2
-rw-r--r--sql/share/estonian/errmsg.txt2
-rw-r--r--sql/share/french/errmsg.txt2
-rw-r--r--sql/share/german/errmsg.txt2
-rw-r--r--sql/share/greek/errmsg.txt2
-rw-r--r--sql/share/hungarian/errmsg.txt2
-rw-r--r--sql/share/italian/errmsg.txt2
-rw-r--r--sql/share/japanese/errmsg.txt2
-rw-r--r--sql/share/korean/errmsg.txt2
-rw-r--r--sql/share/norwegian-ny/errmsg.txt2
-rw-r--r--sql/share/norwegian/errmsg.txt2
-rw-r--r--sql/share/polish/errmsg.txt2
-rw-r--r--sql/share/portuguese/errmsg.txt2
-rw-r--r--sql/share/romanian/errmsg.txt2
-rw-r--r--sql/share/russian/errmsg.txt2
-rw-r--r--sql/share/serbian/errmsg.txt2
-rw-r--r--sql/share/slovak/errmsg.txt2
-rw-r--r--sql/share/spanish/errmsg.txt2
-rw-r--r--sql/share/swedish/errmsg.txt2
-rw-r--r--sql/share/ukrainian/errmsg.txt2
-rw-r--r--sql/sp.cc17
-rw-r--r--sql/sp_head.cc20
-rw-r--r--sql/sql_base.cc6
-rw-r--r--sql/sql_delete.cc4
-rw-r--r--sql/sql_derived.cc8
-rw-r--r--sql/sql_help.cc5
-rw-r--r--sql/sql_insert.cc6
-rw-r--r--sql/sql_lex.cc9
-rw-r--r--sql/sql_lex.h1
-rw-r--r--sql/sql_load.cc7
-rw-r--r--sql/sql_parse.cc6
-rw-r--r--sql/sql_prepare.cc19
-rw-r--r--sql/sql_select.cc4
-rw-r--r--sql/sql_show.cc26
-rw-r--r--sql/sql_update.cc4
-rw-r--r--sql/sql_view.cc59
-rw-r--r--sql/sql_yacc.yy19
-rw-r--r--sql/table.h5
62 files changed, 822 insertions, 208 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 4ca73c35e40..f29057f1d38 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -31,6 +31,7 @@ bk@mysql.r18.ru
brian@avenger.(none)
brian@brian-akers-computer.local
carsten@tsort.bitbybit.dk
+cps@silver_beast.(none)
davida@isil.mysql.com
dlenev@brandersnatch.localdomain
dlenev@build.mysql.com
diff --git a/include/my_sys.h b/include/my_sys.h
index 4724592aa81..0d722a899f6 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -512,6 +512,10 @@ my_off_t my_b_safe_tell(IO_CACHE* info); /* picks the correct tell() */
typedef uint32 ha_checksum;
+/* Define the type of function to be passed to process_default_option_files */
+typedef int (*Process_option_func)(void *ctx, const char *group_name,
+ const char *option);
+
#include <my_alloc.h>
/* Prototypes for mysys and my_func functions */
@@ -747,6 +751,9 @@ extern char *strmake_root(MEM_ROOT *root,const char *str,uint len);
extern char *memdup_root(MEM_ROOT *root,const char *str,uint len);
extern int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv);
+extern int process_default_option_files(const char *conf_file,
+ Process_option_func func,
+ void *func_ctx);
extern void free_defaults(char **argv);
extern void print_defaults(const char *conf_file, const char **groups);
extern my_bool my_compress(byte *, ulong *, ulong *);
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index e1a0b352861..125a39b2249 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -366,7 +366,7 @@
#define ER_WRONG_OBJECT 1347
#define ER_NONUPDATEABLE_COLUMN 1348
#define ER_VIEW_SELECT_DERIVED 1349
-#define ER_VIEW_SELECT_PROCEDURE 1350
+#define ER_VIEW_SELECT_CLAUSE 1350
#define ER_VIEW_SELECT_VARIABLE 1351
#define ER_VIEW_SELECT_TMPTABLE 1352
#define ER_VIEW_WRONG_LIST 1353
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index dba21877644..75d0c9a7e3b 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -141,7 +141,7 @@ COALESCE('a' COLLATE latin1_bin,'b');
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
Warnings:
-Note 1003 select coalesce(1) AS `COALESCE(1)`,coalesce(1.0) AS `COALESCE(1.0)`,coalesce(_latin1'a') AS `COALESCE('a')`,coalesce(1,1.0) AS `COALESCE(1,1.0)`,coalesce(1,_latin1'1') AS `COALESCE(1,'1')`,coalesce(1.1,_latin1'1') AS `COALESCE(1.1,'1')`,coalesce((_latin1'a' collate _latin1'latin1_bin'),_latin1'b') AS `COALESCE('a' COLLATE latin1_bin,'b')`
+Note 1003 select coalesce(1) AS `COALESCE(1)`,coalesce(1.0) AS `COALESCE(1.0)`,coalesce(_latin1'a') AS `COALESCE('a')`,coalesce(1,1.0) AS `COALESCE(1,1.0)`,coalesce(1,_latin1'1') AS `COALESCE(1,'1')`,coalesce(1.1,_latin1'1') AS `COALESCE(1.1,'1')`,coalesce((_latin1'a' collate latin1_bin),_latin1'b') AS `COALESCE('a' COLLATE latin1_bin,'b')`
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result
index 83e103fe57d..f0445199744 100644
--- a/mysql-test/r/func_if.result
+++ b/mysql-test/r/func_if.result
@@ -43,7 +43,7 @@ explain extended select if(u=1,st,binary st) s from t1 where st like "%a%" order
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 7 Using where; Using filesort
Warnings:
-Note 1003 select if((`test`.`t1`.`u` = 1),`test`.`t1`.`st`,cast(`test`.`t1`.`st` as char charset binary)) AS `s` from `test`.`t1` where (`test`.`t1`.`st` like _latin1'%a%') order by if((`test`.`t1`.`u` = 1),`test`.`t1`.`st`,cast(`test`.`t1`.`st` as char charset binary))
+Note 1003 select if((`test`.`t1`.`u` = 1),`test`.`t1`.`st`,(`test`.`t1`.`st` collate BINARY)) AS `s` from `test`.`t1` where (`test`.`t1`.`st` like _latin1'%a%') order by if((`test`.`t1`.`u` = 1),`test`.`t1`.`st`,(`test`.`t1`.`st` collate BINARY))
select nullif(u=0, 'test') from t1;
nullif(u=0, 'test')
NULL
diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result
index b132edab81d..daf36b00693 100644
--- a/mysql-test/r/func_in.result
+++ b/mysql-test/r/func_in.result
@@ -146,7 +146,7 @@ explain extended select * from t1 where 'a' in (a,b,c collate latin1_bin);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where (_latin1'a' in (`test`.`t1`.`a`,`test`.`t1`.`b`,(`test`.`t1`.`c` collate _latin1'latin1_bin')))
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where (_latin1'a' in (`test`.`t1`.`a`,`test`.`t1`.`b`,(`test`.`t1`.`c` collate latin1_bin)))
drop table t1;
set names utf8;
create table t1 (a char(10) character set utf8 not null);
diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result
index a969bf390bc..6f8bc702a80 100644
--- a/mysql-test/r/func_test.result
+++ b/mysql-test/r/func_test.result
@@ -108,7 +108,7 @@ explain extended select _koi8r'a' = _koi8r'A' COLLATE koi8r_general_ci;
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
Warnings:
-Note 1003 select (_koi8r'a' = (_koi8r'A' collate _latin1'koi8r_general_ci')) AS `_koi8r'a' = _koi8r'A' COLLATE koi8r_general_ci`
+Note 1003 select (_koi8r'a' = (_koi8r'A' collate koi8r_general_ci)) AS `_koi8r'a' = _koi8r'A' COLLATE koi8r_general_ci`
select _koi8r'a' = _koi8r'A' COLLATE koi8r_bin;
_koi8r'a' = _koi8r'A' COLLATE koi8r_bin
0
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index 46fe452d9e4..55c34ca471f 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -1,4 +1,27 @@
delete from mysql.proc;
+create function .f1() returns int return 1;
+create procedure .p1() select 1, database();
+create procedure p1() select 2, database();
+alter procedure .p1 sql security invoker;
+select .f1();
+.f1()
+1
+call .p1();
+1 database()
+1 test
+call p1();
+2 database()
+2 test
+select f1();
+ERROR 42000: FUNCTION test.f1 does not exist
+select db,name,type,security_type from mysql.proc;
+db name type security_type
+ f1 FUNCTION DEFINER
+ p1 PROCEDURE INVOKER
+test p1 PROCEDURE DEFINER
+drop function .f1;
+drop procedure .p1;
+drop procedure p1;
create procedure syntaxerror(t int)|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
create procedure syntaxerror(t int)|
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 7ea95a067c4..f0f51945f36 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -1802,6 +1802,24 @@ select @x|
@x
3
drop procedure bug5307|
+create procedure bug5258()
+begin
+end|
+create procedure bug5258_aux()
+begin
+declare c, m char(19);
+select created,modified into c,m from mysql.proc where name = 'bug5258';
+if c = m then
+select 'Ok';
+else
+select c, m;
+end if;
+end|
+call bug5258_aux()|
+Ok
+Ok
+drop procedure bug5258|
+drop procedure bug5258_aux|
drop table if exists fac|
create table fac (n int unsigned not null primary key, f bigint unsigned)|
create procedure ifac(n int unsigned)
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index b67989231e0..4dab9082d2e 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -186,7 +186,7 @@ id select_type table type possible_keys key key_len ref rows Extra
4 SUBQUERY t2 ALL NULL NULL NULL NULL 2
NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`b` = (select `test`.`t3`.`a` AS `a` from `test`.`t3` order by `test`.`t3`.`a` desc limit 1))) union (select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where (`test`.`t4`.`b` = (select (max(`test`.`t2`.`a`) * 4) AS `max(t2.a)*4` from `test`.`t2`)) order by `test`.`t4`.`a`)
+Note 1003 (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`b` = (select `test`.`t3`.`a` AS `a` from `test`.`t3` order by 1 desc limit 1))) union (select `test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b` from `test`.`t4` where (`test`.`t4`.`b` = (select (max(`test`.`t2`.`a`) * 4) AS `max(t2.a)*4` from `test`.`t2`)) order by `test`.`t4`.`a`)
select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
(select a from t3 where a<t2.a*4 order by 1 desc limit 1) a
3 1
@@ -202,7 +202,7 @@ id select_type table type possible_keys key key_len ref rows Extra
3 DERIVED t2 ALL NULL NULL NULL NULL 2 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 Using where; Using filesort
Warnings:
-Note 1003 select (select `test`.`t3`.`a` AS `a` from `test`.`t3` where (`test`.`t3`.`a` < 8) order by `test`.`t3`.`a` desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` > 1)) `tt`
+Note 1003 select (select `test`.`t3`.`a` AS `a` from `test`.`t3` where (`test`.`t3`.`a` < 8) order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`tt`.`a` AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` > 1)) `tt`
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a
2
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index ef3743877c6..572db8a7324 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -940,7 +940,7 @@ grant update,select(b) on mysqltest.t2 to mysqltest_1@localhost;
create view v4 as select b+1 from mysqltest.t2;
REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost;
drop database mysqltest;
-drop view v1,v2;
+drop view v1,v2,v4;
set sql_mode='ansi';
create table t1 ("a*b" int);
create view v1 as select "a*b" from t1;
@@ -1040,7 +1040,6 @@ CREATE VIEW v02 AS SELECT * FROM DUAL;
ERROR HY000: No tables used
SHOW TABLES;
Tables_in_test table_type
-v4 VIEW
CREATE VIEW v1 AS SELECT EXISTS (SELECT 1 UNION SELECT 2);
select * from v1;
EXISTS (SELECT 1 UNION SELECT 2)
@@ -1166,3 +1165,108 @@ Table Create Table
v3 CREATE VIEW `test`.`v3` AS select `v1`.`col1` AS `a`,`v2`.`col1` AS `b` from `test`.`v1` join `test`.`v2` where (`v1`.`col1` = `v2`.`col1`)
drop view v3, v2, v1;
drop table t2, t1;
+create function `f``1` () returns int return 5;
+create view v1 as select test.`f``1` ();
+show create view v1;
+Table Create Table
+v1 CREATE VIEW `test`.`v1` AS select `test`.`f``1`() AS `test.``f````1`` ()`
+select * from v1;
+test.`f``1` ()
+5
+drop view v1;
+drop function `f``1`;
+create function x () returns int return 5;
+create view v1 as select x ();
+select * from v1;
+x ()
+5
+drop view v1;
+drop function x;
+create table t2 (col1 char collate latin1_german2_ci);
+create view v2 as select col1 collate latin1_german1_ci from t2;
+show create view v2;
+Table Create Table
+v2 CREATE VIEW `test`.`v2` AS select (`test`.`t2`.`col1` collate latin1_german1_ci) AS `col1 collate latin1_german1_ci` from `test`.`t2`
+show create view v2;
+Table Create Table
+v2 CREATE VIEW `test`.`v2` AS select (`test`.`t2`.`col1` collate latin1_german1_ci) AS `col1 collate latin1_german1_ci` from `test`.`t2`
+drop view v2;
+drop table t2;
+create table t1 (a int);
+insert into t1 values (1), (2);
+create view v1 as select 5 from t1 order by 1;
+select * from v1;
+5
+5
+5
+drop view v1;
+drop table t1;
+create function x1 () returns int return 5;
+create table t1 (s1 int);
+create view v1 as select x1() from t1;
+drop function x1;
+select * from v1;
+ERROR 42000: FUNCTION test.x1 does not exist
+show table status;
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 MyISAM 9 Fixed 0 0 0 21474836479 1024 0 NULL # # NULL latin1_swedish_ci NULL
+v1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view
+show table status;
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t1 MyISAM 9 Fixed 0 0 0 21474836479 1024 0 NULL # # NULL latin1_swedish_ci NULL
+v1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view
+drop view v1;
+drop table t1;
+create view v1 as select 99999999999999999999999999999999999999999999999999999 as col1;
+show create view v1;
+Table Create Table
+v1 CREATE VIEW `test`.`v1` AS select 99999999999999999999999999999999999999999999999999999 AS `col1`
+drop view v1;
+create table tЭ (cЭ char);
+create view vЭ as select cЭ from tЭ;
+insert into vЭ values ('Э');
+select * from vЭ;
+cЭ
+drop view vЭ;
+drop table tЭ;
+create table t1 (a int, b int);
+insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
+create view v1(c) as select a+1 from t1 where b >= 4;
+select c from v1 where exists (select * from t1 where a=2 and b=c);
+c
+4
+drop view v1;
+drop table t1;
+create view v1 as select cast(1 as char(3));
+show create view v1;
+Table Create Table
+v1 CREATE VIEW `test`.`v1` AS select cast(1 as char(3) charset latin1) AS `cast(1 as char(3))`
+select * from v1;
+cast(1 as char(3))
+1
+drop view v1;
+create view v1 as select 'a',1;
+create view v2 as select * from v1 union all select * from v1;
+create view v3 as select * from v2 where 1 = (select `1` from v2);
+create view v4 as select * from v3;
+select * from v4;
+ERROR 21000: Subquery returns more than 1 row
+drop view v4, v3, v2, v1;
+create view v1 as select 5 into @w;
+ERROR HY000: View's SELECT contains a 'INTO' clause
+create view v1 as select 5 into outfile 'ttt';
+ERROR HY000: View's SELECT contains a 'INTO' clause
+create table t1 (a int);
+create view v1 as select a from t1 procedure analyse();
+ERROR HY000: View's SELECT contains a 'PROCEDURE' clause
+drop table t1;
+create table t1 (s1 int, primary key (s1));
+create view v1 as select * from t1;
+insert into v1 values (1) on duplicate key update s1 = 7;
+insert into v1 values (1) on duplicate key update s1 = 7;
+select * from t1;
+s1
+7
+drop view v1;
+drop table t1;
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index d07c866ff79..12c3016f6e2 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -5,6 +5,29 @@
# Make sure we don't have any procedures left.
delete from mysql.proc;
+# A test "global" procedures, i.e. not belonging to any database.
+create function .f1() returns int return 1;
+create procedure .p1() select 1, database();
+create procedure p1() select 2, database();
+
+alter procedure .p1 sql security invoker;
+
+# This is ok:
+select .f1();
+call .p1();
+call p1();
+
+# This is not ok:
+--error 1304
+select f1();
+
+select db,name,type,security_type from mysql.proc;
+
+drop function .f1;
+drop procedure .p1;
+drop procedure p1;
+
+
delimiter |;
# This should give three syntax errors (sometimes crashed; bug #643)
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index bc811607ef1..05d38d25956 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -1963,6 +1963,30 @@ call bug5307()|
select @x|
drop procedure bug5307|
+#
+# BUG#5258: Stored procedure modified date is 0000-00-00
+# (This was a design flaw)
+create procedure bug5258()
+begin
+end|
+
+create procedure bug5258_aux()
+begin
+ declare c, m char(19);
+
+ select created,modified into c,m from mysql.proc where name = 'bug5258';
+ if c = m then
+ select 'Ok';
+ else
+ select c, m;
+ end if;
+end|
+
+call bug5258_aux()|
+
+drop procedure bug5258|
+drop procedure bug5258_aux|
+
#
# Some "real" examples
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index 51e81987cd9..74ab56cdb34 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -849,7 +849,7 @@ create view v4 as select b+1 from mysqltest.t2;
connection root;
REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost;
drop database mysqltest;
-drop view v1,v2;
+drop view v1,v2,v4;
#
# VIEW fields quoting
@@ -1106,3 +1106,127 @@ select * from v3;
show create view v3;
drop view v3, v2, v1;
drop table t2, t1;
+
+#
+# VIEW based on functions with complex names
+#
+create function `f``1` () returns int return 5;
+create view v1 as select test.`f``1` ();
+show create view v1;
+select * from v1;
+drop view v1;
+drop function `f``1`;
+
+#
+# tested problem when function name length close to ALIGN_SIZE
+#
+create function x () returns int return 5;
+create view v1 as select x ();
+select * from v1;
+drop view v1;
+drop function x;
+
+#
+# VIEW with collation
+#
+create table t2 (col1 char collate latin1_german2_ci);
+create view v2 as select col1 collate latin1_german1_ci from t2;
+show create view v2;
+show create view v2;
+drop view v2;
+drop table t2;
+
+#
+# order by refers on integer field
+#
+create table t1 (a int);
+insert into t1 values (1), (2);
+create view v1 as select 5 from t1 order by 1;
+select * from v1;
+drop view v1;
+drop table t1;
+
+#
+# VIEW over droped function
+#
+create function x1 () returns int return 5;
+create table t1 (s1 int);
+create view v1 as select x1() from t1;
+drop function x1;
+-- error 1304
+select * from v1;
+--replace_column 12 # 13 #
+show table status;
+--replace_column 12 # 13 #
+show table status;
+drop view v1;
+drop table t1;
+
+#
+# VIEW with floating point (long bumber) as column
+#
+create view v1 as select 99999999999999999999999999999999999999999999999999999 as col1;
+show create view v1;
+drop view v1;
+
+#
+# VIEWs with national characters
+#
+create table tЭ (cЭ char);
+create view vЭ as select cЭ from tЭ;
+insert into vЭ values ('Э');
+select * from vЭ;
+drop view vЭ;
+drop table tЭ;
+
+#
+# problem with used_tables() of outer reference resolved in VIEW
+#
+create table t1 (a int, b int);
+insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
+create view v1(c) as select a+1 from t1 where b >= 4;
+select c from v1 where exists (select * from t1 where a=2 and b=c);
+drop view v1;
+drop table t1;
+
+#
+# view with cast operation
+#
+create view v1 as select cast(1 as char(3));
+show create view v1;
+select * from v1;
+drop view v1;
+
+#
+# bug handlimg from VIEWs
+#
+create view v1 as select 'a',1;
+create view v2 as select * from v1 union all select * from v1;
+create view v3 as select * from v2 where 1 = (select `1` from v2);
+create view v4 as select * from v3;
+-- error 1242
+select * from v4;
+drop view v4, v3, v2, v1;
+
+#
+# VIEW over SELECT with prohibited clauses
+#
+-- error 1349
+create view v1 as select 5 into @w;
+-- error 1349
+create view v1 as select 5 into outfile 'ttt';
+create table t1 (a int);
+-- error 1349
+create view v1 as select a from t1 procedure analyse();
+drop table t1;
+
+#
+# INSERT into VIEW with ON DUPLICATE
+#
+create table t1 (s1 int, primary key (s1));
+create view v1 as select * from t1;
+insert into v1 values (1) on duplicate key update s1 = 7;
+insert into v1 values (1) on duplicate key update s1 = 7;
+select * from t1;
+drop view v1;
+drop table t1;
diff --git a/mysys/default.c b/mysys/default.c
index 792233ed10d..a8343c6a21d 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -66,14 +66,210 @@ NullS,
#define windows_ext ".ini"
#endif
-static int search_default_file(DYNAMIC_ARRAY *args,MEM_ROOT *alloc,
+/*
+ This structure defines the context that we pass to callback
+ function 'handle_default_option' used in search_default_file
+ to process each option. This context is used if search_default_file
+ was called from load_defaults.
+*/
+
+struct handle_option_ctx
+{
+ MEM_ROOT *alloc;
+ DYNAMIC_ARRAY *args;
+ TYPELIB *group;
+};
+
+static int search_default_file(Process_option_func func, void *func_ctx,
const char *dir, const char *config_file,
- const char *ext, TYPELIB *group);
+ const char *ext);
static char *remove_end_comment(char *ptr);
/*
+ Process config files in default directories.
+
+ SYNOPSIS
+ search_files()
+ conf_file Basename for configuration file to search for.
+ If this is a path, then only this file is read.
+ argc Pointer to argc of original program
+ argv Pointer to argv of original program
+ args_used Pointer to variable for storing the number of
+ arguments used.
+ func Pointer to the function to process options
+ func_ctx It's context. Usually it is the structure to
+ store additional options.
+ DESCRIPTION
+
+ This function looks for config files in default directories. Then it
+ travesrses each of the files and calls func to process each option.
+
+ RETURN
+ 0 ok
+ 1 given cinf_file doesn't exist
+*/
+
+static int search_files(const char *conf_file, int *argc, char ***argv,
+ uint *args_used, Process_option_func func,
+ void *func_ctx)
+{
+ const char **dirs, *forced_default_file;
+ int error= 0;
+ DBUG_ENTER("search_files");
+
+ args_used= 0;
+
+ /* Check if we want to force the use a specific default file */
+ forced_default_file= 0;
+ if (*argc >= 2)
+ {
+ if (is_prefix(argv[0][1],"--defaults-file="))
+ {
+ forced_default_file= strchr(argv[0][1],'=') + 1;
+ *args_used++;
+ }
+ else if (is_prefix(argv[0][1],"--defaults-extra-file="))
+ {
+ defaults_extra_file= strchr(argv[0][1],'=') + 1;
+ *args_used++;
+ }
+ }
+
+ if (forced_default_file)
+ {
+ if ((error= search_default_file(func, func_ctx, "",
+ forced_default_file, "")) < 0)
+ goto err;
+ if (error > 0)
+ {
+ fprintf(stderr, "Could not open required defaults file: %s\n",
+ forced_default_file);
+ goto err;
+ }
+ }
+ else if (dirname_length(conf_file))
+ {
+ if ((error= search_default_file(func, func_ctx, NullS, conf_file,
+ default_ext)) < 0)
+ goto err;
+ }
+ else
+ {
+#ifdef __WIN__
+ char system_dir[FN_REFLEN];
+ GetWindowsDirectory(system_dir,sizeof(system_dir));
+ if ((search_default_file(func, func_ctx, system_dir, conf_file,
+ windows_ext)))
+ goto err;
+#endif
+#if defined(__EMX__) || defined(OS2)
+ if (getenv("ETC") &&
+ (search_default_file(func, func_ctx, getenv("ETC"), conf_file,
+ default_ext)) < 0)
+ goto err;
+#endif
+ for (dirs= default_directories ; *dirs; dirs++)
+ {
+ if (**dirs)
+ {
+ if (search_default_file(func, func_ctx, *dirs, conf_file, default_ext) < 0)
+ goto err;
+ }
+ else if (defaults_extra_file)
+ {
+ if (search_default_file(func, func_ctx, NullS, defaults_extra_file,
+ default_ext) < 0)
+ goto err; /* Fatal error */
+ }
+ }
+ }
+
+ DBUG_RETURN(error);
+
+err:
+ fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
+ exit(1);
+ return 0; /* Keep compiler happy */
+}
+
+
+/*
+ Simplified version of search_files (no argv, argc to process).
+
+ SYNOPSIS
+ process_default_option_files()
+ conf_file Basename for configuration file to search for.
+ If this is a path, then only this file is read.
+ func Pointer to the function to process options
+ func_ctx It's context. Usually it is the structure to
+ store additional options.
+
+ DESCRIPTION
+
+ Often we want only to get options from default config files. In this case we
+ don't want to provide any argc and argv parameters. This function is a
+ simplified variant of search_files which allows us to forget about
+ argc, argv.
+
+ RETURN
+ 0 ok
+ 1 given cinf_file doesn't exist
+*/
+
+int process_default_option_files(const char *conf_file,
+ Process_option_func func, void *func_ctx)
+{
+ int argc= 1;
+ /* this is a dummy variable for search_files() */
+ uint args_used;
+
+ return search_files(conf_file, &argc, NULL, &args_used, func, func_ctx);
+}
+
+/*
+ The option handler for load_defaults.
+
+ SYNOPSIS
+ handle_deault_option()
+ in_ctx Handler context. In this case it is a
+ handle_option_ctx structure.
+ group_name The name of the group the option belongs to.
+ option The very option to be processed. It is already
+ prepared to be used in argv (has -- prefix)
+
+ DESCRIPTION
+
+ This handler checks whether a group is one of the listed and adds an option
+ to the array if yes. Some other handler can record, for instance, all groups
+ and their options, not knowing in advance the names and amount of groups.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+static int handle_default_option(void *in_ctx, const char *group_name,
+ const char *option)
+{
+ char *tmp;
+ struct handle_option_ctx *ctx;
+ ctx= (struct handle_option_ctx *) in_ctx;
+ if(find_type((char *)group_name, ctx->group, 3))
+ {
+ if (!(tmp= alloc_root(ctx->alloc, (uint) strlen(option) + 1)))
+ return 1;
+ if (insert_dynamic(ctx->args, (gptr) &tmp))
+ return 1;
+ strmov(tmp, option);
+ }
+
+ return 0;
+}
+
+
+/*
Read options from configurations files
SYNOPSIS
@@ -101,7 +297,6 @@ static char *remove_end_comment(char *ptr);
RETURN
0 ok
1 The given conf_file didn't exists
- 2 The given conf_file was not a normal readable file
*/
@@ -109,13 +304,13 @@ int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv)
{
DYNAMIC_ARRAY args;
- const char **dirs, *forced_default_file;
TYPELIB group;
my_bool found_print_defaults=0;
uint args_used=0;
int error= 0;
MEM_ROOT alloc;
char *ptr,**res;
+ struct handle_option_ctx ctx;
DBUG_ENTER("load_defaults");
init_alloc_root(&alloc,512,0);
@@ -137,79 +332,22 @@ int load_defaults(const char *conf_file, const char **groups,
DBUG_RETURN(0);
}
- /* Check if we want to force the use a specific default file */
- forced_default_file=0;
- if (*argc >= 2)
- {
- if (is_prefix(argv[0][1],"--defaults-file="))
- {
- forced_default_file=strchr(argv[0][1],'=')+1;
- args_used++;
- }
- else if (is_prefix(argv[0][1],"--defaults-extra-file="))
- {
- defaults_extra_file=strchr(argv[0][1],'=')+1;
- args_used++;
- }
- }
-
group.count=0;
group.name= "defaults";
group.type_names= groups;
+
for (; *groups ; groups++)
group.count++;
if (my_init_dynamic_array(&args, sizeof(char*),*argc, 32))
goto err;
- if (forced_default_file)
- {
- if ((error= search_default_file(&args, &alloc, "",
- forced_default_file, "", &group)) < 0)
- goto err;
- if (error > 0)
- {
- fprintf(stderr, "Could not open required defaults file: %s\n",
- forced_default_file);
- goto err;
- }
- }
- else if (dirname_length(conf_file))
- {
- if ((error= search_default_file(&args, &alloc, NullS, conf_file,
- default_ext, &group)) < 0)
- goto err;
- }
- else
- {
-#ifdef __WIN__
- char system_dir[FN_REFLEN];
- GetWindowsDirectory(system_dir,sizeof(system_dir));
- if ((search_default_file(&args, &alloc, system_dir, conf_file,
- windows_ext, &group)))
- goto err;
-#endif
-#if defined(__EMX__) || defined(OS2)
- if (getenv("ETC") &&
- (search_default_file(&args, &alloc, getenv("ETC"), conf_file,
- default_ext, &group)) < 0)
- goto err;
-#endif
- for (dirs=default_directories ; *dirs; dirs++)
- {
- if (**dirs)
- {
- if (search_default_file(&args, &alloc, *dirs, conf_file,
- default_ext, &group) < 0)
- goto err;
- }
- else if (defaults_extra_file)
- {
- if (search_default_file(&args, &alloc, NullS, defaults_extra_file,
- default_ext, &group) < 0)
- goto err; /* Fatal error */
- }
- }
- }
+
+ ctx.alloc= &alloc;
+ ctx.args= &args;
+ ctx.group= &group;
+
+ error= search_files(conf_file, argc, argv, &args_used,
+ handle_default_option, (void *) &ctx);
/*
Here error contains <> 0 only if we have a fully specified conf_file
or a forced default file
@@ -274,8 +412,10 @@ void free_defaults(char **argv)
SYNOPSIS
search_default_file()
- args Store pointer to found options here
- alloc Allocate strings in this object
+ opt_handler Option handler function. It is used to process
+ every separate option.
+ handler_ctx Pointer to the structure to store actual
+ parameters of the function.
dir directory to read
config_file Name of configuration file
ext Extension for configuration file
@@ -285,17 +425,17 @@ void free_defaults(char **argv)
0 Success
-1 Fatal error, abort
1 File not found (Warning)
- 2 File is not a regular file (Warning)
*/
-static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
+static int search_default_file(Process_option_func opt_handler, void *handler_ctx,
const char *dir, const char *config_file,
- const char *ext, TYPELIB *group)
+ const char *ext)
{
- char name[FN_REFLEN+10],buff[4096],*ptr,*end,*value,*tmp;
+ char name[FN_REFLEN+10], buff[4096], curr_gr[4096], *ptr, *end;
+ char *value, option[4096];
FILE *fp;
uint line=0;
- my_bool read_values=0,found_group=0;
+ my_bool found_group=0;
if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3)
return 0; /* Ignore wrong paths */
@@ -352,7 +492,8 @@ static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
}
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;/* Remove end space */
end[0]=0;
- read_values=find_type(ptr,group,3) > 0;
+
+ strnmov(curr_gr, ptr, min((uint) (end-ptr)+1, 4096));
continue;
}
if (!found_group)
@@ -362,19 +503,17 @@ static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
name,line);
goto err;
}
- if (!read_values)
- continue;
+
+
end= remove_end_comment(ptr);
if ((value= strchr(ptr, '=')))
end= value; /* Option without argument */
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
if (!value)
{
- if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3)))
- goto err;
- strmake(strmov(tmp,"--"),ptr,(uint) (end-ptr));
- if (insert_dynamic(args,(gptr) &tmp))
- goto err;
+ strmake(strmov(option,"--"),ptr,(uint) (end-ptr));
+ if (opt_handler(handler_ctx, curr_gr, option))
+ goto err;
}
else
{
@@ -396,12 +535,7 @@ static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
value++;
value_end--;
}
- if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3 +
- (uint) (value_end-value)+1)))
- goto err;
- if (insert_dynamic(args,(gptr) &tmp))
- goto err;
- ptr=strnmov(strmov(tmp,"--"),ptr,(uint) (end-ptr));
+ ptr=strnmov(strmov(option,"--"),ptr,(uint) (end-ptr));
*ptr++= '=';
for ( ; value != value_end; value++)
@@ -443,6 +577,8 @@ static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
*ptr++= *value;
}
*ptr=0;
+ if (opt_handler(handler_ctx, curr_gr, option))
+ goto err;
}
}
my_fclose(fp,MYF(0));
diff --git a/sql/item.cc b/sql/item.cc
index 5fa6b2400df..18ae7efd852 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1375,11 +1375,21 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
table_list, ref,
0, 1)) != not_found_field)
{
- if (tmp && tmp != view_ref_found)
- {
- prev_subselect_item->used_tables_cache|= tmp->table->map;
- prev_subselect_item->const_item_cache= 0;
- }
+ if (tmp)
+ {
+ if (tmp != view_ref_found)
+ {
+ prev_subselect_item->used_tables_cache|= tmp->table->map;
+ prev_subselect_item->const_item_cache= 0;
+ }
+ else
+ {
+ prev_subselect_item->used_tables_cache|=
+ (*ref)->used_tables();
+ prev_subselect_item->const_item_cache&=
+ (*ref)->const_item();
+ }
+ }
break;
}
if (sl->resolve_mode == SELECT_LEX::SELECT_MODE &&
@@ -1829,6 +1839,21 @@ int Item_real::save_in_field(Field *field, bool no_conversions)
return field->store(nr);
}
+
+void Item_real::print(String *str)
+{
+ if (presentation)
+ {
+ str->append(presentation);
+ return;
+ }
+ char buffer[20];
+ String num(buffer, sizeof(buffer), &my_charset_bin);
+ num.set(value, decimals, &my_charset_bin);
+ str->append(num);
+}
+
+
/****************************************************************************
** varbinary item
** In string context this is a binary string
@@ -2096,11 +2121,21 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
table_list, reference,
0, 1)) != not_found_field)
{
- if (tmp && tmp != view_ref_found)
- {
- prev_subselect_item->used_tables_cache|= tmp->table->map;
- prev_subselect_item->const_item_cache= 0;
- }
+ if (tmp)
+ {
+ if (tmp != view_ref_found)
+ {
+ prev_subselect_item->used_tables_cache|= tmp->table->map;
+ prev_subselect_item->const_item_cache= 0;
+ }
+ else
+ {
+ prev_subselect_item->used_tables_cache|=
+ (*reference)->used_tables();
+ prev_subselect_item->const_item_cache&=
+ (*reference)->const_item();
+ }
+ }
break;
}
@@ -2145,8 +2180,8 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
if (!((*reference)= fld= new Item_field(tmp)))
return 1;
mark_as_dependent(thd, last, thd->lex->current_select, fld);
- return 0;
register_item_tree_changing(reference);
+ return 0;
}
/*
We can leave expression substituted from view for next PS/SP
diff --git a/sql/item.h b/sql/item.h
index a9e4831b40b..1420a89c76a 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -698,12 +698,13 @@ public:
class Item_real :public Item_num
{
+ char *presentation;
public:
double value;
// Item_real() :value(0) {}
Item_real(const char *str_arg, uint length) :value(my_atof(str_arg))
{
- name=(char*) str_arg;
+ presentation= name=(char*) str_arg;
decimals=(uint8) nr_of_decimals(str_arg);
max_length=length;
fixed= 1;
@@ -711,12 +712,12 @@ public:
Item_real(const char *str,double val_arg,uint decimal_par,uint length)
:value(val_arg)
{
- name=(char*) str;
+ presentation= name=(char*) str;
decimals=(uint8) decimal_par;
max_length=length;
fixed= 1;
}
- Item_real(double value_par) :value(value_par) { fixed= 1; }
+ Item_real(double value_par) :presentation(0), value(value_par) { fixed= 1; }
int save_in_field(Field *field, bool no_conversions);
enum Type type() const { return REAL_ITEM; }
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
@@ -732,6 +733,7 @@ public:
void cleanup() {}
Item *new_item() { return new Item_real(name,value,decimals,max_length); }
Item_num *neg() { value= -value; return this; }
+ void print(String *str);
};
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 7c5b584e645..45564e01e03 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3287,9 +3287,25 @@ Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list)
const char *
Item_func_sp::func_name() const
{
- return m_name->m_name.str;
+ THD *thd= current_thd;
+ /* Calculate length to avoud reallocation of string for sure */
+ uint len= ((m_name->m_db.length +
+ m_name->m_name.length)*2 + //characters*quoting
+ 2 + // ` and `
+ 1 + // .
+ 1 + // end of string
+ ALIGN_SIZE(1)); // to avoid String reallocation
+ String qname((char *)alloc_root(&thd->mem_root, len), len,
+ system_charset_info);
+
+ qname.length(0);
+ append_identifier(thd, &qname, m_name->m_db.str, m_name->m_db.length);
+ qname.append('.');
+ append_identifier(thd, &qname, m_name->m_name.str, m_name->m_name.length);
+ return qname.ptr();
}
+
int
Item_func_sp::execute(Item **itp)
{
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index fac73a1a759..fc667eb61b0 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2280,6 +2280,18 @@ bool Item_func_set_collation::eq(const Item *item, bool binary_cmp) const
return 1;
}
+
+void Item_func_set_collation::print(String *str)
+{
+ str->append('(');
+ args[0]->print(str);
+ str->append(" collate ", 9);
+ DBUG_ASSERT(args[1]->basic_const_item() &&
+ args[1]->type() == Item::STRING_ITEM);
+ args[1]->str_value.print(str);
+ str->append(')');
+}
+
String *Item_func_charset::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 08123370bc6..df8861b2ee0 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -635,7 +635,7 @@ public:
void fix_length_and_dec();
bool eq(const Item *item, bool binary_cmp) const;
const char *func_name() const { return "collate"; }
- void print(String *str) { print_op(str); }
+ void print(String *str);
};
class Item_func_charset :public Item_str_func
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index c558c935090..3f8701a8d50 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2106,7 +2106,7 @@ void Item_char_typecast::print(String *str)
if (cast_cs)
{
str->append(" charset ", 9);
- str->append(cast_cs->name);
+ str->append(cast_cs->csname);
}
str->append(')');
}
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 587a8be7ac8..68f5fbff13c 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -378,7 +378,7 @@ character-set=latin2
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 8d6e23d449e..1153bbecbc8 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -369,7 +369,7 @@ character-set=latin1
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 0c60c63de64..67b0934f2d2 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -378,7 +378,7 @@ character-set=latin1
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index b850c2d36d0..cfe46055bbc 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -366,7 +366,7 @@ character-set=latin1
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index ef958921b5e..e4c139d31b1 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -371,7 +371,7 @@ character-set=latin7
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 8723919ab47..ee9e784ada6 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -366,7 +366,7 @@ character-set=latin1
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 74274ebfc8c..9bd7665ac97 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -379,7 +379,7 @@ character-set=latin1
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index ea148999fc4..e8ed72f6a0f 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -366,7 +366,7 @@ character-set=greek
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index ede873f21c0..bd4f4e56d52 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -371,7 +371,7 @@ character-set=latin2
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 7898503dc03..f1c9b10c8d4 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -366,7 +366,7 @@ character-set=latin1
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index f73eca2a183..03af38e9172 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -370,7 +370,7 @@ character-set=ujis
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 6c8a5c2661a..43b0cd2640e 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -366,7 +366,7 @@ character-set=euckr
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 48ade24703b..b542ffb6a62 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -368,7 +368,7 @@ character-set=latin1
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index e217155a4df..a435479f8a0 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -368,7 +368,7 @@ character-set=latin1
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index c514581ec1c..413e004cec1 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -371,7 +371,7 @@ character-set=latin2
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index ca6cccb7471..85c8cd00dd5 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -368,7 +368,7 @@ character-set=latin1
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 3c69e33a222..1c7e2187084 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -371,7 +371,7 @@ character-set=latin2
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 13c7a410443..a9f1024db87 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -371,7 +371,7 @@ character-set=koi8r
"'%-.64s.%-.64s' - не %s"
"Столбец '%-.64s' не обновляемый"
"View SELECT содержит подзапрос в конструкции FROM"
-"View SELECT содержит конструкцию PROCEDURE"
+"View SELECT содержит конструкцию '%s'"
"View SELECT содержит переменную или параметр"
"View SELECT содержит ссылку на временную таблицу '%-.64s'"
"View SELECT и список полей view имеют разное количество столбцов"
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index b1fa4d86b54..8f3bc3458e1 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -359,7 +359,7 @@ character-set=cp1250
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 9570ba1fef6..c7b67540f2f 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -374,7 +374,7 @@ character-set=latin2
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 4058fcc7c4e..c725caf93c0 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -370,7 +370,7 @@ character-set=latin1
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index e03af70d03c..85d37c2ae9f 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -366,7 +366,7 @@ character-set=latin1
"'%-.64s.%-.64s' is not %s"
"Column '%-.64s' is not updatable"
"View's SELECT contains a subquery in the FROM clause"
-"View's SELECT contains a PROCEDURE clause"
+"View's SELECT contains a '%s' clause"
"View's SELECT contains a variable or parameter"
"View's SELECT contains a temporary table '%-.64s'"
"View's SELECT and view's field list have different column counts"
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index a919422a6cf..cd3917aa123 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -372,7 +372,7 @@ character-set=koi8u
"'%-.64s.%-.64s' не ╓ %s"
"Стовбець '%-.64s' не може бути зминений"
"View SELECT ма╓ п╕дзапит у конструкц╕╖ FROM"
-"View SELECT ма╓ конструкц╕ю PROCEDURE"
+"View SELECT ма╓ конструкц╕ю '%s'"
"View SELECT ма╓ зминну або параметер"
"View SELECT використову╓ тимчасову таблицю '%-.64s'"
"View SELECT ╕ перел╕к стовбц╕в view мають р╕зну к╕льк╕сть сковбц╕в"
diff --git a/sql/sp.cc b/sql/sp.cc
index dda6e0fad60..6475b64eb18 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -93,10 +93,15 @@ db_find_routine_aux(THD *thd, int type, sp_name *name,
key[128]= type;
keylen= sizeof(key);
- for (table= thd->open_tables ; table ; table= table->next)
- if (strcmp(table->table_cache_key, "mysql") == 0 &&
- strcmp(table->real_name, "proc") == 0)
- break;
+ if (thd->lex->proc_table)
+ table= thd->lex->proc_table->table;
+ else
+ {
+ for (table= thd->open_tables ; table ; table= table->next)
+ if (strcmp(table->table_cache_key, "mysql") == 0 &&
+ strcmp(table->real_name, "proc") == 0)
+ break;
+ }
if (table)
*opened= FALSE;
else
@@ -366,6 +371,7 @@ db_create_routine(THD *thd, int type, sp_head *sp)
table->field[MYSQL_PROC_FIELD_DEFINER]->
store(definer, (uint)strlen(definer), system_charset_info);
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time();
+ ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
table->field[MYSQL_PROC_FIELD_SQL_MODE]->
store((longlong)thd->variables.sql_mode);
if (sp->m_chistics->comment.str)
@@ -955,6 +961,7 @@ sp_cache_functions(THD *thd, LEX *lex)
LEX *newlex= new st_lex;
thd->lex= newlex;
+ newlex->proc_table= oldlex->proc_table; // hint if mysql.oper is opened
name.m_name.str= strchr(name.m_qname.str, '.');
name.m_db.length= name.m_name.str - name.m_qname.str;
name.m_db.str= strmake_root(&thd->mem_root,
@@ -1047,6 +1054,8 @@ sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddblen,
DBUG_ENTER("sp_use_new_db");
DBUG_PRINT("enter", ("newdb: %s", newdb));
+ if (! newdb)
+ newdb= (char *)"";
if (thd->db && thd->db[0])
{
if (my_strcasecmp(system_charset_info, thd->db, newdb) == 0)
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index d0ffe3fa051..8c35597fe99 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -297,16 +297,11 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
name->m_db.length, name->m_db.str,
name->m_name.length, name->m_name.str));
/* We have to copy strings to get them into the right memroot */
+ m_db.length= name->m_db.length;
if (name->m_db.length == 0)
- {
- m_db.length= (thd->db ? strlen(thd->db) : 0);
- m_db.str= strmake_root(root, (thd->db ? thd->db : ""), m_db.length);
- }
+ m_db.str= NULL;
else
- {
- m_db.length= name->m_db.length;
m_db.str= strmake_root(root, name->m_db.str, name->m_db.length);
- }
m_name.length= name->m_name.length;
m_name.str= strmake_root(root, name->m_name.str, name->m_name.length);
@@ -454,7 +449,8 @@ sp_head::execute(THD *thd)
#endif
dbchanged= FALSE;
- if ((ret= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0, &dbchanged)))
+ if (m_db.length &&
+ (ret= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0, &dbchanged)))
goto done;
if ((ctx= thd->spcont))
@@ -1204,7 +1200,7 @@ sp_instr_set::execute(THD *thd, uint *nextp)
if (tables &&
((res= check_table_access(thd, SELECT_ACL, tables, 0)) ||
(res= open_and_lock_tables(thd, tables))))
- DBUG_RETURN(-1);
+ DBUG_RETURN(res);
it= sp_eval_func_item(thd, m_value, m_type);
if (! it)
@@ -1305,7 +1301,7 @@ sp_instr_jump_if::execute(THD *thd, uint *nextp)
if (tables &&
((res= check_table_access(thd, SELECT_ACL, tables, 0)) ||
(res= open_and_lock_tables(thd, tables))))
- DBUG_RETURN(-1);
+ DBUG_RETURN(res);
it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY);
if (!it)
@@ -1362,7 +1358,7 @@ sp_instr_jump_if_not::execute(THD *thd, uint *nextp)
if (tables &&
((res= check_table_access(thd, SELECT_ACL, tables, 0)) ||
(res= open_and_lock_tables(thd, tables))))
- DBUG_RETURN(-1);
+ DBUG_RETURN(res);
it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY);
if (! it)
@@ -1418,7 +1414,7 @@ sp_instr_freturn::execute(THD *thd, uint *nextp)
if (tables &&
((res= check_table_access(thd, SELECT_ACL, tables, 0)) ||
(res= open_and_lock_tables(thd, tables))))
- DBUG_RETURN(-1);
+ DBUG_RETURN(res);
it= sp_eval_func_item(thd, m_value, m_type);
if (! it)
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index f07b93ec9f0..e9847a09384 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1708,6 +1708,7 @@ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables)
RETURN
0 - ok
-1 - error
+ 1 - error reported to user
NOTE
The lock will automaticly be freed by close_thread_tables()
@@ -1717,7 +1718,8 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("open_and_lock_tables");
uint counter;
- if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter))
+ if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter)
+ || mysql_handle_derived(thd->lex))
DBUG_RETURN(thd->net.report_error ? -1 : 1); /* purecov: inspected */
/*
Let us propagate pointers to open tables from global table list
@@ -1739,7 +1741,7 @@ int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
}
}
}
- DBUG_RETURN(mysql_handle_derived(thd->lex));
+ DBUG_RETURN(0);
}
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 05b2de8adfd..030541a0093 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -39,8 +39,8 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
ha_rows deleted;
DBUG_ENTER("mysql_delete");
- if ((open_and_lock_tables(thd, table_list)))
- DBUG_RETURN(-1);
+ if ((error= open_and_lock_tables(thd, table_list)))
+ DBUG_RETURN(error);
table= table_list->table;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
thd->proc_info="init";
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 3137890f2ba..5c827741e6d 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -220,10 +220,12 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
table->next= thd->derived_tables;
thd->derived_tables= table;
}
+ }
+ else
+ free_tmp_table(thd, table);
exit:
- delete derived_result;
- lex->current_select= save_current_select;
- }
+ delete derived_result;
+ lex->current_select= save_current_select;
DBUG_RETURN(res);
}
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 85d5271d4c3..8fc0671c808 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -640,11 +640,8 @@ int mysqld_help(THD *thd, const char *mask)
uint mlen= strlen(mask);
MEM_ROOT *mem_root= &thd->mem_root;
- if (open_and_lock_tables(thd, tables))
- {
- res= -1;
+ if (res= open_and_lock_tables(thd, tables))
goto end;
- }
/*
Init tables and fields to be usable from items
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 0e4f803536d..14c4838900f 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -582,6 +582,7 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
bool insert_into_view= (table_list->view != 0);
/* TODO: use this condition for 'WITH CHECK OPTION' */
Item *unused_conds= 0;
+ int res;
DBUG_ENTER("mysql_prepare_insert");
if (mysql_prepare_insert_check_table(thd, table_list, fields, &unused_conds))
@@ -591,7 +592,10 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
!insert_into_view) ||
setup_fields(thd, 0, table_list, *values, 0, 0, 0) ||
(duplic == DUP_UPDATE &&
- (setup_fields(thd, 0, table_list, update_fields, 0, 0, 0) ||
+ ((thd->lex->select_lex.no_wrap_view_item= 1,
+ (res= setup_fields(thd, 0, table_list, update_fields, 0, 0, 0)),
+ thd->lex->select_lex.no_wrap_view_item= 0,
+ res) ||
setup_fields(thd, 0, table_list, update_values, 0, 0, 0))))
DBUG_RETURN(-1);
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 1f0b63b5df3..241e9b863f1 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1480,7 +1480,14 @@ void st_select_lex::print_order(String *str, ORDER *order)
{
for (; order; order= order->next)
{
- (*order->item)->print(str);
+ if (order->counter_used)
+ {
+ char buffer[20];
+ my_snprintf(buffer, 20, "%u", order->counter);
+ str->append(buffer);
+ }
+ else
+ (*order->item)->print(str);
if (!order->asc)
str->append(" desc", 5);
if (order->next)
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index d9eff46ea48..95c9772bac1 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -635,6 +635,7 @@ typedef struct st_lex
TABLE_LIST *query_tables; /* global list of all tables in this query */
/* last element next_global of previous list */
TABLE_LIST **query_tables_last;
+ TABLE_LIST *proc_table; /* refer to mysql.proc if it was opened by VIEW */
List<key_part_spec> col_list;
List<key_part_spec> ref_list;
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 44c6f71c9bd..9b050c0863a 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -99,8 +99,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
loaded is located
*/
char *tdb= thd->db ? thd->db : db; // Result is never null
- bool transactional_table, log_delayed;
ulong skip_lines= ex->skip_lines;
+ int res;
+ bool transactional_table, log_delayed;
DBUG_ENTER("mysql_load");
#ifdef EMBEDDED_LIBRARY
@@ -114,8 +115,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
DBUG_RETURN(-1);
}
table_list->lock_type= lock_type;
- if (open_and_lock_tables(thd, table_list))
- DBUG_RETURN(-1);
+ if ((res= open_and_lock_tables(thd, table_list)))
+ DBUG_RETURN(res);
/* TODO: add key check when we will support VIEWs in LOAD */
if (!table_list->updatable)
{
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index a1180d29e99..9a76fa2da84 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2148,7 +2148,7 @@ mysql_execute_command(THD *thd)
case SQLCOM_DO:
if (all_tables &&
((res= check_table_access(thd, SELECT_ACL, all_tables, 0)) ||
- (res= open_and_lock_tables(thd, all_tables))))
+ (res= open_and_lock_tables(thd, all_tables))))
break;
res= mysql_do(thd, *lex->insert_list);
@@ -2427,7 +2427,6 @@ mysql_execute_command(THD *thd)
if (!(res= open_and_lock_tables(thd, select_tables)))
{
- res= -1; // If error
if ((result= new select_create(create_table,
&lex->create_info,
lex->create_list,
@@ -4316,7 +4315,7 @@ mysql_init_query(THD *thd, uchar *buf, uint length, bool lexonly)
lex->found_colon= 0;
lex->safe_to_cache_query= 1;
lex->time_zone_tables_used= 0;
- lex->query_tables= 0;
+ lex->proc_table= lex->query_tables= 0;
lex->query_tables_last= &lex->query_tables;
lex->variables_used= 0;
lex->select_lex.parent_lex= lex;
@@ -5009,6 +5008,7 @@ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc)
order->asc = asc;
order->free_me=0;
order->used=0;
+ order->counter_used= 0;
list.link_in_list((byte*) order,(byte**) &order->next);
DBUG_RETURN(0);
}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index c84d6457d4f..844a7723d89 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -885,6 +885,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
1 error, sent to the client
-1 error, not sent to client
*/
+
static int mysql_test_insert(Prepared_statement *stmt,
TABLE_LIST *table_list,
List<Item> &fields,
@@ -897,7 +898,7 @@ static int mysql_test_insert(Prepared_statement *stmt,
LEX *lex= stmt->lex;
List_iterator_fast<List_item> its(values_list);
List_item *values;
- int res= -1;
+ int res;
my_bool update= (lex->value_list.elements ? UPDATE_ACL : 0);
DBUG_ENTER("mysql_test_insert");
@@ -908,9 +909,9 @@ static int mysql_test_insert(Prepared_statement *stmt,
open temporary memory pool for temporary data allocated by derived
tables & preparation procedure
*/
- if (open_and_lock_tables(thd, table_list))
+ if ((res= open_and_lock_tables(thd, table_list)))
{
- DBUG_RETURN(-1);
+ DBUG_RETURN(res);
}
if ((values= its++))
@@ -972,9 +973,7 @@ static int mysql_test_update(Prepared_statement *stmt,
if ((res= update_precheck(thd, table_list)))
DBUG_RETURN(res);
- if (open_and_lock_tables(thd, table_list))
- res= -1;
- else
+ if (!(res=open_and_lock_tables(thd, table_list)))
{
if (!(res= mysql_prepare_update(thd, table_list,
&select->where,
@@ -1026,9 +1025,7 @@ static int mysql_test_delete(Prepared_statement *stmt,
if ((res= delete_precheck(thd, table_list)))
DBUG_RETURN(res);
- if (open_and_lock_tables(thd, table_list))
- res= -1;
- else
+ if (!(res=open_and_lock_tables(thd, table_list)))
{
res= mysql_prepare_delete(thd, table_list, &lex->select_lex.where);
lex->unit.cleanup();
@@ -1074,11 +1071,12 @@ static int mysql_test_select(Prepared_statement *stmt,
DBUG_RETURN(1);
#endif
- if (open_and_lock_tables(thd, tables))
+ if ((result= open_and_lock_tables(thd, tables)))
{
send_error(thd);
goto err;
}
+ result= 1;
thd->used_tables= 0; // Updated by setup_fields
@@ -1252,6 +1250,7 @@ end:
1 error, sent to client
-1 error, not sent to client
*/
+
static int mysql_test_create_table(Prepared_statement *stmt)
{
DBUG_ENTER("mysql_test_create_table");
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2d8ea72ed51..def641d9616 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -10058,8 +10058,10 @@ find_order_in_list(THD *thd, Item **ref_pointer_array,
thd->where);
return 1;
}
- order->item= ref_pointer_array + count-1;
+ order->item= ref_pointer_array + count - 1;
order->in_field_list= 1;
+ order->counter= count;
+ order->counter_used= 1;
return 0;
}
uint counter;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 6322d99582d..c31eb4f147f 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -497,6 +497,7 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
TABLE *table;
Protocol *protocol= thd->protocol;
TIME time;
+ int res;
DBUG_ENTER("mysqld_extend_show_tables");
(void) sprintf(path,"%s/%s",mysql_data_home,db);
@@ -554,13 +555,18 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
table_list.select_lex= &thd->lex->select_lex;
if (lower_case_table_names)
my_casedn_str(files_charset_info, file_name);
- if (open_and_lock_tables(thd, &table_list))
+ if ((res= open_and_lock_tables(thd, &table_list)))
{
for (uint i=2 ; i < field_list.elements ; i++)
protocol->store_null();
- // Send error to Comment field
- protocol->store(thd->net.last_error, system_charset_info);
- thd->clear_error();
+ // Send error to Comment field if possible
+ if (res < 0)
+ {
+ protocol->store(thd->net.last_error, system_charset_info);
+ thd->clear_error();
+ }
+ else
+ DBUG_RETURN(1);
}
else if (table_list.view)
{
@@ -696,14 +702,16 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
char tmp1[MAX_FIELD_WIDTH];
Item *item;
Protocol *protocol= thd->protocol;
+ int res;
DBUG_ENTER("mysqld_show_fields");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
table_list->lock_type= TL_UNLOCK;
- if (open_and_lock_tables(thd, table_list))
+ if ((res= open_and_lock_tables(thd, table_list)))
{
- send_error(thd);
+ if (res < 0)
+ send_error(thd);
DBUG_RETURN(1);
}
table= table_list->table;
@@ -852,14 +860,16 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
Protocol *protocol= thd->protocol;
char buff[2048];
String buffer(buff, sizeof(buff), system_charset_info);
+ int res;
DBUG_ENTER("mysqld_show_create");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
/* Only one table for now, but VIEW can involve several tables */
- if (open_and_lock_tables(thd, table_list))
+ if ((res= open_and_lock_tables(thd, table_list)))
{
- send_error(thd);
+ if (res < 0)
+ send_error(thd);
DBUG_RETURN(1);
}
/* TODO: add environment variables show when it become possible */
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index acc93b10910..9d7134aee84 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -113,8 +113,8 @@ int mysql_update(THD *thd,
LINT_INIT(used_index);
LINT_INIT(timestamp_query_id);
- if ((open_and_lock_tables(thd, table_list)))
- DBUG_RETURN(-1);
+ if ((error= open_and_lock_tables(thd, table_list)))
+ DBUG_RETURN(error);
thd->proc_info="init";
table= table_list->table;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 8cc342e99fe..15f38f685dc 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -59,12 +59,21 @@ int mysql_create_view(THD *thd,
int res= 0;
DBUG_ENTER("mysql_create_view");
- if (lex->derived_tables || lex->proc_list.first ||
+ if (lex->proc_list.first ||
+ lex->result)
+ {
+ my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), (lex->result ?
+ "INTO" :
+ "PROCEDURE"));
+ res= -1;
+ goto err;
+ }
+ if (lex->derived_tables ||
lex->variables_used || lex->param_list.elements)
{
- my_error((lex->derived_tables ? ER_VIEW_SELECT_DERIVED :
- (lex->proc_list.first ? ER_VIEW_SELECT_PROCEDURE :
- ER_VIEW_SELECT_VARIABLE)), MYF(0));
+ my_error((lex->derived_tables ?
+ ER_VIEW_SELECT_DERIVED :
+ ER_VIEW_SELECT_VARIABLE), MYF(0));
res= -1;
goto err;
}
@@ -297,8 +306,10 @@ err:
}
-// index of revision number in following table
-static const int revision_number_position= 4;
+/* index of revision number in following table */
+static const int revision_number_position= 5;
+/* index of last required parameter for making view */
+static const int required_view_parameters= 7;
/*
table of VIEW .frm field descriptors
@@ -328,8 +339,6 @@ static File_option view_parameters[]=
FILE_OPTIONS_STRING}
};
-static const uint required_view_parameters= 6;
-
static LEX_STRING view_file_type[]= {{(char*)"VIEW", 4}};
@@ -492,6 +501,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
my_bool
mysql_make_view(File_parser *parser, TABLE_LIST *table)
{
+ bool include_proc_table= 0;
DBUG_ENTER("mysql_make_view");
if (table->view)
@@ -578,7 +588,10 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
*/
thd->options&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES);
+ CHARSET_INFO *save_cs= thd->variables.character_set_client;
+ thd->variables.character_set_client= system_charset_info;
res= yyparse((void *)thd);
+ thd->variables.character_set_client= save_cs;
thd->options= options;
}
if (!res && !thd->is_fatal_error)
@@ -587,8 +600,23 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
table->belong_to_view :
table);
- /* move SP to main LEX */
- sp_merge_funs(old_lex, lex);
+ if (lex->spfuns.records)
+ {
+ /* move SP to main LEX */
+ sp_merge_funs(old_lex, lex);
+ if (old_lex->proc_table == 0 &&
+ (old_lex->proc_table=
+ (TABLE_LIST*)thd->calloc(sizeof(TABLE_LIST))) != 0)
+ {
+ TABLE_LIST *table= old_lex->proc_table;
+ table->db= (char*)"mysql";
+ table->db_length= 5;
+ table->real_name= table->alias= (char*)"proc";
+ table->real_name_length= 4;
+ table->cacheable_table= 1;
+ include_proc_table= 1;
+ }
+ }
if (lex->spfuns.array.buffer)
hash_free(&lex->spfuns);
@@ -718,6 +746,17 @@ ok:
lex->all_selects_list->link_prev=
(st_select_lex_node**)&old_lex->all_selects_list;
+ if (include_proc_table)
+ {
+ TABLE_LIST *proc= old_lex->proc_table;
+ if((proc->next_global= table->next_global))
+ {
+ table->next_global->prev_global= &proc->next_global;
+ }
+ proc->prev_global= &table->next_global;
+ table->next_global= proc;
+ }
+
thd->lex= old_lex;
DBUG_RETURN(0);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 19b6aa4b385..91a20e6e8e5 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1211,7 +1211,12 @@ create:
;
sp_name:
- IDENT_sys '.' IDENT_sys
+ '.' IDENT_sys
+ {
+ $$= new sp_name($2);
+ $$->init_qname(YYTHD);
+ }
+ | IDENT_sys '.' IDENT_sys
{
$$= new sp_name($1, $3);
$$->init_qname(YYTHD);
@@ -4361,6 +4366,18 @@ simple_expr:
{ $$= new Item_func_round($3,$5,1); }
| TRUE_SYM
{ $$= new Item_int((char*) "TRUE",1,1); }
+ | '.' ident '(' udf_expr_list ')'
+ {
+ LEX *lex= Lex;
+ sp_name *name= new sp_name($2);
+
+ name->init_qname(YYTHD);
+ sp_add_fun_to_lex(Lex, name);
+ if ($4)
+ $$= new Item_func_sp(name, *$4);
+ else
+ $$= new Item_func_sp(name);
+ }
| ident '.' ident '(' udf_expr_list ')'
{
LEX *lex= Lex;
diff --git a/sql/table.h b/sql/table.h
index a1db271cc2b..b7cabe21638 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -29,9 +29,12 @@ typedef struct st_order {
Item **item; /* Point at item in select fields */
Item *item_ptr; /* Storage for initial item */
Item **item_copy; /* For SPs; the original item ptr */
+ int counter; /* position in SELECT list, correct
+ only if counter_used is true*/
bool asc; /* true if ascending */
bool free_me; /* true if item isn't shared */
bool in_field_list; /* true if in select field list */
+ bool counter_used; /* parapeter was counter of columns */
Field *field; /* If tmp-table group */
char *buff; /* If tmp-table group */
table_map used,depend_map;
@@ -222,7 +225,7 @@ typedef struct st_table_list
LEX_STRING view_name; /* save view name */
LEX_STRING timestamp; /* GMT time stamp of last operation */
ulonglong file_version; /* version of file's field set */
- ulonglong updatable_view; /* VIEW can be updated */
+ ulonglong updatable_view; /* VIEW can be updated */
ulonglong revision; /* revision control number */
ulonglong algorithm; /* 0 any, 1 tmp tables , 2 merging */
uint effective_algorithm; /* which algorithm was really used */