From 0b01d95d21183fe268d79211fe58b3d4c44905c2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Oct 2004 13:11:15 +0300 Subject: [PATCH 1/7] fixed printing of substring_index (BUG#5911) mysql-test/r/func_str.result: fixed printing of substring_index mysql-test/r/view.result: test of substring_index with view mysql-test/t/view.test: test of substring_index with view sql/item_strfunc.h: fixed printing of substring_index --- mysql-test/r/func_str.result | 6 +++--- mysql-test/r/view.result | 11 +++++++++++ mysql-test/t/view.test | 11 +++++++++++ sql/item_strfunc.h | 2 +- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 400d79be835..ede91e9c376 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -395,9 +395,9 @@ select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2); SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2) abcdabc select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2); -ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'substr_index' +ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE) and (latin2_general_ci,COERCIBLE) for operation 'substring_index' select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_general_ci,_latin1'd' COLLATE latin1_bin,2); -ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'substr_index' +ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT) and (latin1_bin,EXPLICIT) for operation 'substring_index' select _latin1'B' between _latin1'a' and _latin1'c'; _latin1'B' between _latin1'a' and _latin1'c' 1 @@ -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)`,cast(_latin1'HE' as char charset 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")` +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)`,cast(_latin1'HE' as char charset 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)`,substring_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 diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index a401a56aa34..f9a27e572dd 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1517,3 +1517,14 @@ s1 deallocate prepare stmt1; drop view v2; drop table t1, t2; +create table t1 (t time); +create view v1 as select substring_index(t,':',2) as t from t1; +insert into t1 (t) values ('12:24:10'); +select substring_index(t,':',2) from t1; +substring_index(t,':',2) +12:24 +select substring_index(t,':',2) from v1; +substring_index(t,':',2) +12:24 +drop view v1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index d8d49fd038e..570fffa9b5b 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1460,3 +1460,14 @@ execute stmt1; deallocate prepare stmt1; drop view v2; drop table t1, t2; + +# +# test of substring_index with view +# +create table t1 (t time); +create view v1 as select substring_index(t,':',2) as t from t1; +insert into t1 (t) values ('12:24:10'); +select substring_index(t,':',2) from t1; +select substring_index(t,':',2) from v1; +drop view v1; +drop table t1; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 111f0e20698..8ec597f2a27 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -218,7 +218,7 @@ public: Item_func_substr_index(Item *a,Item *b,Item *c) :Item_str_func(a,b,c) {} String *val_str(String *); void fix_length_and_dec(); - const char *func_name() const { return "substr_index"; } + const char *func_name() const { return "substring_index"; } }; From adc1bff4f84cf7cde5a6ea0add93fe0e1b8dba81 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Oct 2004 13:30:25 +0300 Subject: [PATCH 2/7] Allow inheriting check options if view have not WHERE clause (BUG#5988) mysql-test/r/view.result: test of cascaded check option for whiew without WHERE clause mysql-test/t/view.test: test of cascaded check option for whiew without WHERE clause sql/table.cc: Allow inheriting check options if view have not WHERE clause --- mysql-test/r/view.result | 7 +++++++ mysql-test/t/view.test | 11 +++++++++++ sql/table.cc | 11 +++++++---- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f9a27e572dd..9dcf0833c18 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1528,3 +1528,10 @@ substring_index(t,':',2) 12:24 drop view v1; drop table t1; +create table t1 (s1 tinyint); +create view v1 as select * from t1 where s1 <> 0 with local check option; +create view v2 as select * from v1 with cascaded check option; +insert into v2 values (0); +ERROR HY000: CHECK OPTION failed 'test.v2' +drop view v2, v1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 570fffa9b5b..716ed4aa6b3 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1471,3 +1471,14 @@ select substring_index(t,':',2) from t1; select substring_index(t,':',2) from v1; drop view v1; drop table t1; + +# +# test of cascaded check option for whiew without WHERE clause +# +create table t1 (s1 tinyint); +create view v1 as select * from t1 where s1 <> 0 with local check option; +create view v2 as select * from v1 with cascaded check option; +-- error 1369 +insert into v2 values (0); +drop view v2, v1; +drop table t1; diff --git a/sql/table.cc b/sql/table.cc index bfe5395c3db..42eb2455e85 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1586,14 +1586,16 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) field_translation= transl; /* TODO: sort this list? Use hash for big number of fields */ - if (where) + if (where || + (effective_with_check == VIEW_CHECK_CASCADED && + ancestor->check_option)) { Item_arena *arena= thd->current_arena, backup; TABLE_LIST *tbl= this; if (arena->is_conventional()) arena= 0; // For easier test - if (!where->fixed && where->fix_fields(thd, ancestor, &where)) + if (where && !where->fixed && where->fix_fields(thd, ancestor, &where)) goto err; if (arena) @@ -1601,7 +1603,8 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) if (effective_with_check) { - check_option= where->copy_andor_structure(thd); + if (where) + check_option= where->copy_andor_structure(thd); if (effective_with_check == VIEW_CHECK_CASCADED) { check_option= and_conds(check_option, ancestor->check_option); @@ -1612,7 +1615,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) check that it is not VIEW in which we insert with INSERT SELECT (in this case we can't add view WHERE condition to main SELECT_LEX) */ - if (!no_where_clause) + if (where && !no_where_clause) { /* Go up to join tree and try to find left join */ for (; tbl; tbl= tbl->embedding) From e9c3bc7616a6239876c9c03883a5b577b7ce2925 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Oct 2004 13:39:17 +0300 Subject: [PATCH 3/7] fixed default behaviour of WITH CHECK OPTIONS according to standard (BUG#5989) mysql-test/r/view.result: fixed default behaviour of WITH CHECK OPTIONS according to standard sql/sql_yacc.yy: fixed default behaviour of WITH CHECK OPTIONS according to standard --- mysql-test/r/view.result | 2 +- sql/sql_yacc.yy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 9dcf0833c18..2e5d7073c5a 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1467,7 +1467,7 @@ v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` alter algorithm=undefined view v1 as select * from t1 with check option; show create view v1; View Create View -v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` from `test`.`t1` WITH LOCAL CHECK OPTION +v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` from `test`.`t1` WITH CASCADED CHECK OPTION alter algorithm=merge view v1 as select * from t1 with cascaded check option; show create view v1; View Create View diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d2964df008b..6fb13684098 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7921,7 +7921,7 @@ check_option: /* empty */ { Lex->create_view_check= VIEW_CHECK_NONE; } | WITH CHECK_SYM OPTION - { Lex->create_view_check= VIEW_CHECK_LOCAL; } + { Lex->create_view_check= VIEW_CHECK_CASCADED; } | WITH CASCADED CHECK_SYM OPTION { Lex->create_view_check= VIEW_CHECK_CASCADED; } | WITH LOCAL_SYM CHECK_SYM OPTION From 2aad30394d33eef23545d717f4b92eb280c2b19d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Oct 2004 14:32:10 +0300 Subject: [PATCH 4/7] inserting single value with check option failed always get error (part of BUG#5995) mysql-test/r/view.result: inserting single value with check option failed always get error mysql-test/t/view.test: inserting single value with check option failed always get error sql/sql_insert.cc: inserting single value with check option failed always get error --- mysql-test/r/view.result | 12 ++++++++++++ mysql-test/t/view.test | 15 +++++++++++++++ sql/sql_insert.cc | 5 ++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 2e5d7073c5a..c9581598de6 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1535,3 +1535,15 @@ insert into v2 values (0); ERROR HY000: CHECK OPTION failed 'test.v2' drop view v2, v1; drop table t1; +create table t1 (s1 int); +create view v1 as select * from t1 where s1 < 5 with check option; +insert ignore into v1 values (6); +ERROR HY000: CHECK OPTION failed 'test.v1' +insert ignore into v1 values (6),(3); +Warnings: +Error 1369 CHECK OPTION failed 'test.v1' +select * from t1; +s1 +3 +drop view v1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 716ed4aa6b3..282ea827c6a 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1482,3 +1482,18 @@ create view v2 as select * from v1 with cascaded check option; insert into v2 values (0); drop view v2, v1; drop table t1; + +# +# inserting single value with check option failed always get error +# +create table t1 (s1 int); +create view v1 as select * from t1 where s1 < 5 with check option; +#single value +-- error 1369 +insert ignore into v1 values (6); +#several values +insert ignore into v1 values (6),(3); +select * from t1; +drop view v1; +drop table t1; + diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 36ac56799de..2fe0d2f644a 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -319,7 +319,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, break; } } - if ((res= table_list->view_check_option(thd, ignore_err)) == + if ((res= table_list->view_check_option(thd, + (values_list.elements == 1 ? + 0 : + ignore_err))) == VIEW_CHECK_SKIP) continue; else if (res == VIEW_CHECK_ERROR) From 0ea04229074645b2642456158ac120448dfa6334 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Oct 2004 17:05:45 +0300 Subject: [PATCH 5/7] value should be checked after 'before' trigger work (BUG#5992) mysql-test/r/view.result: changing value by trigger and CHECK OPTION mysql-test/t/view.test: changing value by trigger and CHECK OPTION sql/sql_insert.cc: value should be checked after 'before' trigger work --- mysql-test/r/view.result | 11 +++++++++++ mysql-test/t/view.test | 14 ++++++++++++++ sql/sql_insert.cc | 18 +++++++++--------- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index c9581598de6..d866fbe498c 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1547,3 +1547,14 @@ s1 3 drop view v1; drop table t1; +create table t1 (s1 tinyint); +create trigger t1_bi before insert on t1 for each row set new.s1 = 500; +create view v1 as select * from t1 where s1 <> 127 with check option; +insert into v1 values (0); +ERROR HY000: CHECK OPTION failed 'test.v1' +select * from v1; +s1 +select * from t1; +s1 +drop view v1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 282ea827c6a..fdf431f0107 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1497,3 +1497,17 @@ select * from t1; drop view v1; drop table t1; +# +# changing value by trigger and CHECK OPTION +# +create table t1 (s1 tinyint); +create trigger t1_bi before insert on t1 for each row set new.s1 = 500; +create view v1 as select * from t1 where s1 <> 127 with check option; +-- error 1369 +insert into v1 values (0); +select * from v1; +select * from t1; +drop view v1; +drop table t1; + + diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 2fe0d2f644a..d9002c2da29 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -319,6 +319,15 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, break; } } + + /* + FIXME: Actually we should do this before + check_that_all_fields_are_given_values Or even go into write_record ? + */ + if (table->triggers) + table->triggers->process_triggers(thd, TRG_EVENT_INSERT, + TRG_ACTION_BEFORE); + if ((res= table_list->view_check_option(thd, (values_list.elements == 1 ? 0 : @@ -330,15 +339,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, error= 1; break; } - - /* - FIXME: Actually we should do this before - check_that_all_fields_are_given_values Or even go into write_record ? - */ - if (table->triggers) - table->triggers->process_triggers(thd, TRG_EVENT_INSERT, - TRG_ACTION_BEFORE); - #ifndef EMBEDDED_LIBRARY if (lock_type == TL_WRITE_DELAYED) { From 149fda59dd36a8e5ba71f0b637a94882dc40f6c2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Oct 2004 18:10:59 +0300 Subject: [PATCH 6/7] new behaviour of CHECK option build, for mor efficience and more correct: check option build only according most top VIEW CHECK OPTION TYPE (BUG#5993) mysql-test/r/view.result: CASCADED should be used for all underlaying VIEWs mysql-test/t/view.test: CASCADED should be used for all underlaying VIEWs sql/sql_base.cc: new behaviour of CHECK option build, for mor efficience and more correct. sql/table.cc: new behaviour of CHECK option build, for mor efficience and more correct. sql/table.h: new behaviour of CHECK option build, for mor efficience and more correct. --- mysql-test/r/view.result | 12 ++++++++++++ mysql-test/t/view.test | 14 +++++++++++++- sql/sql_base.cc | 4 +++- sql/table.cc | 20 +++++++++++++------- sql/table.h | 2 +- 5 files changed, 42 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index d866fbe498c..8bccec415af 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1556,5 +1556,17 @@ select * from v1; s1 select * from t1; s1 +drop trigger t1.t1_bi; drop view v1; drop table t1; +create table t1 (s1 tinyint); +create view v1 as select * from t1 where s1 <> 0; +create view v2 as select * from v1 where s1 <> 1 with cascaded check option; +insert into v2 values (0); +ERROR HY000: CHECK OPTION failed 'test.v2' +select * from v2; +s1 +select * from t1; +s1 +drop view v2, v1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index fdf431f0107..bb0d6c158ec 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1507,7 +1507,19 @@ create view v1 as select * from t1 where s1 <> 127 with check option; insert into v1 values (0); select * from v1; select * from t1; +drop trigger t1.t1_bi; drop view v1; drop table t1; - +# +# CASCADED should be used for all underlaying VIEWs +# +create table t1 (s1 tinyint); +create view v1 as select * from t1 where s1 <> 0; +create view v2 as select * from v1 where s1 <> 1 with cascaded check option; +-- error 1369 +insert into v2 values (0); +select * from v2; +select * from t1; +drop view v2, v1; +drop table t1; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8199c6fcdce..4f273fbd0c4 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2697,7 +2697,9 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds) table->keys_in_use_for_query.subtract(map); } table->used_keys.intersect(table->keys_in_use_for_query); - if (table_list->ancestor && table_list->setup_ancestor(thd, conds)) + if (table_list->ancestor && + table_list->setup_ancestor(thd, conds, + table_list->effective_with_check)) DBUG_RETURN(1); } if (tablenr > MAX_TABLES) diff --git a/sql/table.cc b/sql/table.cc index 42eb2455e85..e372de57177 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1497,8 +1497,10 @@ void st_table_list::set_ancestor() SYNOPSIS st_table_list::setup_ancestor() - thd - thread handler - conds - condition of this JOIN + thd - thread handler + conds - condition of this JOIN + check_opt_type - WHITH CHECK OPTION type (VIEW_CHECK_NONE, + VIEW_CHECK_LOCAL, VIEW_CHECK_CASCADED) DESCRIPTION It is: @@ -1513,7 +1515,8 @@ void st_table_list::set_ancestor() 1 - error */ -bool st_table_list::setup_ancestor(THD *thd, Item **conds) +bool st_table_list::setup_ancestor(THD *thd, Item **conds, + uint8 check_opt_type) { Item **transl; SELECT_LEX *select= &view->select_lex; @@ -1527,7 +1530,10 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) DBUG_ENTER("st_table_list::setup_ancestor"); if (ancestor->ancestor && - ancestor->setup_ancestor(thd, conds)) + ancestor->setup_ancestor(thd, conds, + (check_opt_type == VIEW_CHECK_CASCADED ? + VIEW_CHECK_CASCADED : + VIEW_CHECK_NONE))) DBUG_RETURN(1); if (field_translation) @@ -1587,7 +1593,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) /* TODO: sort this list? Use hash for big number of fields */ if (where || - (effective_with_check == VIEW_CHECK_CASCADED && + (check_opt_type == VIEW_CHECK_CASCADED && ancestor->check_option)) { Item_arena *arena= thd->current_arena, backup; @@ -1601,11 +1607,11 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) if (arena) thd->set_n_backup_item_arena(arena, &backup); - if (effective_with_check) + if (check_opt_type) { if (where) check_option= where->copy_andor_structure(thd); - if (effective_with_check == VIEW_CHECK_CASCADED) + if (check_opt_type == VIEW_CHECK_CASCADED) { check_option= and_conds(check_option, ancestor->check_option); } diff --git a/sql/table.h b/sql/table.h index 35f6c6803fb..2d2ac12ca9b 100644 --- a/sql/table.h +++ b/sql/table.h @@ -281,7 +281,7 @@ typedef struct st_table_list void calc_md5(char *buffer); void set_ancestor(); int view_check_option(THD *thd, bool ignore_failure); - bool setup_ancestor(THD *thd, Item **conds); + bool setup_ancestor(THD *thd, Item **conds, uint8 check_option); bool placeholder() {return derived || view; } void print(THD *thd, String *str); inline st_table_list *next_independent() From 4d204f4303b9b8f2dfc83e593f2f03e35824fb34 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Oct 2004 21:53:27 +0300 Subject: [PATCH 7/7] added support of view and CHECK OPTION of view to LOAD DATA (BUG#5996) mysql-test/r/view.result: LOAD DATA with view and CHECK OPTION mysql-test/t/view.test: LOAD DATA with view and CHECK OPTION sql/log_event.cc: new parameter for load data sql/mysql_priv.h: new parameter for load data sql/sql_lex.cc: LOAD DATA supported by view sql/sql_load.cc: added support of view and CHECK OPTION of view to LOAD DATA sql/sql_parse.cc: new parameter for CHECK OPTION --- mysql-test/r/view.result | 58 +++++++++++++++++++++++++++++++++++ mysql-test/t/view.test | 31 +++++++++++++++++++ sql/log_event.cc | 2 +- sql/mysql_priv.h | 5 ++-- sql/sql_lex.cc | 1 + sql/sql_load.cc | 65 ++++++++++++++++++++++++++++++---------- sql/sql_parse.cc | 3 +- 7 files changed, 146 insertions(+), 19 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 8bccec415af..9c89de4259e 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1570,3 +1570,61 @@ select * from t1; s1 drop view v2, v1; drop table t1; +create table t1 (a int, b char(10)); +create view v1 as select * from t1 where a != 0 with check option; +load data infile '../../std_data/loaddata3.dat' into table v1 fields terminated by '' enclosed by '' ignore 1 lines; +ERROR HY000: CHECK OPTION failed 'test.v1' +select * from t1; +a b +1 row 1 +2 row 2 +select * from v1; +a b +1 row 1 +2 row 2 +delete from t1; +load data infile '../../std_data/loaddata3.dat' ignore into table v1 fields terminated by '' enclosed by '' ignore 1 lines; +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 3 +Error 1369 CHECK OPTION failed 'test.v1' +Warning 1264 Out of range value adjusted for column 'a' at row 4 +Error 1369 CHECK OPTION failed 'test.v1' +select * from t1; +a b +1 row 1 +2 row 2 +3 row 3 +select * from v1; +a b +1 row 1 +2 row 2 +3 row 3 +drop view v1; +drop table t1; +create table t1 (a text, b text); +create view v1 as select * from t1 where a <> 'Field A' with check option; +load data infile '../../std_data/loaddata2.dat' into table v1 fields terminated by ',' enclosed by ''''; +ERROR HY000: CHECK OPTION failed 'test.v1' +select concat('|',a,'|'), concat('|',b,'|') from t1; +concat('|',a,'|') concat('|',b,'|') +select concat('|',a,'|'), concat('|',b,'|') from v1; +concat('|',a,'|') concat('|',b,'|') +delete from t1; +load data infile '../../std_data/loaddata2.dat' ignore into table v1 fields terminated by ',' enclosed by ''''; +Warnings: +Error 1369 CHECK OPTION failed 'test.v1' +Warning 1261 Row 2 doesn't contain data for all columns +select concat('|',a,'|'), concat('|',b,'|') from t1; +concat('|',a,'|') concat('|',b,'|') +|Field 1| |Field 2' +Field 3,'Field 4| +|Field 5' ,'Field 6| NULL +|Field 6| | 'Field 7'| +select concat('|',a,'|'), concat('|',b,'|') from v1; +concat('|',a,'|') concat('|',b,'|') +|Field 1| |Field 2' +Field 3,'Field 4| +|Field 5' ,'Field 6| NULL +|Field 6| | 'Field 7'| +drop view v1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index bb0d6c158ec..8e38b5616f8 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1523,3 +1523,34 @@ select * from v2; select * from t1; drop view v2, v1; drop table t1; + +# +# LOAD DATA with view and CHECK OPTION +# +# fixed length fields +create table t1 (a int, b char(10)); +create view v1 as select * from t1 where a != 0 with check option; +-- error 1369 +load data infile '../../std_data/loaddata3.dat' into table v1 fields terminated by '' enclosed by '' ignore 1 lines; +select * from t1; +select * from v1; +delete from t1; +load data infile '../../std_data/loaddata3.dat' ignore into table v1 fields terminated by '' enclosed by '' ignore 1 lines; +select * from t1; +select * from v1; +drop view v1; +drop table t1; +# variable length fields +create table t1 (a text, b text); +create view v1 as select * from t1 where a <> 'Field A' with check option; +-- error 1369 +load data infile '../../std_data/loaddata2.dat' into table v1 fields terminated by ',' enclosed by ''''; +select concat('|',a,'|'), concat('|',b,'|') from t1; +select concat('|',a,'|'), concat('|',b,'|') from v1; +delete from t1; +load data infile '../../std_data/loaddata2.dat' ignore into table v1 fields terminated by ',' enclosed by ''''; +select concat('|',a,'|'), concat('|',b,'|') from t1; +select concat('|',a,'|'), concat('|',b,'|') from v1; +drop view v1; +drop table t1; + diff --git a/sql/log_event.cc b/sql/log_event.cc index 01dcb2af21c..c2a684ffe03 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2548,7 +2548,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, thd->net.pkt_nr = net->pkt_nr; } if (mysql_load(thd, &ex, &tables, field_list, handle_dup, net != 0, - TL_WRITE)) + TL_WRITE, 0)) thd->query_error = 1; if (thd->cuted_fields) { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a10722cd726..d8916149b77 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -838,9 +838,10 @@ inline TABLE_LIST *find_table_in_local_list(TABLE_LIST *table, bool eval_const_cond(COND *cond); /* sql_load.cc */ -int mysql_load(THD *thd,sql_exchange *ex, TABLE_LIST *table_list, +int mysql_load(THD *thd, sql_exchange *ex, TABLE_LIST *table_list, List &fields, enum enum_duplicates handle_duplicates, - bool local_file,thr_lock_type lock_type); + bool local_file, thr_lock_type lock_type, + bool ignore_check_option_errors); int write_record(THD *thd, TABLE *table, COPY_INFO *info); /* sql_manager.cc */ diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 59dc1a7ee8b..73f99d0dd68 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1616,6 +1616,7 @@ bool st_lex::can_use_merged() case SQLCOM_INSERT_SELECT: case SQLCOM_REPLACE: case SQLCOM_REPLACE_SELECT: + case SQLCOM_LOAD: return TRUE; default: return FALSE; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 28de2b9d116..95025a8fd77 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -71,16 +71,19 @@ public: void set_io_cache_arg(void* arg) { cache.arg = arg; } }; -static int read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table, +static int read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, List &fields, READ_INFO &read_info, - ulong skip_lines); -static int read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, + ulong skip_lines, + bool ignore_check_option_errors); +static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, List &fields, READ_INFO &read_info, - String &enclosed, ulong skip_lines); + String &enclosed, ulong skip_lines, + bool ignore_check_option_errors); int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, List &fields, enum enum_duplicates handle_duplicates, - bool read_file_from_client,thr_lock_type lock_type) + bool read_file_from_client,thr_lock_type lock_type, + bool ignore_check_option_errors) { char name[FN_REFLEN]; File file; @@ -88,6 +91,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, int error; String *field_term=ex->field_term,*escaped=ex->escaped; String *enclosed=ex->enclosed; + Item *unused_conds; bool is_fifo=0; #ifndef EMBEDDED_LIBRARY LOAD_FILE_INFO lf_info; @@ -117,8 +121,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table_list->lock_type= lock_type; 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) + if (setup_tables(thd, table_list, &unused_conds)) + DBUG_RETURN(-1); + if (!table_list->updatable || check_key_in_view(thd, table_list)) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD"); DBUG_RETURN(-1); @@ -294,11 +299,12 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, MODE_STRICT_ALL_TABLES))); if (!field_term->length() && !enclosed->length()) - error=read_fixed_length(thd,info,table,fields,read_info, - skip_lines); + error= read_fixed_length(thd, info, table_list, fields,read_info, + skip_lines, ignore_check_option_errors); else - error=read_sep_field(thd,info,table,fields,read_info,*enclosed, - skip_lines); + error= read_sep_field(thd, info, table_list, fields, read_info, + *enclosed, skip_lines, + ignore_check_option_errors); if (table->file->end_bulk_insert()) error=1; /* purecov: inspected */ table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); @@ -401,11 +407,13 @@ err: ****************************************************************************/ static int -read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List &fields, - READ_INFO &read_info, ulong skip_lines) +read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, + List &fields, READ_INFO &read_info, ulong skip_lines, + bool ignore_check_option_errors) { List_iterator_fast it(fields); Item_field *sql_field; + TABLE *table= table_list->table; ulonglong id; bool no_trans_update; DBUG_ENTER("read_fixed_length"); @@ -472,6 +480,17 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List &fields, ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count); } + + switch(table_list->view_check_option(thd, + ignore_check_option_errors)) + { + case VIEW_CHECK_SKIP: + read_info.next_line(); + goto continue_loop; + case VIEW_CHECK_ERROR: + DBUG_RETURN(-1); + } + if (thd->killed || write_record(thd,table,&info)) DBUG_RETURN(1); thd->no_trans_update= no_trans_update; @@ -496,6 +515,7 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List &fields, ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count); } thd->row_count++; +continue_loop:; } if (id && !read_info.error) thd->insert_id(id); // For binary/update log @@ -505,12 +525,14 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List &fields, static int -read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, +read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, List &fields, READ_INFO &read_info, - String &enclosed, ulong skip_lines) + String &enclosed, ulong skip_lines, + bool ignore_check_option_errors) { List_iterator_fast it(fields); Item_field *sql_field; + TABLE *table= table_list->table; uint enclosed_length; ulonglong id; bool no_trans_update; @@ -580,6 +602,18 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count); } } + + switch(table_list->view_check_option(thd, + ignore_check_option_errors)) + { + case VIEW_CHECK_SKIP: + read_info.next_line(); + goto continue_loop; + case VIEW_CHECK_ERROR: + DBUG_RETURN(-1); + } + + if (thd->killed || write_record(thd, table, &info)) DBUG_RETURN(1); /* @@ -605,6 +639,7 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, DBUG_RETURN(1); } thd->row_count++; +continue_loop:; } if (id && !read_info.error) thd->insert_id(id); // For binary/update log diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f93aaf09933..54a1240c0ab 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3135,7 +3135,8 @@ unsent_create_error: goto error; } res= mysql_load(thd, lex->exchange, first_table, lex->field_list, - lex->duplicates, (bool) lex->local_file, lex->lock_option); + lex->duplicates, (bool) lex->local_file, + lex->lock_option, lex->duplicates == DUP_IGNORE); break; }