Commit 2ed3a338 authored by unknown's avatar unknown

CREATE ... SELECT extension (WL 317)


BitKeeper/etc/logging_ok:
  Logging to logging@openlogging.org accepted
parent d4e5d2dd
......@@ -70,3 +70,4 @@ zak@linux.local
venu@myvenu.com
walrus@mysql.com
ram@ram.(none)
WAX@sergbook.mysql.com
......@@ -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.
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
example:
the right side of the table, not overlapped onto it.
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
mysql> SELECT * FROM foo;
......@@ -35464,6 +35466,18 @@ mysql> SELECT * FROM bar;
| NULL | 1 |
+------+---+
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
For each row in table @code{foo}, a row is inserted in @code{bar} with
......@@ -94,6 +94,24 @@ d date 0000-00-00
t time 00:00:00
dt datetime 0000-00-00 00:00:00
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));
show create table t1;
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)
describe 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
#
......
......@@ -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,
HA_CREATE_INFO *create_info,
List<create_field> &fields, List<Key> &keys,
bool tmp_table, bool no_log);
// no_log is needed for the case of CREATE TABLE ... SELECT , as the logging
// will be done later in sql_insert.cc
bool tmp_table, bool no_log, uint select_field_count);
/*
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,
const char *db, const char *name,
......
......@@ -1598,7 +1598,7 @@ mysql_execute_command(void)
res = mysql_create_table(thd,tables->db ? tables->db : thd->db,
tables->real_name, &lex->create_info,
lex->create_list,
lex->key_list,0, 0); // do logging
lex->key_list,0,0,0); // do logging
if (!res)
send_ok(&thd->net);
}
......
......@@ -209,7 +209,6 @@ int quick_rm_table(enum db_type base,const char *db,
PRIMARY keys are prioritized.
*/
static int sort_keys(KEY *a, KEY *b)
{
if (a->flags & HA_NOSAME)
......@@ -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,
HA_CREATE_INFO *create_info,
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];
const char *key_name;
......@@ -263,6 +263,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
KEY_PART_INFO *key_part_info;
int auto_increment=0;
handler *file;
int field_no,dup_no;
DBUG_ENTER("mysql_create_table");
/*
......@@ -275,6 +276,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_RETURN(-1);
}
List_iterator<create_field> it(fields),it2(fields);
int select_field_pos=fields.elements - select_field_count;
null_fields=blob_columns=0;
db_options=create_info->table_options;
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,
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) ||
sql_field->sql_type == FIELD_TYPE_VAR_STRING &&
create_info->row_type != ROW_TYPE_FIXED)
......@@ -300,15 +302,30 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
if (!(sql_field->flags & NOT_NULL_FLAG))
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,
sql_field->field_name,
dup_field->field_name) == 0)
{
if (field_no<select_field_pos || dup_no>=select_field_pos)
{
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();
}
......@@ -793,6 +810,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
TABLE tmp_table; // Used during 'create_field()'
TABLE *table;
tmp_table.table_name=0;
uint select_field_count=0;
DBUG_ENTER("create_table_from_items");
/* Add selected items to field list */
......@@ -826,11 +844,12 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
(Field*) 0))))
DBUG_RETURN(0);
extra_fields->push_back(cr_field);
select_field_count++;
}
/* create and lock table */
/* QQ: This should be done atomic ! */
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);
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,
if ((error=mysql_create_table(thd, new_db, tmp_name,
create_info,
create_list,key_list,1,1))) // no logging
create_list,key_list,1,1,0))) // no logging
DBUG_RETURN(error);
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