Merge bk-internal.mysql.com:/home/bk/mysql-5.0

into mishka.local:/home/my/mysql-5.0


BitKeeper/etc/logging_ok:
  auto-union
sql/mysql_priv.h:
  Auto merged
sql/sp.cc:
  Auto merged
sql/sql_acl.cc:
  Auto merged
sql/sql_lex.cc:
  Auto merged
This commit is contained in:
unknown 2004-09-07 11:33:37 +03:00
commit ac473c3813
71 changed files with 1291 additions and 675 deletions

View File

@ -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

View File

@ -506,6 +506,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 */
@ -740,6 +744,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 *);

View File

@ -365,7 +365,7 @@
#define ER_WRONG_OBJECT 1346
#define ER_NONUPDATEABLE_COLUMN 1347
#define ER_VIEW_SELECT_DERIVED 1348
#define ER_VIEW_SELECT_PROCEDURE 1349
#define ER_VIEW_SELECT_CLAUSE 1349
#define ER_VIEW_SELECT_VARIABLE 1350
#define ER_VIEW_SELECT_TMPTABLE 1351
#define ER_VIEW_WRONG_LIST 1352
@ -374,4 +374,4 @@
#define ER_VIEW_INVALID 1355
#define ER_SP_NO_DROP_SP 1356
#define ER_SP_GOTO_IN_HNDLR 1357
#define ER_ERROR_MESSAGES 357
#define ER_ERROR_MESSAGES 358

View File

@ -2384,7 +2384,7 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
char buff[4 /* size of stmt id */ +
5 /* execution flags */];
DBUG_ENTER("execute");
DBUG_PRINT("enter",("packet: %s, length :%d",packet ? packet :" ", length));
DBUG_DUMP("packet", packet, length);
mysql->last_used_con= mysql;
int4store(buff, stmt->stmt_id); /* Send stmt id to server */

View File

@ -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` (

View File

@ -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`,(`test`.`t1`.`st` collate _latin1'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 _latin1'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

View File

@ -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;
select '1.0' in (1,2);
'1.0' in (1,2)

View File

@ -638,7 +638,7 @@ explain extended select md5('hello'), sha('abc'), sha1('abc'), soundex(''), 'moo
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 md5(_latin1'hello') AS `md5('hello')`,sha(_latin1'abc') AS `sha('abc')`,sha(_latin1'abc') AS `sha1('abc')`,soundex(_latin1'') AS `soundex('')`,(soundex(_latin1'mood') = soundex(_latin1'mud')) AS `'mood' sounds like 'mud'`,aes_decrypt(aes_encrypt(_latin1'abc',_latin1'1'),_latin1'1') AS `aes_decrypt(aes_encrypt('abc','1'),'1')`,concat(_latin1'*',repeat(_latin1' ',5),_latin1'*') AS `concat('*',space(5),'*')`,reverse(_latin1'abc') AS `reverse('abc')`,rpad(_latin1'a',4,_latin1'1') AS `rpad('a',4,'1')`,lpad(_latin1'a',4,_latin1'1') AS `lpad('a',4,'1')`,concat_ws(_latin1',',_latin1'',NULL,_latin1'a') AS `concat_ws(',','',NULL,'a')`,make_set(255,_latin2'a',_latin2'b',_latin2'c') AS `make_set(255,_latin2'a',_latin2'b',_latin2'c')`,elt(2,1) AS `elt(2,1)`,locate(_latin1'a',_latin1'b',2) AS `locate("a","b",2)`,format(130,10) AS `format(130,10)`,char(0) AS `char(0)`,conv(130,16,10) AS `conv(130,16,10)`,hex(130) AS `hex(130)`,(_latin1'HE' collate _latin1'BINARY') AS `binary 'HE'`,export_set(255,_latin2'y',_latin2'n',_latin2' ') AS `export_set(255,_latin2'y',_latin2'n',_latin2' ')`,field((_latin1'b' collate _latin1'latin1_bin'),_latin1'A',_latin1'B') AS `FIELD('b' COLLATE latin1_bin,'A','B')`,find_in_set(_latin1'B',_latin1'a,b,c,d') AS `FIND_IN_SET(_latin1'B',_latin1'a,b,c,d')`,collation(conv(130,16,10)) AS `collation(conv(130,16,10))`,coercibility(conv(130,16,10)) AS `coercibility(conv(130,16,10))`,length(_latin1'\n \r\0\\_\\%\\') AS `length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,concat(_latin1'monty',_latin1' was here ',_latin1'again') AS `concat('monty',' was here ','again')`,length(_latin1'hello') AS `length('hello')`,char(ascii(_latin1'h')) AS `char(ascii('h'))`,ord(_latin1'h') AS `ord('h')`,quote((1 / 0)) AS `quote(1/0)`,crc32(_latin1'123') AS `crc32("123")`,replace(_latin1'aaaa',_latin1'a',_latin1'b') AS `replace('aaaa','a','b')`,insert(_latin1'txs',2,1,_latin1'hi') AS `insert('txs',2,1,'hi')`,left(_latin2'a',1) AS `left(_latin2'a',1)`,right(_latin2'a',1) AS `right(_latin2'a',1)`,lcase(_latin2'a') AS `lcase(_latin2'a')`,ucase(_latin2'a') AS `ucase(_latin2'a')`,substr(_latin1'abcdefg',3,2) AS `SUBSTR('abcdefg',3,2)`,substr_index(_latin1'1abcd;2abcd;3abcd;4abcd',_latin1';',2) AS `substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2)`,trim(_latin2' a ') AS `trim(_latin2' a ')`,ltrim(_latin2' a ') AS `ltrim(_latin2' a ')`,rtrim(_latin2' a ') AS `rtrim(_latin2' a ')`,decode(encode(repeat(_latin1'a',100000))) AS `decode(encode(repeat("a",100000),"monty"),"monty")`
Note 1003 select md5(_latin1'hello') AS `md5('hello')`,sha(_latin1'abc') AS `sha('abc')`,sha(_latin1'abc') AS `sha1('abc')`,soundex(_latin1'') AS `soundex('')`,(soundex(_latin1'mood') = soundex(_latin1'mud')) AS `'mood' sounds like 'mud'`,aes_decrypt(aes_encrypt(_latin1'abc',_latin1'1'),_latin1'1') AS `aes_decrypt(aes_encrypt('abc','1'),'1')`,concat(_latin1'*',repeat(_latin1' ',5),_latin1'*') AS `concat('*',space(5),'*')`,reverse(_latin1'abc') AS `reverse('abc')`,rpad(_latin1'a',4,_latin1'1') AS `rpad('a',4,'1')`,lpad(_latin1'a',4,_latin1'1') AS `lpad('a',4,'1')`,concat_ws(_latin1',',_latin1'',NULL,_latin1'a') AS `concat_ws(',','',NULL,'a')`,make_set(255,_latin2'a',_latin2'b',_latin2'c') AS `make_set(255,_latin2'a',_latin2'b',_latin2'c')`,elt(2,1) AS `elt(2,1)`,locate(_latin1'a',_latin1'b',2) AS `locate("a","b",2)`,format(130,10) AS `format(130,10)`,char(0) AS `char(0)`,conv(130,16,10) AS `conv(130,16,10)`,hex(130) AS `hex(130)`,(_latin1'HE' collate BINARY) AS `binary 'HE'`,export_set(255,_latin2'y',_latin2'n',_latin2' ') AS `export_set(255,_latin2'y',_latin2'n',_latin2' ')`,field((_latin1'b' collate latin1_bin),_latin1'A',_latin1'B') AS `FIELD('b' COLLATE latin1_bin,'A','B')`,find_in_set(_latin1'B',_latin1'a,b,c,d') AS `FIND_IN_SET(_latin1'B',_latin1'a,b,c,d')`,collation(conv(130,16,10)) AS `collation(conv(130,16,10))`,coercibility(conv(130,16,10)) AS `coercibility(conv(130,16,10))`,length(_latin1'\n \r\0\\_\\%\\') AS `length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,bit_length(_latin1'\n \r\0\\_\\%\\') AS `bit_length('\n\t\r\b\0\_\%\\')`,concat(_latin1'monty',_latin1' was here ',_latin1'again') AS `concat('monty',' was here ','again')`,length(_latin1'hello') AS `length('hello')`,char(ascii(_latin1'h')) AS `char(ascii('h'))`,ord(_latin1'h') AS `ord('h')`,quote((1 / 0)) AS `quote(1/0)`,crc32(_latin1'123') AS `crc32("123")`,replace(_latin1'aaaa',_latin1'a',_latin1'b') AS `replace('aaaa','a','b')`,insert(_latin1'txs',2,1,_latin1'hi') AS `insert('txs',2,1,'hi')`,left(_latin2'a',1) AS `left(_latin2'a',1)`,right(_latin2'a',1) AS `right(_latin2'a',1)`,lcase(_latin2'a') AS `lcase(_latin2'a')`,ucase(_latin2'a') AS `ucase(_latin2'a')`,substr(_latin1'abcdefg',3,2) AS `SUBSTR('abcdefg',3,2)`,substr_index(_latin1'1abcd;2abcd;3abcd;4abcd',_latin1';',2) AS `substring_index("1abcd;2abcd;3abcd;4abcd", ';', 2)`,trim(_latin2' a ') AS `trim(_latin2' a ')`,ltrim(_latin2' a ') AS `ltrim(_latin2' a ')`,rtrim(_latin2' a ') AS `rtrim(_latin2' a ')`,decode(encode(repeat(_latin1'a',100000))) AS `decode(encode(repeat("a",100000),"monty"),"monty")`
SELECT lpad(12345, 5, "#");
lpad(12345, 5, "#")
12345

View File

@ -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

View File

@ -1764,6 +1764,26 @@ call bug5251()|
Table Checksum
test.t1 0
drop procedure bug5251|
create procedure bug5287(param1 int)
label1:
begin
declare c cursor for select 5;
loop
if param1 >= 0 then
leave label1;
end if;
end loop;
end|
call bug5287(1)|
drop procedure bug5287|
create procedure bug5307()
begin
end; set @x = 3|
call bug5307()|
select @x|
@x
3
drop procedure bug5307|
drop table if exists fac|
create table fac (n int unsigned not null primary key, f bigint unsigned)|
create procedure ifac(n int unsigned)

View File

@ -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

View File

