diff options
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 */ |