Skip to content

Commit 8c5db7a

Browse files
committed
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.
1 parent bc2f155 commit 8c5db7a

File tree

7 files changed

+125
-10
lines changed

7 files changed

+125
-10
lines changed

mysql-test/main/view.result

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7029,3 +7029,49 @@ DROP TABLE t1, t2;
70297029
#
70307030
# End of 10.6 tests
70317031
#
7032+
#
7033+
# MDEV-29587: Allowing insert into a view with columns that
7034+
# are not part the table
7035+
#
7036+
# view with 2 the same fields
7037+
CREATE TABLE table1 (x INT);
7038+
CREATE VIEW view1 AS SELECT x, x as x1 FROM table1;
7039+
INSERT INTO view1(x) VALUES (1);
7040+
INSERT INTO view1(x1) VALUES (1);
7041+
INSERT INTO view1(x1,x) VALUES (1,1);
7042+
ERROR HY000: The target table view1 of the INSERT is not insertable-into
7043+
DROP VIEW view1;
7044+
DROP TABLE table1;
7045+
# view with a field and expression over the field
7046+
CREATE TABLE table1 (x INT);
7047+
CREATE VIEW view1 AS SELECT x, x + 1 as x1 FROM table1;
7048+
INSERT INTO view1(x) VALUES (1);
7049+
INSERT INTO view1(x1) VALUES (1);
7050+
ERROR HY000: The target table view1 of the INSERT is not insertable-into
7051+
INSERT INTO view1(x1,x) VALUES (1,1);
7052+
ERROR HY000: The target table view1 of the INSERT is not insertable-into
7053+
DROP VIEW view1;
7054+
DROP TABLE table1;
7055+
# view with a field and collation expression over the field
7056+
CREATE TABLE table1 (x char(20));
7057+
CREATE VIEW view1 AS SELECT x, x collate latin1_german1_ci as x1 FROM table1;
7058+
INSERT INTO view1(x) VALUES ("ua");
7059+
# we can insert in the field with collation
7060+
INSERT INTO view1(x1) VALUES ("ua");
7061+
INSERT INTO view1(x1,x) VALUES ("ua","ua");
7062+
ERROR HY000: The target table view1 of the INSERT is not insertable-into
7063+
DROP VIEW view1;
7064+
DROP TABLE table1;
7065+
# view with a field and expression over other field
7066+
CREATE TABLE table1 (x INT, y INT);
7067+
CREATE VIEW view1 AS SELECT x, y + 1 as x1 FROM table1;
7068+
INSERT INTO view1(x) VALUES (1);
7069+
INSERT INTO view1(x1) VALUES (1);
7070+
ERROR HY000: The target table view1 of the INSERT is not insertable-into
7071+
INSERT INTO view1(x1,x) VALUES (1,1);
7072+
ERROR HY000: The target table view1 of the INSERT is not insertable-into
7073+
DROP VIEW view1;
7074+
DROP TABLE table1;
7075+
#
7076+
# End of 10.11 test
7077+
#