@ -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ü;
ü
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;

View File

@ -1924,6 +1924,35 @@ call bug5251()|
call bug5251()|
drop procedure bug5251|
#
# BUG#5287: Stored procedure crash if leave outside loop
#
create procedure bug5287(param1 int)
label1:
begin
declare c cursor for select 5;
loop
if param1 >= 0 then
leave label1;
end if;
end loop;
end|
call bug5287(1)|
drop procedure bug5287|
#
# BUG#5307: Stored procedure allows statement after BEGIN ... END
#
create procedure bug5307()
begin
end; set @x = 3|
call bug5307()|
select @x|
drop procedure bug5307|
#
# Some "real" examples

View File

@ -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;

View File

@ -66,13 +66,209 @@ 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
@ -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));

View File

@ -1143,8 +1143,27 @@ bool Item_param::convert_str_value(THD *thd)
return rc;
}
/* End of Item_param related */
void Item_param::print(String *str)
{
if (state == NO_VALUE)
{
str->append('?');
}
else
{
char buffer[80];
String tmp(buffer, sizeof(buffer), &my_charset_bin);
const String *res;
res= query_val_str(&tmp);
str->append(*res);
}
}
/****************************************************************************
Item_copy_string
****************************************************************************/
void Item_copy_string::copy()
{
@ -1302,11 +1321,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 &&
@ -1756,6 +1785,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
@ -2014,11 +2058,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;
}
@ -2063,8 +2117,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

View File

@ -635,7 +635,7 @@ public:
*/
virtual table_map used_tables() const
{ return state != NO_VALUE ? (table_map)0 : PARAM_TABLE_BIT; }
void print(String *str) { str->append('?'); }
void print(String *str);
/* parameter never equal to other parameter of other item */
bool eq(const Item *item, bool binary_cmp) const { return 0; }
};
@ -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);
};

View File

@ -3270,9 +3270,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)
{

View File

@ -2274,6 +2274,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);

View File

@ -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

View File

@ -995,23 +995,6 @@ Item_in_subselect::select_transformer(JOIN *join)
}
Item_subselect::trans_res
Item_in_subselect::no_select_transform()
{
DBUG_ENTER("Item_in_subselect::no_select_transform");
// We have execute fix_fields() for left expression
SELECT_LEX *current= thd->lex->current_select, *up;
thd->lex->current_select= up= current->return_after_parsing();
if (left_expr->fix_fields(thd, up->get_table_list(), &left_expr))
{
thd->lex->current_select= current;
DBUG_RETURN(RES_ERROR);
}
thd->lex->current_select= current;
DBUG_RETURN(RES_OK);
}
void Item_in_subselect::print(String *str)
{
if (transformed)

View File

@ -84,7 +84,6 @@ public:
null_value= 1;
}
virtual trans_res select_transformer(JOIN *join);
virtual trans_res no_select_transform() { return RES_OK; }
bool assigned() { return value_assigned; }
void assigned(bool a) { value_assigned= a; }
enum Type type() const;
@ -220,7 +219,6 @@ public:
was_null= 0;
}
trans_res select_transformer(JOIN *join);
trans_res no_select_transform();
trans_res single_value_transformer(JOIN *join,
Comp_creator *func);
trans_res row_value_transformer(JOIN * join);

View File

@ -2011,7 +2011,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(')');
}

View File

@ -838,13 +838,13 @@ int MYSQL_LOG::purge_logs(const char *to_log,
while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) &&
!log_in_use(log_info.log_file_name))
{
ulong tmp;
LINT_INIT(tmp);
ulong file_size;
LINT_INIT(file_size);
if (decrease_log_space) //stat the file we want to delete
{
MY_STAT s;
if (my_stat(log_info.log_file_name,&s,MYF(0)))
tmp= s.st_size;
file_size= s.st_size;
else
{
/*
@ -852,7 +852,7 @@ int MYSQL_LOG::purge_logs(const char *to_log,
of space that deletion will free. In most cases,
deletion won't work either, so it's not a problem.
*/
tmp= 0;
file_size= 0;
}
}
/*
@ -861,7 +861,7 @@ int MYSQL_LOG::purge_logs(const char *to_log,
*/
DBUG_PRINT("info",("purging %s",log_info.log_file_name));
if (!my_delete(log_info.log_file_name, MYF(0)) && decrease_log_space)
*decrease_log_space-= tmp;
*decrease_log_space-= file_size;
if (find_next_log(&log_info, 0) || exit_loop)
break;
}

View File

@ -398,8 +398,9 @@ void free_items(Item *item);
void cleanup_items(Item *item);
class THD;
void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0);
int check_one_table_access(THD *thd, ulong privilege,
bool check_one_table_access(THD *thd, ulong privilege,
TABLE_LIST *tables);
bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table);
bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST *table_list);
int multi_update_precheck(THD *thd, TABLE_LIST *tables);
@ -767,12 +768,10 @@ void free_io_cache(TABLE *entry);
void intern_close_table(TABLE *entry);
bool close_thread_table(THD *thd, TABLE **table_ptr);
void close_temporary_tables(THD *thd);
TABLE_LIST * find_real_table_in_list(TABLE_LIST *table,
const char *db_name,
const char *table_name);
TABLE_LIST * find_real_table_in_local_list(TABLE_LIST *table,
const char *db_name,
const char *table_name);
TABLE_LIST *find_table_in_list(TABLE_LIST *table,
uint offset_to_list,
const char *db_name,
const char *table_name);
TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name);
bool close_temporary_table(THD *thd, const char *db, const char *table_name);
void close_temporary(TABLE *table, bool delete_table=1);
@ -788,6 +787,23 @@ int fill_record(List<Item> &fields,List<Item> &values, bool ignore_errors);
int fill_record(Field **field,List<Item> &values, bool ignore_errors);
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild);
inline TABLE_LIST *find_table_in_global_list(TABLE_LIST *table,
const char *db_name,
const char *table_name)
{
return find_table_in_list(table, offsetof(TABLE_LIST, next_global),
db_name, table_name);
}
inline TABLE_LIST *find_table_in_local_list(TABLE_LIST *table,
const char *db_name,
const char *table_name)
{
return find_table_in_list(table, offsetof(TABLE_LIST, next_local),
db_name, table_name);
}
/* sql_calc.cc */
bool eval_const_cond(COND *cond);

View File

@ -361,7 +361,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"

View File

@ -1,4 +1,4 @@
/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB
:/* Copyright Abandoned 1997 TCX DataKonsult AB & Monty Program KB & Detron HB
This file is public domain and comes with NO WARRANTY of any kind */
/* Knud Riishøjgård knudriis@post.tele.dk 99 &&
@ -355,7 +355,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"

View File

@ -363,7 +363,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"

View File

@ -352,7 +352,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"

View File

@ -357,7 +357,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"

View File

@ -352,7 +352,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"

View File

@ -364,7 +364,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"

View File

@ -352,7 +352,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"

View File

@ -354,7 +354,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"

View File

@ -352,7 +352,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"

View File

@ -354,7 +354,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"

View File

@ -352,7 +352,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"

View File

@ -354,7 +354,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"

View File

@ -354,7 +354,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"

View File

@ -356,7 +356,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"

View File

@ -353,7 +353,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"

View File

@ -356,7 +356,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"

View File

@ -354,7 +354,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 имеют разное количество столбцов"

View File

@ -358,7 +358,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"

View File

@ -360,7 +360,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"

View File

@ -354,7 +354,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"

View File

@ -352,7 +352,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"

View File

@ -357,7 +357,7 @@ character-set=koi8u
"'%-.64s.%-.64s' ΞΕ € %s"
"σΤΟΧΒΕΓΨ '%-.64s' ΞΕ ΝΟΦΕ ΒΥΤΙ ΪΝΙΞΕΞΙΚ"
"View SELECT ΝΑ€ Π¦ΔΪΑΠΙΤ Υ ΛΟΞΣΤ<CEA3>ΥΛΓ¦§ FROM"
"View SELECT ÍÁ¤ ËÏÎÓÔÒÕËæÀ PROCEDURE"
"View SELECT ÍÁ¤ ËÏÎÓÔÒÕËæÀ '%s'"
"View SELECT ΝΑ€ ΪΝΙΞΞΥ ΑΒΟ ΠΑ<CEA0>ΑΝΕΤΕ<CEA4>"
"View SELECT ΧΙΛΟ<CE9B>ΙΣΤΟΧΥ€ ΤΙΝήΑΣΟΧΥ ΤΑΒΜΙΓΐ '%-.64s'"
"View SELECT ¦ ΠΕ<CEA0>ΕΜ¦Λ ΣΤΟΧΒΓ¦Χ view ΝΑΐΤΨ <20>¦ΪΞΥ Λ¦ΜΨΛ¦ΣΤΨ ΣΛΟΧΒΓ¦Χ"

View File

@ -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
@ -955,6 +960,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,

View File

@ -288,6 +288,7 @@ void
sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
{
DBUG_ENTER("sp_head::init_strings");
uint n; /* Counter for nul trimming */
/* During parsing, we must use thd->mem_root */
MEM_ROOT *root= &thd->mem_root;
@ -351,9 +352,17 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
(char *)m_returns_begin, m_retstr.length);
}
}
m_body.length= lex->end_of_query - m_body_begin;
m_body.length= lex->ptr - m_body_begin;
/* Trim nuls at the end */
n= 0;
while (m_body.length && m_body_begin[m_body.length-1] == '\0')
{
m_body.length-= 1;
n+= 1;
}
m_body.str= strmake_root(root, (char *)m_body_begin, m_body.length);
m_defstr.length= lex->end_of_query - lex->buf;
m_defstr.length= lex->ptr - lex->buf;
m_defstr.length-= n;
m_defstr.str= strmake_root(root, (char *)lex->buf, m_defstr.length);
DBUG_VOID_RETURN;
}
@ -1193,7 +1202,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)
@ -1294,7 +1303,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)
@ -1351,7 +1360,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)
@ -1407,7 +1416,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)

View File

