diff options
author | unknown <bell@sanja.is.com.ua> | 2004-10-04 13:56:48 +0300 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2004-10-04 13:56:48 +0300 |
commit | faea84119ba2779ed76e91e44af0928919868442 (patch) | |
tree | 2339a9b67770ece89b7e96ac64db90238c5d64f9 /sql | |
parent | 99bf885bf5044d99d0597f5e177162c851e32359 (diff) | |
parent | 50cc3e4ab0765fb987b739fdf163e4e1a609fd76 (diff) | |
download | mariadb-git-faea84119ba2779ed76e91e44af0928919868442.tar.gz |
merge
sql/sql_class.h:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_update.cc:
Auto merged
sql/table.cc:
Auto merged
Diffstat (limited to 'sql')
32 files changed, 257 insertions, 40 deletions
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 7b24036d385..0eabb52ded5 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -395,3 +395,5 @@ character-set=latin2 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 81a310a3f0a..2d1c6260625 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -386,3 +386,5 @@ character-set=latin1 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index a67577b1c99..680946c99bb 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -395,3 +395,5 @@ character-set=latin1 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index e7f1d1b7f64..5d178008afc 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -383,3 +383,5 @@ character-set=latin1 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index b6058bc56fc..8d509dff84b 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -388,3 +388,5 @@ character-set=latin7 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 345d20e2203..8126c3954fa 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -383,3 +383,5 @@ character-set=latin1 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index ccc69c68683..e3fe33960b1 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -396,3 +396,5 @@ character-set=latin1 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index edd4e07c4d0..38ff7403b81 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -383,3 +383,5 @@ character-set=greek "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 27c51b3ce2b..c4b11a2c096 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -388,3 +388,5 @@ character-set=latin2 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 40e1271b187..52b1e8cc79a 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -383,3 +383,5 @@ character-set=latin1 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 67de9337ff5..48c18922694 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -387,3 +387,5 @@ character-set=ujis "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index e2d4e29ede7..7cb3a06cdd0 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -383,3 +383,5 @@ character-set=euckr "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index a8bc6129db9..32f8342c04f 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -385,3 +385,5 @@ character-set=latin1 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index ddf6960c740..88ba639181a 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -385,3 +385,5 @@ character-set=latin1 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 5a871fbf776..a7ac5a6cd4e 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -388,3 +388,5 @@ character-set=latin2 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index c0861879702..6e99d800eee 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -385,3 +385,5 @@ character-set=latin1 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 60c3cb4245d..9ec9a0be8af 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -388,3 +388,5 @@ character-set=latin2 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index e62c5a84a44..6dbf49e5ea3 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -388,3 +388,5 @@ character-set=koi8r "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION для необновляемого VIEW '%-.64s.%-.64s'" +"проверка CHECK OPTION для VIEW '%-.64s.%-.64s' провалилась" diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 2c366890653..afd4cda9c5e 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -376,3 +376,5 @@ character-set=cp1250 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 12eacb82dac..276cd8ca74b 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -391,3 +391,5 @@ character-set=latin2 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 94b180914fe..6f8deb6cffb 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -387,3 +387,5 @@ character-set=latin1 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 718db694494..cd8ed0271d6 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -383,3 +383,5 @@ character-set=latin1 "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION on non-updatable view '%-.64s.%-.64s'" +"CHECK OPTION failed '%-.64s.%-.64s'" diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 7a4c37abd1d..9e2e99e4825 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -389,3 +389,5 @@ character-set=koi8u "Field '%-.64s' doesn't have a default value", "Division by 0", "Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld", +"CHECK OPTION для VIEW '%-.64s.%-.64s' що не може бути оновленним" +"перев╕рка CHECK OPTION для VIEW '%-.64s.%-.64s' не пройшла" diff --git a/sql/sql_class.h b/sql/sql_class.h index 43d4b25e518..6d44b82b689 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -227,6 +227,9 @@ typedef struct st_copy_info { /* for INSERT ... UPDATE */ List<Item> *update_fields; List<Item> *update_values; +/* for VIEW ... WITH CHECK OPTION */ + TABLE_LIST *view; + bool ignore; } COPY_INFO; @@ -1278,14 +1281,8 @@ class select_insert :public select_result { bool insert_into_view; select_insert(TABLE_LIST *table_list_par, TABLE *table_par, - List<Item> *fields_par, enum_duplicates duplic) - :table_list(table_list_par), table(table_par), fields(fields_par), - last_insert_id(0), - insert_into_view(table_list_par && table_list_par->view != 0) - { - bzero((char*) &info,sizeof(info)); - info.handle_duplicates=duplic; - } + List<Item> *fields_par, enum_duplicates duplic, + bool ignore_check_option_errors); ~select_insert(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); bool send_fields(List<Item> &list, uint flags) { return 0; } @@ -1311,7 +1308,7 @@ public: List<create_field> &fields_par, List<Key> &keys_par, List<Item> &select_fields,enum_duplicates duplic) - :select_insert (NULL, NULL, &select_fields, duplic), create_table(table), + :select_insert (NULL, NULL, &select_fields, duplic, 0), create_table(table), extra_fields(&fields_par),keys(&keys_par), create_info(create_info_par), lock(0) {} diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 8f082c45e75..4a5bc36befd 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -130,6 +130,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, */ bool log_on= (thd->options & OPTION_BIN_LOG) || (!(thd->master_access & SUPER_ACL)); bool transactional_table, log_delayed; + bool ignore_err= (thd->lex->duplicates == DUP_IGNORE); uint value_count; ulong counter = 1; ulonglong id; @@ -243,6 +244,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, info.handle_duplicates=duplic; info.update_fields=&update_fields; info.update_values=&update_values; + info.view= (table_list->view ? table_list : 0); + info.ignore= ignore_err; /* Count warnings for all inserts. For single line insert, generate an error if try to set a NOT NULL field @@ -315,6 +318,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, break; } } + if ((res= table_list->view_check_option(thd, ignore_err)) == + VIEW_CHECK_SKIP) + continue; + else if (res == VIEW_CHECK_ERROR) + { + error= 1; + break; + } /* FIXME: Actually we should do this before @@ -716,6 +727,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) } if (info->handle_duplicates == DUP_UPDATE) { + int res= 0; /* we don't check for other UNIQUE keys - the first row that matches, is updated. If update causes a conflict again, an error is returned @@ -724,6 +736,15 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) restore_record(table,record[1]); if (fill_record(*info->update_fields, *info->update_values, 0)) goto err; + + /* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */ + if (info->view && + (res= info->view->view_check_option(current_thd, info->ignore)) == + VIEW_CHECK_SKIP) + break; + else if (res == VIEW_CHECK_ERROR) + goto err; + if ((error=table->file->update_row(table->record[1],table->record[0]))) goto err; info->updated++; @@ -1635,6 +1656,11 @@ int mysql_insert_select_prepare(THD *thd) { LEX *lex= thd->lex; DBUG_ENTER("mysql_insert_select_prepare"); + /* + SELECT_LEX do not belong to INSERT statement, so we can't add WHERE + clasue if table is VIEW + */ + lex->query_tables->no_where_clause= 1; if (mysql_prepare_insert_check_table(thd, lex->query_tables, lex->field_list, &lex->select_lex.where)) @@ -1643,6 +1669,21 @@ int mysql_insert_select_prepare(THD *thd) } +select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par, + List<Item> *fields_par, enum_duplicates duplic, + bool ignore_check_option_errors) + :table_list(table_list_par), table(table_par), fields(fields_par), + last_insert_id(0), + insert_into_view(table_list_par && table_list_par->view != 0) +{ + bzero((char*) &info,sizeof(info)); + info.handle_duplicates=duplic; + if (table_list_par) + info.view= (table_list_par->view ? table_list_par : 0); + info.ignore= ignore_check_option_errors; +} + + int select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) { @@ -1702,6 +1743,14 @@ bool select_insert::send_data(List<Item> &values) fill_record(*fields, values, 1); else fill_record(table->field, values, 1); + switch (table_list->view_check_option(thd, + thd->lex->duplicates == DUP_IGNORE)) + { + case VIEW_CHECK_SKIP: + DBUG_RETURN(0); + case VIEW_CHECK_ERROR: + DBUG_RETURN(1); + } if (thd->net.report_error || write_record(thd, table, &info)) DBUG_RETURN(1); if (table->next_number_field) // Clear for next record diff --git a/sql/sql_lex.h b/sql/sql_lex.h index d43b1f81f3d..72d28aa4526 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -691,6 +691,7 @@ typedef struct st_lex uint8 describe; uint8 derived_tables; uint8 create_view_algorithm; + uint8 create_view_check; bool drop_if_exists, drop_temporary, local_file, one_shot_set; bool in_comment, ignore_space, verbose, no_write_to_binlog; /* special JOIN::prepare mode: changing of query is prohibited */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 655ba63c6e5..d95b411ac39 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2818,7 +2818,8 @@ unsent_create_error: if ((res= mysql_insert_select_prepare(thd))) break; if ((result= new select_insert(first_table, first_table->table, - &lex->field_list, lex->duplicates))) + &lex->field_list, lex->duplicates, + lex->duplicates == DUP_IGNORE))) { /* Skip first table, which is the table we are inserting in */ lex->select_lex.table_list.first= (byte*) first_table->next_local; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 024d220b08d..babfe1722a3 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -97,10 +97,12 @@ int mysql_update(THD *thd, ha_rows limit, enum enum_duplicates handle_duplicates) { - bool using_limit=limit != HA_POS_ERROR; + bool using_limit= limit != HA_POS_ERROR; bool safe_update= thd->options & OPTION_SAFE_UPDATES; bool used_key_is_modified, transactional_table, log_delayed; + bool ignore_err= (thd->lex->duplicates == DUP_IGNORE); int error=0; + int res; uint used_index; #ifndef NO_EMBEDDED_ACCESS_CHECKS uint want_privilege; @@ -152,7 +154,7 @@ int mysql_update(THD *thd, #endif { thd->lex->select_lex.no_wrap_view_item= 1; - int res= setup_fields(thd, 0, table_list, fields, 1, 0, 0); + res= setup_fields(thd, 0, table_list, fields, 1, 0, 0); thd->lex->select_lex.no_wrap_view_item= 0; if (res) DBUG_RETURN(-1); /* purecov: inspected */ @@ -369,6 +371,18 @@ int mysql_update(THD *thd, if (compare_record(table, query_id)) { + if ((res= table_list->view_check_option(thd, ignore_err)) != + VIEW_CHECK_OK) + { + found--; + if (res == VIEW_CHECK_SKIP) + continue; + else if (res == VIEW_CHECK_ERROR) + { + error= 1; + break; + } + } if (!(error=table->file->update_row((byte*) table->record[1], (byte*) table->record[0]))) { @@ -979,6 +993,7 @@ multi_update::~multi_update() bool multi_update::send_data(List<Item> ¬_used_values) { TABLE_LIST *cur_table; + bool ignore_err= (thd->lex->duplicates == DUP_IGNORE); DBUG_ENTER("multi_update::send_data"); for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local) @@ -1011,6 +1026,15 @@ bool multi_update::send_data(List<Item> ¬_used_values) if (compare_record(table, thd->query_id)) { int error; + if ((error= cur_table->view_check_option(thd, ignore_err)) != + VIEW_CHECK_OK) + { + found--; + if (error == VIEW_CHECK_SKIP) + continue; + else if (error == VIEW_CHECK_ERROR) + DBUG_RETURN(1); + } if (!updated++) { /* diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 38ba3afee6e..50c260fb642 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -302,7 +302,6 @@ static const int required_view_parameters= 7; Note that one should NOT change the order for this, as it's used by parse() */ - static File_option view_parameters[]= {{{(char*) "query", 5}, offsetof(TABLE_LIST, query), FILE_OPTIONS_STRING}, @@ -312,6 +311,8 @@ static File_option view_parameters[]= FILE_OPTIONS_ULONGLONG}, {{(char*) "algorithm", 9}, offsetof(TABLE_LIST, algorithm), FILE_OPTIONS_ULONGLONG}, + {{"with_check_option", 17}, offsetof(TABLE_LIST, with_check), + FILE_OPTIONS_ULONGLONG}, {{(char*) "revision", 8}, offsetof(TABLE_LIST, revision), FILE_OPTIONS_REV}, {{(char*) "timestamp", 9}, offsetof(TABLE_LIST, timestamp), @@ -383,7 +384,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, 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); @@ -393,7 +394,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, if (mode == VIEW_CREATE_NEW) { my_error(ER_TABLE_EXISTS_ERROR, MYF(0), view->alias); - DBUG_RETURN(1); + DBUG_RETURN(-1); } if (!(parser= sql_parse_prepare(&path, &thd->mem_root, 0))) @@ -404,7 +405,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, { my_error(ER_WRONG_OBJECT, MYF(0), (view->db ? view->db : thd->db), view->real_name, "VIEW"); - DBUG_RETURN(1); + DBUG_RETURN(-1); } /* @@ -416,7 +417,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, if (parser->parse((gptr)view, &thd->mem_root, view_parameters + revision_number_position, 1)) { - DBUG_RETURN(1); + DBUG_RETURN(thd->net.report_error? -1 : 0); } } else @@ -424,7 +425,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, if (mode == VIEW_ALTER) { my_error(ER_NO_SUCH_TABLE, MYF(0), view->db, view->alias); - DBUG_RETURN(1); + DBUG_RETURN(-1); } } } @@ -446,6 +447,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, thd->lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; } view->algorithm= thd->lex->create_view_algorithm; + view->with_check= thd->lex->create_view_check; if ((view->updatable_view= (can_be_merged && view->algorithm != VIEW_ALGORITHM_TMPTABLE))) { @@ -461,10 +463,18 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, } } } + + if (view->with_check != VIEW_CHECK_NONE && + !view->updatable_view) + { + my_error(ER_VIEW_NONUPD_CHECK, MYF(0), view->db, view->real_name); + DBUG_RETURN(-1); + } + if (sql_create_definition_file(&dir, &file, view_file_type, (gptr)view, view_parameters, 3)) { - DBUG_RETURN(1); + DBUG_RETURN(thd->net.report_error? -1 : 1); } DBUG_RETURN(0); } @@ -720,6 +730,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) DBUG_PRINT("info", ("algorithm: TEMPORARY TABLE")); lex->select_lex.linkage= DERIVED_TABLE_TYPE; table->updatable= 0; + table->with_check= VIEW_CHECK_NONE; /* SELECT tree link */ lex->unit.include_down(table->select_lex); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 79c5c094c58..0cdafab7669 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7898,9 +7898,13 @@ algorithm: { Lex->create_view_algorithm= VIEW_ALGORITHM_TMPTABLE; } ; check_option: - /* empty */ {} - | WITH CHECK_SYM OPTION {} - | WITH CASCADED CHECK_SYM OPTION {} - | WITH LOCAL_SYM CHECK_SYM OPTION {} + /* empty */ + { Lex->create_view_check= VIEW_CHECK_NONE; } + | WITH CHECK_SYM OPTION + { Lex->create_view_check= VIEW_CHECK_LOCAL; } + | WITH CASCADED CHECK_SYM OPTION + { Lex->create_view_check= VIEW_CHECK_CASCADED; } + | WITH LOCAL_SYM CHECK_SYM OPTION + { Lex->create_view_check= VIEW_CHECK_LOCAL; } ; diff --git a/sql/table.cc b/sql/table.cc index 88f0cefc09a..43a102abd85 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1595,33 +1595,69 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) if (arena) thd->set_n_backup_item_arena(arena, &backup); - /* Go up to join tree and try to find left join */ - for (; tbl; tbl= tbl->embedding) + if (with_check) { - if (tbl->outer_join) + check_option= where->copy_andor_structure(thd); + if (with_check == VIEW_CHECK_CASCADED) { - /* - Store WHERE condition to ON expression for outer join, because we - 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) - */ - tbl->on_expr= and_conds(tbl->on_expr, where); - break; + check_option= and_conds(check_option, ancestor->check_option); } } - if (tbl == 0) + + /* + 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) { - /* - It is conds of JOIN, but it will be stored in st_select_lex::prep_where - for next reexecution - */ - *conds= and_conds(*conds, where); + /* Go up to join tree and try to find left join */ + for (; tbl; tbl= tbl->embedding) + { + if (tbl->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 expression will not be moved to WHERE condition (i.e. will + be clean correctly for PS/SP) + */ + tbl->on_expr= and_conds(tbl->on_expr, where); + break; + } + } + if (tbl == 0) + { + 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 expression will not be moved to WHERE condition (i.e. will + be clean correctly for PS/SP) + */ + on_expr= and_conds(on_expr, where); + } + else + { + /* + It is conds of JOIN, but it will be stored in + st_select_lex::prep_where for next reexecution + */ + *conds= and_conds(*conds, where); + } + } } if (arena) thd->restore_backup_item_arena(arena, &backup); } + /* + fix_fields do not need tables, because new are only AND operation and we + just need recollect statistics + */ + if (check_option && !check_option->fixed && + check_option->fix_fields(thd, 0, &check_option)) + goto err; /* full text function moving to current select */ if (view->select_lex.ftfunc_list->elements) @@ -1655,6 +1691,40 @@ err: } +/* + check CHECK OPTION condition + + SYNOPSIS + check_option() + ignore_failure ignore check option fail + + RETURN + VIEW_CHECK_OK OK + VIEW_CHECK_ERROR FAILED + VIEW_CHECK_SKIP FAILED, but continue +*/ + +int st_table_list::view_check_option(THD *thd, bool ignore_failure) +{ + if (check_option && check_option->val_int() == 0) + { + if (ignore_failure) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_VIEW_CHECK_FAILED, ER(ER_VIEW_CHECK_FAILED), + view_db.str, view_name.str); + return(VIEW_CHECK_SKIP); + } + else + { + my_error(ER_VIEW_CHECK_FAILED, MYF(0), view_db.str, view_name.str); + return(VIEW_CHECK_ERROR); + } + } + return(VIEW_CHECK_OK); +} + + void Field_iterator_view::set(TABLE_LIST *table) { ptr= table->field_translation; diff --git a/sql/table.h b/sql/table.h index f31c3c21d63..ddc21261e48 100644 --- a/sql/table.h +++ b/sql/table.h @@ -188,6 +188,16 @@ struct st_table { #define VIEW_ALGORITHM_TMPTABLE 1 #define VIEW_ALGORITHM_MERGE 2 +/* view WITH CHECK OPTION parameter options */ +#define VIEW_CHECK_NONE 0 +#define VIEW_CHECK_LOCAL 1 +#define VIEW_CHECK_CASCADED 2 + +/* result of view WITH CHECK OPTION parameter check */ +#define VIEW_CHECK_OK 0 +#define VIEW_CHECK_ERROR 1 +#define VIEW_CHECK_SKIP 2 + struct st_lex; typedef struct st_table_list @@ -223,6 +233,7 @@ typedef struct st_table_list /* next_global before adding VIEW tables */ st_table_list *old_next; Item *where; /* VIEW WHERE clause condition */ + Item *check_option; /* WITH CHECK OPTION condition */ LEX_STRING query; /* text of (CRETE/SELECT) statement */ LEX_STRING md5; /* md5 of query tesxt */ LEX_STRING source; /* source of CREATE VIEW */ @@ -233,6 +244,7 @@ typedef struct st_table_list ulonglong updatable_view; /* VIEW can be updated */ ulonglong revision; /* revision control number */ ulonglong algorithm; /* 0 any, 1 tmp tables , 2 merging */ + ulonglong with_check; /* WITH CHECK OPTION */ uint effective_algorithm; /* which algorithm was really used */ GRANT_INFO grant; thr_lock_type lock_type; @@ -244,6 +256,7 @@ typedef struct st_table_list bool updating; /* for replicate-do/ignore table */ bool force_index; /* prefer index over table scan */ bool ignore_leaves; /* preload only non-leaf nodes */ + bool no_where_clause; /* do not attach WHERE to SELECT */ table_map dep_tables; /* tables the table depends on */ table_map on_expr_dep_tables; /* tables on expression depends on */ struct st_nested_join *nested_join; /* if the element is a nested join */ @@ -262,6 +275,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 placeholder() {return derived || view; } void print(THD *thd, String *str); |