mysql-test/main/view.test

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6792,3 +6792,56 @@ DROP TABLE t1, t2;
67926792
--echo #
67936793
--echo # End of 10.6 tests
67946794
--echo #
6795+
6796+
6797+
--echo #
6798+
--echo # MDEV-29587: Allowing insert into a view with columns that
6799+
--echo # are not part the table
6800+
--echo #
6801+
6802+
--echo # view with 2 the same fields
6803+
CREATE TABLE table1 (x INT);
6804+
CREATE VIEW view1 AS SELECT x, x as x1 FROM table1;
6805+
INSERT INTO view1(x) VALUES (1);
6806+
INSERT INTO view1(x1) VALUES (1);
6807+
--error ER_NON_INSERTABLE_TABLE
6808+
INSERT INTO view1(x1,x) VALUES (1,1);
6809+
DROP VIEW view1;
6810+
DROP TABLE table1;
6811+
6812+
--echo # view with a field and expression over the field
6813+
CREATE TABLE table1 (x INT);
6814+
CREATE VIEW view1 AS SELECT x, x + 1 as x1 FROM table1;
6815+
INSERT INTO view1(x) VALUES (1);
6816+
--error ER_NON_INSERTABLE_TABLE
6817+
INSERT INTO view1(x1) VALUES (1);
6818+
--error ER_NON_INSERTABLE_TABLE
6819+
INSERT INTO view1(x1,x) VALUES (1,1);
6820+
DROP VIEW view1;
6821+
DROP TABLE table1;
6822+
6823+
--echo # view with a field and collation expression over the field
6824+
CREATE TABLE table1 (x char(20));
6825+
CREATE VIEW view1 AS SELECT x, x collate latin1_german1_ci as x1 FROM table1;
6826+
INSERT INTO view1(x) VALUES ("ua");
6827+
--echo # we can insert in the field with collation
6828+
INSERT INTO view1(x1) VALUES ("ua");
6829+
--error ER_NON_INSERTABLE_TABLE
6830+
INSERT INTO view1(x1,x) VALUES ("ua","ua");
6831+
DROP VIEW view1;
6832+
DROP TABLE table1;
6833+
6834+
--echo # view with a field and expression over other field
6835+
CREATE TABLE table1 (x INT, y INT);
6836+
CREATE VIEW view1 AS SELECT x, y + 1 as x1 FROM table1;
6837+
INSERT INTO view1(x) VALUES (1);
6838+
--error ER_NON_INSERTABLE_TABLE
6839+
INSERT INTO view1(x1) VALUES (1);
6840+
--error ER_NON_INSERTABLE_TABLE
6841+
INSERT INTO view1(x1,x) VALUES (1,1);
6842+
DROP VIEW view1;
6843+
DROP TABLE table1;
6844+
6845+
--echo #
6846+
--echo # End of 10.11 test
6847+
--echo #

mysql-test/suite/funcs_1/r/innodb_views.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22145,9 +22145,9 @@ DELETE FROM t1;
2214522145
DROP VIEW v1;
2214622146
CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1;
2214722147
INSERT INTO v1 SET f1 = 1;
22148-
ERROR HY000: The target table v1 of the INSERT is not insertable-into
2214922148
SELECT * from t1;
2215022149
f1 f2 f3 f4
22150+
1 NULL NULL NULL
2215122151
DELETE FROM t1;
2215222152
INSERT INTO v1 SET f1 = 1, my_greeting = 'HELLO';
2215322153
ERROR HY000: The target table v1 of the INSERT is not insertable-into

mysql-test/suite/funcs_1/r/memory_views.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22147,9 +22147,9 @@ DELETE FROM t1;
2214722147
DROP VIEW v1;
2214822148
CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1;
2214922149
INSERT INTO v1 SET f1 = 1;
22150-
ERROR HY000: The target table v1 of the INSERT is not insertable-into
2215122150
SELECT * from t1;
2215222151
f1 f2 f3 f4
22152+
1 NULL NULL NULL
2215322153
DELETE FROM t1;
2215422154
INSERT INTO v1 SET f1 = 1, my_greeting = 'HELLO';
2215522155
ERROR HY000: The target table v1 of the INSERT is not insertable-into

mysql-test/suite/funcs_1/r/myisam_views-big.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23849,9 +23849,9 @@ DELETE FROM t1;
2384923849
DROP VIEW v1;
2385023850
CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1;
2385123851
INSERT INTO v1 SET f1 = 1;
23852-
ERROR HY000: The target table v1 of the INSERT is not insertable-into
2385323852
SELECT * from t1;
2385423853
f1 f2 f3 f4
23854+
1 NULL NULL NULL
2385523855
DELETE FROM t1;
2385623856
INSERT INTO v1 SET f1 = 1, my_greeting = 'HELLO';
2385723857
ERROR HY000: The target table v1 of the INSERT is not insertable-into

mysql-test/suite/funcs_1/views/views_master.inc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3479,7 +3479,6 @@ CREATE VIEW v1 AS SELECT f1, f2, f3, 'HELLO' AS my_greeting FROM t1;
34793479

34803480
# Maybe the SQL standard allows the following INSERT.
34813481
# But it would be a very sophisticated DBMS.
3482-
--error ER_NON_INSERTABLE_TABLE
34833482
INSERT INTO v1 SET f1 = 1;
34843483
SELECT * from t1;
34853484
DELETE FROM t1;

sql/sql_insert.cc

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ static void end_delayed_insert(THD *thd);
9696
pthread_handler_t handle_delayed_insert(void *arg);
9797
static void unlink_blobs(TABLE *table);
9898
#endif
99-
static bool check_view_insertability(THD *thd, TABLE_LIST *view);
99+
static bool check_view_insertability(THD *thd, TABLE_LIST *view,
100+
List<Item> &fields);
100101
static int binlog_show_create_table_(THD *thd, TABLE *table,
101102
Table_specification_st *create_info);
102103

@@ -311,7 +312,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
311312

312313
if (check_key_in_view(thd, table_list) ||
313314
(table_list->view &&
314-
check_view_insertability(thd, table_list)))
315+
check_view_insertability(thd, table_list, fields)))
315316
{
316317
my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias.str, "INSERT");
317318
DBUG_RETURN(-1);
@@ -1426,6 +1427,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
14261427
check_view_insertability()
14271428
thd - thread handler
14281429
view - reference on VIEW
1430+
fields - fields used in insert
14291431
14301432
IMPLEMENTATION
14311433
A view is insertable if the folloings are true:
@@ -1441,7 +1443,8 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
14411443
TRUE - can't be used for insert
14421444
*/
14431445

1444-
static bool check_view_insertability(THD * thd, TABLE_LIST *view)
1446+
static bool check_view_insertability(THD *thd, TABLE_LIST *view,
1447+
List<Item> &fields)
14451448
{
14461449
uint num= view->view->first_select_lex()->item_list.elements;
14471450
TABLE *table= view->table;
@@ -1452,6 +1455,8 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view)
14521455
uint32 *used_fields_buff= (uint32*)thd->alloc(used_fields_buff_size);
14531456
MY_BITMAP used_fields;
14541457
enum_column_usage saved_column_usage= thd->column_usage;
1458+
List_iterator_fast<Item> it(fields);
1459+
Item *ex;
14551460
DBUG_ENTER("check_key_in_view");
14561461

14571462
if (!used_fields_buff)
@@ -1480,6 +1485,17 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view)
14801485
/* simple SELECT list entry (field without expression) */
14811486
if (!(field= trans->item->field_for_view_update()))
14821487
{
1488+
// Do not check fields which we are not inserting into
1489+
while((ex= it++))
1490+
{
1491+
// The field used in the INSERT
1492+
if (ex->real_item()->field_for_view_update() ==
1493+
trans->item->field_for_view_update())
1494+
break;
1495+
}
1496+
it.rewind();
1497+
if (!ex)
1498+
continue;
14831499
thd->column_usage= saved_column_usage;
14841500
DBUG_RETURN(TRUE);
14851501
}
@@ -1494,11 +1510,12 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view)
14941510
}
14951511
thd->column_usage= saved_column_usage;
14961512
/* unique test */
1497-
for (trans= trans_start; trans != trans_end; trans++)
1513+
while((ex= it++))
14981514
{
14991515
/* Thanks to test above, we know that all columns are of type Item_field */
1500-
Item_field *field= (Item_field *)trans->item;
1501-
/* check fields belong to table in which we are inserting */
1516+
DBUG_ASSERT(ex->real_item()->field_for_view_update()->type() ==
1517+
Item::FIELD_ITEM);
1518+
Item_field *field= (Item_field *)ex->real_item()->field_for_view_update();
15021519
if (field->field->table == table &&
15031520
bitmap_fast_test_and_set(&used_fields, field->field->field_index))
15041521
DBUG_RETURN(TRUE);

0 commit comments

Comments
 (0)