CREATE ... SELECT extension (WL 317)

parent 17204b1c
...@@ -70,3 +70,4 @@ zak@linux.local ...@@ -70,3 +70,4 @@ zak@linux.local
venu@myvenu.com venu@myvenu.com
walrus@mysql.com walrus@mysql.com
ram@ram.(none) ram@ram.(none)
WAX@sergbook.mysql.com
...@@ -35442,8 +35442,10 @@ mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT, ...@@ -35442,8 +35442,10 @@ mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
This will create a @code{MyISAM} table with three columns, a, b, and c. This will create a @code{MyISAM} table with three columns, a, b, and c.
Notice that the columns from the @code{SELECT} statement are appended to Notice that the columns from the @code{SELECT} statement are appended to
the right side of the table, not overlapped onto it. Take the following the right side of the table, not overlapped onto it.
example: Still, the column from the @code{SELECT} will overlap the column from
the @code{CREATE} clause if they both have the same name. Take the following
examples:
@example @example
mysql> SELECT * FROM foo; mysql> SELECT * FROM foo;
...@@ -35464,6 +35466,18 @@ mysql> SELECT * FROM bar; ...@@ -35464,6 +35466,18 @@ mysql> SELECT * FROM bar;
| NULL | 1 | | NULL | 1 |
+------+---+ +------+---+
1 row in set (0.00 sec) 1 row in set (0.00 sec)
mysql> CREATE TABLE foobar (n FLOAT(3,2), m INT) SELECT n FROM foo;
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM foobar;
+------+------+
| n | m |
+------+------+
| 1.00 | NULL |
+------+------+
1 row in set (0.00 sec)
@end example @end example
For each row in table @code{foo}, a row is inserted in @code{bar} with For each row in table @code{foo}, a row is inserted in @code{bar} with
...@@ -94,6 +94,24 @@ d date 0000-00-00 ...@@ -94,6 +94,24 @@ d date 0000-00-00
t time 00:00:00 t time 00:00:00
dt datetime 0000-00-00 00:00:00 dt datetime 0000-00-00 00:00:00
drop table t1,t2; drop table t1,t2;
create table t1 (a tinyint);
create table t2 (a int) select * from t1;
describe t1;
Field Type Null Key Default Extra
a tinyint(4) YES NULL
describe t2;
Field Type Null Key Default Extra
a int(11) YES NULL
drop table if exists t2;
create table t2 (a int, a float) select * from t1;
Duplicate column name 'a'
drop table if exists t2;
create table t2 (a int) select a as b, a+1 as b from t1;
Duplicate column name 'b'
drop table if exists t2;
create table t2 (b int) select a as b, a+1 as b from t1;
Duplicate column name 'b'
drop table if exists t1,t2;
create table t1 (a int not null, b int, primary key(a), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b)); create table t1 (a int not null, b int, primary key(a), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b), key (b));
show create table t1; show create table t1;
Table Create Table Table Create Table
......
...@@ -82,6 +82,22 @@ create table t2 select CAST("2001-12-29" AS DATE) as d, CAST("20:45:11" AS TIME) ...@@ -82,6 +82,22 @@ create table t2 select CAST("2001-12-29" AS DATE) as d, CAST("20:45:11" AS TIME)
describe t2; describe t2;
drop table t1,t2; drop table t1,t2;
#
# Test of CREATE ... SELECT with duplicate fields
#
create table t1 (a tinyint);
create table t2 (a int) select * from t1;
describe t1;
describe t2;
drop table if exists t2;
!$1060 create table t2 (a int, a float) select * from t1;
drop table if exists t2;
!$1060 create table t2 (a int) select a as b, a+1 as b from t1;
drop table if exists t2;
!$1060 create table t2 (b int) select a as b, a+1 as b from t1;
drop table if exists t1,t2;
# #
# Test of primary key with 32 index # Test of primary key with 32 index
# #
......
...@@ -382,9 +382,13 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -382,9 +382,13 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
int mysql_create_table(THD *thd,const char *db, const char *table_name, int mysql_create_table(THD *thd,const char *db, const char *table_name,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
List<create_field> &fields, List<Key> &keys, List<create_field> &fields, List<Key> &keys,
bool tmp_table, bool no_log); bool tmp_table, bool no_log, uint select_field_count);
// no_log is needed for the case of CREATE TABLE ... SELECT , as the logging /*
// will be done later in sql_insert.cc no_log is needed for the case of CREATE ... SELECT,
as the logging will be done later in sql_insert.cc
select_field_count is also used for CREATE ... SELECT,
and must be zero for standart create of table
*/
TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
const char *db, const char *name, const char *db, const char *name,
......
...@@ -1598,7 +1598,7 @@ mysql_execute_command(void) ...@@ -1598,7 +1598,7 @@ mysql_execute_command(void)
res = mysql_create_table(thd,tables->db ? tables->db : thd->db, res = mysql_create_table(thd,tables->db ? tables->db : thd->db,
tables->real_name, &lex->create_info, tables->real_name, &lex->create_info,
lex->create_list, lex->create_list,
lex->key_list,0, 0); // do logging lex->key_list,0,0,0); // do logging
if (!res) if (!res)
send_ok(&thd->net); send_ok(&thd->net);
} }
......
...@@ -70,7 +70,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists) ...@@ -70,7 +70,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
} }
error=mysql_rm_table_part2(thd,tables,if_exists,0); error=mysql_rm_table_part2(thd,tables,if_exists,0);
err: err:
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
...@@ -209,7 +209,6 @@ int quick_rm_table(enum db_type base,const char *db, ...@@ -209,7 +209,6 @@ int quick_rm_table(enum db_type base,const char *db,
PRIMARY keys are prioritized. PRIMARY keys are prioritized.
*/ */
static int sort_keys(KEY *a, KEY *b) static int sort_keys(KEY *a, KEY *b)
{ {
if (a->flags & HA_NOSAME) if (a->flags & HA_NOSAME)
...@@ -251,7 +250,8 @@ static int sort_keys(KEY *a, KEY *b) ...@@ -251,7 +250,8 @@ static int sort_keys(KEY *a, KEY *b)
int mysql_create_table(THD *thd,const char *db, const char *table_name, int mysql_create_table(THD *thd,const char *db, const char *table_name,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,bool tmp_table,bool no_log) List<Key> &keys,bool tmp_table,bool no_log,
uint select_field_count)
{ {
char path[FN_REFLEN]; char path[FN_REFLEN];
const char *key_name; const char *key_name;
...@@ -259,10 +259,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -259,10 +259,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
int error= -1; int error= -1;
uint db_options,field,null_fields,blob_columns; uint db_options,field,null_fields,blob_columns;
ulong pos; ulong pos;
KEY *key_info,*key_info_buffer; KEY *key_info,*key_info_buffer;
KEY_PART_INFO *key_part_info; KEY_PART_INFO *key_part_info;
int auto_increment=0; int auto_increment=0;
handler *file; handler *file;
int field_no,dup_no;
DBUG_ENTER("mysql_create_table"); DBUG_ENTER("mysql_create_table");
/* /*
...@@ -275,6 +276,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -275,6 +276,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
List_iterator<create_field> it(fields),it2(fields); List_iterator<create_field> it(fields),it2(fields);
int select_field_pos=fields.elements - select_field_count;
null_fields=blob_columns=0; null_fields=blob_columns=0;
db_options=create_info->table_options; db_options=create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC) if (create_info->row_type == ROW_TYPE_DYNAMIC)
...@@ -288,10 +290,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -288,10 +290,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
/* Don't pack keys in old tables if the user has requested this */
while ((sql_field=it++)) for(field_no=0; (sql_field=it++) ; field_no++)
{ {
/* Don't pack keys in old tables if the user has requested this */
if ((sql_field->flags & BLOB_FLAG) || if ((sql_field->flags & BLOB_FLAG) ||
sql_field->sql_type == FIELD_TYPE_VAR_STRING && sql_field->sql_type == FIELD_TYPE_VAR_STRING &&
create_info->row_type != ROW_TYPE_FIXED) create_info->row_type != ROW_TYPE_FIXED)
...@@ -300,14 +302,29 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, ...@@ -300,14 +302,29 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
} }
if (!(sql_field->flags & NOT_NULL_FLAG)) if (!(sql_field->flags & NOT_NULL_FLAG))
null_fields++; null_fields++;
while ((dup_field=it2++) != sql_field) for(dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
{ {
if (my_strcasecmp(system_charset_info, if (my_strcasecmp(system_charset_info,
sql_field->field_name, sql_field->field_name,
dup_field->field_name) == 0) dup_field->field_name) == 0)
{ {
my_error(ER_DUP_FIELDNAME,MYF(0),sql_field->field_name); if (field_no<select_field_pos || dup_no>=select_field_pos)
DBUG_RETURN(-1); {
my_error(ER_DUP_FIELDNAME,MYF(0),sql_field->field_name);
DBUG_RETURN(-1);
}
else
{
sql_field->length=dup_field->length;
sql_field->decimals=dup_field->decimals;
sql_field->flags=dup_field->flags;
sql_field->pack_length=dup_field->pack_length;
sql_field->unireg_check=dup_field->unireg_check;
sql_field->sql_type=dup_field->sql_type;
it2.remove();
select_field_pos--;
break;
}
} }
} }
it2.rewind(); it2.rewind();
...@@ -793,6 +810,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, ...@@ -793,6 +810,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
TABLE tmp_table; // Used during 'create_field()' TABLE tmp_table; // Used during 'create_field()'
TABLE *table; TABLE *table;
tmp_table.table_name=0; tmp_table.table_name=0;
uint select_field_count=0;
DBUG_ENTER("create_table_from_items"); DBUG_ENTER("create_table_from_items");
/* Add selected items to field list */ /* Add selected items to field list */
...@@ -826,11 +844,12 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, ...@@ -826,11 +844,12 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
(Field*) 0)))) (Field*) 0))))
DBUG_RETURN(0); DBUG_RETURN(0);
extra_fields->push_back(cr_field); extra_fields->push_back(cr_field);
select_field_count++;
} }
/* create and lock table */ /* create and lock table */
/* QQ: This should be done atomic ! */ /* QQ: This should be done atomic ! */
if (mysql_create_table(thd,db,name,create_info,*extra_fields, if (mysql_create_table(thd,db,name,create_info,*extra_fields,
*keys,0,1)) // no logging *keys,0,1,select_field_count)) // no logging
DBUG_RETURN(0); DBUG_RETURN(0);
if (!(table=open_table(thd,db,name,name,(bool*) 0))) if (!(table=open_table(thd,db,name,name,(bool*) 0)))
{ {
...@@ -1719,7 +1738,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1719,7 +1738,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if ((error=mysql_create_table(thd, new_db, tmp_name, if ((error=mysql_create_table(thd, new_db, tmp_name,
create_info, create_info,
create_list,key_list,1,1))) // no logging create_list,key_list,1,1,0))) // no logging
DBUG_RETURN(error); DBUG_RETURN(error);
if (table->tmp_table) if (table->tmp_table)
......
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