mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
Merge gleb.loc:/home/uchum/work/bk/mysql-5.0-opt-27827-fresh
into gleb.loc:/home/uchum/work/bk/mysql-5.0-opt
This commit is contained in:
commit
92737068ea
4 changed files with 177 additions and 17 deletions
|
@ -3394,4 +3394,65 @@ WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION;
|
|||
UPDATE v1 SET c=1;
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1,t2;
|
||||
CREATE TABLE t1 (a1 INT, c INT DEFAULT 0);
|
||||
CREATE TABLE t2 (a2 INT);
|
||||
CREATE TABLE t3 (a3 INT);
|
||||
CREATE TABLE t4 (a4 INT);
|
||||
INSERT INTO t1 (a1) VALUES (1),(2);
|
||||
INSERT INTO t2 (a2) VALUES (1),(2);
|
||||
INSERT INTO t3 (a3) VALUES (1),(2);
|
||||
INSERT INTO t4 (a4) VALUES (1),(2);
|
||||
CREATE VIEW v1 AS
|
||||
SELECT t1.a1, t1.c FROM t1 JOIN t2 ON t1.a1=t2.a2 AND t1.c < 3
|
||||
WITH CHECK OPTION;
|
||||
SELECT * FROM v1;
|
||||
a1 c
|
||||
1 0
|
||||
2 0
|
||||
UPDATE v1 SET c=3;
|
||||
ERROR HY000: CHECK OPTION failed 'test.v1'
|
||||
PREPARE t FROM 'UPDATE v1 SET c=3';
|
||||
EXECUTE t;
|
||||
ERROR HY000: CHECK OPTION failed 'test.v1'
|
||||
EXECUTE t;
|
||||
ERROR HY000: CHECK OPTION failed 'test.v1'
|
||||
INSERT INTO v1(a1, c) VALUES (3, 3);
|
||||
ERROR HY000: CHECK OPTION failed 'test.v1'
|
||||
UPDATE v1 SET c=1 WHERE a1=1;
|
||||
SELECT * FROM v1;
|
||||
a1 c
|
||||
1 1
|
||||
2 0
|
||||
SELECT * FROM t1;
|
||||
a1 c
|
||||
1 1
|
||||
2 0
|
||||
CREATE VIEW v2 AS SELECT t1.a1, t1.c
|
||||
FROM (t1 JOIN t2 ON t1.a1=t2.a2 AND t1.c < 3)
|
||||
JOIN (t3 JOIN t4 ON t3.a3=t4.a4)
|
||||
ON t2.a2=t3.a3 WITH CHECK OPTION;
|
||||
SELECT * FROM v2;
|
||||
a1 c
|
||||
1 1
|
||||
2 0
|
||||
UPDATE v2 SET c=3;
|
||||
ERROR HY000: CHECK OPTION failed 'test.v2'
|
||||
PREPARE t FROM 'UPDATE v2 SET c=3';
|
||||
EXECUTE t;
|
||||
ERROR HY000: CHECK OPTION failed 'test.v2'
|
||||
EXECUTE t;
|
||||
ERROR HY000: CHECK OPTION failed 'test.v2'
|
||||
INSERT INTO v2(a1, c) VALUES (3, 3);
|
||||
ERROR HY000: CHECK OPTION failed 'test.v2'
|
||||
UPDATE v2 SET c=2 WHERE a1=1;
|
||||
SELECT * FROM v2;
|
||||
a1 c
|
||||
1 2
|
||||
2 0
|
||||
SELECT * FROM t1;
|
||||
a1 c
|
||||
1 2
|
||||
2 0
|
||||
DROP VIEW v1,v2;
|
||||
DROP TABLE t1,t2,t3,t4;
|
||||
End of 5.0 tests.
|
||||
|
|
|
@ -3268,4 +3268,56 @@ UPDATE v1 SET c=1;
|
|||
DROP VIEW v1;
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
#
|
||||
# Bug #27827: CHECK OPTION ignores ON conditions when updating
|
||||
# a multi-table view with CHECK OPTION.
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (a1 INT, c INT DEFAULT 0);
|
||||
CREATE TABLE t2 (a2 INT);
|
||||
CREATE TABLE t3 (a3 INT);
|
||||
CREATE TABLE t4 (a4 INT);
|
||||
INSERT INTO t1 (a1) VALUES (1),(2);
|
||||
INSERT INTO t2 (a2) VALUES (1),(2);
|
||||
INSERT INTO t3 (a3) VALUES (1),(2);
|
||||
INSERT INTO t4 (a4) VALUES (1),(2);
|
||||
|
||||
CREATE VIEW v1 AS
|
||||
SELECT t1.a1, t1.c FROM t1 JOIN t2 ON t1.a1=t2.a2 AND t1.c < 3
|
||||
WITH CHECK OPTION;
|
||||
SELECT * FROM v1;
|
||||
--error 1369
|
||||
UPDATE v1 SET c=3;
|
||||
PREPARE t FROM 'UPDATE v1 SET c=3';
|
||||
--error 1369
|
||||
EXECUTE t;
|
||||
--error 1369
|
||||
EXECUTE t;
|
||||
--error 1369
|
||||
INSERT INTO v1(a1, c) VALUES (3, 3);
|
||||
UPDATE v1 SET c=1 WHERE a1=1;
|
||||
SELECT * FROM v1;
|
||||
SELECT * FROM t1;
|
||||
|
||||
CREATE VIEW v2 AS SELECT t1.a1, t1.c
|
||||
FROM (t1 JOIN t2 ON t1.a1=t2.a2 AND t1.c < 3)
|
||||
JOIN (t3 JOIN t4 ON t3.a3=t4.a4)
|
||||
ON t2.a2=t3.a3 WITH CHECK OPTION;
|
||||
SELECT * FROM v2;
|
||||
--error 1369
|
||||
UPDATE v2 SET c=3;
|
||||
PREPARE t FROM 'UPDATE v2 SET c=3';
|
||||
--error 1369
|
||||
EXECUTE t;
|
||||
--error 1369
|
||||
EXECUTE t;
|
||||
--error 1369
|
||||
INSERT INTO v2(a1, c) VALUES (3, 3);
|
||||
UPDATE v2 SET c=2 WHERE a1=1;
|
||||
SELECT * FROM v2;
|
||||
SELECT * FROM t1;
|
||||
|
||||
DROP VIEW v1,v2;
|
||||
DROP TABLE t1,t2,t3,t4;
|
||||
|
||||
--echo End of 5.0 tests.
|
||||
|
|
79
sql/table.cc
79
sql/table.cc
|
@ -1985,6 +1985,47 @@ bool st_table_list::prep_where(THD *thd, Item **conds,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Merge ON expressions for a view
|
||||
|
||||
SYNOPSIS
|
||||
merge_on_conds()
|
||||
thd thread handle
|
||||
table table for the VIEW
|
||||
is_cascaded TRUE <=> merge ON expressions from underlying views
|
||||
|
||||
DESCRIPTION
|
||||
This function returns the result of ANDing the ON expressions
|
||||
of the given view and all underlying views. The ON expressions
|
||||
of the underlying views are added only if is_cascaded is TRUE.
|
||||
|
||||
RETURN
|
||||
Pointer to the built expression if there is any.
|
||||
Otherwise and in the case of a failure NULL is returned.
|
||||
*/
|
||||
|
||||
static Item *
|
||||
merge_on_conds(THD *thd, TABLE_LIST *table, bool is_cascaded)
|
||||
{
|
||||
DBUG_ENTER("merge_on_conds");
|
||||
|
||||
Item *cond= NULL;
|
||||
DBUG_PRINT("info", ("alias: %s", table->alias));
|
||||
if (table->on_expr)
|
||||
cond= table->on_expr->copy_andor_structure(thd);
|
||||
if (!table->nested_join)
|
||||
DBUG_RETURN(cond);
|
||||
List_iterator<TABLE_LIST> li(table->nested_join->join_list);
|
||||
while (TABLE_LIST *tbl= li++)
|
||||
{
|
||||
if (tbl->view && !is_cascaded)
|
||||
continue;
|
||||
cond= and_conds(cond, merge_on_conds(thd, tbl, is_cascaded));
|
||||
}
|
||||
DBUG_RETURN(cond);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Prepare check option expression of table
|
||||
|
||||
|
@ -2001,8 +2042,8 @@ bool st_table_list::prep_where(THD *thd, Item **conds,
|
|||
VIEW_CHECK_LOCAL option.
|
||||
|
||||
NOTE
|
||||
This method build check options for every call
|
||||
(usual execution or every SP/PS call)
|
||||
This method builds check option condition to use it later on
|
||||
every call (usual execution or every SP/PS call).
|
||||
This method have to be called after WHERE preparation
|
||||
(st_table_list::prep_where)
|
||||
|
||||
|
@ -2014,38 +2055,42 @@ bool st_table_list::prep_where(THD *thd, Item **conds,
|
|||
bool st_table_list::prep_check_option(THD *thd, uint8 check_opt_type)
|
||||
{
|
||||
DBUG_ENTER("st_table_list::prep_check_option");
|
||||
bool is_cascaded= check_opt_type == VIEW_CHECK_CASCADED;
|
||||
|
||||
for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
|
||||
{
|
||||
/* see comment of check_opt_type parameter */
|
||||
if (tbl->view &&
|
||||
tbl->prep_check_option(thd,
|
||||
((check_opt_type == VIEW_CHECK_CASCADED) ?
|
||||
VIEW_CHECK_CASCADED :
|
||||
VIEW_CHECK_NONE)))
|
||||
{
|
||||
if (tbl->view && tbl->prep_check_option(thd, (is_cascaded ?
|
||||
VIEW_CHECK_CASCADED :
|
||||
VIEW_CHECK_NONE)))
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (check_opt_type)
|
||||
if (check_opt_type && !check_option_processed)
|
||||
{
|
||||
Item *item= 0;
|
||||
Query_arena *arena= thd->stmt_arena, backup;
|
||||
arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test
|
||||
|
||||
if (where)
|
||||
{
|
||||
DBUG_ASSERT(where->fixed);
|
||||
item= where->copy_andor_structure(thd);
|
||||
check_option= where->copy_andor_structure(thd);
|
||||
}
|
||||
if (check_opt_type == VIEW_CHECK_CASCADED)
|
||||
if (is_cascaded)
|
||||
{
|
||||
for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
|
||||
{
|
||||
if (tbl->check_option)
|
||||
item= and_conds(item, tbl->check_option);
|
||||
check_option= and_conds(check_option, tbl->check_option);
|
||||
}
|
||||
}
|
||||
if (item)
|
||||
thd->change_item_tree(&check_option, item);
|
||||
check_option= and_conds(check_option,
|
||||
merge_on_conds(thd, this, is_cascaded));
|
||||
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
check_option_processed= TRUE;
|
||||
|
||||
}
|
||||
|
||||
if (check_option)
|
||||
|
@ -2150,7 +2195,7 @@ void st_table_list::cleanup_items()
|
|||
check CHECK OPTION condition
|
||||
|
||||
SYNOPSIS
|
||||
check_option()
|
||||
st_table_list::view_check_option()
|
||||
ignore_failure ignore check option fail
|
||||
|
||||
RETURN
|
||||
|
|
|
@ -685,6 +685,8 @@ typedef struct st_table_list
|
|||
bool compact_view_format; /* Use compact format for SHOW CREATE VIEW */
|
||||
/* view where processed */
|
||||
bool where_processed;
|
||||
/* TRUE <=> VIEW CHECK OPTION expression has been processed */
|
||||
bool check_option_processed;
|
||||
/* FRMTYPE_ERROR if any type is acceptable */
|
||||
enum frm_type_enum required_type;
|
||||
char timestamp_buffer[20]; /* buffer for timestamp (19+1) */
|
||||
|
|
Loading…
Reference in a new issue