summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <Sinisa@sinisa.nasamreza.org>2002-12-28 21:37:16 +0200
committerunknown <Sinisa@sinisa.nasamreza.org>2002-12-28 21:37:16 +0200
commit13587ca070a75fa10882f03ae4a46a89b2374355 (patch)
treeed559bd5ebeb72916bcfa5ce7fdd4634dfa7002b /sql
parent84a9a9fe5bc7583905672c0b94011cfa1606b08d (diff)
parenta3fecf4ad407ceb34c428e1f7fe36663d5ffbd6a (diff)
downloadmariadb-git-13587ca070a75fa10882f03ae4a46a89b2374355.tar.gz
Merge sinisa@work.mysql.com:/home/bk/mysql-4.1
into sinisa.nasamreza.org:/mnt/work/mysql-4.1 sql/sql_parse.cc: Auto merged sql/sql_yacc.yy: Auto merged
Diffstat (limited to 'sql')
-rw-r--r--sql/mysql_priv.h3
-rw-r--r--sql/sql_parse.cc12
-rw-r--r--sql/sql_table.cc119
-rw-r--r--sql/sql_yacc.yy9
4 files changed, 138 insertions, 5 deletions
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index cf0cefd76da..1b0608e5f79 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -422,6 +422,9 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
bool simple_alter=0);
+int mysql_create_like_table(THD *thd, TABLE_LIST *table,
+ HA_CREATE_INFO *create_info,
+ Table_ident *src_table);
bool mysql_rename_table(enum db_type base,
const char *old_db,
const char * old_name,
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 6d57ee21f3a..c7c378b3339 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1830,10 +1830,14 @@ mysql_execute_command(THD *thd)
}
else // regular create
{
- 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,0); // do logging
+ if (lex->name)
+ res= mysql_create_like_table(thd, tables, &lex->create_info,
+ (Table_ident *)lex->name);
+ else
+ 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,0); // do logging
if (!res)
send_ok(thd);
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 1ab84531e40..7cb1cee7e3c 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1376,6 +1376,125 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
}
+/*
+ Create a table identical to the specified table
+
+ SYNOPSIS
+ mysql_create_like_table()
+ thd Thread object
+ table Table list (one table only)
+ create_info Create info
+ table_ident Src table_ident
+
+ RETURN VALUES
+ 0 ok
+ -1 error
+*/
+
+int mysql_create_like_table(THD* thd, TABLE_LIST* table,
+ HA_CREATE_INFO *create_info,
+ Table_ident *table_ident)
+{
+ TABLE **tmp_table;
+ char src_path[FN_REFLEN], dst_path[FN_REFLEN];
+ char *db= table->db;
+ char *table_name= table->real_name;
+ char *src_db= thd->db;
+ char *src_table= table_ident->table.str;
+ int err;
+
+ DBUG_ENTER("mysql_create_like_table");
+
+ /*
+ Validate the source table
+ */
+ if (table_ident->table.length > NAME_LEN ||
+ (table_ident->table.length &&
+ check_table_name(src_table,table_ident->table.length)) ||
+ table_ident->db.str && check_db_name((src_db= table_ident->db.str)))
+ {
+ net_printf(thd,ER_WRONG_TABLE_NAME,src_table);
+ DBUG_RETURN(0);
+ }
+
+ if ((tmp_table= find_temporary_table(thd, src_db, src_table)))
+ strxmov(src_path, (*tmp_table)->path, reg_ext, NullS);
+ else
+ {
+ strxmov(src_path, mysql_data_home, "/", src_db, "/", src_table,
+ reg_ext, NullS);
+ if (access(src_path, F_OK))
+ {
+ my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table);
+ DBUG_RETURN(-1);
+ }
+ }
+
+ /*
+ Validate the destination table
+
+ skip the destination table name checking as this is already
+ validated.
+ */
+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
+ {
+ if (find_temporary_table(thd, db, table_name))
+ goto table_exists;
+ sprintf(dst_path,"%s%s%lx_%lx_%x%s",mysql_tmpdir,tmp_file_prefix,
+ current_pid, thd->thread_id, thd->tmp_table++,reg_ext);
+ create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
+ }
+ else
+ {
+ strxmov(dst_path, mysql_data_home, "/", db, "/", table_name,
+ reg_ext, NullS);
+ if (!access(dst_path, F_OK))
+ goto table_exists;
+ }
+
+ /*
+ Create a new table by copying from source table
+ */
+ if (my_copy(src_path, dst_path, MYF(MY_WME)))
+ DBUG_RETURN(-1);
+
+ /*
+ As mysql_truncate don't work on a new table at this stage of
+ creation, instead create the table directly (for both normal
+ and temporary tables).
+ */
+ *fn_ext(dst_path)= 0;
+ err= ha_create_table(dst_path, create_info, 1);
+
+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
+ {
+ if (err || !open_temporary_table(thd, dst_path, db, table_name, 1))
+ {
+ (void) rm_temporary_table(create_info->db_type, dst_path);
+ DBUG_RETURN(-1);
+ }
+ }
+ else if (err)
+ {
+ (void) quick_rm_table(create_info->db_type, db, table_name);
+ DBUG_RETURN(-1);
+ }
+ DBUG_RETURN(0);
+
+table_exists:
+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
+ {
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+ sprintf(warn_buff,ER(ER_TABLE_EXISTS_ERROR),table_name);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TABLE_EXISTS_ERROR,warn_buff);
+ DBUG_RETURN(0);
+ }
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
+ DBUG_RETURN(-1);
+}
+
+
int mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
#ifdef OS2
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index d64d69b7c2f..5feeb006299 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -835,6 +835,7 @@ create:
lex->create_info.options=$2 | $4;
lex->create_info.db_type= (enum db_type) lex->thd->variables.table_type;
lex->create_info.table_charset=thd->db_charset?thd->db_charset:default_charset_info;
+ lex->name=0;
}
create2
{}
@@ -883,7 +884,13 @@ create:
create2:
'(' field_list ')' opt_create_table_options create3 {}
| opt_create_table_options create3 {}
- ;
+ | LIKE table_ident
+ {
+ LEX *lex=Lex;
+ if (!(lex->name= (char *)$2))
+ YYABORT;
+ }
+ ;
create3:
/* empty */ {}