diff --git a/client/mysql.cc b/client/mysql.cc index 36c9ada441c..a77901e5220 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1230,7 +1230,8 @@ static bool add_line(String &buffer,char *line,char *in_string, continue; } #endif - if (!*ml_comment && inchar == '\\') + if (!*ml_comment && inchar == '\\' && + !(mysql.server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)) { // Found possbile one character command like \c diff --git a/mysql-test/r/mysql_client.result b/mysql-test/r/mysql_client.result index 87d09428ff6..a20bd60aaf3 100644 --- a/mysql-test/r/mysql_client.result +++ b/mysql-test/r/mysql_client.result @@ -2,3 +2,7 @@ 1 ERROR 1064 (42000) at line 3: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 ERROR at line 1: USE must be followed by a database name +\ +\\ +'; +'; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index a7d797773ce..2de47f44556 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -193,7 +193,7 @@ c d 2 5 3 10 drop view v100; -ERROR 42S02: Unknown table 'test.v100' +ERROR 42S02: Unknown table 'v100' drop view t1; ERROR HY000: 'test.t1' is not VIEW drop table v1; @@ -2807,6 +2807,17 @@ yadda yad DROP VIEW v1; DROP TABLE t1; +CREATE TABLE t1 (x INT, y INT); +CREATE ALGORITHM=TEMPTABLE SQL SECURITY INVOKER VIEW v1 AS SELECT x FROM t1; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY INVOKER VIEW `v1` AS select `t1`.`x` AS `x` from `t1` +ALTER VIEW v1 AS SELECT x, y FROM t1; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY INVOKER VIEW `v1` AS select `t1`.`x` AS `x`,`t1`.`y` AS `y` from `t1` +DROP VIEW v1; +DROP TABLE t1; CREATE TABLE t1 (s1 char); INSERT INTO t1 VALUES ('Z'); CREATE VIEW v1 AS SELECT s1 collate latin1_german1_ci AS col FROM t1; @@ -2820,3 +2831,22 @@ b c DROP VIEW v1, v2; DROP TABLE t1; +CREATE TABLE t1 (id INT); +CREATE VIEW v1 AS SELECT id FROM t1; +SHOW TABLES; +Tables_in_test +t1 +v1 +DROP VIEW v2,v1; +ERROR 42S02: Unknown table 'v2' +SHOW TABLES; +Tables_in_test +t1 +CREATE VIEW v1 AS SELECT id FROM t1; +DROP VIEW t1,v1; +ERROR HY000: 'test.t1' is not VIEW +SHOW TABLES; +Tables_in_test +t1 +DROP TABLE t1; +DROP VIEW IF EXISTS v1; diff --git a/mysql-test/t/mysql_client.test b/mysql-test/t/mysql_client.test index e4b6658b631..003a086212e 100644 --- a/mysql-test/t/mysql_client.test +++ b/mysql-test/t/mysql_client.test @@ -27,3 +27,14 @@ # client comment recognized, but parameter missing => error --exec echo "use" > $MYSQLTEST_VARDIR/tmp/bug20432.sql --exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20432.sql 2>&1 + +# +# Bug #20103: Escaping with backslash does not work +# +--exec echo "SET SQL_MODE = 'NO_BACKSLASH_ESCAPES';" > $MYSQLTEST_VARDIR/tmp/bug20103.sql +--exec echo "SELECT '\';" >> $MYSQLTEST_VARDIR/tmp/bug20103.sql +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20103.sql 2>&1 + +--exec echo "SET SQL_MODE = '';" > $MYSQLTEST_VARDIR/tmp/bug20103.sql +--exec echo "SELECT '\';';" >> $MYSQLTEST_VARDIR/tmp/bug20103.sql +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20103.sql 2>&1 diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 2099e07fadd..ee37429d694 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2674,6 +2674,17 @@ DROP VIEW v1; DROP TABLE t1; # +#Bug #21080: ALTER VIEW makes user restate SQL SECURITY mode, and ALGORITHM +# +CREATE TABLE t1 (x INT, y INT); +CREATE ALGORITHM=TEMPTABLE SQL SECURITY INVOKER VIEW v1 AS SELECT x FROM t1; +SHOW CREATE VIEW v1; + +ALTER VIEW v1 AS SELECT x, y FROM t1; +SHOW CREATE VIEW v1; + +DROP VIEW v1; +DROP TABLE t1; # Bug #21086: server crashes when VIEW defined with a SELECT with COLLATE # clause is called # @@ -2691,3 +2702,24 @@ INSERT INTO v2 (col) VALUES ('c'); SELECT s1 FROM t1; DROP VIEW v1, v2; DROP TABLE t1; + +# +# Bug #11551: Asymmetric + undocumented behaviour of DROP VIEW and DROP TABLE +# +CREATE TABLE t1 (id INT); +CREATE VIEW v1 AS SELECT id FROM t1; +SHOW TABLES; + +--error 1051 +DROP VIEW v2,v1; +SHOW TABLES; + +CREATE VIEW v1 AS SELECT id FROM t1; +--error 1347 +DROP VIEW t1,v1; +SHOW TABLES; + +DROP TABLE t1; +--disable_warnings +DROP VIEW IF EXISTS v1; +--enable_warnings diff --git a/sql/sql_lex.h b/sql/sql_lex.h index f42f70d4397..55dc6cb55a4 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1047,7 +1047,7 @@ typedef struct st_lex : public Query_tables_list /* view created to be run from definer (standard behaviour) */ - bool create_view_suid; + uint8 create_view_suid; /* Characterstics of trigger being created */ st_trg_chistics trg_chistics; /* diff --git a/sql/sql_view.cc b/sql/sql_view.cc index d24b247a22f..546d940e3a4 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -155,6 +155,54 @@ err: DBUG_RETURN(TRUE); } +/* + Fill defined view parts + + SYNOPSIS + fill_defined_view_parts() + thd current thread. + view view to operate on + + DESCRIPTION + This function will initialize the parts of the view + definition that are not specified in ALTER VIEW + to their values from CREATE VIEW. + The view must be opened to get its definition. + We use a copy of the view when opening because we want + to preserve the original view instance. + + RETURN VALUE + TRUE can't open table + FALSE success +*/ +static bool +fill_defined_view_parts (THD *thd, TABLE_LIST *view) +{ + LEX *lex= thd->lex; + bool not_used; + TABLE_LIST decoy; + + memcpy (&decoy, view, sizeof (TABLE_LIST)); + if (!open_table(thd, &decoy, thd->mem_root, ¬_used, 0) && + !decoy.view) + { + return TRUE; + } + if (!lex->definer) + { + view->definer.host= decoy.definer.host; + view->definer.user= decoy.definer.user; + lex->definer= &view->definer; + } + if (lex->create_view_algorithm == VIEW_ALGORITHM_UNDEFINED) + lex->create_view_algorithm= 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; +} + /* Creating/altering VIEW procedure @@ -207,7 +255,15 @@ bool mysql_create_view(THD *thd, } if (mode != VIEW_CREATE_NEW) + { + if (mode == VIEW_ALTER && + fill_defined_view_parts(thd, view)) + { + res= TRUE; + goto err; + } sp_cache_invalidate(); + } if (!lex->definer) { @@ -1238,6 +1294,10 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) { char path[FN_REFLEN]; TABLE_LIST *view; + frm_type_enum type; + String non_existant_views; + char *wrong_object_db= NULL, *wrong_object_name= NULL; + bool error= FALSE; enum legacy_db_type not_used; DBUG_ENTER("mysql_drop_view"); @@ -1248,8 +1308,9 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) build_table_filename(path, sizeof(path), view->db, view->table_name, reg_ext); VOID(pthread_mutex_lock(&LOCK_open)); - if (access(path, F_OK) || - (type= (mysql_frm_type(thd, path, ¬_used) != FRMTYPE_VIEW))) + type= FRMTYPE_ERROR; + if (access(path, F_OK) || + FRMTYPE_VIEW != (type= mysql_frm_type(thd, path, ¬_used))) { char name[FN_REFLEN]; my_snprintf(name, sizeof(name), "%s.%s", view->db, view->table_name); @@ -1261,14 +1322,25 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) VOID(pthread_mutex_unlock(&LOCK_open)); continue; } - if (type) - my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW"); + if (type == FRMTYPE_TABLE) + { + if (!wrong_object_name) + { + wrong_object_db= view->db; + wrong_object_name= view->table_name; + } + } else - my_error(ER_BAD_TABLE_ERROR, MYF(0), name); - goto err; + { + if (non_existant_views.length()) + non_existant_views.append(','); + non_existant_views.append(String(view->table_name,system_charset_info)); + } + VOID(pthread_mutex_unlock(&LOCK_open)); + continue; } if (my_delete(path, MYF(MY_WME))) - goto err; + error= TRUE; /* For a view, there is only one table_share object which should never @@ -1287,13 +1359,23 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) sp_cache_invalidate(); VOID(pthread_mutex_unlock(&LOCK_open)); } + if (error) + { + DBUG_RETURN(TRUE); + } + if (wrong_object_name) + { + my_error(ER_WRONG_OBJECT, MYF(0), wrong_object_db, wrong_object_name, + "VIEW"); + DBUG_RETURN(TRUE); + } + if (non_existant_views.length()) + { + my_error(ER_BAD_TABLE_ERROR, MYF(0), non_existant_views.c_ptr()); + DBUG_RETURN(TRUE); + } send_ok(thd); DBUG_RETURN(FALSE); - -err: - VOID(pthread_mutex_unlock(&LOCK_open)); - DBUG_RETURN(TRUE); - } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9236820cd25..b8d68a91afc 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -10866,11 +10866,11 @@ view_algorithm_opt: view_suid: /* empty */ - { Lex->create_view_suid= TRUE; } + { Lex->create_view_suid= VIEW_SUID_DEFAULT; } | SQL_SYM SECURITY_SYM DEFINER_SYM - { Lex->create_view_suid= TRUE; } + { Lex->create_view_suid= VIEW_SUID_DEFINER; } | SQL_SYM SECURITY_SYM INVOKER_SYM - { Lex->create_view_suid= FALSE; } + { Lex->create_view_suid= VIEW_SUID_INVOKER; } ; view_tail: diff --git a/sql/table.h b/sql/table.h index ee8dd7ac65e..0d8ec4f98e1 100644 --- a/sql/table.h +++ b/sql/table.h @@ -472,6 +472,10 @@ typedef struct st_schema_table #define VIEW_ALGORITHM_TMPTABLE 1 #define VIEW_ALGORITHM_MERGE 2 +#define VIEW_SUID_INVOKER 0 +#define VIEW_SUID_DEFINER 1 +#define VIEW_SUID_DEFAULT 2 + /* view WITH CHECK OPTION parameter options */ #define VIEW_CHECK_NONE 0 #define VIEW_CHECK_LOCAL 1