@ -28,7 +28,7 @@
sp_pcontext::sp_pcontext(sp_pcontext *prev)
: Sql_alloc(), m_psubsize(0), m_csubsize(0), m_hsubsize(0),
m_parent(prev), m_handlers(0)
m_handlers(0), m_parent(prev)
{
VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8));
@ -94,7 +94,7 @@ sp_pcontext::diff_handlers(sp_pcontext *ctx)
while (pctx && pctx != ctx)
{
n+= pctx->max_handlers();
n+= pctx->m_handlers;
pctx= pctx->parent_context();
}
if (pctx)
@ -109,12 +109,9 @@ sp_pcontext::diff_cursors(sp_pcontext *ctx)
sp_pcontext *pctx= this;
while (pctx && pctx != ctx)
{
n+= pctx->max_cursors();
pctx= pctx->parent_context();
}
if (pctx)
return n;
return ctx->current_cursors() - pctx->current_cursors();
return 0; // Didn't find ctx
}

View File

@ -275,6 +275,7 @@ protected:
uint m_psubsize;
uint m_csubsize;
uint m_hsubsize;
uint m_handlers; // No. of handlers in this context
private:
@ -282,7 +283,6 @@ private:
uint m_poffset; // Variable offset for this context
uint m_coffset; // Cursor offset for this context
uint m_handlers; // No. of handlers in this context
DYNAMIC_ARRAY m_pvar; // Parameters/variables
DYNAMIC_ARRAY m_cond; // Conditions

View File

