mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-29587 Allowing insert into a view with columns that are not part the table
We can check only fields which take part in inserts.
This commit is contained in:
@@ -7029,3 +7029,49 @@ DROP TABLE t1, t2;
|
|||||||
#
|
#
|
||||||
# End of 10.6 tests
|
# End of 10.6 tests
|
||||||
#
|
#
|
||||||
|
#
|
||||||
|
# MDEV-29587: Allowing insert into a view with columns that
|
||||||
|
# are not part the table
|
||||||
|
#
|
||||||
|
# view with 2 the same fields
|
||||||
|
CREATE TABLE table1 (x INT);
|
||||||
|
CREATE VIEW view1 AS SELECT x, x as x1 FROM table1;
|
||||||
|
INSERT INTO view1(x) VALUES (1);
|
||||||
|
INSERT INTO view1(x1) VALUES (1);
|
||||||
|
INSERT INTO view1(x1,x) VALUES (1,1);
|
||||||
|
ERROR HY000: The target table view1 of the INSERT is not insertable-into
|
||||||
|
DROP VIEW view1;
|
||||||
|
DROP TABLE table1;
|
||||||
|
# view with a field and expression over the field
|
||||||
|
CREATE TABLE table1 (x INT);
|
||||||
|
CREATE VIEW view1 AS SELECT x, x + 1 as x1 FROM table1;
|
||||||
|
INSERT INTO view1(x) VALUES (1);
|
||||||
|
INSERT INTO view1(x1) VALUES (1);
|
||||||
|
ERROR HY000: The target table view1 of the INSERT is not insertable-into
|
||||||
|
INSERT INTO view1(x1,x) VALUES (1,1);
|
||||||
|
ERROR HY000: The target table view1 of the INSERT is not insertable-into
|
||||||
|
DROP VIEW view1;
|
||||||
|
DROP TABLE table1;
|
||||||
|
# view with a field and collation expression over the field
|
||||||
|
CREATE TABLE table1 (x char(20));
|
||||||
|
CREATE VIEW view1 AS SELECT x, x collate latin1_german1_ci as x1 FROM table1;
|
||||||
|
INSERT INTO view1(x) VALUES ("ua");
|
||||||
|
# we can insert in the field with collation
|
||||||
|
INSERT INTO view1(x1) VALUES ("ua");
|
||||||
|
INSERT INTO view1(x1,x) VALUES ("ua","ua");
|
||||||
|
ERROR HY000: The target table view1 of the INSERT is not insertable-into
|
||||||
|
DROP VIEW view1;
|
||||||
|
DROP TABLE table1;
|
||||||
|
# view with a field and expression over other field
|
||||||
|
CREATE TABLE table1 (x INT, y INT);
|
||||||
|
CREATE VIEW view1 AS SELECT x, y + 1 as x1 FROM table1;
|
||||||
|
INSERT INTO view1(x) VALUES (1);
|
||||||
|
INSERT INTO view1(x1) VALUES (1);
|
||||||
|
ERROR HY000: The target table view1 of the INSERT is not insertable-into
|
||||||
|
INSERT INTO view1(x1,x) VALUES (1,1);
|
||||||
|
ERROR HY000: The target table view1 of the INSERT is not insertable-into
|
||||||
|
DROP VIEW view1;
|
||||||
|
DROP TABLE table1;
|
||||||
|
#
|
||||||
|
# End of 10.11 test
|
||||||
|
#
|
||||||
|
@@ -6792,3 +6792,56 @@ DROP TABLE t1, t2;
|
|||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.6 tests
|
--echo # End of 10.6 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-29587: Allowing insert into a view with columns that
|
||||||
|
--echo # are not part the table
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo # view with 2 the same fields
|
||||||
|
CREATE TABLE table1 (x INT);
|
||||||
|
CREATE VIEW view1 AS SELECT x, x as x1 FROM table1;
|
||||||
|
INSERT INTO view1(x) VALUES (1);
|
||||||
|
INSERT INTO view1(x1) VALUES (1);
|
||||||
|
--error ER_NON_INSERTABLE_TABLE
|
||||||
|
INSERT INTO view1(x1,x) VALUES (1,1);
|
||||||
|
DROP VIEW view1;
|
||||||
|
DROP TABLE table1;
|
||||||
|
|
||||||
|
--echo # view with a field and expression over the field
|
||||||
|
CREATE TABLE table1 (x INT);
|
||||||
|
CREATE VIEW view1 AS SELECT x, x + 1 as x1 FROM table1;
|
||||||
|
INSERT INTO view1(x) VALUES (1);
|
||||||
|
--error ER_NON_INSERTABLE_TABLE
|
||||||
|
INSERT INTO view1(x1) VALUES (1);
|
||||||
|
--error ER_NON_INSERTABLE_TABLE
|
||||||
|
INSERT INTO view1(x1,x) VALUES (1,1);
|
||||||
|
DROP VIEW view1;
|
||||||
|
DROP TABLE table1;
|
||||||
|
|
||||||
|
--echo # view with a field and collation expression over the field
|
||||||
|
CREATE TABLE table1 (x char(20));
|
||||||
|
CREATE VIEW view1 AS SELECT x, x collate latin1_german1_ci as x1 FROM table1;
|
||||||
|
INSERT INTO view1(x) VALUES ("ua");
|
||||||
|
--echo # we can insert in the field with collation
|
||||||
|
INSERT INTO view1(x1) VALUES ("ua");
|
||||||
|
--error ER_NON_INSERTABLE_TABLE
|
||||||
|
INSERT INTO view1(x1,x) VALUES ("ua","ua");
|
||||||
|
DROP VIEW view1;
|
||||||
|
DROP TABLE table1;
|
||||||
|
|
||||||
|
--echo # view with a field and expression over other field
|
||||||
|
CREATE TABLE table1 (x INT, y INT);
|
||||||
|
CREATE VIEW view1 AS SELECT x, y + 1 as x1 FROM table1;
|
||||||
|
INSERT INTO view1(x) VALUES (1);
|
||||||
|
--error ER_NON_INSERTABLE_TABLE
|
||||||
|
INSERT INTO view1(x1) VALUES (1);
|
||||||
|
--error ER_NON_INSERTABLE_TABLE
|
||||||
|
INSERT INTO view1(x1,x) VALUES (1,1);
|
||||||
|
DROP VIEW view1;
|
||||||
|
DROP TABLE table1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # End of 10.11 test
|
||||||
|
--echo #
|
||||||
|
@@ -22145,9 +22145,9 @@ DELETE FROM t1;
|
|||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1;
|
CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1;
|
||||||
INSERT INTO v1 SET f1 = 1;
|
INSERT INTO v1 SET f1 = 1;
|
||||||
ERROR HY000: The target table v1 of the INSERT is not insertable-into
|
|
||||||
SELECT * from t1;
|
SELECT * from t1;
|
||||||
f1 f2 f3 f4
|
f1 f2 f3 f4
|
||||||
|
1 NULL NULL NULL
|
||||||
DELETE FROM t1;
|
DELETE FROM t1;
|
||||||
INSERT INTO v1 SET f1 = 1, my_greeting = 'HELLO';
|
INSERT INTO v1 SET f1 = 1, my_greeting = 'HELLO';
|
||||||
ERROR HY000: The target table v1 of the INSERT is not insertable-into
|
ERROR HY000: The target table v1 of the INSERT is not insertable-into
|
||||||
|
@@ -22147,9 +22147,9 @@ DELETE FROM t1;
|
|||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1;
|
CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1;
|
||||||
INSERT INTO v1 SET f1 = 1;
|
INSERT INTO v1 SET f1 = 1;
|
||||||
ERROR HY000: The target table v1 of the INSERT is not insertable-into
|
|
||||||
SELECT * from t1;
|
SELECT * from t1;
|
||||||
f1 f2 f3 f4
|
f1 f2 f3 f4
|
||||||
|
1 NULL NULL NULL
|
||||||
DELETE FROM t1;
|
DELETE FROM t1;
|
||||||
INSERT INTO v1 SET f1 = 1, my_greeting = 'HELLO';
|
INSERT INTO v1 SET f1 = 1, my_greeting = 'HELLO';
|
||||||
ERROR HY000: The target table v1 of the INSERT is not insertable-into
|
ERROR HY000: The target table v1 of the INSERT is not insertable-into
|
||||||
|
@@ -23849,9 +23849,9 @@ DELETE FROM t1;
|
|||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1;
|
CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1;
|
||||||
INSERT INTO v1 SET f1 = 1;
|
INSERT INTO v1 SET f1 = 1;
|
||||||
ERROR HY000: The target table v1 of the INSERT is not insertable-into
|
|
||||||
SELECT * from t1;
|
SELECT * from t1;
|
||||||
f1 f2 f3 f4
|
f1 f2 f3 f4
|
||||||
|
1 NULL NULL NULL
|
||||||
DELETE FROM t1;
|
DELETE FROM t1;
|
||||||
INSERT INTO v1 SET f1 = 1, my_greeting = 'HELLO';
|
INSERT INTO v1 SET f1 = 1, my_greeting = 'HELLO';
|
||||||
ERROR HY000: The target table v1 of the INSERT is not insertable-into
|
ERROR HY000: The target table v1 of the INSERT is not insertable-into
|
||||||
|
@@ -3479,7 +3479,6 @@ CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1;
|
|||||||
|
|
||||||
# Maybe the SQL standard allows the following INSERT.
|
# Maybe the SQL standard allows the following INSERT.
|
||||||
# But it would be a very sophisticated DBMS.
|
# But it would be a very sophisticated DBMS.
|
||||||
--error ER_NON_INSERTABLE_TABLE
|
|
||||||
INSERT INTO v1 SET f1 = 1;
|
INSERT INTO v1 SET f1 = 1;
|
||||||
SELECT * from t1;
|
SELECT * from t1;
|
||||||
DELETE FROM t1;
|
DELETE FROM t1;
|
||||||
|
@@ -96,7 +96,8 @@ static void end_delayed_insert(THD *thd);
|
|||||||
pthread_handler_t handle_delayed_insert(void *arg);
|
pthread_handler_t handle_delayed_insert(void *arg);
|
||||||
static void unlink_blobs(TABLE *table);
|
static void unlink_blobs(TABLE *table);
|
||||||
#endif
|
#endif
|
||||||
static bool check_view_insertability(THD *thd, TABLE_LIST *view);
|
static bool check_view_insertability(THD *thd, TABLE_LIST *view,
|
||||||
|
List<Item> &fields);
|
||||||
static int binlog_show_create_table_(THD *thd, TABLE *table,
|
static int binlog_show_create_table_(THD *thd, TABLE *table,
|
||||||
Table_specification_st *create_info);
|
Table_specification_st *create_info);
|
||||||
|
|
||||||
@@ -311,7 +312,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
|||||||
|
|
||||||
if (check_key_in_view(thd, table_list) ||
|
if (check_key_in_view(thd, table_list) ||
|
||||||
(table_list->view &&
|
(table_list->view &&
|
||||||
check_view_insertability(thd, table_list)))
|
check_view_insertability(thd, table_list, fields)))
|
||||||
{
|
{
|
||||||
my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias.str, "INSERT");
|
my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias.str, "INSERT");
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
@@ -1426,6 +1427,7 @@ abort:
|
|||||||
check_view_insertability()
|
check_view_insertability()
|
||||||
thd - thread handler
|
thd - thread handler
|
||||||
view - reference on VIEW
|
view - reference on VIEW
|
||||||
|
fields - fields used in insert
|
||||||
|
|
||||||
IMPLEMENTATION
|
IMPLEMENTATION
|
||||||
A view is insertable if the folloings are true:
|
A view is insertable if the folloings are true:
|
||||||
@@ -1441,7 +1443,8 @@ abort:
|
|||||||
TRUE - can't be used for insert
|
TRUE - can't be used for insert
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool check_view_insertability(THD * thd, TABLE_LIST *view)
|
static bool check_view_insertability(THD *thd, TABLE_LIST *view,
|
||||||
|
List<Item> &fields)
|
||||||
{
|
{
|
||||||
uint num= view->view->first_select_lex()->item_list.elements;
|
uint num= view->view->first_select_lex()->item_list.elements;
|
||||||
TABLE *table= view->table;
|
TABLE *table= view->table;
|
||||||
@@ -1452,6 +1455,8 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view)
|
|||||||
uint32 *used_fields_buff= (uint32*)thd->alloc(used_fields_buff_size);
|
uint32 *used_fields_buff= (uint32*)thd->alloc(used_fields_buff_size);
|
||||||
MY_BITMAP used_fields;
|
MY_BITMAP used_fields;
|
||||||
enum_column_usage saved_column_usage= thd->column_usage;
|
enum_column_usage saved_column_usage= thd->column_usage;
|
||||||
|
List_iterator_fast<Item> it(fields);
|
||||||
|
Item *ex;
|
||||||
DBUG_ENTER("check_key_in_view");
|
DBUG_ENTER("check_key_in_view");
|
||||||
|
|
||||||
if (!used_fields_buff)
|
if (!used_fields_buff)
|
||||||
@@ -1480,6 +1485,17 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view)
|
|||||||
/* simple SELECT list entry (field without expression) */
|
/* simple SELECT list entry (field without expression) */
|
||||||
if (!(field= trans->item->field_for_view_update()))
|
if (!(field= trans->item->field_for_view_update()))
|
||||||
{
|
{
|
||||||
|
// Do not check fields which we are not inserting into
|
||||||
|
while((ex= it++))
|
||||||
|
{
|
||||||
|
// The field used in the INSERT
|
||||||
|
if (ex->real_item()->field_for_view_update() ==
|
||||||
|
trans->item->field_for_view_update())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
it.rewind();
|
||||||
|
if (!ex)
|
||||||
|
continue;
|
||||||
thd->column_usage= saved_column_usage;
|
thd->column_usage= saved_column_usage;
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
@@ -1494,11 +1510,12 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view)
|
|||||||
}
|
}
|
||||||
thd->column_usage= saved_column_usage;
|
thd->column_usage= saved_column_usage;
|
||||||
/* unique test */
|
/* unique test */
|
||||||
for (trans= trans_start; trans != trans_end; trans++)
|
while((ex= it++))
|
||||||
{
|
{
|
||||||
/* Thanks to test above, we know that all columns are of type Item_field */
|
/* Thanks to test above, we know that all columns are of type Item_field */
|
||||||
Item_field *field= (Item_field *)trans->item;
|
DBUG_ASSERT(ex->real_item()->field_for_view_update()->type() ==
|
||||||
/* check fields belong to table in which we are inserting */
|
Item::FIELD_ITEM);
|
||||||
|
Item_field *field= (Item_field *)ex->real_item()->field_for_view_update();
|
||||||
if (field->field->table == table &&
|
if (field->field->table == table &&
|
||||||
bitmap_fast_test_and_set(&used_fields, field->field->field_index))
|
bitmap_fast_test_and_set(&used_fields, field->field->field_index))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
Reference in New Issue
Block a user