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.cc210
1 files changed, 171 insertions, 39 deletions
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index a3d2b1bc4ac..07a85afdf82 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2004, 2013, Oracle and/or its affiliates.
- Copyright (c) 2011, 2014, SkySQL Ab.
+ Copyright (c) 2011, 2015, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -215,8 +215,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
TABLE_LIST decoy;
memcpy (&decoy, view, sizeof (TABLE_LIST));
- if (tdc_open_view(thd, &decoy, decoy.alias, thd->mem_root,
- OPEN_VIEW_NO_PARSE))
+ if (tdc_open_view(thd, &decoy, decoy.alias, OPEN_VIEW_NO_PARSE))
return TRUE;
if (!lex->definer)
@@ -690,6 +689,26 @@ err:
}
+static void make_view_filename(LEX_STRING *dir, char *dir_buff,
+ size_t dir_buff_len,
+ LEX_STRING *path, char *path_buff,
+ size_t path_buff_len,
+ LEX_STRING *file,
+ TABLE_LIST *view)
+{
+ /* print file name */
+ dir->length= build_table_filename(dir_buff, dir_buff_len - 1,
+ view->db, "", "", 0);
+ dir->str= dir_buff;
+
+ path->length= build_table_filename(path_buff, path_buff_len - 1,
+ view->db, view->table_name, reg_ext, 0);
+ path->str= path_buff;
+
+ file->str= path->str + dir->length;
+ file->length= path->length - dir->length;
+}
+
/* number of required parameters for making view */
static const int required_view_parameters= 15;
@@ -752,6 +771,67 @@ static File_option view_parameters[]=
static LEX_STRING view_file_type[]= {{(char*) 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;
+ DBUG_ENTER("mariadb_fix_view");
+
+ if (!wrong_checksum && view->mariadb_version)
+ DBUG_RETURN(HA_ADMIN_OK);
+
+ make_view_filename(&dir, dir_buff, sizeof(dir_buff),
+ &path, path_buff, sizeof(path_buff),
+ &file, view);
+ /* init timestamp */
+ if (!view->timestamp.str)
+ view->timestamp.str= view->timestamp_buffer;
+
+ if (swap_alg && view->algorithm != VIEW_ALGORITHM_UNDEFINED)
+ {
+ DBUG_ASSERT(view->algorithm == VIEW_ALGORITHM_MERGE ||
+ view->algorithm == VIEW_ALGORITHM_TMPTABLE);
+ if (view->algorithm == VIEW_ALGORITHM_MERGE)
+ view->algorithm= VIEW_ALGORITHM_TMPTABLE;
+ else
+ view->algorithm= VIEW_ALGORITHM_MERGE;
+ }
+ else
+ swap_alg= 0;
+ if (wrong_checksum)
+ {
+ if (view->md5.length != 32)
+ {
+ if ((view->md5.str= (char *)thd->alloc(32 + 1)) == NULL)
+ DBUG_RETURN(HA_ADMIN_FAILED);
+ }
+ view->calc_md5(view->md5.str);
+ view->md5.length= 32;
+ }
+ view->mariadb_version= MYSQL_VERSION_ID;
+
+ if (sql_create_definition_file(&dir, &file, view_file_type,
+ (uchar*)view, view_parameters))
+ {
+ sql_print_error("View '%-.192s'.'%-.192s': algorithm swap error.",
+ view->db, view->table_name);
+ 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,
+ (wrong_checksum ? ", checksum corrected" : ""),
+ (swap_alg ?
+ ((view->algorithm == VIEW_ALGORITHM_MERGE) ?
+ ", algorithm restored to be MERGE"
+ : ", algorithm restored to be TEMPTABLE")
+ : ""));
+
+
+ DBUG_RETURN(HA_ADMIN_OK);
+}
+
+
/*
Register VIEW (write .frm & process .frm's history backups)
@@ -900,17 +980,9 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
}
loop_out:
/* print file name */
- dir.length= build_table_filename(dir_buff, sizeof(dir_buff) - 1,
- view->db, "", "", 0);
- dir.str= dir_buff;
-
- path.length= build_table_filename(path_buff, sizeof(path_buff) - 1,
- view->db, view->table_name, reg_ext, 0);
- path.str= path_buff;
-
- file.str= path.str + dir.length;
- file.length= path.length - dir.length;
-
+ make_view_filename(&dir, dir_buff, sizeof(dir_buff),
+ &path, path_buff, sizeof(path_buff),
+ &file, view);
/* init timestamp */
if (!view->timestamp.str)
view->timestamp.str= view->timestamp_buffer;
@@ -931,7 +1003,7 @@ loop_out:
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
- view->db, view->table_name);
+ view->table_name);
DBUG_RETURN(0);
}
else if (mode == VIEW_CREATE_NEW)
@@ -1038,22 +1110,19 @@ err:
-/*
+/**
read VIEW .frm and create structures
- SYNOPSIS
- mysql_make_view()
- thd Thread handler
- parser parser object
- table TABLE_LIST structure for filling
- flags flags
- RETURN
- 0 ok
- 1 error
-*/
+ @param[in] thd Thread handler
+ @param[in] share Share object of view
+ @param[in] table TABLE_LIST structure for filling
+ @param[in] open_view_no_parse Flag to indicate open view but
+ do not parse.
-bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
- uint flags)
+ @return false-in case of success, true-in case of error.
+*/
+bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
+ bool open_view_no_parse)
{
SELECT_LEX *end, *UNINIT_VAR(view_select);
LEX *old_lex, *lex;
@@ -1065,6 +1134,13 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
DBUG_ENTER("mysql_make_view");
DBUG_PRINT("info", ("table: 0x%lx (%s)", (ulong) table, table->table_name));
+ if (table->required_type == FRMTYPE_TABLE)
+ {
+ my_error(ER_WRONG_OBJECT, MYF(0), share->db.str, share->table_name.str,
+ "BASE TABLE");
+ DBUG_RETURN(true);
+ }
+
if (table->view)
{
/*
@@ -1137,12 +1213,14 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
table->definer.user.length= table->definer.host.length= 0;
/*
- TODO: when VIEWs will be stored in cache, table mem_root should
- be used here
+ TODO: when VIEWs will be stored in cache (not only parser),
+ table mem_root should be used here
*/
- if ((result= parser->parse((uchar*)table, thd->mem_root,
- view_parameters, required_view_parameters,
- &file_parser_dummy_hook)))
+ DBUG_ASSERT(share->view_def != NULL);
+ if ((result= share->view_def->parse((uchar*)table, thd->mem_root,
+ view_parameters,
+ required_view_parameters,
+ &file_parser_dummy_hook)))
goto end;
/*
@@ -1174,7 +1252,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
*/
table->view_creation_ctx= View_creation_ctx::create(thd, table);
- if (flags & OPEN_VIEW_NO_PARSE)
+ if (open_view_no_parse)
{
if (arena)
thd->restore_active_arena(arena, &backup);
@@ -1292,11 +1370,12 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
Security_context *security_ctx= 0;
/*
- Check rights to run commands (EXPLAIN SELECT & SHOW CREATE) which show
- underlying tables.
+ Check rights to run commands (ANALYZE SELECT, EXPLAIN SELECT &
+ SHOW CREATE) which show underlying tables.
Skip this step if we are opening view for prelocking only.
*/
- if (!table->prelocking_placeholder && (old_lex->describe))
+ if (!table->prelocking_placeholder && (old_lex->describe ||
+ old_lex->analyze_stmt))
{
/*
The user we run EXPLAIN as (either the connected user who issued
@@ -1612,6 +1691,7 @@ end:
if (arena)
thd->restore_active_arena(arena, &backup);
thd->lex= old_lex;
+ status_var_increment(thd->status_var.opened_views);
DBUG_RETURN(result);
err:
@@ -1629,7 +1709,7 @@ err:
SYNOPSIS
mysql_drop_view()
- thd - thread handler
+ thd - thread handle
views - views to delete
drop_mode - cascade/check
@@ -1746,7 +1826,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
SYNOPSIS
check_key_in_view()
- thd thread handler
+ thd thread handle
view view for check with opened table
DESCRIPTION
@@ -1932,6 +2012,58 @@ int view_checksum(THD *thd, TABLE_LIST *view)
HA_ADMIN_OK);
}
+/**
+ Check view
+
+ @param thd thread handle
+ @param view view for check
+ @param check_opt check options
+
+ @retval HA_ADMIN_OK OK
+ @retval HA_ADMIN_NOT_IMPLEMENTED it is not VIEW
+ @retval HA_ADMIN_WRONG_CHECKSUM check sum is wrong
+*/
+int view_check(THD *thd, TABLE_LIST *view, HA_CHECK_OPT *check_opt)
+{
+ DBUG_ENTER("view_check");
+
+ int res= view_checksum(thd, view);
+ if (res != HA_ADMIN_OK)
+ DBUG_RETURN(res);
+
+ if (((check_opt->sql_flags & TT_FOR_UPGRADE) && !view->mariadb_version))
+ DBUG_RETURN(HA_ADMIN_NEEDS_UPGRADE);
+
+ DBUG_RETURN(HA_ADMIN_OK);
+}
+
+
+/**
+ Repair view
+
+ @param thd thread handle
+ @param view view for check
+ @param check_opt check options
+
+ @retval HA_ADMIN_OK OK
+ @retval HA_ADMIN_NOT_IMPLEMENTED it is not VIEW
+ @retval HA_ADMIN_WRONG_CHECKSUM check sum is wrong
+*/
+
+int view_repair(THD *thd, TABLE_LIST *view, HA_CHECK_OPT *check_opt)
+{
+ DBUG_ENTER("view_repair");
+ bool swap_alg= (check_opt->sql_flags & TT_FROM_MYSQL);
+ bool wrong_checksum= view_checksum(thd, view) != HA_ADMIN_OK;
+ int ret;
+ if (wrong_checksum || swap_alg || (!view->mariadb_version))
+ {
+ ret= mariadb_fix_view(thd, view, wrong_checksum, swap_alg);
+ DBUG_RETURN(ret);
+ }
+ DBUG_RETURN(HA_ADMIN_OK);
+}
+
/*
rename view