Commit db5d1974 authored by unknown's avatar unknown

Fixed bug #19089.

When a CREATE TABLE command created a table from a materialized
view id does not inherit default values from the underlying table.
Moreover the temporary table used for the view materialization
does not inherit those default values.
In the case when the underlying table contained ENUM fields it caused
misleading error messages. In other cases the created table contained
wrong default values.
The code was modified to ensure inheritance of default values for
materialized views.


mysql-test/r/view.result:
  Added a test case for bug #19089.
mysql-test/t/view.test:
  Added a test case for bug #19089.
sql/field.cc:
  Fixed bug ##19089.
  Added field dflt_field to the class Field.
  This field is set for temp table fields that inherits
  default values of items from which they are created.
sql/field.h:
  Fixed bug ##19089.
  Added field dflt_field to the class Field.
  This field is set for temp table fields that inherits
  default values of items from which they are created.
sql/sql_select.cc:
  Fixed bug #19089.
  When a CREATE TABLE command created a table from a materialized
  view id does not inherit default values from the underlying table.
  Moreover the temporary table used for the view materialization
  does not inherit those default values.
  The code was modified to ensure inheritance of default values for
  materialized views.
parent 47302570
...@@ -2649,3 +2649,45 @@ ldt ...@@ -2649,3 +2649,45 @@ ldt
2006-01-01 03:00:00 2006-01-01 03:00:00
drop view v1, v2; drop view v1, v2;
drop table t1; drop table t1;
CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, a char(6) DEFAULT 'xxx');
INSERT INTO t1(id) VALUES (1), (2), (3), (4);
INSERT INTO t1 VALUES (5,'yyy'), (6,'yyy');
SELECT * FROM t1;
id a
1 xxx
2 xxx
3 xxx
4 xxx
5 yyy
6 yyy
CREATE VIEW v1(a, m) AS SELECT a, MIN(id) FROM t1 GROUP BY a;
SELECT * FROM v1;
a m
xxx 1
yyy 5
CREATE TABLE t2 SELECT * FROM v1;
INSERT INTO t2(m) VALUES (0);
SELECT * FROM t2;
a m
xxx 1
yyy 5
NULL 0
DROP VIEW v1;
DROP TABLE t1,t2;
CREATE TABLE t1 (id int PRIMARY KEY, e ENUM('a','b') NOT NULL DEFAULT 'b');
INSERT INTO t1(id) VALUES (1), (2), (3);
INSERT INTO t1 VALUES (4,'a');
SELECT * FROM t1;
id e
1 b
2 b
3 b
4 a
CREATE VIEW v1(m, e) AS SELECT MIN(id), e FROM t1 GROUP BY e;
CREATE TABLE t2 SELECT * FROM v1;
SELECT * FROM t2;
m e
4 a
1 b
DROP VIEW v1;
DROP TABLE IF EXISTS t1,t2;
...@@ -2512,3 +2512,34 @@ create view v2 as select convert_tz(dt, 'UTC', 'Europe/Moscow') as ldt from v1; ...@@ -2512,3 +2512,34 @@ create view v2 as select convert_tz(dt, 'UTC', 'Europe/Moscow') as ldt from v1;
select * from v2; select * from v2;
drop view v1, v2; drop view v1, v2;
drop table t1; drop table t1;
#
# Bug #19089: wrong inherited dafault values in temp table views
#
CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, a char(6) DEFAULT 'xxx');
INSERT INTO t1(id) VALUES (1), (2), (3), (4);
INSERT INTO t1 VALUES (5,'yyy'), (6,'yyy');
SELECT * FROM t1;
CREATE VIEW v1(a, m) AS SELECT a, MIN(id) FROM t1 GROUP BY a;
SELECT * FROM v1;
CREATE TABLE t2 SELECT * FROM v1;
INSERT INTO t2(m) VALUES (0);
SELECT * FROM t2;
DROP VIEW v1;
DROP TABLE t1,t2;
CREATE TABLE t1 (id int PRIMARY KEY, e ENUM('a','b') NOT NULL DEFAULT 'b');
INSERT INTO t1(id) VALUES (1), (2), (3);
INSERT INTO t1 VALUES (4,'a');
SELECT * FROM t1;
CREATE VIEW v1(m, e) AS SELECT MIN(id), e FROM t1 GROUP BY e;
CREATE TABLE t2 SELECT * FROM v1;
SELECT * FROM t2;
DROP VIEW v1;
DROP TABLE IF EXISTS t1,t2;
...@@ -1233,6 +1233,7 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, ...@@ -1233,6 +1233,7 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
flags=null_ptr ? 0: NOT_NULL_FLAG; flags=null_ptr ? 0: NOT_NULL_FLAG;
comment.str= (char*) ""; comment.str= (char*) "";
comment.length=0; comment.length=0;
dflt_field= 0;
} }
uint Field::offset() uint Field::offset()
......
...@@ -53,6 +53,7 @@ public: ...@@ -53,6 +53,7 @@ public:
char *ptr; // Position to field in record char *ptr; // Position to field in record
uchar *null_ptr; // Byte where null_bit is uchar *null_ptr; // Byte where null_bit is
Field *dflt_field; // Field to copy default value from
/* /*
Note that you can use table->in_use as replacement for current_thd member Note that you can use table->in_use as replacement for current_thd member
only inside of val_*() and store() members (e.g. you can't use it in cons) only inside of val_*() and store() members (e.g. you can't use it in cons)
......
...@@ -8378,6 +8378,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -8378,6 +8378,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
bool make_copy_field, bool make_copy_field,
uint convert_blob_length) uint convert_blob_length)
{ {
Field *result;
Item::Type orig_type= type; Item::Type orig_type= type;
Item *orig_item= 0; Item *orig_item= 0;
...@@ -8394,7 +8395,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -8394,7 +8395,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case Item::SUM_FUNC_ITEM: case Item::SUM_FUNC_ITEM:
{ {
Item_sum *item_sum=(Item_sum*) item; Item_sum *item_sum=(Item_sum*) item;
Field *result= item_sum->create_tmp_field(group, table, convert_blob_length); result= item_sum->create_tmp_field(group, table, convert_blob_length);
if (!result) if (!result)
thd->fatal_error(); thd->fatal_error();
return result; return result;
...@@ -8404,7 +8405,6 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -8404,7 +8405,6 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
{ {
Item_field *field= (Item_field*) item; Item_field *field= (Item_field*) item;
bool orig_modify= modify_item; bool orig_modify= modify_item;
Field *result;
if (orig_type == Item::REF_ITEM) if (orig_type == Item::REF_ITEM)
modify_item= 0; modify_item= 0;
/* /*
...@@ -8438,6 +8438,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -8438,6 +8438,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
convert_blob_length); convert_blob_length);
if (orig_type == Item::REF_ITEM && orig_modify) if (orig_type == Item::REF_ITEM && orig_modify)
((Item_ref*)orig_item)->set_result_field(result); ((Item_ref*)orig_item)->set_result_field(result);
if (field->field->eq_def(result))
result->dflt_field= field->field;
return result; return result;
} }
/* Fall through */ /* Fall through */
...@@ -8460,10 +8462,10 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -8460,10 +8462,10 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
DBUG_ASSERT(((Item_result_field*)item)->result_field); DBUG_ASSERT(((Item_result_field*)item)->result_field);
*from_field= ((Item_result_field*)item)->result_field; *from_field= ((Item_result_field*)item)->result_field;
} }
return create_tmp_field_from_item(thd, item, table, (make_copy_field ? 0 : return create_tmp_field_from_item(thd, item, table,
copy_func), modify_item, (make_copy_field ? 0 : copy_func),
convert_blob_length); modify_item, convert_blob_length);
case Item::TYPE_HOLDER: case Item::TYPE_HOLDER:
return ((Item_type_holder *)item)->make_field_by_type(table); return ((Item_type_holder *)item)->make_field_by_type(table);
default: // Dosen't have to be stored default: // Dosen't have to be stored
return 0; return 0;
...@@ -8914,6 +8916,30 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -8914,6 +8916,30 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
null_count+= (field->field_length & 7); null_count+= (field->field_length & 7);
} }
field->reset(); field->reset();
if (field->dflt_field && field->dflt_field->ptr)
{
/*
field->dflt_field is set only in the cases when 'field' can
inherit the default value that is defined for the field referred
by the Item_field object from which 'field' has been created.
For a field created not from a Item_field item dflt_field == 0.
*/
my_ptrdiff_t diff;
Field *orig_field= field->dflt_field;
/* Get the value from default_values */
diff= (my_ptrdiff_t) (orig_field->table->s->default_values-
orig_field->table->record[0]);
orig_field->move_field(diff); // Points now at default_values
bool is_null= orig_field->is_real_null();
char *from= orig_field->ptr;
orig_field->move_field(-diff); // Back to record[0]
if (is_null)
field->set_null();
else
memcpy(field->ptr, from, field->pack_length());
}
if (from_field[i]) if (from_field[i])
{ /* Not a table Item */ { /* Not a table Item */
copy->set(field,from_field[i],save_sum_fields); copy->set(field,from_field[i],save_sum_fields);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment