summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/view.result33
-rw-r--r--mysql-test/t/view.test35
-rw-r--r--sql/item.cc3
-rw-r--r--sql/sql_select.cc6
-rw-r--r--sql/sql_view.cc5
-rw-r--r--sql/sql_yacc.yy9
6 files changed, 91 insertions, 0 deletions
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 57065d74274..b008e623b5d 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -5479,6 +5479,39 @@ UPDATE t1, t2 SET a = 1 WHERE a IN ( SELECT 0 FROM v3 );
EXECUTE stmt;
DROP TABLE t1, t2, t3;
DROP VIEW v3;
+#
+# MDEV-8632: Segmentation fault on INSERT
+#
+CREATE TABLE `t1` (
+`id` int(10) unsigned NOT NULL,
+`r` float NOT NULL,
+PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+create view v1 as select id, if(r=r,1,2) as d from t1;
+create view v2 as
+select id,
+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d as p
+from v1;
+insert into t1 (id, r)
+select id,p from
+(
+select id,
+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d as p
+from (
+select id, if(r=r,1,2) as d
+from t1
+) a
+) b
+on duplicate key update r=p;
+insert into t1 (id, r)
+select id,p from v2
+on duplicate key update r=p;
+prepare stmt from "insert into t1 (id, r) select id,p from v2 on duplicate key update r=p";
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+drop view v1,v2;
+drop table `t1`;
# -----------------------------------------------------------------
# -- End of 5.5 tests.
# -----------------------------------------------------------------
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index fe04cdfecec..815be87b04e 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -5445,6 +5445,41 @@ EXECUTE stmt;
DROP TABLE t1, t2, t3;
DROP VIEW v3;
+--echo #
+--echo # MDEV-8632: Segmentation fault on INSERT
+--echo #
+CREATE TABLE `t1` (
+ `id` int(10) unsigned NOT NULL,
+ `r` float NOT NULL,
+ PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+create view v1 as select id, if(r=r,1,2) as d from t1;
+create view v2 as
+ select id,
+ d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d as p
+ from v1;
+insert into t1 (id, r)
+select id,p from
+(
+ select id,
+ d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d as p
+ from (
+ select id, if(r=r,1,2) as d
+ from t1
+ ) a
+) b
+on duplicate key update r=p;
+insert into t1 (id, r)
+select id,p from v2
+on duplicate key update r=p;
+
+prepare stmt from "insert into t1 (id, r) select id,p from v2 on duplicate key update r=p";
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+
+drop view v1,v2;
+drop table `t1`;
--echo # -----------------------------------------------------------------
--echo # -- End of 5.5 tests.
--echo # -----------------------------------------------------------------
diff --git a/sql/item.cc b/sql/item.cc
index 878c9604ca2..840272c57a4 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1891,6 +1891,8 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
*/
Item_aggregate_ref *item_ref;
uint el= fields.elements;
+ DBUG_ASSERT(fields.elements <=
+ thd->lex->current_select->ref_pointer_array_size);
/*
If this is an item_ref, get the original item
This is a safety measure if this is called for things that is
@@ -6719,6 +6721,7 @@ Item *Item_field::update_value_transformer(uchar *select_arg)
{
List<Item> *all_fields= &select->join->all_fields;
Item **ref_pointer_array= select->ref_pointer_array;
+ DBUG_ASSERT(all_fields->elements <= select->ref_pointer_array_size);
int el= all_fields->elements;
Item_ref *ref;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e960a3d7c45..ef1b5b0014e 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -427,6 +427,7 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
if (ref_pointer_array && !ref->found_in_select_list)
{
int el= all_fields.elements;
+ DBUG_ASSERT(all_fields.elements <= select->ref_pointer_array_size);
ref_pointer_array[el]= item;
/* Add the field item to the select list of the current select. */
all_fields.push_front(item);
@@ -832,6 +833,7 @@ JOIN::prepare(Item ***rref_pointer_array,
{
Item_field *field= new Item_field(thd, *(Item_field**)ord->item);
int el= all_fields.elements;
+ DBUG_ASSERT(all_fields.elements <= select_lex->ref_pointer_array_size);
ref_pointer_array[el]= field;
all_fields.push_front(field);
ord->item= ref_pointer_array + el;
@@ -20596,6 +20598,8 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
return TRUE; /* Wrong field. */
uint el= all_fields.elements;
+ DBUG_ASSERT(all_fields.elements <=
+ thd->lex->current_select->ref_pointer_array_size);
all_fields.push_front(order_item); /* Add new field to field list. */
ref_pointer_array[el]= order_item;
/*
@@ -20855,6 +20859,8 @@ create_distinct_group(THD *thd, Item **ref_pointer_array,
*/
Item_field *new_item= new Item_field(thd, (Item_field*)item);
int el= all_fields.elements;
+ DBUG_ASSERT(all_fields.elements <=
+ thd->lex->current_select->ref_pointer_array_size);
orig_ref_pointer_array[el]= new_item;
all_fields.push_front(new_item);
ord->item= orig_ref_pointer_array + el;
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 255f876e02a..e6c5ffddfcf 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1520,6 +1520,11 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
*/
lex->sql_command= old_lex->sql_command;
lex->duplicates= old_lex->duplicates;
+
+ /* Fields in this view can be used in upper select in case of merge. */
+ if (table->select_lex)
+ table->select_lex->select_n_where_fields+=
+ lex->select_lex.select_n_where_fields;
}
/*
This method has a dependency on the proper lock type being set,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index a49dea6380e..11d7efdbadf 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -9872,6 +9872,15 @@ table_factor:
sel->add_joined_table($$);
lex->pop_context();
lex->nest_level--;
+ /*
+ Fields in derived table can be used in upper select in
+ case of merge. We do not add HAVING fields because we do
+ not merge such derived. We do not add union because
+ also do not merge them
+ */
+ if (!sel->next_select())
+ $2->select_n_where_fields+=
+ sel->select_n_where_fields;
}
/*else if (($3->select_lex &&
$3->select_lex->master_unit()->is_union() &&