summaryrefslogtreecommitdiff
path: root/sql/sql_view.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_view.cc')
-rw-r--r--sql/sql_view.cc347
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