@ -2761,7 +2761,22 @@ void grant_reload(THD *thd)
/****************************************************************************
Check table level grants
All errors are written directly to the client if no_errors is given !
SYNPOSIS
bool check_grant()
thd Thread handler
want_access Bits of privileges user needs to have
tables List of tables to check. The user should have 'want_access'
to all tables in list.
show_table <> 0 if we are in show table. In this case it's enough to have
any privilege for the table
number Check at most this number of tables.
no_errors If 0 then we write an error. The error is sent directly to
the client
RETURN
0 ok
1 Error: User did not have the requested privielges
****************************************************************************/
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
@ -2769,14 +2784,17 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
{
TABLE_LIST *table;
char *user = thd->priv_user;
DBUG_ENTER("check_grant");
DBUG_ASSERT(number > 0);
want_access &= ~thd->master_access;
want_access&= ~thd->master_access;
if (!want_access)
return 0; // ok
DBUG_RETURN(0); // ok
rw_rdlock(&LOCK_grant);
for (table= tables; table && number--; table= table->next_global)
{
GRANT_TABLE *grant_table;
if (!(~table->grant.privilege & want_access) || table->derived)
{
/*
@ -2786,10 +2804,8 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
table->grant.want_privilege= 0;
continue; // Already checked
}
GRANT_TABLE *grant_table = table_hash_search(thd->host,thd->ip,
table->db,user,
table->real_name,0);
if (!grant_table)
if (!(grant_table= table_hash_search(thd->host,thd->ip,
table->db,user, table->real_name,0)))
{
want_access &= ~table->grant.privilege;
goto err; // No grants
@ -2813,7 +2829,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
}
}
rw_unlock(&LOCK_grant);
return 0;
DBUG_RETURN(0);
err:
rw_unlock(&LOCK_grant);
@ -2848,7 +2864,7 @@ err:
thd->host_or_ip,
table ? table->real_name : "unknown");
}
return 1;
DBUG_RETURN(1);
}
@ -2942,7 +2958,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
if (!(grant_table= grant->grant_table))
goto err; /* purecov: inspected */
for (; fields->end(); fields->next())
for (; !fields->end_of_fields(); fields->next())
{
const char *field_name= fields->name();
grant_column= column_hash_search(grant_table, field_name,

View File

@ -549,81 +549,37 @@ void close_temporary_tables(THD *thd)
thd->temporary_tables=0;
}
#ifdef UNUSED
/*
Find first suitable table by alias in given list.
Find table in list.
SYNOPSIS
find_table_in_list()
table - pointer to table list
db_name - data base name or 0 for any
table_name - table name or 0 for any
table Pointer to table list
offset Offset to which list in table structure to use
db_name Data base name
table_name Table name
NOTES:
This is called by find_table_in_local_list() and
find_table_in_global_list().
RETURN VALUES
NULL Table not found
# Pointer to found table.
*/
TABLE_LIST * find_table_in_list(TABLE_LIST *table,
const char *db_name, const char *table_name)
TABLE_LIST *find_table_in_list(TABLE_LIST *table,
uint offset,
const char *db_name,
const char *table_name)
{
for (; table; table= table->next)
if ((!db_name || !strcmp(table->db, db_name)) &&
(!table_name || !my_strcasecmp(table_alias_charset,
table->alias, table_name)))
break;
return table;
}
#endif /*UNUSED*/
/*
Find real table in given global list.
SYNOPSIS
find_real_table_in_list()
table - pointer to table list
db_name - data base name
table_name - table name
RETURN VALUES
NULL Table not found
# Pointer to found table.
*/
TABLE_LIST * find_real_table_in_list(TABLE_LIST *table,
const char *db_name,
const char *table_name)
{
for (; table; table= table->next_global)
if (!strcmp(table->db, db_name) &&
!strcmp(table->real_name, table_name))
break;
return table;
}
/*
Find real table in given local list.
SYNOPSIS
find_real_table_in_local_list()
table - pointer to table list
db_name - data base name
table_name - table name
RETURN VALUES
NULL Table not found
# Pointer to found table.
*/
TABLE_LIST * find_real_table_in_local_list(TABLE_LIST *table,
const char *db_name,
const char *table_name)
{
for (; table; table= table->next_local)
for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
{
if (!strcmp(table->db, db_name) &&
!strcmp(table->real_name, table_name))
break;
}
return table;
}
@ -1364,7 +1320,7 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name)
db Database name
name Table name
alias Alias name
table_desc TABLE_LIST descriptor
table_desc TABLE_LIST descriptor (used with views)
mem_root temporary mem_root for parsing
NOTES
@ -1402,10 +1358,10 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
if (!entry->crashed)
{
/*
Frm file could not be found on disk
Since it does not exist, no one can be using it
LOCK_open has been locked to protect from someone else
trying to discover the table at the same time.
Frm file could not be found on disk
Since it does not exist, no one can be using it
LOCK_open has been locked to protect from someone else
trying to discover the table at the same time.
*/
if (discover_retry_count++ != 0)
goto err;
@ -1610,7 +1566,7 @@ int open_tables(THD *thd, TABLE_LIST *start, uint *counter)
tables->table->grant= tables->grant;
}
thd->proc_info=0;
free_root(&new_frm_mem, MYF(0));
free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block
DBUG_RETURN(result);
}
@ -1680,7 +1636,8 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
thd->current_tablenr= 0;
/* open_ltable can be used only for BASIC TABLEs */
table_list->required_type= FRMTYPE_TABLE;
while (!(table= open_table(thd, table_list, 0, &refresh)) && refresh) ;
while (!(table= open_table(thd, table_list, 0, &refresh)) && refresh)
;
if (table)
{
@ -1751,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()
@ -1760,9 +1718,9 @@ 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 */
DBUG_RETURN(mysql_handle_derived(thd->lex));
}
@ -1909,7 +1867,7 @@ bool rm_temporary_table(enum db_type base, char *path)
** return unique field
******************************************************************************/
// Special Field pointers for find_field_in_tables returning
/* Special Field pointers for find_field_in_tables returning */
const Field *not_found_field= (Field*) 0x1;
const Field *view_ref_found= (Field*) 0x2;
@ -2005,6 +1963,7 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
return fld;
}
/*
Find field in table
@ -2594,23 +2553,47 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
}
/****************************************************************************
This just drops in all fields instead of current '*' field
Returns pointer to last inserted field if ok
****************************************************************************/
/*
Drops in all fields instead of current '*' field
SYNOPSIS
insert_fields()
thd Thread handler
tables List of tables
db_name Database name in case of 'database_name.table_name.*'
table_name Table name in case of 'table_name.*'
it Pointer to '*'
any_privileges 0 If we should ensure that we have SELECT privileges
for all columns
1 If any privilege is ok
RETURN
0 ok
'it' is updated to point at last inserted
1 error. The error message is sent to client
*/
bool
insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
const char *table_name, List_iterator<Item> *it,
bool any_privileges)
{
/* allocate variables on stack to avoid pool alloaction */
Field_iterator_table table_iter;
Field_iterator_view view_iter;
uint found;
DBUG_ENTER("insert_fields");
found=0;
found= 0;
for (; tables; tables= tables->next_local)
{
TABLE *table=tables->table;
Field_iterator *iterator;
TABLE_LIST *natural_join_table;
Field *field;
TABLE_LIST *embedded;
TABLE_LIST *last;
TABLE_LIST *embedding;
TABLE *table= tables->table;
if (!table_name || (!my_strcasecmp(table_alias_charset, table_name,
tables->alias) &&
(!db_name || !strcmp(tables->db,db_name))))
@ -2621,36 +2604,26 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
{
if (tables->view)
{
Field_iterator_view fields;
fields.set(tables);
view_iter.set(tables);
if (check_grant_all_columns(thd, SELECT_ACL, &tables->grant,
tables->view_db.str,
tables->view_name.str,
&fields))
DBUG_RETURN(1);
&view_iter))
goto err;
}
else
{
Field_iterator_table fields;
fields.set(tables);
table_iter.set(tables);
if (check_grant_all_columns(thd, SELECT_ACL, &table->grant,
table->table_cache_key, table->real_name,
&fields))
DBUG_RETURN(1);
&table_iter))
goto err;
}
}
#endif
/* allocate 2 variables on stack to avoid pool alloaction */
Field_iterator_table table_iter;
Field_iterator_view view_iter;
Field_iterator *iterator;
TABLE_LIST *natural_join_table= 0;
Field *field;
thd->used_tables|=table->map;
TABLE_LIST *embedded= tables;
TABLE_LIST *last= embedded;
TABLE_LIST *embedding;
natural_join_table= 0;
thd->used_tables|= table->map;
last= embedded= tables;
while ((embedding= embedded->embedding) &&
embedding->join_list->elements != 1)
@ -2681,7 +2654,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
iterator= &table_iter;
iterator->set(tables);
for (; iterator->end(); iterator->next())
for (; !iterator->end_of_fields(); iterator->next())
{
Item *not_used_item;
uint not_used_field_index= NO_CACHED_FIELD_INDEX;
@ -2733,9 +2706,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
thd->host_or_ip,
fld->field_name,
tab);
/* TODO: should be removed to have only one send_error */
send_error(thd);
DBUG_RETURN(1);
goto err;
}
}
#endif
@ -2769,15 +2740,17 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
table->used_fields=table->fields;
}
}
if (!found)
{
if (!table_name)
my_error(ER_NO_TABLES_USED,MYF(0));
else
my_error(ER_BAD_TABLE_ERROR,MYF(0),table_name);
send_error(thd);
}
DBUG_RETURN(!found);
if (found)
DBUG_RETURN(0);
if (!table_name)
my_error(ER_NO_TABLES_USED, MYF(0));
else
my_error(ER_BAD_TABLE_ERROR, MYF(0), table_name);
err:
send_error(thd);
DBUG_RETURN(1);
}
@ -2866,13 +2839,16 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
if (arena)
thd->set_n_backup_item_arena(arena, &backup);
TABLE *t1=tab1->table;
TABLE *t2=tab2->table;
/* allocate 2 variables on stack to avoid pool alloaction */
Field_iterator_table table_iter;
Field_iterator_view view_iter;
Field_iterator *iterator;
Field *t1_field, *t2_field;
Item *item_t2;
Item_cond_and *cond_and=new Item_cond_and();
if (!cond_and) // If not out of memory
DBUG_RETURN(1);
cond_and->top_level_item();
@ -2888,9 +2864,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
table_iter.set(tab1);
}
Field *t1_field, *t2_field;
Item *item_t2;
for (; iterator->end(); iterator->next())
for (; !iterator->end_of_fields(); iterator->next())
{
const char *t1_field_name= iterator->name();
uint not_used_field_index= NO_CACHED_FIELD_INDEX;
@ -3227,6 +3201,7 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order)
table_desc TABLE_LIST descriptor
mem_root temporary MEM_ROOT for parsing
*/
static my_bool
open_new_frm(const char *path, const char *alias,
const char *db, const char *table_name,
@ -3234,16 +3209,17 @@ open_new_frm(const char *path, const char *alias,
uint ha_open_flags, TABLE *outparam, TABLE_LIST *table_desc,
MEM_ROOT *mem_root)
{
DBUG_ENTER("open_new_frm");
LEX_STRING pathstr;
pathstr.str= (char *)path;
File_parser *parser;
DBUG_ENTER("open_new_frm");
pathstr.str= (char*) path;
pathstr.length= strlen(path);
if (!mem_root)
mem_root= &current_thd->mem_root;
File_parser *parser= sql_parse_prepare(&pathstr, mem_root, 1);
if (parser)
if ((parser= sql_parse_prepare(&pathstr, mem_root, 1)))
{
if (!strncmp("VIEW", parser->type()->str, parser->type()->length))
{
@ -3261,12 +3237,9 @@ open_new_frm(const char *path, const char *alias,
my_error(ER_FRM_UNKNOWN_TYPE, MYF(0), path, parser->type()->str);
goto err;
}
DBUG_RETURN(0);
}
else
goto err;
DBUG_RETURN(0);
err:
bzero(outparam, sizeof(TABLE)); // do not run repair
DBUG_RETURN(1);

View File

@ -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";
@ -282,7 +282,7 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
DBUG_RETURN(-1);
}
if (find_real_table_in_list(table_list->next_global,
if (find_table_in_global_list(table_list->next_global,
table_list->db, table_list->real_name))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);

View File

@ -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);
}

View File

@ -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

View File

@ -51,6 +51,7 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
List<Item> &values, ulong counter, bool check_unique)
{
TABLE *table= table_list->table;
if (fields.elements == 0 && values.elements != 0)
{
if (values.elements != table->fields)
@ -61,11 +62,11 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
return -1;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (grant_option)
{
Field_iterator_table fields;
fields.set_table(table);
if (grant_option &&
check_grant_all_columns(thd, INSERT_ACL, &table->grant,
if (check_grant_all_columns(thd, INSERT_ACL, &table->grant,
table->table_cache_key, table->real_name,
&fields))
return -1;
@ -75,7 +76,7 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
}
else
{ // Part field list
TABLE_LIST *save_next= table_list->next_local;
TABLE_LIST *save_next;
int res;
if (fields.elements != values.elements)
{
@ -85,16 +86,15 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
return -1;
}
table_list->next_local= 0;
thd->dupp_field=0;
thd->lex->select_lex.no_wrap_view_item= 1;
save_next= table_list->next_local; // fields only from first table
table_list->next_local= 0;
res= setup_fields(thd, 0, table_list, fields, 1, 0, 0);
thd->lex->select_lex.no_wrap_view_item= 0;
table_list->next_local= save_next;
thd->lex->select_lex.no_wrap_view_item= 0;
if (res)
{
return -1;
}
if (check_unique && thd->dupp_field)
{
@ -410,7 +410,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
!thd->cuted_fields))
{
thd->row_count_func= info.copied+info.deleted+info.updated;
send_ok(thd, (ulong) (ulong) thd->row_count_func, id);
send_ok(thd, (ulong) thd->row_count_func, id);
}
else
{
@ -423,7 +423,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
(ulong) (info.deleted+info.updated), (ulong) thd->cuted_fields);
thd->row_count_func= info.copied+info.deleted+info.updated;
::send_ok(thd, (ulong) thd->row_count_func, (ulonglong)id,buff);
::send_ok(thd, (ulong) thd->row_count_func, id, buff);
}
free_underlaid_joins(thd, &thd->lex->select_lex);
table->insert_values=0;
@ -447,46 +447,58 @@ abort:
check_view_insertability()
view - reference on VIEW
IMPLEMENTATION
A view is insertable if the folloings are true:
- All columns in the view are columns from a table
- All not used columns in table have a default values
- All field in view are unique (not referring to the same column)
RETURN
FALSE - OK
view->contain_auto_increment is 1 if and only if the view contains an
auto_increment field
TRUE - can't be used for insert
*/
static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
{
uint num= view->view->select_lex.item_list.elements;
TABLE *table= view->table;
Item **trans_start= view->field_translation, **trans_end=trans_start+num;
Item **trans;
Field **field_ptr= table->field;
ulong other_query_id= query_id - 1;
DBUG_ENTER("check_key_in_view");
uint i;
TABLE *table= view->table;
Item **trans= view->field_translation;
Field **field_ptr= table->field;
uint num= view->view->select_lex.item_list.elements;
ulong other_query_id= query_id - 1;
DBUG_ASSERT(view->table != 0 && view->field_translation != 0);
view->contain_auto_increment= 0;
/* check simplicity and prepare unique test of view */
for (i= 0; i < num; i++)
for (trans= trans_start; trans != trans_end; trans++)
{
Item_field *field;
/* simple SELECT list entry (field without expression) */
if (trans[i]->type() != Item::FIELD_ITEM)
if ((*trans)->type() != Item::FIELD_ITEM)
DBUG_RETURN(TRUE);
if (((Item_field *)trans[i])->field->unireg_check == Field::NEXT_NUMBER)
field= (Item_field *)(*trans);
if (field->field->unireg_check == Field::NEXT_NUMBER)
view->contain_auto_increment= 1;
/* prepare unique test */
((Item_field *)trans[i])->field->query_id= other_query_id;
field->field->query_id= other_query_id;
}
/* unique test */
for (i= 0; i < num; i++)
for (trans= trans_start; trans != trans_end; trans++)
{
Item_field *field= (Item_field *)trans[i];
/* Thanks to test above, we know that all columns are of type Item_field */
Item_field *field= (Item_field *)(*trans);
if (field->field->query_id == query_id)
DBUG_RETURN(TRUE);
field->field->query_id= query_id;
}
/* VIEW contain all fields without default value */
for (; *field_ptr; ++field_ptr)
for (; *field_ptr; field_ptr++)
{
Field *field= *field_ptr;
/* field have not default value */
@ -494,14 +506,13 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
(table->timestamp_field != field ||
field->unireg_check == Field::TIMESTAMP_UN_FIELD))
{
uint i= 0;
for (; i < num; i++)
for (trans= trans_start; ; trans++)
{
if (((Item_field *)trans[i])->field == *field_ptr)
break;
if (trans == trans_end)
DBUG_RETURN(TRUE); // Field was not part of view
if (((Item_field *)(*trans))->field == *field_ptr)
break; // ok
}
if (i >= num)
DBUG_RETURN(TRUE);
}
}
DBUG_RETURN(FALSE);
@ -509,29 +520,28 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
/*
Prepare items in INSERT statement
Check if table can be updated
SYNOPSIS
mysql_prepare_insert()
thd - thread handler
table_list - global/local table list
mysql_prepare_insert_check_table()
thd Thread handle
table_list Table list (only one table)
fields List of fields to be updated
where Pointer to where clause
RETURN VALUE
0 - OK
-1 - error (message is not sent to user)
RETURN
0 ok
1 ERROR
*/
int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
List<Item> &fields, List_item *values,
List<Item> &update_fields, List<Item> &update_values,
enum_duplicates duplic)
static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
List<Item> &fields, COND **where)
{
bool insert_into_view= (table_list->view != 0);
DBUG_ENTER("mysql_prepare_insert");
DBUG_ENTER("mysql_prepare_insert_check_table");
/* TODO: use this condition for 'WHITH CHECK OPTION' */
Item *unused_conds= 0;
if (setup_tables(thd, table_list, &unused_conds))
DBUG_RETURN(-1);
if (setup_tables(thd, table_list, where))
DBUG_RETURN(1);
if (insert_into_view && !fields.elements)
{
@ -545,18 +555,51 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
check_view_insertability(table_list, thd->query_id)))
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
DBUG_RETURN(-1);
DBUG_RETURN(1);
}
DBUG_RETURN(0);
}
/*
Prepare items in INSERT statement
SYNOPSIS
mysql_prepare_insert()
thd Thread handler
table_list Global/local table list
RETURN VALUE
0 OK
-1 error (message is not sent to user)
*/
int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
List<Item> &fields, List_item *values,
List<Item> &update_fields, List<Item> &update_values,
enum_duplicates duplic)
{
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))
DBUG_RETURN(-1);
if (check_insert_fields(thd, table_list, fields, *values, 1,
!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);
if (find_real_table_in_list(table_list->next_global,
if (find_table_in_global_list(table_list->next_global,
table_list->db, table_list->real_name))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
@ -1558,27 +1601,11 @@ bool delayed_insert::handle_inserts(void)
int mysql_insert_select_prepare(THD *thd)
{
LEX *lex= thd->lex;
TABLE_LIST *table_list= lex->query_tables;
bool insert_into_view= (table_list->view != 0);
DBUG_ENTER("mysql_insert_select_prepare");
if (setup_tables(thd, table_list, &lex->select_lex.where))
if (mysql_prepare_insert_check_table(thd, lex->query_tables,
lex->field_list,
&lex->select_lex.where))
DBUG_RETURN(-1);
if (insert_into_view && !lex->field_list.elements)
{
lex->empty_field_list_on_rset= 1;
insert_view_fields(&lex->field_list, table_list);
}
if (!table_list->updatable ||
check_key_in_view(thd, table_list) ||
(insert_into_view &&
check_view_insertability(table_list, thd->query_id)))
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
DBUG_RETURN(-1);
}
DBUG_RETURN(0);
}

View File

@ -1421,7 +1421,7 @@ bool st_select_lex_unit::check_updateable(char *db, char *table)
*/
bool st_select_lex::check_updateable(char *db, char *table)
{
if (find_real_table_in_local_list(get_table_list(), db, table))
if (find_table_in_local_list(get_table_list(), db, table))
return 1;
for (SELECT_LEX_UNIT *un= first_inner_unit();
@ -1470,7 +1470,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)
@ -1655,14 +1662,16 @@ void st_select_lex_unit::set_limit(SELECT_LEX *values,
SYNOPSIS
unlink_first_table()
link_to_local do we need link this table to local
link_to_local Set to 1 if caller should link this table to local
NOTES
We rely on fact that first table in both list are same or local list
is empty
RETURN
0 If 'query_tables' == 0
unlinked table
In this case link_to_local is set.
*/
TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local)
@ -1716,11 +1725,11 @@ void st_lex::first_lists_tables_same()
TABLE_LIST *first_table= (TABLE_LIST*) select_lex.table_list.first;
if (query_tables != first_table && first_table != 0)
{
TABLE_LIST *next;
if (query_tables_last == &first_table->next_global)
query_tables_last= first_table->prev_global;
TABLE_LIST *next= *first_table->prev_global= first_table->next_global;
first_table->next_global= 0;
if (next)
if ((next= *first_table->prev_global= first_table->next_global))
next->prev_global= first_table->prev_global;
/* include in new place */
first_table->next_global= query_tables;

View File

@ -641,6 +641,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;

View File

@ -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)
{

View File

@ -78,6 +78,7 @@ const char *command_name[]={
"Connect","Kill","Debug","Ping","Time","Delayed_insert","Change user",
"Binlog Dump","Table Dump", "Connect Out", "Register Slave",
"Prepare", "Prepare Execute", "Long Data", "Close stmt",
"Reset stmt", "Set option", "Fetch",
"Error" // Last command number
};
@ -1910,7 +1911,7 @@ mysql_execute_command(THD *thd)
DBUG_ASSERT(first_table == all_tables && first_table != 0);
*/
lex->first_lists_tables_same();
/* should be assigned after making firts tables same */
/* should be assigned after making first tables same */
all_tables= lex->query_tables;
if (lex->sql_command != SQLCOM_CREATE_PROCEDURE &&
@ -2136,7 +2137,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);
@ -2386,8 +2387,8 @@ mysql_execute_command(THD *thd)
of query
*/
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
find_real_table_in_list(select_tables, create_table->db,
create_table->real_name))
find_table_in_global_list(select_tables, create_table->db,
create_table->real_name))
{
net_printf(thd, ER_UPDATE_TABLE_USED, create_table->real_name);
goto create_error;
@ -2400,7 +2401,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,
@ -2757,7 +2757,7 @@ unsent_create_error:
unit->set_limit(select_lex, select_lex);
// is table which we are changing used somewhere in other parts of query
if (find_real_table_in_list(all_tables->next_global,
if (find_table_in_global_list(all_tables->next_global,
first_table->db, first_table->real_name))
{
/* Using same table for INSERT and SELECT */
@ -3916,7 +3916,7 @@ error:
1 - access denied, error is sent to client
*/
int check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
{
if (check_access(thd, privilege, all_tables->db,
&all_tables->grant.privilege, 0, 0))
@ -3960,13 +3960,13 @@ bool
check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
bool dont_check_global_grants, bool no_errors)
{
DBUG_ENTER("check_access");
DBUG_PRINT("enter",("want_access: %lu master_access: %lu", want_access,
thd->master_access));
#ifndef NO_EMBEDDED_ACCESS_CHECKS
ulong db_access;
#endif
ulong dummy;
DBUG_ENTER("check_access");
DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu",
db ? db : "", want_access, thd->master_access));
if (save_priv)
*save_priv=0;
else
@ -3974,8 +3974,9 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if ((!db || !db[0]) && !thd->db && !dont_check_global_grants)
{
DBUG_PRINT("error",("No database"));
if (!no_errors)
send_error(thd,ER_NO_DB_ERROR); /* purecov: tested */
send_error(thd,ER_NO_DB_ERROR); /* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
}
@ -4000,6 +4001,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if (((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL)) ||
! db && dont_check_global_grants)
{ // We can never grant this
DBUG_PRINT("error",("No possible access"));
if (!no_errors)
net_printf(thd,ER_ACCESS_DENIED_ERROR,
thd->priv_user,
@ -4018,13 +4020,17 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
db_access=thd->db_access;
/* Remove SHOW attribute and access rights we already have */
want_access &= ~(thd->master_access | EXTRA_ACL);
DBUG_PRINT("info",("db_access: %lu want_access: %lu",
db_access, want_access));
db_access= ((*save_priv=(db_access | thd->master_access)) & want_access);
/* grant_option is set if there exists a single table or column grant */
if (db_access == want_access ||
((grant_option && !dont_check_global_grants) &&
(grant_option && !dont_check_global_grants &&
!(want_access & ~(db_access | TABLE_ACLS))))
DBUG_RETURN(FALSE); /* Ok */
DBUG_PRINT("error",("Access denied"));
if (!no_errors)
net_printf(thd,ER_DBACCESS_DENIED_ERROR,
thd->priv_user,
@ -4112,6 +4118,42 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
return FALSE;
}
/*
Check if the given table has any of the asked privileges
SYNOPSIS
check_some_access()
thd Thread handler
want_access Bitmap of possible privileges to check for
RETURN
0 ok
1 error
*/
bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table)
{
ulong access;
DBUG_ENTER("check_some_access");
/* This loop will work as long as we have less than 32 privileges */
for (access= 1; access < want_access ; access<<= 1)
{
if (access & want_access)
{
if (!check_access(thd, access, table->db,
&table->grant.privilege, 0, 1) &&
!grant_option || !check_grant(thd, access, table, 0, 1, 1))
DBUG_RETURN(0);
}
}
DBUG_PRINT("exit",("no matching access rights"));
DBUG_RETURN(1);
}
bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST *table_list)
{
@ -4247,7 +4289,7 @@ mysql_init_query(THD *thd, uchar *buf, uint length, bool lexonly)
lex->lock_option= TL_READ;
lex->found_colon= 0;
lex->safe_to_cache_query= 1;
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;
@ -4936,6 +4978,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);
}
@ -4971,6 +5014,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
{
register TABLE_LIST *ptr;
char *alias_str;
LEX *lex= thd->lex;
DBUG_ENTER("add_table_to_list");
if (!table)
@ -5022,7 +5066,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
ptr->derived= table->sel;
ptr->select_lex= thd->lex->current_select;
ptr->select_lex= lex->current_select;
ptr->cacheable_table= 1;
if (use_index_arg)
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index_arg,
@ -5046,8 +5090,9 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
}
}
}
/* Link table in local list (list for current select) */
table_list.link_in_list((byte*) ptr, (byte**) &ptr->next_local);
LEX *lex= thd->lex;
/* Link table in global list (all used tables) */
*(ptr->prev_global= lex->query_tables_last)= ptr;
lex->query_tables_last= &ptr->next_global;
DBUG_RETURN(ptr);

View File

@ -897,10 +897,10 @@ static int mysql_test_insert(Prepared_statement *stmt,
tables & preparation procedure
*/
thd->allocate_temporary_memory_pool_for_ps_preparing();
if (open_and_lock_tables(thd, table_list))
if ((res= open_and_lock_tables(thd, table_list)))
{
thd->free_temporary_memory_pool_for_ps_preparing();
DBUG_RETURN(-1);
DBUG_RETURN(res);
}
if ((values= its++))
@ -969,9 +969,7 @@ static int mysql_test_update(Prepared_statement *stmt,
*/
thd->allocate_temporary_memory_pool_for_ps_preparing();
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,
@ -1030,9 +1028,7 @@ static int mysql_test_delete(Prepared_statement *stmt,
*/
thd->allocate_temporary_memory_pool_for_ps_preparing();
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();
@ -1065,6 +1061,7 @@ static int mysql_test_select(Prepared_statement *stmt,
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
SELECT_LEX_UNIT *unit= &lex->unit;
int res;
DBUG_ENTER("mysql_test_select");
@ -1084,11 +1081,11 @@ static int mysql_test_select(Prepared_statement *stmt,
tables & preparation procedure
*/
thd->allocate_temporary_memory_pool_for_ps_preparing();
if (open_and_lock_tables(thd, tables))
if ((res= open_and_lock_tables(thd, tables)))
{
send_error(thd);
goto err;
}
res= 1;
thd->used_tables= 0; // Updated by setup_fields
@ -1126,7 +1123,7 @@ err_prep:
unit->cleanup();
err:
thd->free_temporary_memory_pool_for_ps_preparing();
DBUG_RETURN(1);
DBUG_RETURN(res);
}
@ -1683,8 +1680,8 @@ void reset_stmt_for_execute(THD *thd, LEX *lex)
if (lex->empty_field_list_on_rset)
{
lex->field_list.empty();
lex->empty_field_list_on_rset= 0;
lex->field_list.empty();
}
for (; sl; sl= sl->next_select_in_list())
{

View File

@ -225,25 +225,18 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
thd->net.report_error));
if (thd->net.report_error)
res= 1;
if (res > 0)
if (unlikely(res))
{
if (result)
{
result->send_error(0, NullS);
if (res > 0)
result->send_error(0, NullS);
result->abort();
}
else
else if (res > 0)
send_error(thd, 0, NullS);
res= 1; // Error sent to client
}
if (res < 0)
{
if (result)
{
result->abort();
}
res= 1;
}
if (result != lex->result)
delete result;
DBUG_RETURN(res);
@ -348,9 +341,7 @@ JOIN::prepare(Item ***rref_pointer_array,
if ((subselect= select_lex->master_unit()->item))
{
Item_subselect::trans_res res;
if ((res= ((!thd->lex->view_prepare_mode) ?
subselect->select_transformer(this) :
subselect->no_select_transform())) !=
if ((res= subselect->select_transformer(this)) !=
Item_subselect::RES_OK)
{
select_lex->fix_prepare_information(thd, &conds);
@ -552,6 +543,7 @@ JOIN::optimize()
if (cond_value == Item::COND_FALSE ||
(!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
{ /* Impossible cond */
DBUG_PRINT("info", ("Impossible WHERE"));
zero_result_cause= "Impossible WHERE";
error= 0;
DBUG_RETURN(0);
@ -569,20 +561,24 @@ JOIN::optimize()
{
if (res > 1)
{
DBUG_PRINT("error",("Error from opt_sum_query"));
DBUG_RETURN(1);
}
if (res < 0)
{
DBUG_PRINT("info",("No matching min/max row"));
zero_result_cause= "No matching min/max row";
error=0;
DBUG_RETURN(0);
}
DBUG_PRINT("info",("Select tables optimized away"));
zero_result_cause= "Select tables optimized away";
tables_list= 0; // All tables resolved
}
}
if (!tables_list)
{
DBUG_PRINT("info",("No tables"));
error= 0;
DBUG_RETURN(0);
}
@ -10066,8 +10062,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;
@ -11568,7 +11566,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
SYNOPSIS
print_join()
thd thread handler
str string where table should bbe printed
str string where table should be printed
tables list of tables in join
*/
@ -11624,30 +11622,31 @@ void st_table_list::print(THD *thd, String *str)
print_join(thd, str, &nested_join->join_list);
str->append(')');
}
else if (view_name.str)
{
append_identifier(thd, str, view_db.str, view_db.length);
str->append('.');
append_identifier(thd, str, view_name.str, view_name.length);
if (my_strcasecmp(table_alias_charset, view_name.str, alias))
{
str->append(' ');
append_identifier(thd, str, alias, strlen(alias));
}
}
else if (derived)
{
str->append('(');
derived->print(str);
str->append(") ", 2);
append_identifier(thd, str, alias, strlen(alias));
}
else
{
append_identifier(thd, str, db, db_length);
str->append('.');
append_identifier(thd, str, real_name, real_name_length);
if (my_strcasecmp(table_alias_charset, real_name, alias))
const char *cmp_name; // Name to compare with alias
if (view_name.str)
{
append_identifier(thd, str, view_db.str, view_db.length);
str->append('.');
append_identifier(thd, str, view_name.str, view_name.length);
cmp_name= view_name.str;
}
else if (derived)
{
str->append('(');
derived->print(str);
str->append(')');
cmp_name= ""; // Force printing of alias
}
else
{
append_identifier(thd, str, db, db_length);
str->append('.');
append_identifier(thd, str, real_name, real_name_length);
cmp_name= real_name;
}
if (my_strcasecmp(table_alias_charset, cmp_name, alias))
{
str->append(' ');
append_identifier(thd, str, alias, strlen(alias));
@ -11663,7 +11662,7 @@ void st_select_lex::print(THD *thd, String *str)
str->append("select ", 7);
//options
/* First add options */
if (options & SELECT_STRAIGHT_JOIN)
str->append("straight_join ", 14);
if ((thd->lex->lock_option == TL_READ_HIGH_PRIORITY) &&

View File

@ -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)
{
@ -695,14 +701,16 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
char tmp[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;
@ -836,14 +844,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 */
@ -1565,11 +1575,11 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
MODE_MAXDB |
MODE_ANSI)) != 0;
buff->append("CREATE ", 7);
if(!foreign_db_mode && (table->algorithm == VIEW_ALGORITHM_MERGE ||
table->algorithm == VIEW_ALGORITHM_TMEPTABLE))
if (!foreign_db_mode && (table->algorithm == VIEW_ALGORITHM_MERGE ||
table->algorithm == VIEW_ALGORITHM_TMPTABLE))
{
buff->append("ALGORITHM=", 10);
if (table->algorithm == VIEW_ALGORITHM_TMEPTABLE)
if (table->algorithm == VIEW_ALGORITHM_TMPTABLE)
buff->append("TMPTABLE ", 9);
else
buff->append("MERGE ", 6);

View File

@ -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);
@ -496,7 +496,7 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(-1);
/* Check that we are not using table that we are updating in a sub select */
if (find_real_table_in_list(table_list->next_global,
if (find_table_in_global_list(table_list->next_global,
table_list->db, table_list->real_name))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
@ -788,7 +788,7 @@ int multi_update::prepare(List<Item> &not_used_values,
{
TABLE *table=table_ref->table;
if (!(tables_to_update & table->map) &&
find_real_table_in_list(update_tables, table_ref->db,
find_table_in_global_list(update_tables, table_ref->db,
table_ref->real_name))
table->no_cache= 1; // Disable row cache
}

View File

@ -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;
}
@ -81,25 +90,8 @@ int mysql_create_view(THD *thd,
/*
Ensure that we have some privilage on this table, more strict check
will be done on column level after preparation,
SELECT_ACL will be checked for sure for all fields because it is
listed first (if we have not rights to SELECT from whole table this
right will be written as tbl->grant.want_privilege and will be checked
later (except fields which need any privilege and can be updated).
*/
if ((check_access(thd, SELECT_ACL, tbl->db,
&tbl->grant.privilege, 0, 1) ||
grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 1)) &&
(check_access(thd, INSERT_ACL, tbl->db,
&tbl->grant.privilege, 0, 1) ||
grant_option && check_grant(thd, INSERT_ACL, tbl, 0, 1, 1)) &&
(check_access(thd, DELETE_ACL, tbl->db,
&tbl->grant.privilege, 0, 1) ||
grant_option && check_grant(thd, DELETE_ACL, tbl, 0, 1, 1)) &&
(check_access(thd, UPDATE_ACL, tbl->db,
&tbl->grant.privilege, 0, 1) ||
grant_option && check_grant(thd, UPDATE_ACL, tbl, 0, 1, 1))
)
if (check_some_access(thd, VIEW_ANY_ACL, tbl))
{
my_printf_error(ER_TABLEACCESS_DENIED_ERROR,
ER(ER_TABLEACCESS_DENIED_ERROR),
@ -115,7 +107,7 @@ int mysql_create_view(THD *thd,
/*
We need to check only SELECT_ACL for all normal fields, fields
where we need any privilege will be pmarked later
where we need any privilege will be marked later
*/
tbl->grant.want_privilege= SELECT_ACL;
/*
@ -167,7 +159,7 @@ int mysql_create_view(THD *thd,
/* check that tables are not temporary */
for (tbl= tables; tbl; tbl= tbl->next_global)
{
if (tbl->table->tmp_table != NO_TMP_TABLE && !test(tbl->view))
if (tbl->table->tmp_table != NO_TMP_TABLE && !tbl->view)
{
my_error(ER_VIEW_SELECT_TMPTABLE, MYF(0), tbl->alias);
res= -1;
@ -197,19 +189,18 @@ int mysql_create_view(THD *thd,
/* view list (list of view fields names) */
if (lex->view_list.elements)
{
List_iterator_fast<Item> it(select_lex->item_list);
List_iterator_fast<LEX_STRING> nm(lex->view_list);
Item *item;
LEX_STRING *name;
if (lex->view_list.elements != select_lex->item_list.elements)
{
my_message(ER_VIEW_WRONG_LIST, ER(ER_VIEW_WRONG_LIST), MYF(0));
goto err;
}
List_iterator_fast<Item> it(select_lex->item_list);
List_iterator_fast<LEX_STRING> nm(lex->view_list);
Item *item;
LEX_STRING *name;
while((item= it++, name= nm++))
{
while ((item= it++, name= nm++))
item->set_name(name->str, name->length, system_charset_info);
}
}
/* Test absence of duplicates names */
@ -217,11 +208,11 @@ int mysql_create_view(THD *thd,
Item *item;
List_iterator_fast<Item> it(select_lex->item_list);
it++;
while((item= it++))
while ((item= it++))
{
Item *check;
List_iterator_fast<Item> itc(select_lex->item_list);
while((check= itc++) && check != item)
while ((check= itc++) && check != item)
{
if (strcmp(item->name, check->name) == 0)
{
@ -243,7 +234,7 @@ int mysql_create_view(THD *thd,
Item *item;
fill_effective_table_privileges(thd, &view->grant, db,
view->real_name);
while((item= it++))
while ((item= it++))
{
uint priv= (get_column_grant(thd, &view->grant, db,
view->real_name, item->name) &
@ -252,10 +243,10 @@ int mysql_create_view(THD *thd,
{
Item_field *fld= (Item_field *)item;
/*
There are no any privileges on VIWE column or there are
There are no any privileges on VIEW column or there are
some other privileges then we have for underlaying table
*/
if (priv == 0 || test(~fld->have_privileges & priv))
if (priv == 0 || (~fld->have_privileges & priv))
{
/* VIEW column has more privileges */
my_printf_error(ER_COLUMNACCESS_DENIED_ERROR,
@ -271,7 +262,7 @@ int mysql_create_view(THD *thd,
}
else
{
if (!test(priv & SELECT_ACL))
if (!(priv & SELECT_ACL))
{
/* user have not privilege to SELECT expression */
my_printf_error(ER_COLUMNACCESS_DENIED_ERROR,
@ -295,14 +286,11 @@ int mysql_create_view(THD *thd,
goto err;
}
VOID(pthread_mutex_lock(&LOCK_open));
if ((res= mysql_register_view(thd, view, mode)))
{
VOID(pthread_mutex_unlock(&LOCK_open));
start_waiting_global_read_lock(thd);
goto err;
}
res= mysql_register_view(thd, view, mode);
VOID(pthread_mutex_unlock(&LOCK_open));
start_waiting_global_read_lock(thd);
if (res)
goto err;
send_ok(thd);
lex->link_first_table_back(view, link_to_local);
@ -318,38 +306,34 @@ 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;
static char *view_field_names[]=
{
(char*)"query",
(char*)"md5",
(char*)"updatable",
(char*)"algorithm",
(char*)"revision",
(char*)"timestamp",
(char*)"create-version",
(char*)"source"
};
/*
table of VIEW .frm field descriptors
Note that one should NOT change the order for this, as it's used by
parse()
*/
// table of VIEW .frm field descriprors
static File_option view_parameters[]=
{{{view_field_names[0], 5}, offsetof(TABLE_LIST, query),
{{{(char*) "query", 5}, offsetof(TABLE_LIST, query),
FILE_OPTIONS_STRING},
{{view_field_names[1], 3}, offsetof(TABLE_LIST, md5),
{{(char*) "md5", 3}, offsetof(TABLE_LIST, md5),
FILE_OPTIONS_STRING},
{{view_field_names[2], 9}, offsetof(TABLE_LIST, updatable_view),
{{(char*) "updatable", 9}, offsetof(TABLE_LIST, updatable_view),
FILE_OPTIONS_ULONGLONG},
{{view_field_names[3], 9}, offsetof(TABLE_LIST, algorithm),
{{(char*) "algorithm", 9}, offsetof(TABLE_LIST, algorithm),
FILE_OPTIONS_ULONGLONG},
{{view_field_names[4], 8}, offsetof(TABLE_LIST, revision),
{{(char*) "revision", 8}, offsetof(TABLE_LIST, revision),
FILE_OPTIONS_REV},
{{view_field_names[5], 9}, offsetof(TABLE_LIST, timestamp),
{{(char*) "timestamp", 9}, offsetof(TABLE_LIST, timestamp),
FILE_OPTIONS_TIMESTAMP},
{{view_field_names[6], 14}, offsetof(TABLE_LIST, file_version),
{{(char*)"create-version", 14},offsetof(TABLE_LIST, file_version),
FILE_OPTIONS_ULONGLONG},
{{view_field_names[7], 6}, offsetof(TABLE_LIST, source),
{{(char*) "source", 6}, offsetof(TABLE_LIST, source),
FILE_OPTIONS_ESTRING},
{{NULL, 0}, 0,
FILE_OPTIONS_STRING}
@ -402,16 +386,18 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
dir.length= strlen(dir_buff);
file.str= file_buff;
file.length= my_snprintf(file_buff, FN_REFLEN, "%s%s",
view->real_name, reg_ext);
file.length= (strxnmov(file_buff, FN_REFLEN, view->real_name, reg_ext,
NullS) - file_buff);
/* init timestamp */
if (!test(view->timestamp.str))
if (!view->timestamp.str)
view->timestamp.str= view->timestamp_buffer;
// check old .frm
{
char path_buff[FN_REFLEN];
LEX_STRING path;
File_parser *parser;
path.str= path_buff;
fn_format(path_buff, file.str, dir.str, 0, MY_UNPACK_FILENAME);
path.length= strlen(path_buff);
@ -424,34 +410,27 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
DBUG_RETURN(1);
}
File_parser *parser= sql_parse_prepare(&path, &thd->mem_root, 0);
if (parser)
{
if(parser->ok() &&
!strncmp("VIEW", parser->type()->str, parser->type()->length))
{
/*
read revision number
TODO: read dependense list, too, to process cascade/restrict
TODO: special cascade/restrict procedure for alter?
*/
if (parser->parse((gptr)view, &thd->mem_root,
view_parameters + revision_number_position, 1))
{
DBUG_RETURN(1);
}
}
else
{
my_error(ER_WRONG_OBJECT, MYF(0), (view->db?view->db:thd->db),
view->real_name, "VIEW");
DBUG_RETURN(1);
}
}
else
{
if (!(parser= sql_parse_prepare(&path, &thd->mem_root, 0)))
DBUG_RETURN(1);
if (!parser->ok() ||
strncmp("VIEW", parser->type()->str, parser->type()->length))
{
my_error(ER_WRONG_OBJECT, MYF(0), (view->db ? view->db : thd->db),
view->real_name, "VIEW");
DBUG_RETURN(1);
}
/*
read revision number
TODO: read dependense list, too, to process cascade/restrict
TODO: special cascade/restrict procedure for alter?
*/
if (parser->parse((gptr)view, &thd->mem_root,
view_parameters + revision_number_position, 1))
{
DBUG_RETURN(1);
}
}
else
@ -482,14 +461,14 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
}
view->algorithm= thd->lex->create_view_algorithm;
if ((view->updatable_view= (can_be_merged &&
view->algorithm != VIEW_ALGORITHM_TMEPTABLE)))
view->algorithm != VIEW_ALGORITHM_TMPTABLE)))
{
// TODO: change here when we will support UNIONs
for (TABLE_LIST *tbl= (TABLE_LIST *)thd->lex->select_lex.table_list.first;
tbl;
tbl= tbl->next_local)
{
if (tbl->view != 0 && !tbl->updatable_view)
if (tbl->view && !tbl->updatable_view)
{
view->updatable_view= 0;
break;
@ -514,18 +493,21 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
table - TABLE_LIST structure for filling
RETURN
TRUE OK
FALSE error
0 ok
1 error
*/
my_bool
mysql_make_view(File_parser *parser, TABLE_LIST *table)
{
bool include_proc_table= 0;
DBUG_ENTER("mysql_make_view");
if (table->view)
{
DBUG_PRINT("info",
("VIEW %s.%s is already processed on previos PS/SP execution",
("VIEW %s.%s is already processed on previous PS/SP execution",
table->view_db.str, table->view_name.str));
DBUG_RETURN(0);
}
@ -545,13 +527,14 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
thd->set_n_backup_item_arena(arena, &backup);
/* init timestamp */
if (!test(table->timestamp.str))
if (!table->timestamp.str)
table->timestamp.str= table->timestamp_buffer;
/*
TODO: when VIEWs will be stored in cache, table mem_root should
be used here
*/
if (parser->parse((gptr)table, &thd->mem_root, view_parameters, 6))
if (parser->parse((gptr)table, &thd->mem_root, view_parameters,
required_view_parameters))
goto err;
/*
@ -603,7 +586,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)
@ -612,8 +598,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);
@ -656,7 +657,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
- VIEW SELECT allow marging
- VIEW used in subquery or command support MERGE algorithm
*/
if (table->algorithm != VIEW_ALGORITHM_TMEPTABLE &&
if (table->algorithm != VIEW_ALGORITHM_TMPTABLE &&
lex->can_be_merged() &&
(table->select_lex->master_unit() != &old_lex->unit ||
old_lex->can_use_merged()) &&
@ -702,7 +703,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
goto ok;
}
table->effective_algorithm= VIEW_ALGORITHM_TMEPTABLE;
table->effective_algorithm= VIEW_ALGORITHM_TMPTABLE;
DBUG_PRINT("info", ("algorithm: TEMPORARY TABLE"));
lex->select_lex.linkage= DERIVED_TABLE_TYPE;
table->updatable= 0;
@ -715,7 +716,8 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
{
if ((tbl_end= table->next_global))
{
for (; (tbl_next= tbl_end->next_global); tbl_end= tbl_next);
for (; (tbl_next= tbl_end->next_global); tbl_end= tbl_next)
;
if ((tbl_end->next_global= old_next))
tbl_end->next_global->prev_global= &tbl_end->next_global;
}
@ -742,6 +744,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);
@ -768,6 +781,7 @@ err:
-1 Error
1 Error and error message given
*/
int mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
{
DBUG_ENTER("mysql_drop_view");
@ -777,8 +791,8 @@ int mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
for (view= views; view; view= view->next_local)
{
strxmov(path, mysql_data_home, "/", view->db, "/", view->real_name,
reg_ext, NullS);
strxnmov(path, FN_REFLEN, mysql_data_home, "/", view->db, "/",
view->real_name, reg_ext, NullS);
(void) unpack_filename(path, path);
VOID(pthread_mutex_lock(&LOCK_open));
if (access(path, F_OK) || (type= (mysql_frm_type(path) != FRMTYPE_VIEW)))
@ -830,21 +844,20 @@ frm_type_enum mysql_frm_type(char *path)
{
File file;
char header[10]; //"TYPE=VIEW\n" it is 10 characters
int length;
DBUG_ENTER("mysql_frm_type");
if ((file= my_open(path, O_RDONLY | O_SHARE, MYF(MY_WME))) < 0)
{
DBUG_RETURN(FRMTYPE_ERROR);
}
if (my_read(file, (byte*) header, 10, MYF(MY_WME)) == MY_FILE_ERROR)
{
my_close(file, MYF(MY_WME));
DBUG_RETURN(FRMTYPE_ERROR);
}
length= my_read(file, (byte*) header, 10, MYF(MY_WME));
my_close(file, MYF(MY_WME));
if (strncmp(header, "TYPE=VIEW\n", 10) != 0)
DBUG_RETURN(FRMTYPE_TABLE);
DBUG_RETURN(FRMTYPE_VIEW);
if (length == (int) MY_FILE_ERROR)
DBUG_RETURN(FRMTYPE_ERROR);
if (!strncmp(header, "TYPE=VIEW\n", 10))
DBUG_RETURN(FRMTYPE_VIEW);
DBUG_RETURN(FRMTYPE_TABLE); // Is probably a .frm table
}
@ -863,72 +876,81 @@ frm_type_enum mysql_frm_type(char *path)
bool check_key_in_view(THD *thd, TABLE_LIST *view)
{
TABLE *table;
Item **trans;
KEY *key_info, *key_info_end;
uint i, elements_in_view;
DBUG_ENTER("check_key_in_view");
if (!view->view)
DBUG_RETURN(FALSE); /* it is normal table */
table= view->table;
trans= view->field_translation;
key_info_end= (key_info= table->key_info)+ table->keys;
TABLE *table= view->table;
Item **trans= view->field_translation;
KEY *key_info= table->key_info;
uint primary_key= table->primary_key;
uint num= view->view->select_lex.item_list.elements;
elements_in_view= view->view->select_lex.item_list.elements;
DBUG_ASSERT(view->table != 0 && view->field_translation != 0);
/* try to find key */
for (uint i=0; i < table->keys; i++, key_info++)
/* Loop over all keys to see if a unique-not-null key is used */
for (;key_info != key_info_end ; key_info++)
{
if (i == primary_key && !strcmp(key_info->name, primary_key_name) ||
key_info->flags & HA_NOSAME)
if ((key_info->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
{
KEY_PART_INFO *key_part= key_info->key_part;
bool found= 1;
for (uint j=0; j < key_info->key_parts && found; j++, key_part++)
KEY_PART_INFO *key_part_end= key_part + key_info->key_parts;
/* check that all key parts are used */
for (;;)
{
found= 0;
for (uint k= 0; k < num; k++)
uint k;
for (k= 0; k < elements_in_view; k++)
{
if (trans[k]->type() == Item::FIELD_ITEM &&
((Item_field *)trans[k])->field == key_part->field &&
(key_part->field->flags & NOT_NULL_FLAG))
{
found= 1;
((Item_field *)trans[k])->field == key_part->field)
break;
}
}
if (k == elements_in_view)
break; // Key is not possible
if (++key_part == key_part_end)
DBUG_RETURN(FALSE); // Found usable key
}
if (found)
DBUG_RETURN(FALSE);
}
}
DBUG_PRINT("info", ("checking if all fields of table are used"));
/* check all fields presence */
{
Field **field_ptr= table->field;
for (; *field_ptr; ++field_ptr)
Field **field_ptr;
for (field_ptr= table->field; *field_ptr; field_ptr++)
{
uint i= 0;
for (; i < num; i++)
for (i= 0; i < elements_in_view; i++)
{
if (trans[i]->type() == Item::FIELD_ITEM &&
((Item_field *)trans[i])->field == *field_ptr)
break;
}
if (i >= num)
if (i == elements_in_view) // If field didn't exists
{
ulong mode= thd->variables.sql_updatable_view_key;
/* 1 == YES, 2 == LIMIT1 */
/*
0 == NO ; Don't give any errors
1 == YES ; Give always an error
2 == LIMIT1 ; Give an error if this is used with LIMIT 1
This is used to protect against gui programs that
uses LIMIT 1 to update just the current row. This
doesn't work reliable if the view doesn't have a
unique key or if the view doesn't use all fields in
table.
*/
if (mode == 1 ||
(mode == 2 &&
thd->lex->select_lex.select_limit == 1))
thd->lex->unit.global_parameters->select_limit == 1))
{
DBUG_RETURN(TRUE);
}
else
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_WARN_VIEW_WITHOUT_KEY, ER(ER_WARN_VIEW_WITHOUT_KEY));
DBUG_RETURN(FALSE);
}
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_WARN_VIEW_WITHOUT_KEY, ER(ER_WARN_VIEW_WITHOUT_KEY));
DBUG_RETURN(FALSE);
}
}
}
@ -947,18 +969,17 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
void insert_view_fields(List<Item> *list, TABLE_LIST *view)
{
uint num= view->view->select_lex.item_list.elements;
Item **trans= view->field_translation;
uint elements_in_view= view->view->select_lex.item_list.elements;
Item **trans;
DBUG_ENTER("insert_view_fields");
if (!trans)
if (!(trans= view->field_translation))
DBUG_VOID_RETURN;
for (uint i= 0; i < num; i++)
for (uint i= 0; i < elements_in_view; i++)
{
if (trans[i]->type() == Item::FIELD_ITEM)
{
list->push_back(trans[i]);
}
}
DBUG_VOID_RETURN;
}

View File

@ -7553,7 +7553,7 @@ algorithm:
| ALGORITHM_SYM EQ MERGE_SYM
{ Lex->create_view_algorithm= VIEW_ALGORITHM_MERGE; }
| ALGORITHM_SYM EQ TEMPTABLE_SYM
{ Lex->create_view_algorithm= VIEW_ALGORITHM_TMEPTABLE; }
{ Lex->create_view_algorithm= VIEW_ALGORITHM_TMPTABLE; }
;
check_option:
/* empty */ {}

View File

@ -88,6 +88,8 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
DBUG_PRINT("enter",("name: '%s' form: %lx",name,outparam));
error=1;
disk_buff=NULL;
old_root= my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
if ((file=my_open(fn_format(index_file, name, "", reg_ext,
MY_UNPACK_FILENAME),
@ -118,11 +120,8 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
bzero((char*) outparam,sizeof(*outparam));
outparam->blob_ptr_size=sizeof(char*);
disk_buff=NULL; record= NULL; keynames=NullS;
outparam->db_stat = db_stat;
init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
old_root= my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
my_pthread_setspecific_ptr(THR_MALLOC,&outparam->mem_root);
outparam->real_name=strdup_root(&outparam->mem_root,
@ -742,11 +741,9 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
DBUG_RETURN (0);
err_w_init:
//awoid problem with uninitialized data
/* Avoid problem with uninitialized data */
bzero((char*) outparam,sizeof(*outparam));
outparam->real_name= (char*)name+dirname_length(name);
old_root= my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
disk_buff= 0;
err_not_open:
x_free((gptr) disk_buff);
@ -1447,13 +1444,14 @@ db_type get_table_type(const char *name)
st_table_list::calc_md5()
buffer buffer for md5 writing
*/
void st_table_list::calc_md5(char *buffer)
{
my_MD5_CTX context;
unsigned char digest[16];
my_MD5Init (&context);
my_MD5Update (&context,(unsigned char *) query.str, query.length);
my_MD5Final (digest, &context);
uchar digest[16];
my_MD5Init(&context);
my_MD5Update(&context,(uchar *) query.str, query.length);
my_MD5Final(digest, &context);
sprintf((char *) buffer,
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
digest[0], digest[1], digest[2], digest[3],
@ -1469,6 +1467,7 @@ void st_table_list::calc_md5(char *buffer)
SYNOPSIS
st_table_list::set_ancestor()
*/
void st_table_list::set_ancestor()
{
if (ancestor->ancestor)
@ -1496,6 +1495,7 @@ void st_table_list::set_ancestor()
(without fields) for name resolving, but substituted expressions will
return correct used tables mask.
*/
bool st_table_list::setup_ancestor(THD *thd, Item **conds)
{
Item **transl;
@ -1520,15 +1520,15 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
thd->set_query_id= 1;
/* this view was prepared already on previous PS/SP execution */
Item **end= field_translation + select->item_list.elements;
for (Item **i= field_translation; i < end; i++)
for (Item **item= field_translation; item < end; item++)
{
//TODO: fix for several tables in VIEW
/* TODO: fix for several tables in VIEW */
uint want_privilege= ancestor->table->grant.want_privilege;
/* real rights will be checked in VIEW field */
ancestor->table->grant.want_privilege= 0;
/* aggregate function are allowed */
thd->allow_sum_func= 1;
if (!(*i)->fixed && (*i)->fix_fields(thd, ancestor, i))
if (!(*item)->fixed && (*item)->fix_fields(thd, ancestor, item))
goto err;
ancestor->table->grant.want_privilege= want_privilege;
}
@ -1557,21 +1557,19 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
thd->set_query_id= 1;
while ((item= it++))
{
//TODO: fix for several tables in VIEW
/* TODO: fix for several tables in VIEW */
uint want_privilege= ancestor->table->grant.want_privilege;
/* real rights will be checked in VIEW field */
ancestor->table->grant.want_privilege= 0;
/* aggregate function are allowed */
thd->allow_sum_func= 1;
if (!item->fixed && item->fix_fields(thd, ancestor, &item))
{
goto err;
}
ancestor->table->grant.want_privilege= want_privilege;
transl[i++]= item;
}
field_translation= transl;
//TODO: sort this list? Use hash for big number of fields
/* TODO: sort this list? Use hash for big number of fields */
if (where)
{
@ -1580,12 +1578,12 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
goto err;
if (arena)
thd->set_n_backup_item_arena(arena, &backup);
thd->set_n_backup_item_arena(arena, &backup);
if (outer_join)
{
/*
Store WHERE condition to ON expression for outer join, because we
can't use WHERE to correctly execute jeft joins on VIEWs and this
can't use WHERE to correctly execute jeft joins on VIEWs and this
expression will not be moved to WHERE condition (i.e. will be clean
correctly for PS/SP)
*/

View File

@ -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;
@ -179,7 +182,7 @@ struct st_table {
#define JOIN_TYPE_RIGHT 2
#define VIEW_ALGORITHM_UNDEFINED 0
#define VIEW_ALGORITHM_TMEPTABLE 1
#define VIEW_ALGORITHM_TMPTABLE 1
#define VIEW_ALGORITHM_MERGE 2
struct st_lex;
@ -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 */
@ -267,7 +270,7 @@ public:
virtual ~Field_iterator() {}
virtual void set(TABLE_LIST *)= 0;
virtual void next()= 0;
virtual bool end()= 0;
virtual bool end_of_fields()= 0; /* Return 1 at end of list */
virtual const char *name()= 0;
virtual Item *item(THD *)= 0;
virtual Field *field()= 0;
@ -282,7 +285,7 @@ public:
void set(TABLE_LIST *table) { ptr= table->table->field; }
void set_table(TABLE *table) { ptr= table->field; }
void next() { ptr++; }
bool end() { return test(*ptr); }
bool end_of_fields() { return *ptr == 0; }
const char *name();
Item *item(THD *thd);
Field *field() { return *ptr; }
@ -296,7 +299,7 @@ public:
Field_iterator_view() :ptr(0), array_end(0) {}
void set(TABLE_LIST *table);
void next() { ptr++; }
bool end() { return ptr < array_end; }
bool end_of_fields() { return ptr == array_end; }
const char *name();
Item *item(THD *thd) { return *ptr; }
Field *field() { return 0; }

View File

@ -30,6 +30,7 @@
#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
#define MAX_KEY 64
/* set default options */
static char *opt_db= 0;
@ -5507,6 +5508,7 @@ static void test_subselect()
MYSQL_STMT *stmt;
int rc, id;
MYSQL_BIND bind[1];
DBUG_ENTER("test_subselect");
myheader("test_subselect");
@ -5608,6 +5610,7 @@ static void test_subselect()
assert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
DBUG_VOID_RETURN;
}
@ -7018,13 +7021,13 @@ static void test_explain_bug()
"", "", "", 10, 0);
verify_prepare_field(result, 4, "possible_keys", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN*64, 0);
"", "", "", NAME_LEN*MAX_KEY, 0);
verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN, 0);
verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN*64, 0);
"", "", "", NAME_LEN*MAX_KEY, 0);
verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN*16, 0);