diff options
author | unknown <Sinisa@sinisa.nasamreza.org> | 2002-12-28 21:37:16 +0200 |
---|---|---|
committer | unknown <Sinisa@sinisa.nasamreza.org> | 2002-12-28 21:37:16 +0200 |
commit | 13587ca070a75fa10882f03ae4a46a89b2374355 (patch) | |
tree | ed559bd5ebeb72916bcfa5ce7fdd4634dfa7002b /sql | |
parent | 84a9a9fe5bc7583905672c0b94011cfa1606b08d (diff) | |
parent | a3fecf4ad407ceb34c428e1f7fe36663d5ffbd6a (diff) | |
download | mariadb-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.h | 3 | ||||
-rw-r--r-- | sql/sql_parse.cc | 12 | ||||
-rw-r--r-- | sql/sql_table.cc | 119 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 9 |
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 */ {} |