diff options
Diffstat (limited to 'sql/sql_view.cc')
-rw-r--r-- | sql/sql_view.cc | 347 |
1 files changed, 193 insertions, 154 deletions
diff --git a/sql/sql_view.cc b/sql/sql_view.cc index b1c5fd1d8aa..1ab72fad17b 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -16,7 +16,7 @@ */ #define MYSQL_LEX 1 -#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */ +#include "mariadb.h" /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" #include "unireg.h" #include "sql_view.h" @@ -39,7 +39,7 @@ #define MD5_BUFF_LENGTH 33 -const LEX_STRING view_type= { C_STRING_WITH_LEN("VIEW") }; +const LEX_CSTRING view_type= { STRING_WITH_LEN("VIEW") }; static int mysql_register_view(THD *, TABLE_LIST *, enum_view_create_mode); @@ -63,9 +63,9 @@ static void make_unique_view_field_name(THD *thd, Item *target, List<Item> &item_list, Item *last_element) { - char *name= (target->orig_name ? - target->orig_name : - target->name); + const char *name= (target->orig_name ? + target->orig_name : + target->name.str); size_t name_len; uint attempt; char buff[NAME_LEN+1]; @@ -85,7 +85,7 @@ static void make_unique_view_field_name(THD *thd, Item *target, { check= itc++; if (check != target && - my_strcasecmp(system_charset_info, buff, check->name) == 0) + my_strcasecmp(system_charset_info, buff, check->name.str) == 0) { ok= FALSE; break; @@ -96,7 +96,7 @@ static void make_unique_view_field_name(THD *thd, Item *target, itc.rewind(); } - target->orig_name= target->name; + target->orig_name= target->name.str; target->set_name(thd, buff, name_len, system_charset_info); } @@ -140,7 +140,7 @@ bool check_duplicate_names(THD *thd, List<Item> &item_list, bool gen_unique_view itc.rewind(); while ((check= itc++) && check != item) { - if (my_strcasecmp(system_charset_info, item->name, check->name) == 0) + if (lex_string_cmp(system_charset_info, &item->name, &check->name) == 0) { if (!gen_unique_view_name) goto err; @@ -156,7 +156,7 @@ bool check_duplicate_names(THD *thd, List<Item> &item_list, bool gen_unique_view DBUG_RETURN(FALSE); err: - my_error(ER_DUP_FIELDNAME, MYF(0), item->name); + my_error(ER_DUP_FIELDNAME, MYF(0), item->name.str); DBUG_RETURN(TRUE); } @@ -171,17 +171,17 @@ err: void make_valid_column_names(THD *thd, List<Item> &item_list) { Item *item; - uint name_len; + size_t name_len; List_iterator_fast<Item> it(item_list); char buff[NAME_LEN]; DBUG_ENTER("make_valid_column_names"); for (uint column_no= 1; (item= it++); column_no++) { - if (!item->is_autogenerated_name || !check_column_name(item->name)) + if (!item->is_autogenerated_name || !check_column_name(item->name.str)) continue; name_len= my_snprintf(buff, NAME_LEN, "Name_exp_%u", column_no); - item->orig_name= item->name; + item->orig_name= item->name.str; item->set_name(thd, buff, name_len, system_charset_info); } @@ -226,10 +226,10 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) view->definer.user= decoy.definer.user; lex->definer= &view->definer; } - if (lex->create_view_algorithm == VIEW_ALGORITHM_INHERIT) - lex->create_view_algorithm= (uint8) decoy.algorithm; - if (lex->create_view_suid == VIEW_SUID_DEFAULT) - lex->create_view_suid= decoy.view_suid ? + if (lex->create_view->algorithm == VIEW_ALGORITHM_INHERIT) + lex->create_view->algorithm= (uint8) decoy.algorithm; + if (lex->create_view->suid == VIEW_SUID_DEFAULT) + lex->create_view->suid= decoy.view_suid ? VIEW_SUID_DEFINER : VIEW_SUID_INVOKER; return FALSE; @@ -274,13 +274,13 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, checked that we have not more privileges on correspondent column of view table (i.e. user will not get some privileges by view creation) */ - if ((check_access(thd, CREATE_VIEW_ACL, view->db, + if ((check_access(thd, CREATE_VIEW_ACL, view->db.str, &view->grant.privilege, &view->grant.m_internal, 0, 0) || check_grant(thd, CREATE_VIEW_ACL, view, FALSE, 1, FALSE)) || (mode != VIEW_CREATE_NEW && - (check_access(thd, DROP_ACL, view->db, + (check_access(thd, DROP_ACL, view->db.str, &view->grant.privilege, &view->grant.m_internal, 0, 0) || @@ -299,7 +299,7 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, { my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "ANY", thd->security_ctx->priv_user, - thd->security_ctx->priv_host, tbl->table_name); + thd->security_ctx->priv_host, tbl->table_name.str); goto err; } /* @@ -320,8 +320,7 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, tbl->table_name will be correct name of table because VIEWs are not opened yet. */ - fill_effective_table_privileges(thd, &tbl->grant, tbl->db, - tbl->table_name); + fill_effective_table_privileges(thd, &tbl->grant, tbl->db.str, tbl->table_name.str); } } @@ -457,9 +456,9 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, view= lex->unlink_first_table(&link_to_local); - if (check_db_dir_existence(view->db)) + if (check_db_dir_existence(view->db.str)) { - my_error(ER_BAD_DB_ERROR, MYF(0), view->db); + my_error(ER_BAD_DB_ERROR, MYF(0), view->db.str); res= TRUE; goto err; } @@ -495,8 +494,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, { /* is this table view and the same view which we creates now? */ if (tbl->view && - strcmp(tbl->view_db.str, view->db) == 0 && - strcmp(tbl->view_name.str, view->table_name) == 0) + cmp(&tbl->view_db, &view->db) == 0 && + cmp(&tbl->view_name, &view->table_name) == 0) { my_error(ER_NO_SUCH_TABLE, MYF(0), tbl->view_db.str, tbl->view_name.str); res= TRUE; @@ -516,7 +515,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, if (tbl->table->s->tmp_table != NO_TMP_TABLE && !tbl->view && !tbl->schema_table) { - my_error(ER_VIEW_SELECT_TMPTABLE, MYF(0), tbl->alias); + my_error(ER_VIEW_SELECT_TMPTABLE, MYF(0), tbl->alias.str); res= TRUE; goto err; } @@ -531,7 +530,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, /* prepare select to resolve all fields */ lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW; - if (unit->prepare(thd, 0, 0)) + if (unit->prepare(unit->derived, 0, 0)) { /* some errors from prepare are reported to user, if is not then @@ -545,9 +544,9 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, if (lex->view_list.elements) { List_iterator_fast<Item> it(select_lex->item_list); - List_iterator_fast<LEX_STRING> nm(lex->view_list); + List_iterator_fast<LEX_CSTRING> nm(lex->view_list); Item *item; - LEX_STRING *name; + LEX_CSTRING *name; if (lex->view_list.elements != select_lex->item_list.elements) { @@ -577,8 +576,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, Compare/check grants on view with grants of underlying tables */ - fill_effective_table_privileges(thd, &view->grant, view->db, - view->table_name); + fill_effective_table_privileges(thd, &view->grant, view->db.str, + view->table_name.str); /* Make sure that the current user does not have more column-level privileges @@ -597,24 +596,32 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, for (sl= select_lex; sl; sl= sl->next_select()) { - DBUG_ASSERT(view->db); /* Must be set in the parser */ + DBUG_ASSERT(view->db.str); /* Must be set in the parser */ List_iterator_fast<Item> it(sl->item_list); Item *item; while ((item= it++)) { Item_field *fld= item->field_for_view_update(); - uint priv= (get_column_grant(thd, &view->grant, view->db, - view->table_name, item->name) & + uint priv= (get_column_grant(thd, &view->grant, view->db.str, + view->table_name.str, item->name.str) & VIEW_ANY_ACL); - if (fld && !fld->field->table->s->tmp_table) + if (!fld) + continue; + TABLE_SHARE *s= fld->field->table->s; + const Lex_ident field_name= fld->field->field_name; + if (s->tmp_table || + (s->versioned && + (field_name.streq(s->vers_start_field()->field_name) || + field_name.streq(s->vers_end_field()->field_name)))) { + continue; + } - final_priv&= fld->have_privileges; + final_priv&= fld->have_privileges; - if (~fld->have_privileges & priv) - report_item= item; - } + if (~fld->have_privileges & priv) + report_item= item; } } @@ -622,8 +629,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, { my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), "create view", thd->security_ctx->priv_user, - thd->security_ctx->priv_host, report_item->name, - view->table_name); + thd->security_ctx->priv_host, report_item->name.str, + view->table_name.str); res= TRUE; goto err; } @@ -639,19 +646,18 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, */ if (!res) - tdc_remove_table(thd, TDC_RT_REMOVE_ALL, view->db, view->table_name, false); + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, view->db.str, view->table_name.str, false); if (!res && mysql_bin_log.is_open()) { StringBuffer<128> buff(thd->variables.character_set_client); DBUG_ASSERT(buff.charset()->mbminlen == 1); - const LEX_STRING command[3]= - {{ C_STRING_WITH_LEN("CREATE ") }, - { C_STRING_WITH_LEN("ALTER ") }, - { C_STRING_WITH_LEN("CREATE OR REPLACE ") }}; + const LEX_CSTRING command[3]= + {{ STRING_WITH_LEN("CREATE ") }, + { STRING_WITH_LEN("ALTER ") }, + { STRING_WITH_LEN("CREATE OR REPLACE ") }}; - buff.append(command[thd->lex->create_view_mode].str, - command[thd->lex->create_view_mode].length); + buff.append(&command[thd->lex->create_view->mode]); view_store_options(thd, views, &buff); buff.append(STRING_WITH_LEN("VIEW ")); @@ -660,34 +666,39 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, buff.append(STRING_WITH_LEN("IF NOT EXISTS ")); /* Test if user supplied a db (ie: we did not use thd->db) */ - if (views->db && views->db[0] && - (thd->db == NULL || strcmp(views->db, thd->db))) + if (views->db.str && views->db.str[0] && + (thd->db.str == NULL || cmp(&views->db, &thd->db))) { - append_identifier(thd, &buff, views->db, - views->db_length); + append_identifier(thd, &buff, &views->db); buff.append('.'); } - append_identifier(thd, &buff, views->table_name, - views->table_name_length); + append_identifier(thd, &buff, &views->table_name); if (lex->view_list.elements) { - List_iterator_fast<LEX_STRING> names(lex->view_list); - LEX_STRING *name; + List_iterator_fast<LEX_CSTRING> names(lex->view_list); + LEX_CSTRING *name; int i; for (i= 0; (name= names++); i++) { buff.append(i ? ", " : "("); - append_identifier(thd, &buff, name->str, name->length); + append_identifier(thd, &buff, name); } buff.append(')'); } buff.append(STRING_WITH_LEN(" AS ")); + /* views->source doesn't end with \0 */ buff.append(views->source.str, views->source.length); int errcode= query_error_code(thd, TRUE); + /* + Don't log any unsafe warnings for CREATE VIEW as it's safely replicated + with statement based replication + */ + thd->reset_unsafe_warnings(); if (thd->binlog_query(THD::STMT_QUERY_TYPE, - buff.ptr(), buff.length(), FALSE, FALSE, FALSE, errcode)) + buff.ptr(), buff.length(), FALSE, FALSE, FALSE, + errcode) > 0) res= TRUE; } @@ -705,27 +716,26 @@ WSREP_ERROR_LABEL: res= TRUE; err: - THD_STAGE_INFO(thd, stage_end); lex->link_first_table_back(view, link_to_local); unit->cleanup(); DBUG_RETURN(res || thd->is_error()); } -static void make_view_filename(LEX_STRING *dir, char *dir_buff, +static void make_view_filename(LEX_CSTRING *dir, char *dir_buff, size_t dir_buff_len, - LEX_STRING *path, char *path_buff, + LEX_CSTRING *path, char *path_buff, size_t path_buff_len, - LEX_STRING *file, + LEX_CSTRING *file, TABLE_LIST *view) { /* print file name */ dir->length= build_table_filename(dir_buff, dir_buff_len - 1, - view->db, "", "", 0); + view->db.str, "", "", 0); dir->str= dir_buff; path->length= build_table_filename(path_buff, path_buff_len - 1, - view->db, view->table_name, reg_ext, 0); + view->db.str, view->table_name.str, reg_ext, 0); path->str= path_buff; file->str= path->str + dir->length; @@ -742,37 +752,37 @@ static const int required_view_parameters= 15; parse() */ static File_option view_parameters[]= -{{{ C_STRING_WITH_LEN("query")}, +{{{ STRING_WITH_LEN("query")}, my_offsetof(TABLE_LIST, select_stmt), FILE_OPTIONS_ESTRING}, - {{ C_STRING_WITH_LEN("md5")}, + {{ STRING_WITH_LEN("md5")}, my_offsetof(TABLE_LIST, md5), FILE_OPTIONS_STRING}, - {{ C_STRING_WITH_LEN("updatable")}, + {{ STRING_WITH_LEN("updatable")}, my_offsetof(TABLE_LIST, updatable_view), FILE_OPTIONS_ULONGLONG}, - {{ C_STRING_WITH_LEN("algorithm")}, + {{ STRING_WITH_LEN("algorithm")}, my_offsetof(TABLE_LIST, algorithm), FILE_OPTIONS_VIEW_ALGO}, - {{ C_STRING_WITH_LEN("definer_user")}, + {{ STRING_WITH_LEN("definer_user")}, my_offsetof(TABLE_LIST, definer.user), FILE_OPTIONS_STRING}, - {{ C_STRING_WITH_LEN("definer_host")}, + {{ STRING_WITH_LEN("definer_host")}, my_offsetof(TABLE_LIST, definer.host), FILE_OPTIONS_STRING}, - {{ C_STRING_WITH_LEN("suid")}, + {{ STRING_WITH_LEN("suid")}, my_offsetof(TABLE_LIST, view_suid), FILE_OPTIONS_ULONGLONG}, - {{ C_STRING_WITH_LEN("with_check_option")}, + {{ STRING_WITH_LEN("with_check_option")}, my_offsetof(TABLE_LIST, with_check), FILE_OPTIONS_ULONGLONG}, - {{ C_STRING_WITH_LEN("timestamp")}, + {{ STRING_WITH_LEN("timestamp")}, my_offsetof(TABLE_LIST, timestamp), FILE_OPTIONS_TIMESTAMP}, - {{ C_STRING_WITH_LEN("create-version")}, + {{ STRING_WITH_LEN("create-version")}, my_offsetof(TABLE_LIST, file_version), FILE_OPTIONS_ULONGLONG}, - {{ C_STRING_WITH_LEN("source")}, + {{ STRING_WITH_LEN("source")}, my_offsetof(TABLE_LIST, source), FILE_OPTIONS_ESTRING}, {{(char*) STRING_WITH_LEN("client_cs_name")}, @@ -784,21 +794,21 @@ static File_option view_parameters[]= {{(char*) STRING_WITH_LEN("view_body_utf8")}, my_offsetof(TABLE_LIST, view_body_utf8), FILE_OPTIONS_ESTRING}, - {{ C_STRING_WITH_LEN("mariadb-version")}, + {{ STRING_WITH_LEN("mariadb-version")}, my_offsetof(TABLE_LIST, mariadb_version), FILE_OPTIONS_ULONGLONG}, {{NullS, 0}, 0, FILE_OPTIONS_STRING} }; -static LEX_STRING view_file_type[]= {{(char*) STRING_WITH_LEN("VIEW") }}; +static LEX_CSTRING view_file_type[]= {{STRING_WITH_LEN("VIEW") }}; int mariadb_fix_view(THD *thd, TABLE_LIST *view, bool wrong_checksum, bool swap_alg) { char dir_buff[FN_REFLEN + 1], path_buff[FN_REFLEN + 1]; - LEX_STRING dir, file, path; + LEX_CSTRING dir, file, path; DBUG_ENTER("mariadb_fix_view"); if (!wrong_checksum && view->mariadb_version) @@ -838,11 +848,12 @@ int mariadb_fix_view(THD *thd, TABLE_LIST *view, bool wrong_checksum, (uchar*)view, view_parameters)) { sql_print_error("View '%-.192s'.'%-.192s': algorithm swap error.", - view->db, view->table_name); + view->db.str, view->table_name.str); DBUG_RETURN(HA_ADMIN_INTERNAL_ERROR); } sql_print_information("View %`s.%`s: the version is set to %llu%s%s", - view->db, view->table_name, view->mariadb_version, + view->db.str, view->table_name.str, + view->mariadb_version, (wrong_checksum ? ", checksum corrected" : ""), (swap_alg ? ((view->algorithm == VIEW_ALGORITHM_MERGE) ? @@ -906,7 +917,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, char md5[MD5_BUFF_LENGTH]; bool can_be_merged; char dir_buff[FN_REFLEN + 1], path_buff[FN_REFLEN + 1]; - LEX_STRING dir, file, path; + LEX_CSTRING dir, file, path; int error= 0; DBUG_ENTER("mysql_register_view"); @@ -928,7 +939,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, DBUG_PRINT("info", ("View: %.*s", view_query.length(), view_query.ptr())); /* fill structure */ - view->source= thd->lex->create_view_select; + view->source= thd->lex->create_view->select; if (!thd->make_lex_string(&view->select_stmt, view_query.ptr(), view_query.length())) @@ -953,18 +964,18 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, } view->md5.length= 32; can_be_merged= lex->can_be_merged(); - if (lex->create_view_algorithm == VIEW_ALGORITHM_MERGE && + if (lex->create_view->algorithm == VIEW_ALGORITHM_MERGE && !lex->can_be_merged()) { push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_WARN_VIEW_MERGE, ER_THD(thd, ER_WARN_VIEW_MERGE)); - lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED; + lex->create_view->algorithm= DTYPE_ALGORITHM_UNDEFINED; } - view->algorithm= lex->create_view_algorithm; + view->algorithm= lex->create_view->algorithm; view->definer.user= lex->definer->user; view->definer.host= lex->definer->host; - view->view_suid= lex->create_view_suid; - view->with_check= lex->create_view_check; + view->view_suid= lex->create_view->suid; + view->with_check= lex->create_view->check; DBUG_EXECUTE_IF("simulate_register_view_failure", { @@ -1008,26 +1019,26 @@ loop_out: /* check old .frm */ { char path_buff[FN_REFLEN]; - LEX_STRING path; + LEX_CSTRING path; File_parser *parser; path.str= path_buff; fn_format(path_buff, file.str, dir.str, "", MY_UNPACK_FILENAME); path.length= strlen(path_buff); - if (ha_table_exists(thd, view->db, view->table_name, NULL)) + if (ha_table_exists(thd, &view->db, &view->table_name)) { if (lex->create_info.if_not_exists()) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_TABLE_EXISTS_ERROR, ER_THD(thd, ER_TABLE_EXISTS_ERROR), - view->table_name); + view->table_name.str); DBUG_RETURN(0); } else if (mode == VIEW_CREATE_NEW) { - my_error(ER_TABLE_EXISTS_ERROR, MYF(0), view->alias); + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), view->alias.str); error= -1; goto err; } @@ -1040,7 +1051,8 @@ loop_out: if (!parser->ok() || !is_equal(&view_type, parser->type())) { - my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW"); + my_error(ER_WRONG_OBJECT, MYF(0), view->db.str, view->table_name.str, + "VIEW"); error= -1; goto err; } @@ -1054,7 +1066,7 @@ loop_out: { if (mode == VIEW_ALTER) { - my_error(ER_NO_SUCH_TABLE, MYF(0), view->db, view->alias); + my_error(ER_NO_SUCH_TABLE, MYF(0), view->db.str, view->alias.str); error= -1; goto err; } @@ -1095,11 +1107,11 @@ loop_out: UNION */ if (view->updatable_view && - !lex->select_lex.master_unit()->is_union() && + !lex->select_lex.master_unit()->is_unit_op() && !(lex->select_lex.table_list.first)->next_local && find_table_in_global_list(lex->query_tables->next_global, - lex->query_tables->db, - lex->query_tables->table_name)) + &lex->query_tables->db, + &lex->query_tables->table_name)) { view->updatable_view= 0; } @@ -1107,7 +1119,7 @@ loop_out: if (view->with_check != VIEW_CHECK_NONE && !view->updatable_view) { - my_error(ER_VIEW_NONUPD_CHECK, MYF(0), view->db, view->table_name); + my_error(ER_VIEW_NONUPD_CHECK, MYF(0), view->db.str, view->table_name.str); error= -1; goto err; } @@ -1151,9 +1163,9 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, bool result, view_is_mergeable; TABLE_LIST *UNINIT_VAR(view_main_select_tables); DBUG_ENTER("mysql_make_view"); - DBUG_PRINT("info", ("table: %p (%s)", table, table->table_name)); + DBUG_PRINT("info", ("table: %p (%s)", table, table->table_name.str)); - if (table->required_type == FRMTYPE_TABLE) + if (table->required_type == TABLE_TYPE_NORMAL) { my_error(ER_WRONG_OBJECT, MYF(0), share->db.str, share->table_name.str, "BASE TABLE"); @@ -1195,7 +1207,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, if (table->index_hints && table->index_hints->elements) { my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), - table->index_hints->head()->key_name.str, table->table_name); + table->index_hints->head()->key_name.str, table->table_name.str); DBUG_RETURN(TRUE); } @@ -1204,12 +1216,12 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, precedent; precedent= precedent->referencing_view) { - if (precedent->view_name.length == table->table_name_length && - precedent->view_db.length == table->db_length && + if (precedent->view_name.length == table->table_name.length && + precedent->view_db.length == table->db.length && my_strcasecmp(system_charset_info, - precedent->view_name.str, table->table_name) == 0 && + precedent->view_name.str, table->table_name.str) == 0 && my_strcasecmp(system_charset_info, - precedent->view_db.str, table->db) == 0) + precedent->view_db.str, table->db.str) == 0) { my_error(ER_VIEW_RECURSIVE, MYF(0), top_view->view_db.str, top_view->view_name.str); @@ -1253,7 +1265,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, !table->definer.host.length); push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_VIEW_FRM_NO_USER, ER_THD(thd, ER_VIEW_FRM_NO_USER), - table->db, table->table_name); + table->db.str, table->table_name.str); get_default_definer(thd, &table->definer, false); } @@ -1283,10 +1295,8 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, Save VIEW parameters, which will be wiped out by derived table processing */ - table->view_db.str= table->db; - table->view_db.length= table->db_length; - table->view_name.str= table->table_name; - table->view_name.length= table->table_name_length; + table->view_db= table->db; + table->view_name= table->table_name; /* We don't invalidate a prepared statement when a view changes, or when someone creates a temporary table. @@ -1326,18 +1336,19 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, { char old_db_buf[SAFE_NAME_LEN+1]; - LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; + LEX_CSTRING old_db= { old_db_buf, sizeof(old_db_buf) }; bool dbchanged; Parser_state parser_state; if (parser_state.init(thd, table->select_stmt.str, - table->select_stmt.length)) + (uint)table->select_stmt.length)) goto err; /* Use view db name as thread default database, in order to ensure that the view is parsed and prepared correctly. */ - if ((result= mysql_opt_change_db(thd, &table->view_db, &old_db, 1, + if ((result= mysql_opt_change_db(thd, &table->view_db, + (LEX_STRING*) &old_db, 1, &dbchanged))) goto end; @@ -1357,7 +1368,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, * MODE_NO_UNSIGNED_SUBTRACTION affect execution - MODE_NO_DIR_IN_CREATE affect table creation only - MODE_POSTGRESQL compounded from other modes - - MODE_ORACLE compounded from other modes + - MODE_ORACLE affects Item creation (e.g for CONCAT) - MODE_MSSQL compounded from other modes - MODE_DB2 compounded from other modes - MODE_MAXDB affect only CREATE TABLE parsing @@ -1372,7 +1383,8 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, + MODE_NO_BACKSLASH_ESCAPES affect expression parsing */ thd->variables.sql_mode&= ~(MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES); + MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES | + MODE_ORACLE); /* Parse the query. */ @@ -1478,6 +1490,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, privileges of top_view */ tbl->grant.want_privilege= SELECT_ACL; + /* After unfolding the view we lose the list of tables referenced in it (we will have only a list of underlying tables in case of MERGE @@ -1528,6 +1541,18 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, views with subqueries in select list. */ view_main_select_tables= lex->select_lex.table_list.first; + /* + Mergeable view can be used for inserting, so we move the flag down + */ + if (table->for_insert_data) + { + for (TABLE_LIST *t= view_main_select_tables; + t; + t= t->next_local) + { + t->for_insert_data= TRUE; + } + } /* Let us set proper lock type for tables of the view's main @@ -1538,7 +1563,9 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, */ for (tbl= view_main_select_tables; tbl; tbl= tbl->next_local) { - tbl->lock_type= table->lock_type; + /* We have to keep the lock type for sequence tables */ + if (!tbl->sequence) + tbl->lock_type= table->lock_type; tbl->mdl_request.set_type(table->mdl_request.type); tbl->updating= table->updating; } @@ -1669,7 +1696,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, We can safely ignore the VIEW's ORDER BY if we merge into union branch, as order is not important there. */ - if (!table->select_lex->master_unit()->is_union() && + if (!table->select_lex->master_unit()->is_unit_op() && table->select_lex->order_list.elements == 0) table->select_lex->order_list.push_back(&lex->select_lex.order_list); else @@ -1677,12 +1704,12 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, if (old_lex->sql_command == SQLCOM_SELECT && (old_lex->describe & DESCRIBE_EXTENDED) && lex->select_lex.order_list.elements && - !table->select_lex->master_unit()->is_union()) + !table->select_lex->master_unit()->is_unit_op()) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_VIEW_ORDERBY_IGNORED, ER_THD(thd, ER_VIEW_ORDERBY_IGNORED), - table->db, table->table_name); + table->db.str, table->table_name.str); } } /* @@ -1699,7 +1726,6 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, view_select->linkage= DERIVED_TABLE_TYPE; table->updatable= 0; table->effective_with_check= VIEW_CHECK_NONE; - old_lex->subqueries= TRUE; table->derived= &lex->unit; } @@ -1760,7 +1786,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) char path[FN_REFLEN + 1]; TABLE_LIST *view; String non_existant_views; - char *wrong_object_db= NULL, *wrong_object_name= NULL; + const char *wrong_object_db= NULL, *wrong_object_name= NULL; bool error= FALSE; bool some_views_deleted= FALSE; bool something_wrong= FALSE; @@ -1772,30 +1798,32 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) TABLES we have to simply prohibit dropping of views. */ - if (thd->locked_tables_mode) + if (unlikely(thd->locked_tables_mode)) { my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); DBUG_RETURN(TRUE); } - if (lock_table_names(thd, views, 0, thd->variables.lock_wait_timeout, 0)) + if (unlikely(lock_table_names(thd, views, 0, + thd->variables.lock_wait_timeout, 0))) DBUG_RETURN(TRUE); for (view= views; view; view= view->next_local) { bool not_exist; build_table_filename(path, sizeof(path) - 1, - view->db, view->table_name, reg_ext, 0); + view->db.str, view->table_name.str, reg_ext, 0); if ((not_exist= my_access(path, F_OK)) || !dd_frm_is_view(thd, path)) { char name[FN_REFLEN]; - my_snprintf(name, sizeof(name), "%s.%s", view->db, view->table_name); + my_snprintf(name, sizeof(name), "%s.%s", view->db.str, + view->table_name.str); if (thd->lex->if_exists()) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_BAD_TABLE_ERROR, - ER_THD(thd, ER_BAD_TABLE_ERROR), + ER_UNKNOWN_VIEW, + ER_THD(thd, ER_UNKNOWN_VIEW), name); continue; } @@ -1809,13 +1837,13 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) { if (!wrong_object_name) { - wrong_object_db= view->db; - wrong_object_name= view->table_name; + wrong_object_db= view->db.str; + wrong_object_name= view->table_name.str; } } continue; } - if (mysql_file_delete(key_file_frm, path, MYF(MY_WME))) + if (unlikely(mysql_file_delete(key_file_frm, path, MYF(MY_WME)))) error= TRUE; some_views_deleted= TRUE; @@ -1824,20 +1852,20 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) For a view, there is a TABLE_SHARE object. Remove it from the table definition cache, in case the view was cached. */ - tdc_remove_table(thd, TDC_RT_REMOVE_ALL, view->db, view->table_name, + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, view->db.str, view->table_name.str, FALSE); query_cache_invalidate3(thd, view, 0); sp_cache_invalidate(); } - if (wrong_object_name) + if (unlikely(wrong_object_name)) { my_error(ER_WRONG_OBJECT, MYF(0), wrong_object_db, wrong_object_name, "VIEW"); } - if (non_existant_views.length()) + if (unlikely(non_existant_views.length())) { - my_error(ER_BAD_TABLE_ERROR, MYF(0), non_existant_views.c_ptr_safe()); + my_error(ER_UNKNOWN_VIEW, MYF(0), non_existant_views.c_ptr_safe()); } something_wrong= error || wrong_object_name || non_existant_views.length(); @@ -1846,11 +1874,12 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) /* if something goes wrong, bin-log with possible error code, otherwise bin-log with error code cleared. */ - if (write_bin_log(thd, !something_wrong, thd->query(), thd->query_length())) + if (unlikely(write_bin_log(thd, !something_wrong, thd->query(), + thd->query_length()))) something_wrong= 1; } - if (something_wrong) + if (unlikely(something_wrong)) { DBUG_RETURN(TRUE); } @@ -1909,19 +1938,19 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) this operation should not have influence on Field::query_id, to avoid marking as used fields which are not used */ - enum_mark_columns save_mark_used_columns= thd->mark_used_columns; - thd->mark_used_columns= MARK_COLUMNS_NONE; - DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns)); + enum_column_usage saved_column_usage= thd->column_usage; + thd->column_usage= COLUMNS_WRITE; + DBUG_PRINT("info", ("thd->column_usage: %d", thd->column_usage)); for (Field_translator *fld= trans; fld < end_of_trans; fld++) { - if (!fld->item->fixed && fld->item->fix_fields(thd, &fld->item)) + if (fld->item->fix_fields_if_needed(thd, &fld->item)) { - thd->mark_used_columns= save_mark_used_columns; + thd->column_usage= saved_column_usage; DBUG_RETURN(TRUE); } } - thd->mark_used_columns= save_mark_used_columns; - DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns)); + thd->column_usage= saved_column_usage; + DBUG_PRINT("info", ("thd->column_usage: %d", thd->column_usage)); } /* Loop over all keys to see if a unique-not-null key is used */ for (;key_info != key_info_end ; key_info++) @@ -1999,7 +2028,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) RETURN FALSE OK - TRUE error (is not sent to cliet) + TRUE error (is not sent to client) */ bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view) @@ -2016,10 +2045,18 @@ bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view) { Item_field *fld; if ((fld= entry->item->field_for_view_update())) + { + TABLE_SHARE *s= fld->context->table_list->table->s; + Lex_ident field_name= fld->field_name; + if (s->versioned && + (field_name.streq(s->vers_start_field()->field_name) || + field_name.streq(s->vers_end_field()->field_name))) + continue; list->push_back(fld, thd->mem_root); + } else { - my_error(ER_NON_INSERTABLE_TABLE, MYF(0), view->alias, "INSERT"); + my_error(ER_NON_INSERTABLE_TABLE, MYF(0), view->alias.str, "INSERT"); DBUG_RETURN(TRUE); } } @@ -2027,7 +2064,7 @@ bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view) } /* - checking view md5 check suum + checking view md5 check sum SINOPSYS view_checksum() @@ -2121,11 +2158,11 @@ int view_repair(THD *thd, TABLE_LIST *view, HA_CHECK_OPT *check_opt) */ bool mysql_rename_view(THD *thd, - const char *new_db, - const char *new_name, + const LEX_CSTRING *new_db, + const LEX_CSTRING *new_name, TABLE_LIST *view) { - LEX_STRING pathstr; + LEX_CSTRING pathstr; File_parser *parser; char path_buff[FN_REFLEN + 1]; bool error= TRUE; @@ -2133,7 +2170,7 @@ mysql_rename_view(THD *thd, pathstr.str= (char *) path_buff; pathstr.length= build_table_filename(path_buff, sizeof(path_buff) - 1, - view->db, view->table_name, + view->db.str, view->table_name.str, reg_ext, 0); if ((parser= sql_parse_prepare(&pathstr, thd->mem_root, 1)) && @@ -2141,7 +2178,7 @@ mysql_rename_view(THD *thd, { TABLE_LIST view_def; char dir_buff[FN_REFLEN + 1]; - LEX_STRING dir, file; + LEX_CSTRING dir, file; /* To be PS-friendly we should either to restore state of @@ -2160,16 +2197,17 @@ mysql_rename_view(THD *thd, goto err; /* rename view and it's backups */ - if (rename_in_schema_file(thd, view->db, view->table_name, new_db, new_name)) + if (rename_in_schema_file(thd, view->db.str, view->table_name.str, + new_db->str, new_name->str)) goto err; dir.str= dir_buff; dir.length= build_table_filename(dir_buff, sizeof(dir_buff) - 1, - new_db, "", "", 0); + new_db->str, "", "", 0); pathstr.str= path_buff; pathstr.length= build_table_filename(path_buff, sizeof(path_buff) - 1, - new_db, new_name, reg_ext, 0); + new_db->str, new_name->str, reg_ext, 0); file.str= pathstr.str + dir.length; file.length= pathstr.length - dir.length; @@ -2178,7 +2216,8 @@ mysql_rename_view(THD *thd, (uchar*)&view_def, view_parameters)) { /* restore renamed view in case of error */ - rename_in_schema_file(thd, new_db, new_name, view->db, view->table_name); + rename_in_schema_file(thd, new_db->str, new_name->str, view->db.str, + view->table_name.str); goto err; } } else |