Below is the list of changes that have just been committed into a local
5.0 repository of andrey. When andrey does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2006-11-16 13:31:35+01:00, andrey@stripped +3 -0
Merge example.com:/work/bug24219/my41
into example.com:/work/bug24219/my50
MERGE: 1.1616.2697.89
mysql-test/r/alter_table.result@stripped, 2006-11-16 13:31:32+01:00, andrey@stripped +21
-21
manual merge
MERGE: 1.40.1.10
mysql-test/t/alter_table.test@stripped, 2006-11-16 13:31:32+01:00, andrey@stripped +21
-20
manual merge
MERGE: 1.29.1.11
sql/sql_table.cc@stripped, 2006-11-16 13:30:55+01:00, andrey@stripped +718 -1185
manual-merge
MERGE: 1.157.2.153
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: andrey
# Host: example.com
# Root: /work/bug24219/my50/RESYNC
--- 1.324/sql/sql_table.cc 2006-11-16 13:31:47 +01:00
+++ 1.325/sql/sql_table.cc 2006-11-16 13:31:47 +01:00
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
/* drop and alter of tables */
#include "mysql_priv.h"
@@ -23,8 +24,6 @@
#include <hash.h>
#include <myisam.h>
#include <my_dir.h>
-#include "sp_head.h"
-#include "sql_trigger.h"
#ifdef __WIN__
#include <io.h>
@@ -35,12 +34,11 @@ const char *primary_key_name="PRIMARY";
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
static int copy_data_between_tables(TABLE *from,TABLE *to,
- List<create_field> &create, bool ignore,
+ List<create_field> &create,
+ enum enum_duplicates handle_duplicates,
+ bool ignore,
uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted);
-static bool prepare_blob_field(THD *thd, create_field *sql_field);
-static bool check_engine(THD *thd, const char *table_name,
- enum db_type *new_engine);
/*
@@ -88,41 +86,41 @@ static uint build_table_path(char *buff,
Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set.
RETURN
- FALSE OK. In this case ok packet is sent to user
- TRUE Error
+ 0 ok. In this case ok packet is sent to user
+ -1 Error (Error message given but not sent to user)
*/
-bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
- my_bool drop_temporary)
+int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
+ my_bool drop_temporary)
{
- bool error= FALSE, need_start_waiters= FALSE;
+ int error= 0;
DBUG_ENTER("mysql_rm_table");
/* mark for close and remove all cached entries */
- if (!drop_temporary)
- {
- if ((error= wait_if_global_read_lock(thd, 0, 1)))
- {
- my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name);
- DBUG_RETURN(TRUE);
- }
- else
- need_start_waiters= TRUE;
- }
-
- /*
- Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
- LOCK_open during wait_if_global_read_lock(), other threads could not
- close their tables. This would make a pretty deadlock.
- */
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
VOID(pthread_mutex_lock(&LOCK_open));
- error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
+ if (!drop_temporary && global_read_lock)
+ {
+ if (thd->global_read_lock)
+ {
+ my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0),
+ tables->real_name);
+ error= 1;
+ goto err;
+ }
+ while (global_read_lock && ! thd->killed)
+ {
+ (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+ }
+ }
+ error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary, 0);
+
+ err:
pthread_mutex_unlock(&LOCK_open);
pthread_mutex_lock(&thd->mysys_var->mutex);
@@ -130,13 +128,10 @@ bool mysql_rm_table(THD *thd,TABLE_LIST
thd->mysys_var->current_cond= 0;
pthread_mutex_unlock(&thd->mysys_var->mutex);
- if (need_start_waiters)
- start_waiting_global_read_lock(thd);
-
if (error)
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(-1);
send_ok(thd);
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(0);
}
@@ -144,12 +139,11 @@ bool mysql_rm_table(THD *thd,TABLE_LIST
delete (drop) tables.
SYNOPSIS
- mysql_rm_table_part2_with_lock()
- thd Thread handle
- tables List of tables to delete
- if_exists If 1, don't give error if one table doesn't exists
- dont_log_query Don't write query to log files. This will also not
- generate warnings if the handler files doesn't exists
+ mysql_rm_table_part2_with_lock()
+ thd Thread handle
+ tables List of tables to delete
+ if_exists If 1, don't give error if one table doesn't exists
+ dont_log_query Don't write query to log files
NOTES
Works like documented in mysql_rm_table(), but don't check
@@ -169,8 +163,8 @@ int mysql_rm_table_part2_with_lock(THD *
thd->mysys_var->current_cond= &COND_refresh;
VOID(pthread_mutex_lock(&LOCK_open));
- error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 1,
- dont_log_query);
+ error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary,
+ dont_log_query);
pthread_mutex_unlock(&LOCK_open);
@@ -192,9 +186,7 @@ int mysql_rm_table_part2_with_lock(THD *
if_exists If set, don't give an error if table doesn't exists.
In this case we give an warning of level 'NOTE'
drop_temporary Only drop temporary tables
- drop_view Allow to delete VIEW .frm
- dont_log_query Don't write query to log files. This will also not
- generate warnings if the handler files doesn't exists
+ dont_log_query Don't log the query
TODO:
When logging to the binary log, we should log
@@ -213,30 +205,23 @@ int mysql_rm_table_part2_with_lock(THD *
*/
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
- bool drop_temporary, bool drop_view,
- bool dont_log_query)
+ bool drop_temporary, bool dont_log_query)
{
TABLE_LIST *table;
char path[FN_REFLEN], *alias;
String wrong_tables;
int error;
bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
-
DBUG_ENTER("mysql_rm_table_part2");
if (!drop_temporary && lock_table_names(thd, tables))
DBUG_RETURN(1);
- /* Don't give warnings for not found errors, as we already generate notes */
- thd->no_warnings_for_error= 1;
-
- for (table= tables; table; table= table->next_local)
+ for (table=tables ; table ; table=table->next)
{
char *db=table->db;
- db_type table_type= DB_TYPE_UNKNOWN;
-
mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, TRUE);
- if (!close_temporary_table(thd, db, table->table_name))
+ if (!close_temporary_table(thd, db, table->real_name))
{
tmp_table_deleted=1;
continue; // removed temporary table
@@ -245,69 +230,55 @@ int mysql_rm_table_part2(THD *thd, TABLE
error=0;
if (!drop_temporary)
{
- abort_locked_tables(thd, db, table->table_name);
- remove_table_from_cache(thd, db, table->table_name,
- RTFC_WAIT_OTHER_THREAD_FLAG |
- RTFC_CHECK_KILLED_FLAG);
- drop_locked_tables(thd, db, table->table_name);
+ abort_locked_tables(thd,db,table->real_name);
+ remove_table_from_cache(thd,db,table->real_name,
+ RTFC_WAIT_OTHER_THREAD_FLAG |
+ RTFC_CHECK_KILLED_FLAG);
+ drop_locked_tables(thd,db,table->real_name);
if (thd->killed)
- {
- thd->no_warnings_for_error= 0;
DBUG_RETURN(-1);
- }
- alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
+ alias= (lower_case_table_names == 2) ? table->alias : table->real_name;
/* remove form file and isam files */
build_table_path(path, sizeof(path), db, alias, reg_ext);
}
if (drop_temporary ||
- (access(path,F_OK) &&
- ha_create_table_from_engine(thd,db,alias)) ||
- (!drop_view &&
- mysql_frm_type(thd, path, &table_type) != FRMTYPE_TABLE))
+ (access(path,F_OK) &&
+ ha_create_table_from_engine(thd, db, alias)))
{
// Table was not found on disk and table can't be created from engine
if (if_exists)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
- table->table_name);
+ table->real_name);
else
error= 1;
}
else
{
char *end;
- if (table_type == DB_TYPE_UNKNOWN)
- mysql_frm_type(thd, path, &table_type);
+ db_type table_type= get_table_type(path);
*(end=fn_ext(path))=0; // Remove extension for delete
- error= ha_delete_table(thd, table_type, path, table->table_name,
- !dont_log_query);
- if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
- (if_exists || table_type == DB_TYPE_UNKNOWN))
- error= 0;
+ error=ha_delete_table(table_type, path);
+ if (error == ENOENT && if_exists)
+ error = 0;
if (error == HA_ERR_ROW_IS_REFERENCED)
{
/* the table is referenced by a foreign key constraint */
foreign_key_error=1;
}
- if (!error || error == ENOENT || error == HA_ERR_NO_SUCH_TABLE)
+ if (!error || error == ENOENT)
{
- int new_error;
/* Delete the table definition file */
strmov(end,reg_ext);
- if (!(new_error=my_delete(path,MYF(MY_WME))))
- {
+ if (!(error=my_delete(path,MYF(MY_WME))))
some_tables_deleted=1;
- new_error= Table_triggers_list::drop_all_triggers(thd, db,
- table->table_name);
- }
- error|= new_error;
}
}
if (error)
{
if (wrong_tables.length())
wrong_tables.append(',');
- wrong_tables.append(String(table->table_name,system_charset_info));
+ wrong_tables.append(String(table->real_name,system_charset_info));
}
}
thd->tmp_table_used= tmp_table_deleted;
@@ -316,27 +287,32 @@ int mysql_rm_table_part2(THD *thd, TABLE
{
if (!foreign_key_error)
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
- wrong_tables.c_ptr());
+ wrong_tables.c_ptr());
else
- my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
+ my_error(ER_ROW_IS_REFERENCED, MYF(0));
error= 1;
}
if (some_tables_deleted || tmp_table_deleted || !error)
{
query_cache_invalidate3(thd, tables, 0);
- if (!dont_log_query && mysql_bin_log.is_open())
+ if (!dont_log_query)
{
- if (!error)
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
- mysql_bin_log.write(&qinfo);
+ mysql_update_log.write(thd, thd->query,thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ if (!error)
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ tmp_table_deleted && !some_tables_deleted,
+ FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
}
}
if (!drop_temporary)
- unlock_table_names(thd, tables, (TABLE_LIST*) 0);
- thd->no_warnings_for_error= 0;
+ unlock_table_names(thd, tables);
DBUG_RETURN(error);
}
@@ -350,7 +326,7 @@ int quick_rm_table(enum db_type base,con
if (my_delete(path,MYF(0)))
error=1; /* purecov: inspected */
*fn_ext(path)= 0; // Remove reg_ext
- return ha_delete_table(current_thd, base, path, table_name, 0) || error;
+ return ha_delete_table(base,path) || error;
}
/*
@@ -473,171 +449,6 @@ void calculate_interval_lengths(CHARSET_
/*
- Prepare a create_table instance for packing
-
- SYNOPSIS
- prepare_create_field()
- sql_field field to prepare for packing
- blob_columns count for BLOBs
- timestamps count for timestamps
- table_flags table flags
-
- DESCRIPTION
- This function prepares a create_field instance.
- Fields such as pack_flag are valid after this call.
-
- RETURN VALUES
- 0 ok
- 1 Error
-*/
-
-int prepare_create_field(create_field *sql_field,
- uint *blob_columns,
- int *timestamps, int *timestamps_with_niladic,
- uint table_flags)
-{
- DBUG_ENTER("prepare_field");
-
- /*
- This code came from mysql_prepare_table.
- Indent preserved to make patching easier
- */
- DBUG_ASSERT(sql_field->charset);
-
- switch (sql_field->sql_type) {
- case FIELD_TYPE_BLOB:
- case FIELD_TYPE_MEDIUM_BLOB:
- case FIELD_TYPE_TINY_BLOB:
- case FIELD_TYPE_LONG_BLOB:
- sql_field->pack_flag=FIELDFLAG_BLOB |
- pack_length_to_packflag(sql_field->pack_length -
- portable_sizeof_char_ptr);
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- sql_field->length=8; // Unireg field length
- sql_field->unireg_check=Field::BLOB_FIELD;
- (*blob_columns)++;
- break;
- case FIELD_TYPE_GEOMETRY:
-#ifdef HAVE_SPATIAL
- if (!(table_flags & HA_CAN_GEOMETRY))
- {
- my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
- MYF(0), "GEOMETRY");
- DBUG_RETURN(1);
- }
- sql_field->pack_flag=FIELDFLAG_GEOM |
- pack_length_to_packflag(sql_field->pack_length -
- portable_sizeof_char_ptr);
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- sql_field->length=8; // Unireg field length
- sql_field->unireg_check=Field::BLOB_FIELD;
- (*blob_columns)++;
- break;
-#else
- my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
- DBUG_RETURN(1);
-#endif /*HAVE_SPATIAL*/
- case MYSQL_TYPE_VARCHAR:
-#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
- if (table_flags & HA_NO_VARCHAR)
- {
- /* convert VARCHAR to CHAR because handler is not yet up to date */
- sql_field->sql_type= MYSQL_TYPE_VAR_STRING;
- sql_field->pack_length= calc_pack_length(sql_field->sql_type,
- (uint) sql_field->length);
- if ((sql_field->length / sql_field->charset->mbmaxlen) >
- MAX_FIELD_CHARLENGTH)
- {
- my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
- MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
- DBUG_RETURN(1);
- }
- }
-#endif
- /* fall through */
- case FIELD_TYPE_STRING:
- sql_field->pack_flag=0;
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- break;
- case FIELD_TYPE_ENUM:
- sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
- FIELDFLAG_INTERVAL;
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- sql_field->unireg_check=Field::INTERVAL_FIELD;
- check_duplicates_in_interval("ENUM",sql_field->field_name,
- sql_field->interval,
- sql_field->charset);
- break;
- case FIELD_TYPE_SET:
- sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
- FIELDFLAG_BITFIELD;
- if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
- sql_field->unireg_check=Field::BIT_FIELD;
- check_duplicates_in_interval("SET",sql_field->field_name,
- sql_field->interval,
- sql_field->charset);
- break;
- case FIELD_TYPE_DATE: // Rest of string types
- case FIELD_TYPE_NEWDATE:
- case FIELD_TYPE_TIME:
- case FIELD_TYPE_DATETIME:
- case FIELD_TYPE_NULL:
- sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
- break;
- case FIELD_TYPE_BIT:
- /*
- We have sql_field->pack_flag already set here, see mysql_prepare_table().
- */
- break;
- case FIELD_TYPE_NEWDECIMAL:
- sql_field->pack_flag=(FIELDFLAG_NUMBER |
- (sql_field->flags & UNSIGNED_FLAG ? 0 :
- FIELDFLAG_DECIMAL) |
- (sql_field->flags & ZEROFILL_FLAG ?
- FIELDFLAG_ZEROFILL : 0) |
- (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
- break;
- case FIELD_TYPE_TIMESTAMP:
- /* We should replace old TIMESTAMP fields with their newer analogs */
- if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
- {
- if (!*timestamps)
- {
- sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
- (*timestamps_with_niladic)++;
- }
- else
- sql_field->unireg_check= Field::NONE;
- }
- else if (sql_field->unireg_check != Field::NONE)
- (*timestamps_with_niladic)++;
-
- (*timestamps)++;
- /* fall-through */
- default:
- sql_field->pack_flag=(FIELDFLAG_NUMBER |
- (sql_field->flags & UNSIGNED_FLAG ? 0 :
- FIELDFLAG_DECIMAL) |
- (sql_field->flags & ZEROFILL_FLAG ?
- FIELDFLAG_ZEROFILL : 0) |
- f_settype((uint) sql_field->sql_type) |
- (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
- break;
- }
- if (!(sql_field->flags & NOT_NULL_FLAG))
- sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
- if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
- sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
- DBUG_RETURN(0);
-}
-
-/*
Preparation for table creation
SYNOPSIS
@@ -650,43 +461,34 @@ int prepare_create_field(create_field *s
DESCRIPTION
Prepares the table and key structures for table creation.
- NOTES
- sets create_info->varchar if the table has a varchar
-
RETURN VALUES
0 ok
-1 error
*/
-static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
- List<create_field> *fields,
- List<Key> *keys, bool tmp_table,
- uint *db_options,
- handler *file, KEY **key_info_buffer,
- uint *key_count, int select_field_count)
+int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
+ List<create_field> &fields,
+ List<Key> &keys, bool tmp_table, uint &db_options,
+ handler *file, KEY *&key_info_buffer,
+ uint *key_count, int select_field_count)
{
const char *key_name;
create_field *sql_field,*dup_field;
- uint field,null_fields,blob_columns,max_key_length;
+ uint field,null_fields,blob_columns;
ulong record_offset= 0;
KEY *key_info;
KEY_PART_INFO *key_part_info;
int timestamps= 0, timestamps_with_niladic= 0;
int field_no,dup_no;
int select_field_pos,auto_increment=0;
- List_iterator<create_field> it(*fields),it2(*fields);
- uint total_uneven_bit_length= 0;
DBUG_ENTER("mysql_prepare_table");
- select_field_pos= fields->elements - select_field_count;
+ List_iterator<create_field> it(fields),it2(fields);
+ select_field_pos=fields.elements - select_field_count;
null_fields=blob_columns=0;
- create_info->varchar= 0;
- max_key_length= file->max_key_length();
for (field_no=0; (sql_field=it++) ; field_no++)
{
- CHARSET_INFO *save_cs;
-
/*
Initialize length from its original value (number of characters),
which was set in the parser. This is necessary if we're
@@ -704,43 +506,42 @@ static int mysql_prepare_table(THD *thd,
if (create_info->table_charset && sql_field->charset !=
&my_charset_bin)
sql_field->charset= create_info->table_charset;
- save_cs= sql_field->charset;
+ CHARSET_INFO *savecs= sql_field->charset;
if ((sql_field->flags & BINCMP_FLAG) &&
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
MY_CS_BINSORT,MYF(0))))
{
char tmp[64];
- strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
- STRING_WITH_LEN("_bin"));
+ strmake(strmake(tmp, savecs->csname, sizeof(tmp)-4), "_bin", 4);
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
DBUG_RETURN(-1);
}
/*
- Convert the default value from client character
+ Convert the default value character
set into the column character set if necessary.
*/
if (sql_field->def &&
- save_cs != sql_field->def->collation.collation &&
+ savecs != sql_field->def->collation.collation &&
(sql_field->sql_type == FIELD_TYPE_VAR_STRING ||
sql_field->sql_type == FIELD_TYPE_STRING ||
sql_field->sql_type == FIELD_TYPE_SET ||
sql_field->sql_type == FIELD_TYPE_ENUM))
{
- Query_arena backup_arena;
- bool need_to_change_arena= !thd->stmt_arena->is_conventional();
+ Item_arena backup_arena;
+ bool need_to_change_arena=
+ !thd->current_arena->is_conventional_execution();
if (need_to_change_arena)
{
- /* Asser that we don't do that at every PS execute */
- DBUG_ASSERT(thd->stmt_arena->is_first_stmt_execute() ||
- thd->stmt_arena->is_first_sp_execute());
- thd->set_n_backup_active_arena(thd->stmt_arena, &backup_arena);
+ /* Assert that we don't do that at every PS execute */
+ DBUG_ASSERT(thd->current_arena->is_first_stmt_execute());
+ thd->set_n_backup_item_arena(thd->current_arena, &backup_arena);
}
- sql_field->def= sql_field->def->safe_charset_converter(save_cs);
+ sql_field->def= sql_field->def->safe_charset_converter(savecs);
if (need_to_change_arena)
- thd->restore_active_arena(thd->stmt_arena, &backup_arena);
+ thd->restore_backup_item_arena(thd->current_arena, &backup_arena);
if (sql_field->def == NULL)
{
@@ -768,7 +569,7 @@ static int mysql_prepare_table(THD *thd,
Create the typelib in prepared statement memory if we're
executing one.
*/
- MEM_ROOT *stmt_root= thd->stmt_arena->mem_root;
+ MEM_ROOT *stmt_root= thd->current_arena->mem_root;
interval= sql_field->interval= typelib(stmt_root,
sql_field->interval_list);
@@ -781,20 +582,21 @@ static int mysql_prepare_table(THD *thd,
DBUG_ASSERT(comma_length > 0);
for (uint i= 0; (tmp= it++); i++)
{
- uint lengthsp;
if (String::needs_conversion(tmp->length(), tmp->charset(),
cs, &dummy))
{
uint cnv_errs;
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs,
&cnv_errs);
- interval->type_names[i]= strmake_root(stmt_root, conv.ptr(),
- conv.length());
+ char *buf= (char*) alloc_root(stmt_root, conv.length()+1);
+ memcpy(buf, conv.ptr(), conv.length());
+ buf[conv.length()]= '\0';
+ interval->type_names[i]= buf;
interval->type_lengths[i]= conv.length();
}
// Strip trailing spaces.
- lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
- interval->type_lengths[i]);
+ uint lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
+ interval->type_lengths[i]);
interval->type_lengths[i]= lengthsp;
((uchar *)interval->type_names[i])[lengthsp]= '\0';
if (sql_field->sql_type == FIELD_TYPE_SET)
@@ -803,7 +605,9 @@ static int mysql_prepare_table(THD *thd,
interval->type_lengths[i],
comma_buf, comma_length, NULL, 0))
{
- my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", tmp->ptr());
+ my_printf_error(ER_UNKNOWN_ERROR,
+ "Illegal %s '%-.64s' value found during parsing",
+ MYF(0), "set", tmp->ptr());
DBUG_RETURN(-1);
}
}
@@ -813,7 +617,6 @@ static int mysql_prepare_table(THD *thd,
if (sql_field->sql_type == FIELD_TYPE_SET)
{
- uint32 field_length;
if (sql_field->def != NULL)
{
char *not_used;
@@ -844,12 +647,11 @@ static int mysql_prepare_table(THD *thd,
DBUG_RETURN(-1);
}
}
- calculate_interval_lengths(cs, interval, &dummy, &field_length);
- sql_field->length= field_length + (interval->count - 1);
+ calculate_interval_lengths(cs, interval, &dummy, &sql_field->length);
+ sql_field->length+= (interval->count - 1);
}
else /* FIELD_TYPE_ENUM */
{
- uint32 field_length;
DBUG_ASSERT(sql_field->sql_type == FIELD_TYPE_ENUM);
if (sql_field->def != NULL)
{
@@ -874,25 +676,20 @@ static int mysql_prepare_table(THD *thd,
}
}
}
- calculate_interval_lengths(cs, interval, &field_length, &dummy);
- sql_field->length= field_length;
+ calculate_interval_lengths(cs, interval, &sql_field->length, &dummy);
}
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
}
- if (sql_field->sql_type == FIELD_TYPE_BIT)
- {
- sql_field->pack_flag= FIELDFLAG_NUMBER;
- if (file->table_flags() & HA_CAN_BIT_FIELD)
- total_uneven_bit_length+= sql_field->length & 7;
- else
- sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
- }
-
sql_field->create_length_to_internal_length();
- if (prepare_blob_field(thd, sql_field))
- DBUG_RETURN(-1);
+ /* 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)
+ {
+ db_options|=HA_OPTION_PACK_RECORD;
+ }
if (!(sql_field->flags & NOT_NULL_FLAG))
null_fields++;
@@ -915,7 +712,7 @@ static int mysql_prepare_table(THD *thd,
*/
if (field_no < select_field_pos || dup_no >= select_field_pos)
{
- my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
+ my_error(ER_DUP_FIELDNAME,MYF(0),sql_field->field_name);
DBUG_RETURN(-1);
}
else
@@ -928,7 +725,6 @@ static int mysql_prepare_table(THD *thd,
create_info->default_table_charset);
sql_field->length= dup_field->char_length;
sql_field->pack_length= dup_field->pack_length;
- sql_field->key_length= dup_field->key_length;
sql_field->create_length_to_internal_length();
sql_field->decimals= dup_field->decimals;
sql_field->unireg_check= dup_field->unireg_check;
@@ -947,29 +743,115 @@ static int mysql_prepare_table(THD *thd,
}
}
}
- /* Don't pack rows in old tables if the user has requested this */
- if ((sql_field->flags & BLOB_FLAG) ||
- sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
- create_info->row_type != ROW_TYPE_FIXED)
- (*db_options)|= HA_OPTION_PACK_RECORD;
it2.rewind();
}
/* record_offset will be increased with 'length-of-null-bits' later */
record_offset= 0;
- null_fields+= total_uneven_bit_length;
it.rewind();
while ((sql_field=it++))
{
- DBUG_ASSERT(sql_field->charset != 0);
+ DBUG_ASSERT(sql_field->charset);
- if (prepare_create_field(sql_field, &blob_columns,
- ×tamps, ×tamps_with_niladic,
- file->table_flags()))
+ switch (sql_field->sql_type) {
+ case FIELD_TYPE_BLOB:
+ case FIELD_TYPE_MEDIUM_BLOB:
+ case FIELD_TYPE_TINY_BLOB:
+ case FIELD_TYPE_LONG_BLOB:
+ sql_field->pack_flag=FIELDFLAG_BLOB |
+ pack_length_to_packflag(sql_field->pack_length -
+ portable_sizeof_char_ptr);
+ if (sql_field->charset->state & MY_CS_BINSORT)
+ sql_field->pack_flag|=FIELDFLAG_BINARY;
+ sql_field->length=8; // Unireg field length
+ sql_field->unireg_check=Field::BLOB_FIELD;
+ blob_columns++;
+ break;
+ case FIELD_TYPE_GEOMETRY:
+#ifdef HAVE_SPATIAL
+ if (!(file->table_flags() & HA_CAN_GEOMETRY))
+ {
+ my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
+ MYF(0), "GEOMETRY");
+ DBUG_RETURN(-1);
+ }
+ sql_field->pack_flag=FIELDFLAG_GEOM |
+ pack_length_to_packflag(sql_field->pack_length -
+ portable_sizeof_char_ptr);
+ if (sql_field->charset->state & MY_CS_BINSORT)
+ sql_field->pack_flag|=FIELDFLAG_BINARY;
+ sql_field->length=8; // Unireg field length
+ sql_field->unireg_check=Field::BLOB_FIELD;
+ blob_columns++;
+ break;
+#else
+ my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0),
+ sym_group_geom.name, sym_group_geom.needed_define);
DBUG_RETURN(-1);
- if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
- create_info->varchar= 1;
+#endif /*HAVE_SPATIAL*/
+ case FIELD_TYPE_VAR_STRING:
+ case FIELD_TYPE_STRING:
+ sql_field->pack_flag=0;
+ if (sql_field->charset->state & MY_CS_BINSORT)
+ sql_field->pack_flag|=FIELDFLAG_BINARY;
+ break;
+ case FIELD_TYPE_ENUM:
+ sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
+ FIELDFLAG_INTERVAL;
+ if (sql_field->charset->state & MY_CS_BINSORT)
+ sql_field->pack_flag|=FIELDFLAG_BINARY;
+ sql_field->unireg_check=Field::INTERVAL_FIELD;
+ check_duplicates_in_interval("ENUM",sql_field->field_name,
+ sql_field->interval,
+ sql_field->charset);
+ break;
+ case FIELD_TYPE_SET:
+ sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
+ FIELDFLAG_BITFIELD;
+ if (sql_field->charset->state & MY_CS_BINSORT)
+ sql_field->pack_flag|=FIELDFLAG_BINARY;
+ sql_field->unireg_check=Field::BIT_FIELD;
+ check_duplicates_in_interval("SET",sql_field->field_name,
+ sql_field->interval,
+ sql_field->charset);
+ break;
+ case FIELD_TYPE_DATE: // Rest of string types
+ case FIELD_TYPE_NEWDATE:
+ case FIELD_TYPE_TIME:
+ case FIELD_TYPE_DATETIME:
+ case FIELD_TYPE_NULL:
+ sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
+ break;
+ case FIELD_TYPE_TIMESTAMP:
+ /* We should replace old TIMESTAMP fields with their newer analogs */
+ if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
+ {
+ if (!timestamps)
+ {
+ sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
+ timestamps_with_niladic++;
+ }
+ else
+ sql_field->unireg_check= Field::NONE;
+ }
+ else if (sql_field->unireg_check != Field::NONE)
+ timestamps_with_niladic++;
+
+ timestamps++;
+ /* fall-through */
+ default:
+ sql_field->pack_flag=(FIELDFLAG_NUMBER |
+ (sql_field->flags & UNSIGNED_FLAG ? 0 :
+ FIELDFLAG_DECIMAL) |
+ (sql_field->flags & ZEROFILL_FLAG ?
+ FIELDFLAG_ZEROFILL : 0) |
+ f_settype((uint) sql_field->sql_type) |
+ (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
+ break;
+ }
+ if (!(sql_field->flags & NOT_NULL_FLAG))
+ sql_field->pack_flag|=FIELDFLAG_MAYBE_NULL;
sql_field->offset= record_offset;
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
auto_increment++;
@@ -977,33 +859,30 @@ static int mysql_prepare_table(THD *thd,
}
if (timestamps_with_niladic > 1)
{
- my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
- ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
+ my_error(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,MYF(0));
DBUG_RETURN(-1);
}
if (auto_increment > 1)
{
- my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
+ my_error(ER_WRONG_AUTO_KEY,MYF(0));
DBUG_RETURN(-1);
}
if (auto_increment &&
(file->table_flags() & HA_NO_AUTO_INCREMENT))
{
- my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
- ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
+ my_error(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,MYF(0));
DBUG_RETURN(-1);
}
if (blob_columns && (file->table_flags() & HA_NO_BLOBS))
{
- my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
- MYF(0));
+ my_error(ER_TABLE_CANT_HANDLE_BLOB,MYF(0));
DBUG_RETURN(-1);
}
/* Create keys */
- List_iterator<Key> key_iterator(*keys), key_iterator2(*keys);
+ List_iterator<Key> key_iterator(keys), key_iterator2(keys);
uint key_parts=0, fk_key_count=0;
bool primary_key=0,unique_key=0;
Key *key, *key2;
@@ -1023,9 +902,9 @@ static int mysql_prepare_table(THD *thd,
if (fk_key->ref_columns.elements &&
fk_key->ref_columns.elements != fk_key->columns.elements)
{
- my_error(ER_WRONG_FK_DEF, MYF(0),
- (fk_key->name ? fk_key->name : "foreign key without name"),
- ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
+ my_error(ER_WRONG_FK_DEF, MYF(0), fk_key->name ? fk_key->name :
+ "foreign key without name",
+ ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
DBUG_RETURN(-1);
}
continue;
@@ -1090,9 +969,9 @@ static int mysql_prepare_table(THD *thd,
DBUG_RETURN(-1);
}
- (*key_info_buffer) = key_info= (KEY*) sql_calloc(sizeof(KEY)* *key_count);
+ key_info_buffer=key_info=(KEY*) sql_calloc(sizeof(KEY)* *key_count);
key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
- if (!*key_info_buffer || ! key_part_info)
+ if (!key_info_buffer || ! key_part_info)
DBUG_RETURN(-1); // Out of memory
key_iterator.rewind();
@@ -1124,8 +1003,8 @@ static int mysql_prepare_table(THD *thd,
key_info->flags= HA_SPATIAL;
break;
#else
- my_error(ER_FEATURE_DISABLED, MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
+ my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0),
+ sym_group_geom.name, sym_group_geom.needed_define);
DBUG_RETURN(-1);
#endif
case Key::FOREIGN_KEY:
@@ -1147,8 +1026,7 @@ static int mysql_prepare_table(THD *thd,
{
if (!(file->table_flags() & HA_CAN_FULLTEXT))
{
- my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
- MYF(0));
+ my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
DBUG_RETURN(-1);
}
}
@@ -1163,15 +1041,10 @@ static int mysql_prepare_table(THD *thd,
/* TODO: Add proper checks if handler supports key_type and algorithm */
if (key_info->flags & HA_SPATIAL)
{
- if (!(file->table_flags() & HA_CAN_RTREEKEYS))
- {
- my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
- MYF(0));
- DBUG_RETURN(-1);
- }
if (key_info->key_parts != 1)
{
- my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
+ my_printf_error(ER_WRONG_ARGUMENTS,
+ ER(ER_WRONG_ARGUMENTS),MYF(0),"SPATIAL INDEX");
DBUG_RETURN(-1);
}
}
@@ -1180,15 +1053,17 @@ static int mysql_prepare_table(THD *thd,
#ifdef HAVE_RTREE_KEYS
if ((key_info->key_parts & 1) == 1)
{
- my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
+ my_printf_error(ER_WRONG_ARGUMENTS,
+ ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX");
DBUG_RETURN(-1);
}
/* TODO: To be deleted */
- my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
+ my_printf_error(ER_NOT_SUPPORTED_YET, ER(ER_NOT_SUPPORTED_YET),
+ MYF(0), "RTREE INDEX");
DBUG_RETURN(-1);
#else
- my_error(ER_FEATURE_DISABLED, MYF(0),
- sym_group_rtree.name, sym_group_rtree.needed_define);
+ my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0),
+ sym_group_rtree.name, sym_group_rtree.needed_define);
DBUG_RETURN(-1);
#endif
}
@@ -1197,7 +1072,6 @@ static int mysql_prepare_table(THD *thd,
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
{
- uint length;
key_part_spec *dup_column;
it.rewind();
@@ -1209,7 +1083,9 @@ static int mysql_prepare_table(THD *thd,
field++;
if (!sql_field)
{
- my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
+ my_printf_error(ER_KEY_COLUMN_DOES_NOT_EXITS,
+ ER(ER_KEY_COLUMN_DOES_NOT_EXITS),MYF(0),
+ column->field_name);
DBUG_RETURN(-1);
}
while ((dup_column= cols2++) != column)
@@ -1226,14 +1102,15 @@ static int mysql_prepare_table(THD *thd,
cols2.rewind();
if (key->type == Key::FULLTEXT)
{
- if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
- sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
+ if ((sql_field->sql_type != FIELD_TYPE_STRING &&
+ sql_field->sql_type != FIELD_TYPE_VAR_STRING &&
!f_is_blob(sql_field->pack_flag)) ||
sql_field->charset == &my_charset_bin ||
sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
(ft_key_charset && sql_field->charset != ft_key_charset))
{
- my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
+ my_printf_error(ER_BAD_FT_COLUMN,ER(ER_BAD_FT_COLUMN),MYF(0),
+ column->field_name);
DBUG_RETURN(-1);
}
ft_key_charset=sql_field->charset;
@@ -1250,33 +1127,32 @@ static int mysql_prepare_table(THD *thd,
{
column->length*= sql_field->charset->mbmaxlen;
- if (f_is_blob(sql_field->pack_flag) ||
- (f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
+ if (f_is_blob(sql_field->pack_flag))
{
if (!(file->table_flags() & HA_CAN_INDEX_BLOBS))
{
- my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
+ my_printf_error(ER_BLOB_USED_AS_KEY,ER(ER_BLOB_USED_AS_KEY),MYF(0),
+ column->field_name);
DBUG_RETURN(-1);
}
- if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
- Field::GEOM_POINT)
- column->length= 21;
if (!column->length)
{
- my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
+ my_printf_error(ER_BLOB_KEY_WITHOUT_LENGTH,
+ ER(ER_BLOB_KEY_WITHOUT_LENGTH),MYF(0),
+ column->field_name);
DBUG_RETURN(-1);
}
}
#ifdef HAVE_SPATIAL
- if (key->type == Key::SPATIAL)
+ if (key->type == Key::SPATIAL)
{
- if (!column->length)
+ if (!column->length )
{
/*
- 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
- Lately we'll extend this code to support more dimensions
+ BAR: 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
+ Lately we'll extend this code to support more dimensions
*/
- column->length= 4*sizeof(double);
+ column->length=4*sizeof(double);
}
}
#endif
@@ -1293,13 +1169,13 @@ static int mysql_prepare_table(THD *thd,
key_info->flags|= HA_NULL_PART_KEY;
if (!(file->table_flags() & HA_NULL_IN_KEY))
{
- my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
+ my_printf_error(ER_NULL_COLUMN_IN_INDEX,ER(ER_NULL_COLUMN_IN_INDEX),
+ MYF(0),column->field_name);
DBUG_RETURN(-1);
}
if (key->type == Key::SPATIAL)
{
- my_message(ER_SPATIAL_CANT_HAVE_NULL,
- ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
+ my_error(ER_SPATIAL_CANT_HAVE_NULL, MYF(0));
DBUG_RETURN(-1);
}
}
@@ -1313,16 +1189,15 @@ static int mysql_prepare_table(THD *thd,
key_part_info->fieldnr= field;
key_part_info->offset= (uint16) sql_field->offset;
key_part_info->key_type=sql_field->pack_flag;
- length= sql_field->key_length;
-
+ uint length=sql_field->pack_length;
if (column->length)
{
if (f_is_blob(sql_field->pack_flag))
{
- if ((length=column->length) > max_key_length ||
+ if ((length=column->length) > file->max_key_length() ||
length > file->max_key_part_length())
{
- length=min(max_key_length, file->max_key_part_length());
+ length=min(file->max_key_length(), file->max_key_part_length());
if (key->type == Key::MULTIPLE)
{
/* not a critical problem */
@@ -1346,7 +1221,7 @@ static int mysql_prepare_table(THD *thd,
(key_info->flags & HA_NOSAME))) &&
column->length != length)))
{
- my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
+ my_error(ER_WRONG_SUB_KEY,MYF(0));
DBUG_RETURN(-1);
}
else if (!(file->table_flags() & HA_NO_PREFIX_CHAR_KEYS))
@@ -1354,14 +1229,13 @@ static int mysql_prepare_table(THD *thd,
}
else if (length == 0)
{
- my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
+ my_printf_error(ER_WRONG_KEY_COLUMN, ER(ER_WRONG_KEY_COLUMN), MYF(0),
+ column->field_name);
DBUG_RETURN(-1);
}
- if (length > file->max_key_part_length() && key->type !=
Key::FULLTEXT)
+ if (length > file->max_key_part_length())
{
- length= file->max_key_part_length();
- /* Align key length to multibyte char boundary */
- length-= length % sql_field->charset->mbmaxlen;
+ length=file->max_key_part_length();
if (key->type == Key::MULTIPLE)
{
/* not a critical problem */
@@ -1379,15 +1253,14 @@ static int mysql_prepare_table(THD *thd,
}
key_part_info->length=(uint16) length;
/* Use packed keys for long strings on the first column */
- if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
+ if (!(db_options & HA_OPTION_NO_PACK_KEYS) &&
(length >= KEY_DEFAULT_PACK_LENGTH &&
- (sql_field->sql_type == MYSQL_TYPE_STRING ||
- sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
+ (sql_field->sql_type == FIELD_TYPE_STRING ||
+ sql_field->sql_type == FIELD_TYPE_VAR_STRING ||
sql_field->pack_flag & FIELDFLAG_BLOB)))
{
- if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB) ||
- sql_field->sql_type == MYSQL_TYPE_VARCHAR)
- key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
+ if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB))
+ key_info->flags|= HA_BINARY_PACK_KEY;
else
key_info->flags|= HA_PACK_KEY;
}
@@ -1401,8 +1274,7 @@ static int mysql_prepare_table(THD *thd,
{
if (primary_key)
{
- my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
- MYF(0));
+ my_error(ER_MULTIPLE_PRI_KEY,MYF(0));
DBUG_RETURN(-1);
}
key_name=primary_key_name;
@@ -1410,10 +1282,10 @@ static int mysql_prepare_table(THD *thd,
}
else if (!(key_name = key->name))
key_name=make_unique_key_name(sql_field->field_name,
- *key_info_buffer, key_info);
- if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
+ key_info_buffer,key_info);
+ if (check_if_keyname_exists(key_name,key_info_buffer,key_info))
{
- my_error(ER_DUP_KEYNAME, MYF(0), key_name);
+ my_error(ER_DUP_KEYNAME,MYF(0),key_name);
DBUG_RETURN(-1);
}
key_info->name=(char*) key_name;
@@ -1427,6 +1299,7 @@ static int mysql_prepare_table(THD *thd,
if (!(key_info->flags & HA_NULL_PART_KEY))
unique_key=1;
key_info->key_length=(uint16) key_length;
+ uint max_key_length= file->max_key_length();
if (key_length > max_key_length && key->type != Key::FULLTEXT)
{
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
@@ -1437,16 +1310,16 @@ static int mysql_prepare_table(THD *thd,
if (!unique_key && !primary_key &&
(file->table_flags() & HA_REQUIRE_PRIMARY_KEY))
{
- my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
+ my_error(ER_REQUIRES_PRIMARY_KEY,MYF(0));
DBUG_RETURN(-1);
}
if (auto_increment > 0)
{
- my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
+ my_error(ER_WRONG_AUTO_KEY,MYF(0));
DBUG_RETURN(-1);
}
/* Sort keys in optimized order */
- qsort((gptr) *key_info_buffer, *key_count, sizeof(KEY),
+ qsort((gptr) key_info_buffer, *key_count, sizeof(KEY),
(qsort_cmp) sort_keys);
create_info->null_bits= null_fields;
@@ -1455,109 +1328,6 @@ static int mysql_prepare_table(THD *thd,
/*
- Extend long VARCHAR fields to blob & prepare field if it's a blob
-
- SYNOPSIS
- prepare_blob_field()
- sql_field Field to check
-
- RETURN
- 0 ok
- 1 Error (sql_field can't be converted to blob)
- In this case the error is given
-*/
-
-static bool prepare_blob_field(THD *thd, create_field *sql_field)
-{
- DBUG_ENTER("prepare_blob_field");
-
- if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
- !(sql_field->flags & BLOB_FLAG))
- {
- /* Convert long VARCHAR columns to TEXT or BLOB */
- char warn_buff[MYSQL_ERRMSG_SIZE];
-
- if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES
|
- MODE_STRICT_ALL_TABLES)))
- {
- my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
- MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
- DBUG_RETURN(1);
- }
- sql_field->sql_type= FIELD_TYPE_BLOB;
- sql_field->flags|= BLOB_FLAG;
- sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
- (sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
- (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
- warn_buff);
- }
-
- if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
- {
- if (sql_field->sql_type == FIELD_TYPE_BLOB)
- {
- /* The user has given a length to the blob column */
- sql_field->sql_type= get_blob_type_from_length(sql_field->length);
- sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
- }
- sql_field->length= 0;
- }
- DBUG_RETURN(0);
-}
-
-
-/*
- Preparation of create_field for SP function return values.
- Based on code used in the inner loop of mysql_prepare_table() above
-
- SYNOPSIS
- sp_prepare_create_field()
- thd Thread object
- sql_field Field to prepare
-
- DESCRIPTION
- Prepares the field structures for field creation.
-
-*/
-
-void sp_prepare_create_field(THD *thd, create_field *sql_field)
-{
- if (sql_field->sql_type == FIELD_TYPE_SET ||
- sql_field->sql_type == FIELD_TYPE_ENUM)
- {
- uint32 field_length, dummy;
- if (sql_field->sql_type == FIELD_TYPE_SET)
- {
- calculate_interval_lengths(sql_field->charset,
- sql_field->interval, &dummy,
- &field_length);
- sql_field->length= field_length +
- (sql_field->interval->count - 1);
- }
- else /* FIELD_TYPE_ENUM */
- {
- calculate_interval_lengths(sql_field->charset,
- sql_field->interval,
- &field_length, &dummy);
- sql_field->length= field_length;
- }
- set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
- }
-
- if (sql_field->sql_type == FIELD_TYPE_BIT)
- {
- sql_field->pack_flag= FIELDFLAG_NUMBER |
- FIELDFLAG_TREAT_BIT_AS_CHAR;
- }
- sql_field->create_length_to_internal_length();
- DBUG_ASSERT(sql_field->def == 0);
- /* Can't go wrong as sql_field->def is not defined */
- (void) prepare_blob_field(thd, sql_field);
-}
-
-
-/*
Create a table
SYNOPSIS
@@ -1568,11 +1338,11 @@ void sp_prepare_create_field(THD *thd, c
create_info Create information (like MAX_ROWS)
fields List of fields to create
keys List of keys to create
- internal_tmp_table Set to 1 if this is an internal temporary table
+ tmp_table Set to 1 if this is an internal temporary table
(From ALTER TABLE)
DESCRIPTION
- If one creates a temporary table, this is automatically opened
+ If one creates a temporary table, this is automaticly opened
no_log is needed for the case of CREATE ... SELECT,
as the logging will be done later in sql_insert.cc
@@ -1580,38 +1350,46 @@ void sp_prepare_create_field(THD *thd, c
and must be zero for standard create of table.
RETURN VALUES
- FALSE OK
- TRUE error
+ 0 ok
+ -1 error
*/
-bool 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 internal_tmp_table,
- uint select_field_count)
+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,
+ uint select_field_count)
{
char path[FN_REFLEN];
const char *alias;
+ int error= -1;
uint db_options, key_count;
KEY *key_info_buffer;
handler *file;
- bool error= TRUE;
+ enum db_type new_db_type;
DBUG_ENTER("mysql_create_table");
/* Check for duplicate fields and check type of table to create */
if (!fields.elements)
{
- my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
- MYF(0));
- DBUG_RETURN(TRUE);
- }
- if (check_engine(thd, table_name, &create_info->db_type))
- DBUG_RETURN(TRUE);
- db_options= create_info->table_options;
+ my_error(ER_TABLE_MUST_HAVE_COLUMNS,MYF(0));
+ DBUG_RETURN(-1);
+ }
+ if ((new_db_type= ha_checktype(create_info->db_type)) !=
+ create_info->db_type)
+ {
+ create_info->db_type= new_db_type;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_USING_OTHER_HANDLER,
+ ER(ER_WARN_USING_OTHER_HANDLER),
+ ha_get_storage_engine(new_db_type),
+ table_name);
+ }
+ db_options=create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC)
db_options|=HA_OPTION_PACK_RECORD;
alias= table_case_name(create_info, table_name);
- file= get_new_handler((TABLE*) 0, thd->mem_root, create_info->db_type);
+ file=get_new_handler((TABLE*) 0, create_info->db_type);
#ifdef NOT_USED
/*
@@ -1624,8 +1402,8 @@ bool mysql_create_table(THD *thd,const c
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
(file->table_flags() & HA_NO_TEMP_TABLES))
{
- my_error(ER_ILLEGAL_HA, MYF(0), table_name);
- DBUG_RETURN(TRUE);
+ my_error(ER_ILLEGAL_HA,MYF(0),table_name);
+ DBUG_RETURN(-1);
}
#endif
@@ -1637,17 +1415,18 @@ bool mysql_create_table(THD *thd,const c
if (!create_info->default_table_charset)
{
HA_CREATE_INFO db_info;
-
- load_db_opt_by_name(thd, db, &db_info);
-
+ char path[FN_REFLEN];
+ /* Abuse build_table_path() to build the path to the db.opt file */
+ build_table_path(path, sizeof(path), db, MY_DB_OPT_FILE, "");
+ load_db_opt(thd, path, &db_info);
create_info->default_table_charset= db_info.default_table_charset;
}
- if (mysql_prepare_table(thd, create_info, &fields,
- &keys, internal_tmp_table, &db_options, file,
- &key_info_buffer, &key_count,
+ if (mysql_prepare_table(thd, create_info, fields,
+ keys, tmp_table, db_options, file,
+ key_info_buffer, &key_count,
select_field_count))
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(-1);
/* Check if table exists */
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
@@ -1659,23 +1438,8 @@ bool mysql_create_table(THD *thd,const c
my_casedn_str(files_charset_info, path);
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
}
- else
- {
- #ifdef FN_DEVCHAR
- /* check if the table name contains FN_DEVCHAR when defined */
- const char *start= alias;
- while (*start != '\0')
- {
- if (*start == FN_DEVCHAR)
- {
- my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
- DBUG_RETURN(TRUE);
- }
- start++;
- }
- #endif
+ else
build_table_path(path, sizeof(path), db, alias, reg_ext);
- }
/* Check if table already exists */
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE)
@@ -1687,13 +1451,15 @@ bool mysql_create_table(THD *thd,const c
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
alias);
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(0);
}
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(-1);
}
+ if (wait_if_global_read_lock(thd, 0, 1))
+ DBUG_RETURN(error);
VOID(pthread_mutex_lock(&LOCK_open));
- if (!internal_tmp_table && !(create_info->options &
HA_LEX_CREATE_TMP_TABLE))
+ if (!tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
{
if (!access(path,F_OK))
{
@@ -1749,26 +1515,35 @@ bool mysql_create_table(THD *thd,const c
}
thd->tmp_table_used= 1;
}
- if (!internal_tmp_table && mysql_bin_log.is_open())
+ if (!tmp_table)
{
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
- mysql_bin_log.write(&qinfo);
+ // Must be written before unlock
+ mysql_update_log.write(thd,thd->query, thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ test(create_info->options &
+ HA_LEX_CREATE_TMP_TABLE),
+ FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
}
- error= FALSE;
-
-end:
- VOID(pthread_mutex_unlock(&LOCK_open));
- thd->proc_info="After create";
- DBUG_RETURN(error);
+ error=0;
+ goto end;
warn:
- error= FALSE;
+ error= 0;
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
alias);
create_info->table_existed= 1; // Mark that table existed
- goto end;
+
+end:
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ start_waiting_global_read_lock(thd);
+ thd->proc_info="After create";
+ DBUG_RETURN(error);
}
/*
@@ -1811,6 +1586,84 @@ make_unique_key_name(const char *field_n
/****************************************************************************
+** Create table from a list of fields and items
+****************************************************************************/
+
+TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
+ const char *db, const char *name,
+ List<create_field> *extra_fields,
+ List<Key> *keys,
+ List<Item> *items,
+ MYSQL_LOCK **lock)
+{
+ TABLE tmp_table; // Used during 'create_field()'
+ TABLE *table= 0;
+ tmp_table.table_name=0;
+ uint select_field_count= items->elements;
+ DBUG_ENTER("create_table_from_items");
+
+ /* Add selected items to field list */
+ List_iterator_fast<Item> it(*items);
+ Item *item;
+ Field *tmp_field;
+ tmp_table.db_create_options=0;
+ tmp_table.null_row=tmp_table.maybe_null=0;
+ tmp_table.blob_ptr_size=portable_sizeof_char_ptr;
+ tmp_table.db_low_byte_first= test(create_info->db_type == DB_TYPE_MYISAM ||
+ create_info->db_type == DB_TYPE_HEAP);
+
+ while ((item=it++))
+ {
+ create_field *cr_field;
+ Field *field;
+ if (item->type() == Item::FUNC_ITEM)
+ field=item->tmp_table_field(&tmp_table);
+ else
+ field=create_tmp_field(thd, &tmp_table, item, item->type(),
+ (Item ***) 0, &tmp_field, 0, 0, 0, 0);
+ if (!field ||
+ !(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ?
+ ((Item_field *)item)->field :
+ (Field*) 0))))
+ DBUG_RETURN(0);
+ extra_fields->push_back(cr_field);
+ }
+ /* create and lock table */
+ /* QQ: create and open should be done atomic ! */
+ /*
+ We don't log the statement, it will be logged later.
+ If this is a HEAP table, the automatic DELETE FROM which is written to the
+ binlog when a HEAP table is opened for the first time since startup, must
+ not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we
+ don't want to delete from it) 2) it would be written before the CREATE
+ TABLE, which is a wrong order. So we keep binary logging disabled when we
+ open_table().
+ */
+ tmp_disable_binlog(thd);
+ if (!mysql_create_table(thd,db,name,create_info,*extra_fields,
+ *keys,0,select_field_count))
+ {
+ if (!(table=open_table(thd,db,name,name,(bool*) 0)))
+ quick_rm_table(create_info->db_type,db,table_case_name(create_info,name));
+ }
+ reenable_binlog(thd);
+ if (!table)
+ DBUG_RETURN(0);
+ table->reginfo.lock_type=TL_WRITE;
+ if (! ((*lock)= mysql_lock_tables(thd, &table, 1, MYSQL_LOCK_IGNORE_FLUSH)))
+ {
+ VOID(pthread_mutex_lock(&LOCK_open));
+ hash_delete(&open_cache,(byte*) table);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ quick_rm_table(create_info->db_type,db,table_case_name(create_info, name));
+ DBUG_RETURN(0);
+ }
+ table->file->extra(HA_EXTRA_WRITE_CACHE);
+ DBUG_RETURN(table);
+}
+
+
+/****************************************************************************
** Alter a table definition
****************************************************************************/
@@ -1821,12 +1674,10 @@ mysql_rename_table(enum db_type base,
const char *new_db,
const char *new_name)
{
- THD *thd= current_thd;
char from[FN_REFLEN], to[FN_REFLEN], lc_from[FN_REFLEN], lc_to[FN_REFLEN];
char *from_base= from, *to_base= to;
char tmp_name[NAME_LEN+1];
- handler *file= (base == DB_TYPE_UNKNOWN ? 0 :
- get_new_handler((TABLE*) 0, thd->mem_root, base));
+ handler *file=get_new_handler((TABLE*) 0, base);
int error=0;
DBUG_ENTER("mysql_rename_table");
@@ -1838,8 +1689,7 @@ mysql_rename_table(enum db_type base,
file system) and the storage is not HA_FILE_BASED, we need to provide
a lowercase file name, but we leave the .frm in mixed case.
*/
- if (lower_case_table_names == 2 && file &&
- !(file->table_flags() & HA_FILE_BASED))
+ if (lower_case_table_names == 2 && !(file->table_flags() &
HA_FILE_BASED))
{
strmov(tmp_name, old_name);
my_casedn_str(files_charset_info, tmp_name);
@@ -1852,14 +1702,13 @@ mysql_rename_table(enum db_type base,
to_base= lc_to;
}
- if (!file || !(error=file->rename_table(from_base, to_base)))
+ if (!(error=file->rename_table(from_base, to_base)))
{
if (rename_file_ext(from,to,reg_ext))
{
error=my_errno;
/* Restore old file name */
- if (file)
- file->rename_table(to_base, from_base);
+ file->rename_table(to_base, from_base);
}
}
delete file;
@@ -1892,7 +1741,7 @@ mysql_rename_table(enum db_type base,
static void wait_while_table_is_used(THD *thd,TABLE *table,
enum ha_extra_function function)
{
- DBUG_PRINT("enter",("table: %s", table->s->table_name));
+ DBUG_PRINT("enter",("table: %s", table->real_name));
DBUG_ENTER("wait_while_table_is_used");
safe_mutex_assert_owner(&LOCK_open);
@@ -1901,8 +1750,8 @@ static void wait_while_table_is_used(THD
mysql_lock_abort(thd, table); // end threads waiting on lock
/* Wait until all there are no other threads that has this table open */
- remove_table_from_cache(thd, table->s->db,
- table->s->table_name, RTFC_WAIT_OTHER_THREAD_FLAG);
+ remove_table_from_cache(thd,table->table_cache_key,
+ table->real_name, RTFC_WAIT_OTHER_THREAD_FLAG);
DBUG_VOID_RETURN;
}
@@ -1923,7 +1772,7 @@ static void wait_while_table_is_used(THD
Win32 clients must also have a WRITE LOCK on the table !
*/
-void close_cached_table(THD *thd, TABLE *table)
+static bool close_cached_table(THD *thd, TABLE *table)
{
DBUG_ENTER("close_cached_table");
@@ -1938,8 +1787,8 @@ void close_cached_table(THD *thd, TABLE
thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
/* When lock on LOCK_open is freed other threads can continue */
- broadcast_refresh();
- DBUG_VOID_RETURN;
+ pthread_cond_broadcast(&COND_refresh);
+ DBUG_RETURN(0);
}
static int send_check_errmsg(THD *thd, TABLE_LIST* table,
@@ -1950,9 +1799,9 @@ static int send_check_errmsg(THD *thd, T
protocol->prepare_for_resend();
protocol->store(table->alias, system_charset_info);
protocol->store((char*) operator_name, system_charset_info);
- protocol->store(STRING_WITH_LEN("error"), system_charset_info);
+ protocol->store("error", 5, system_charset_info);
protocol->store(errmsg, system_charset_info);
- thd->clear_error();
+ thd->net.last_error[0]=0;
if (protocol->write())
return -1;
return 1;
@@ -1974,8 +1823,8 @@ static int prepare_for_restore(THD* thd,
{
char* backup_dir= thd->lex->backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
- char* table_name= table->table_name;
- char* db= table->db;
+ char* table_name = table->real_name;
+ char* db = thd->db ? thd->db : table->db;
if (fn_format_relative_to_data_home(src_path, table_name, backup_dir,
reg_ext))
@@ -2011,15 +1860,12 @@ static int prepare_for_restore(THD* thd,
Now we should be able to open the partially restored table
to finish the restore in the handler later on
*/
- pthread_mutex_lock(&LOCK_open);
- if (reopen_name_locked_table(thd, table))
+ if (!(table->table = reopen_name_locked_table(thd, table)))
{
+ pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table);
pthread_mutex_unlock(&LOCK_open);
- DBUG_RETURN(send_check_errmsg(thd, table, "restore",
- "Failed to open partially restored table"));
}
- pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(0);
}
@@ -2038,8 +1884,8 @@ static int prepare_for_repair(THD* thd,
{
char name[FN_REFLEN];
build_table_path(name, sizeof(name), table_list->db,
- table_list->table_name, "");
- if (openfrm(thd, name, "", 0, 0, 0, &tmp_table))
+ table_list->real_name, "");
+ if (openfrm(name, "", 0, 0, 0, &tmp_table))
DBUG_RETURN(0); // Can't open frm file
table= &tmp_table;
}
@@ -2065,7 +1911,7 @@ static int prepare_for_repair(THD* thd,
if (!ext[0] || !ext[1])
goto end; // No data file
- strxmov(from, table->s->path, ext[1], NullS); // Name of data file
+ strxmov(from, table->path, ext[1], NullS); // Name of data file
if (!my_stat(from, &stat_info, MYF(0)))
goto end; // Can't use USE_FRM flag
@@ -2116,16 +1962,12 @@ static int prepare_for_repair(THD* thd,
Now we should be able to open the partially repaired table
to finish the repair in the handler later on.
*/
- pthread_mutex_lock(&LOCK_open);
- if (reopen_name_locked_table(thd, table_list))
+ if (!(table_list->table = reopen_name_locked_table(thd, table_list)))
{
+ pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table_list);
pthread_mutex_unlock(&LOCK_open);
- error= send_check_errmsg(thd, table_list, "repair",
- "Failed to open partially repaired table");
- goto end;
}
- pthread_mutex_unlock(&LOCK_open);
end:
if (table == &tmp_table)
@@ -2134,33 +1976,27 @@ end:
}
-
/*
RETURN VALUES
- FALSE Message sent to net (admin operation went ok)
- TRUE Message should be sent by caller
- (admin operation or network communication failed)
-*/
-static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
- HA_CHECK_OPT* check_opt,
- const char *operator_name,
- thr_lock_type lock_type,
- bool open_for_modify,
- bool no_warnings_for_error,
- uint extra_open_options,
- int (*prepare_func)(THD *, TABLE_LIST *,
- HA_CHECK_OPT *),
- int (handler::*operator_func)(THD *,
- HA_CHECK_OPT *),
- int (view_operator_func)(THD *, TABLE_LIST*))
+ 0 Message sent to net (admin operation went ok)
+ -1 Message should be sent by caller
+ (admin operation or network communication failed)
+*/
+static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
+ HA_CHECK_OPT* check_opt,
+ const char *operator_name,
+ thr_lock_type lock_type,
+ bool open_for_modify,
+ uint extra_open_options,
+ int (*prepare_func)(THD *, TABLE_LIST *,
+ HA_CHECK_OPT *),
+ int (handler::*operator_func)
+ (THD *, HA_CHECK_OPT *))
{
- TABLE_LIST *table, *save_next_global, *save_next_local;
- SELECT_LEX *select= &thd->lex->select_lex;
+ TABLE_LIST *table;
List<Item> field_list;
Item *item;
Protocol *protocol= thd->protocol;
- LEX *lex= thd->lex;
- int result_code;
DBUG_ENTER("mysql_admin_table");
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
@@ -2171,42 +2007,22 @@ static bool mysql_admin_table(THD* thd,
item->maybe_null = 1;
field_list.push_back(item = new Item_empty_string("Msg_text", 255));
item->maybe_null = 1;
- if (protocol->send_fields(&field_list,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(TRUE);
+ if (protocol->send_fields(&field_list, 1))
+ DBUG_RETURN(-1);
mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL, FALSE);
- for (table= tables; table; table= table->next_local)
+ for (table = tables; table; table = table->next)
{
char table_name[NAME_LEN*2+2];
char* db = table->db;
bool fatal_error=0;
+ strxmov(table_name, db, ".", table->real_name, NullS);
- strxmov(table_name, db, ".", table->table_name, NullS);
thd->open_options|= extra_open_options;
- table->lock_type= lock_type;
- /* open only one table from local list of command */
- save_next_global= table->next_global;
- table->next_global= 0;
- save_next_local= table->next_local;
- table->next_local= 0;
- select->table_list.first= (byte*)table;
- /*
- Time zone tables and SP tables can be add to lex->query_tables list,
- so it have to be prepared.
- TODO: Investigate if we can put extra tables into argument instead of
- using lex->query_tables
- */
- lex->query_tables= table;
- lex->query_tables_last= &table->next_global;
- lex->query_tables_own_last= 0;
- thd->no_warnings_for_error= no_warnings_for_error;
- if (view_operator_func == NULL)
- table->required_type=FRMTYPE_TABLE;
- open_and_lock_tables(thd, table);
- thd->no_warnings_for_error= 0;
- table->next_global= save_next_global;
- table->next_local= save_next_local;
+ table->table = open_ltable(thd, table, lock_type);
+#ifdef EMBEDDED_LIBRARY
+ thd->net.last_errno= 0; // these errors shouldn't get client
+#endif
thd->open_options&= ~extra_open_options;
if (prepare_func)
@@ -2222,63 +2038,31 @@ static bool mysql_admin_table(THD* thd,
}
}
- /*
- CHECK TABLE command is only command where VIEW allowed here and this
- command use only temporary teble method for VIEWs resolving => there
- can't be VIEW tree substitition of join view => if opening table
- succeed then table->table will have real TABLE pointer as value (in
- case of join view substitution table->table can be 0, but here it is
- impossible)
- */
if (!table->table)
{
- char buf[ERRMSGSIZE+ERRMSGSIZE+2];
const char *err_msg;
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
- protocol->store(STRING_WITH_LEN("error"), system_charset_info);
+ protocol->store("error",5, system_charset_info);
if (!(err_msg=thd->net.last_error))
err_msg=ER(ER_CHECK_NO_SUCH_TABLE);
- /* if it was a view will check md5 sum */
- if (table->view &&
- view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM)
- {
- strxmov(buf, err_msg, "; ", ER(ER_VIEW_CHECKSUM), NullS);
- err_msg= (const char *)buf;
- }
protocol->store(err_msg, system_charset_info);
- lex->cleanup_after_one_table_open();
- thd->clear_error();
- /*
- View opening can be interrupted in the middle of process so some
- tables can be left opening
- */
- close_thread_tables(thd);
- lex->reset_query_tables_list(FALSE);
+ thd->net.last_error[0]=0;
if (protocol->write())
goto err;
continue;
}
-
- if (table->view)
- {
- result_code= (*view_operator_func)(thd, table);
- goto send_result;
- }
-
table->table->pos_in_table_list= table;
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
- uint length;
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
- protocol->store(STRING_WITH_LEN("error"), system_charset_info);
- length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
- table_name);
- protocol->store(buff, length, system_charset_info);
+ protocol->store("error", 5, system_charset_info);
+ my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY), table_name);
+ protocol->store(buff, system_charset_info);
close_thread_tables(thd);
table->table=0; // For query cache
if (protocol->write())
@@ -2287,14 +2071,14 @@ static bool mysql_admin_table(THD* thd,
}
/* Close all instances of the table to allow repair to rename files */
- if (lock_type == TL_WRITE && table->table->s->version)
+ if (lock_type == TL_WRITE && table->table->version)
{
pthread_mutex_lock(&LOCK_open);
const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
"Waiting to get writelock");
mysql_lock_abort(thd,table->table);
- remove_table_from_cache(thd, table->table->s->db,
- table->table->s->table_name,
+ remove_table_from_cache(thd, table->table->table_cache_key,
+ table->table->real_name,
RTFC_WAIT_OTHER_THREAD_FLAG |
RTFC_CHECK_KILLED_FLAG);
thd->exit_cond(old_message);
@@ -2305,39 +2089,10 @@ static bool mysql_admin_table(THD* thd,
open_for_modify= 0;
}
- if (table->table->s->crashed && operator_func ==
&handler::ha_check)
- {
- protocol->prepare_for_resend();
- protocol->store(table_name, system_charset_info);
- protocol->store(operator_name, system_charset_info);
- protocol->store(STRING_WITH_LEN("warning"), system_charset_info);
- protocol->store(STRING_WITH_LEN("Table is marked as crashed"),
- system_charset_info);
- if (protocol->write())
- goto err;
- }
-
- if (operator_func == &handler::ha_repair)
- {
- if ((table->table->file->check_old_types() == HA_ADMIN_NEEDS_ALTER) ||
- (table->table->file->ha_check_for_upgrade(check_opt) ==
- HA_ADMIN_NEEDS_ALTER))
- {
- close_thread_tables(thd);
- tmp_disable_binlog(thd); // binlogging is done by caller if wanted
- result_code= mysql_recreate_table(thd, table, 0);
- reenable_binlog(thd);
- goto send_result;
- }
-
- }
-
- result_code = (table->table->file->*operator_func)(thd, check_opt);
-
-send_result:
-
- lex->cleanup_after_one_table_open();
- thd->clear_error(); // these errors shouldn't get client
+ int result_code = (table->table->file->*operator_func)(thd, check_opt);
+#ifdef EMBEDDED_LIBRARY
+ thd->net.last_errno= 0; // these errors shouldn't get client
+#endif
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
@@ -2351,55 +2106,41 @@ send_result_message:
char buf[ERRMSGSIZE+20];
uint length=my_snprintf(buf, ERRMSGSIZE,
ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
- protocol->store(STRING_WITH_LEN("note"), system_charset_info);
+ protocol->store("note", 4, system_charset_info);
protocol->store(buf, length, system_charset_info);
}
break;
- case HA_ADMIN_NOT_BASE_TABLE:
- {
- char buf[ERRMSGSIZE+20];
- uint length= my_snprintf(buf, ERRMSGSIZE,
- ER(ER_BAD_TABLE_ERROR), table_name);
- protocol->store(STRING_WITH_LEN("note"), system_charset_info);
- protocol->store(buf, length, system_charset_info);
- }
- break;
-
case HA_ADMIN_OK:
- protocol->store(STRING_WITH_LEN("status"), system_charset_info);
- protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
+ protocol->store("status", 6, system_charset_info);
+ protocol->store("OK",2, system_charset_info);
break;
case HA_ADMIN_FAILED:
- protocol->store(STRING_WITH_LEN("status"), system_charset_info);
- protocol->store(STRING_WITH_LEN("Operation failed"),
- system_charset_info);
+ protocol->store("status", 6, system_charset_info);
+ protocol->store("Operation failed",16, system_charset_info);
break;
case HA_ADMIN_REJECT:
- protocol->store(STRING_WITH_LEN("status"), system_charset_info);
- protocol->store(STRING_WITH_LEN("Operation need committed state"),
- system_charset_info);
+ protocol->store("status", 6, system_charset_info);
+ protocol->store("Operation need committed state",30, system_charset_info);
open_for_modify= FALSE;
break;
case HA_ADMIN_ALREADY_DONE:
- protocol->store(STRING_WITH_LEN("status"), system_charset_info);
- protocol->store(STRING_WITH_LEN("Table is already up to date"),
- system_charset_info);
+ protocol->store("status", 6, system_charset_info);
+ protocol->store("Table is already up to date", 27, system_charset_info);
break;
case HA_ADMIN_CORRUPT:
- protocol->store(STRING_WITH_LEN("error"), system_charset_info);
- protocol->store(STRING_WITH_LEN("Corrupt"), system_charset_info);
+ protocol->store("error", 5, system_charset_info);
+ protocol->store("Corrupt", 7, system_charset_info);
fatal_error=1;
break;
case HA_ADMIN_INVALID:
- protocol->store(STRING_WITH_LEN("error"), system_charset_info);
- protocol->store(STRING_WITH_LEN("Invalid argument"),
- system_charset_info);
+ protocol->store("error", 5, system_charset_info);
+ protocol->store("Invalid argument",16, system_charset_info);
break;
case HA_ADMIN_TRY_ALTER:
@@ -2410,9 +2151,8 @@ send_result_message:
reopen the table and do ha_innobase::analyze() on it.
*/
close_thread_tables(thd);
- TABLE_LIST *save_next_local= table->next_local,
- *save_next_global= table->next_global;
- table->next_local= table->next_global= 0;
+ TABLE_LIST *save_next= table->next;
+ table->next= 0;
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
result_code= mysql_recreate_table(thd, table, 0);
reenable_binlog(thd);
@@ -2435,7 +2175,7 @@ send_result_message:
else
{
/* Hijack the row already in-progress. */
- protocol->store(STRING_WITH_LEN("error"), system_charset_info);
+ protocol->store("error", 5, system_charset_info);
protocol->store(err_msg, system_charset_info);
(void)protocol->write();
/* Start off another row for HA_ADMIN_FAILED */
@@ -2446,116 +2186,84 @@ send_result_message:
}
}
result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
- table->next_local= save_next_local;
- table->next_global= save_next_global;
+ table->next= save_next;
goto send_result_message;
}
- case HA_ADMIN_WRONG_CHECKSUM:
- {
- protocol->store(STRING_WITH_LEN("note"), system_charset_info);
- protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)),
- system_charset_info);
- break;
- }
-
- case HA_ADMIN_NEEDS_UPGRADE:
- case HA_ADMIN_NEEDS_ALTER:
- {
- char buf[ERRMSGSIZE];
- uint length;
- protocol->store(STRING_WITH_LEN("error"), system_charset_info);
- length=my_snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE),
table->table_name);
- protocol->store(buf, length, system_charset_info);
+ default: // Probably HA_ADMIN_INTERNAL_ERROR
+ protocol->store("error", 5, system_charset_info);
+ protocol->store("Unknown - internal error during operation", 41
+ , system_charset_info);
fatal_error=1;
break;
}
-
- default: // Probably HA_ADMIN_INTERNAL_ERROR
+ if (fatal_error)
+ table->table->version=0; // Force close of table
+ else if (open_for_modify)
+ {
+ if (table->table->tmp_table)
+ table->table->file->info(HA_STATUS_CONST);
+ else
{
- char buf[ERRMSGSIZE+20];
- uint length=my_snprintf(buf, ERRMSGSIZE,
- "Unknown - internal error %d during operation",
- result_code);
- protocol->store(STRING_WITH_LEN("error"), system_charset_info);
- protocol->store(buf, length, system_charset_info);
- fatal_error=1;
- break;
- }
- }
- if (table->table)
- {
- if (fatal_error)
- table->table->s->version=0; // Force close of table
- else if (open_for_modify)
- {
- if (table->table->s->tmp_table)
- table->table->file->info(HA_STATUS_CONST);
- else
- {
- pthread_mutex_lock(&LOCK_open);
- remove_table_from_cache(thd, table->table->s->db,
- table->table->s->table_name, RTFC_NO_FLAG);
- pthread_mutex_unlock(&LOCK_open);
- }
- /* May be something modified consequently we have to invalidate cache */
- query_cache_invalidate3(thd, table->table, 0);
+ pthread_mutex_lock(&LOCK_open);
+ remove_table_from_cache(thd, table->table->table_cache_key,
+ table->table->real_name, RTFC_NO_FLAG);
+ pthread_mutex_unlock(&LOCK_open);
}
+ /* May be something modified consequently we have to invalidate cache */
+ query_cache_invalidate3(thd, table->table, 0);
}
close_thread_tables(thd);
- lex->reset_query_tables_list(FALSE);
table->table=0; // For query cache
if (protocol->write())
goto err;
}
send_eof(thd);
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(0);
err:
close_thread_tables(thd); // Shouldn't be needed
if (table)
table->table=0;
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(-1);
}
-bool mysql_backup_table(THD* thd, TABLE_LIST* table_list)
+int mysql_backup_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("mysql_backup_table");
DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
- "backup", TL_READ, 0, 0, 0, 0,
- &handler::backup, 0));
+ "backup", TL_READ, 0, 0, 0,
+ &handler::backup));
}
-bool mysql_restore_table(THD* thd, TABLE_LIST* table_list)
+int mysql_restore_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("mysql_restore_table");
DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
- "restore", TL_WRITE, 1, 1, 0,
+ "restore", TL_WRITE, 1, 0,
&prepare_for_restore,
- &handler::restore, 0));
+ &handler::restore));
}
-bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
+int mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
DBUG_ENTER("mysql_repair_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
- "repair", TL_WRITE, 1,
- test(check_opt->sql_flags & TT_USEFRM),
- HA_OPEN_FOR_REPAIR,
+ "repair", TL_WRITE, 1, HA_OPEN_FOR_REPAIR,
&prepare_for_repair,
- &handler::ha_repair, 0));
+ &handler::repair));
}
-bool mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
+int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
DBUG_ENTER("mysql_optimize_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
- "optimize", TL_WRITE, 1,0,0,0,
- &handler::optimize, 0));
+ "optimize", TL_WRITE, 1,0,0,
+ &handler::optimize));
}
@@ -2568,11 +2276,11 @@ bool mysql_optimize_table(THD* thd, TABL
tables Table list (one table only)
RETURN VALUES
- FALSE ok
- TRUE error
+ 0 ok
+ -1 error
*/
-bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
+int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
LEX_STRING *key_cache_name)
{
HA_CHECK_OPT check_opt;
@@ -2585,13 +2293,13 @@ bool mysql_assign_to_keycache(THD* thd,
{
pthread_mutex_unlock(&LOCK_global_system_variables);
my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(-1);
}
pthread_mutex_unlock(&LOCK_global_system_variables);
check_opt.key_cache= key_cache;
DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt,
- "assign_to_keycache", TL_READ_NO_INSERT, 0, 0,
- 0, 0, &handler::assign_to_keycache, 0));
+ "assign_to_keycache", TL_READ_NO_INSERT, 0,
+ 0, 0, &handler::assign_to_keycache));
}
@@ -2643,16 +2351,16 @@ int reassign_keycache_tables(THD *thd, K
tables Table list (one table only)
RETURN VALUES
- FALSE ok
- TRUE error
+ 0 ok
+ -1 error
*/
-bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
+int mysql_preload_keys(THD* thd, TABLE_LIST* tables)
{
DBUG_ENTER("mysql_preload_keys");
DBUG_RETURN(mysql_admin_table(thd, tables, 0,
- "preload_keys", TL_READ, 0, 0, 0, 0,
- &handler::preload_keys, 0));
+ "preload_keys", TL_READ, 0, 0, 0,
+ &handler::preload_keys));
}
@@ -2667,28 +2375,24 @@ bool mysql_preload_keys(THD* thd, TABLE_
table_ident Src table_ident
RETURN VALUES
- FALSE OK
- TRUE error
+ 0 ok
+ -1 error
*/
-bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
- HA_CREATE_INFO *create_info,
- Table_ident *table_ident)
+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->table_name;
+ char *table_name= table->real_name;
char *src_db;
char *src_table= table_ident->table.str;
- int err;
- bool res= TRUE;
- db_type not_used;
-
+ int err, res= -1;
TABLE_LIST src_tables_list;
DBUG_ENTER("mysql_create_like_table");
- DBUG_ASSERT(table_ident->db.str); /* Must be set in the parser */
- src_db= table_ident->db.str;
+ src_db= table_ident->db.str ? table_ident->db.str : thd->db;
/*
Validate the source table
@@ -2698,7 +2402,7 @@ bool mysql_create_like_table(THD* thd, T
check_table_name(src_table,table_ident->table.length)))
{
my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(-1);
}
if (!src_db || check_db_name(src_db))
{
@@ -2706,15 +2410,15 @@ bool mysql_create_like_table(THD* thd, T
DBUG_RETURN(-1);
}
- bzero((gptr)&src_tables_list, sizeof(src_tables_list));
src_tables_list.db= src_db;
- src_tables_list.table_name= src_table;
+ src_tables_list.real_name= src_table;
+ src_tables_list.next= 0;
if (lock_and_wait_for_table_name(thd, &src_tables_list))
goto err;
if ((tmp_table= find_temporary_table(thd, src_db, src_table)))
- strxmov(src_path, (*tmp_table)->s->path, reg_ext, NullS);
+ strxmov(src_path, (*tmp_table)->path, reg_ext, NullS);
else
{
strxmov(src_path, mysql_data_home, "/", src_db, "/", src_table,
@@ -2730,15 +2434,6 @@ bool mysql_create_like_table(THD* thd, T
}
}
- /*
- create like should be not allowed for Views, Triggers, ...
- */
- if (mysql_frm_type(thd, src_path, ¬_used) != FRMTYPE_TABLE)
- {
- my_error(ER_WRONG_OBJECT, MYF(0), src_db, src_table, "BASE TABLE");
- goto err;
- }
-
/*
Validate the destination table
@@ -2802,13 +2497,17 @@ bool mysql_create_like_table(THD* thd, T
}
// Must be written before unlock
+ mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ test(create_info->options &
+ HA_LEX_CREATE_TMP_TABLE),
+ FALSE);
mysql_bin_log.write(&qinfo);
}
- res= FALSE;
+ res= 0;
goto err;
table_exists:
@@ -2817,9 +2516,9 @@ table_exists:
char warn_buff[MYSQL_ERRMSG_SIZE];
my_snprintf(warn_buff, sizeof(warn_buff),
ER(ER_TABLE_EXISTS_ERROR), table_name);
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TABLE_EXISTS_ERROR,warn_buff);
- res= FALSE;
+ res= 0;
}
else
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
@@ -2832,7 +2531,7 @@ err:
}
-bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
+int mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
#ifdef OS2
thr_lock_type lock_type = TL_WRITE;
@@ -2842,12 +2541,12 @@ bool mysql_analyze_table(THD* thd, TABLE
DBUG_ENTER("mysql_analyze_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
- "analyze", lock_type, 1, 0, 0, 0,
- &handler::analyze, 0));
+ "analyze", lock_type, 1,0,0,
+ &handler::analyze));
}
-bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
+int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
{
#ifdef OS2
thr_lock_type lock_type = TL_WRITE;
@@ -2858,8 +2557,8 @@ bool mysql_check_table(THD* thd, TABLE_L
DBUG_ENTER("mysql_check_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"check", lock_type,
- 0, HA_OPEN_FOR_REPAIR, 0, 0,
- &handler::ha_check, &view_checksum));
+ 0, HA_OPEN_FOR_REPAIR, 0,
+ &handler::check));
}
@@ -2913,23 +2612,24 @@ mysql_discard_or_import_tablespace(THD *
error=1;
if (error)
goto err;
+ mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
err:
close_thread_tables(thd);
thd->tablespace_op=FALSE;
-
if (error == 0)
{
send_ok(thd);
DBUG_RETURN(0);
}
- table->file->print_error(error, MYF(0));
-
+ if (error == HA_ERR_ROW_IS_REFERENCED)
+ my_error(ER_ROW_IS_REFERENCED, MYF(0));
+
DBUG_RETURN(-1);
}
@@ -2984,9 +2684,9 @@ int mysql_create_indexes(THD *thd, TABLE
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
db_options= 0;
- if (mysql_prepare_table(thd, &create_info, &fields,
- &keys, /*tmp_table*/ 0, &db_options, table->file,
- &key_info_buffer, key_count,
+ if (mysql_prepare_table(thd, &create_info, fields,
+ keys, /*tmp_table*/ 0, db_options, table->file,
+ key_info_buffer, key_count,
/*select_field_count*/ 0))
DBUG_RETURN(-1);
@@ -3009,7 +2709,7 @@ int mysql_create_indexes(THD *thd, TABLE
create_info.default_table_charset= thd->variables.collation_database;
/* Cleanup the fields list. We do not want to create existing fields. */
fields.delete_elements();
- if (real_alter_table(thd, table_list->db, table_list->table_name,
+ if (real_alter_table(thd, table_list->db, table_list->real_name,
&create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_ADD_INDEX, DUP_ERROR))
@@ -3021,7 +2721,7 @@ int mysql_create_indexes(THD *thd, TABLE
if (table->file->add_index(table, key_info_buffer, key_count)||
build_table_path(path, sizeof(path), table_list->db,
(lower_case_table_names == 2) ?
- table_list->alias : table_list->table_name,
+ table_list->alias : table_list->real_name,
reg_ext) == 0 ||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
@@ -3105,7 +2805,7 @@ int mysql_drop_indexes(THD *thd, TABLE_L
if ((drop_key)|| (drop.elements<= 0))
{
- if (real_alter_table(thd, table_list->db, table_list->table_name,
+ if (real_alter_table(thd, table_list->db, table_list->real_name,
&create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_DROP_INDEX, DUP_ERROR))
@@ -3116,13 +2816,13 @@ int mysql_drop_indexes(THD *thd, TABLE_L
{
db_options= 0;
if (table->file->drop_index(table, key_numbers, key_count)||
- mysql_prepare_table(thd, &create_info, &fields,
- &keys, /*tmp_table*/ 0, &db_options, table->file,
- &key_info_buffer, key_count,
+ mysql_prepare_table(thd, &create_info, fields,
+ keys, /*tmp_table*/ 0, db_options, table->file,
+ key_info_buffer, key_count,
/*select_field_count*/ 0)||
build_table_path(path, sizeof(path), table_list->db,
(lower_case_table_names == 2) ?
- table_list->alias : table_list->table_name,
+ table_list->alias : table_list->real_name,
reg_ext) == 0 ||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
@@ -3140,14 +2840,15 @@ int mysql_drop_indexes(THD *thd, TABLE_L
Alter table
*/
-bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
- HA_CREATE_INFO *create_info,
- TABLE_LIST *table_list,
- List<create_field> &fields, List<Key> &keys,
- uint order_num, ORDER *order, bool ignore,
- ALTER_INFO *alter_info, bool do_send_ok)
+int mysql_alter_table(THD *thd,char *new_db, char *new_name,
+ HA_CREATE_INFO *create_info,
+ TABLE_LIST *table_list,
+ List<create_field> &fields, List<Key> &keys,
+ uint order_num, ORDER *order,
+ enum enum_duplicates handle_duplicates, bool ignore,
+ ALTER_INFO *alter_info, bool do_send_ok)
{
- TABLE *table,*new_table=0;
+ TABLE *table,*new_table;
int error;
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
@@ -3155,14 +2856,11 @@ bool mysql_alter_table(THD *thd,char *ne
ha_rows copied,deleted;
ulonglong next_insert_id;
uint db_create_options, used_fields;
- enum db_type old_db_type, new_db_type, table_type;
- bool need_copy_table;
- bool no_table_reopen= FALSE, varchar= FALSE;
- frm_type_enum frm_type;
+ enum db_type old_db_type,new_db_type;
DBUG_ENTER("mysql_alter_table");
thd->proc_info="init";
- table_name=table_list->table_name;
+ table_name=table_list->real_name;
alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
db=table_list->db;
@@ -3174,56 +2872,10 @@ bool mysql_alter_table(THD *thd,char *ne
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
- /* Conditionally writes to binlog. */
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
alter_info->tablespace_op));
- sprintf(new_name_buff,"%s/%s/%s%s",mysql_data_home, db, table_name, reg_ext);
- unpack_filename(new_name_buff, new_name_buff);
- if (lower_case_table_names != 2)
- my_casedn_str(files_charset_info, new_name_buff);
- frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
- /* Rename a view */
- if (frm_type == FRMTYPE_VIEW && !(alter_info->flags & ~ALTER_RENAME))
- {
- /*
- Avoid problems with a rename on a table that we have locked or
- if the user is trying to to do this in a transcation context
- */
-
- if (thd->locked_tables || thd->active_transaction())
- {
- my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
- ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
- DBUG_RETURN(1);
- }
-
- if (wait_if_global_read_lock(thd,0,1))
- DBUG_RETURN(1);
- VOID(pthread_mutex_lock(&LOCK_open));
- if (lock_table_names(thd, table_list))
- goto view_err;
-
- error=0;
- if (!do_rename(thd, table_list, new_db, new_name, new_name, 1))
- {
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
- mysql_bin_log.write(&qinfo);
- }
- send_ok(thd);
- }
-
- unlock_table_names(thd, table_list, (TABLE_LIST*) 0);
-
-view_err:
- pthread_mutex_unlock(&LOCK_open);
- start_waiting_global_read_lock(thd);
- DBUG_RETURN(error);
- }
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(-1);
/* Check that we are not trying to rename to an existing table */
if (new_name)
@@ -3250,12 +2902,12 @@ view_err:
}
else
{
- if (table->s->tmp_table)
+ if (table->tmp_table)
{
if (find_temporary_table(thd,new_db,new_name_buff))
{
- my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
- DBUG_RETURN(TRUE);
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff);
+ DBUG_RETURN(-1);
}
}
else
@@ -3266,8 +2918,8 @@ view_err:
F_OK))
{
/* Table will be closed in do_command() */
- my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
- DBUG_RETURN(TRUE);
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0), new_alias);
+ DBUG_RETURN(-1);
}
}
}
@@ -3278,38 +2930,62 @@ view_err:
new_name= table_name;
}
- old_db_type= table->s->db_type;
+ old_db_type=table->db_type;
if (create_info->db_type == DB_TYPE_DEFAULT)
- create_info->db_type= old_db_type;
- if (check_engine(thd, new_name, &create_info->db_type))
- DBUG_RETURN(TRUE);
- new_db_type= create_info->db_type;
+ create_info->db_type=old_db_type;
+ if ((new_db_type= ha_checktype(create_info->db_type)) !=
+ create_info->db_type)
+ {
+ create_info->db_type= new_db_type;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_USING_OTHER_HANDLER,
+ ER(ER_WARN_USING_OTHER_HANDLER),
+ ha_get_storage_engine(new_db_type),
+ new_name);
+ }
if (create_info->row_type == ROW_TYPE_NOT_USED)
- create_info->row_type= table->s->row_type;
+ create_info->row_type=table->row_type;
- DBUG_PRINT("info", ("old type: %d new type: %d", old_db_type, new_db_type));
- if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
- ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
- {
- DBUG_PRINT("info", ("doesn't support alter"));
- my_error(ER_ILLEGAL_HA, MYF(0), table_name);
- DBUG_RETURN(TRUE);
- }
-
thd->proc_info="setup";
- if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
- !table->s->tmp_table) // no need to touch frm
+ if (alter_info->is_simple && !table->tmp_table)
{
- error=0;
- VOID(pthread_mutex_lock(&LOCK_open));
- if (new_name != table_name || new_db != db)
+ switch (alter_info->keys_onoff) {
+ case LEAVE_AS_IS:
+ error= 0;
+ break;
+ case ENABLE:
+ VOID(pthread_mutex_lock(&LOCK_open));
+ wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
+ /* COND_refresh will be signaled in close_thread_tables() */
+ break;
+ case DISABLE:
+ VOID(pthread_mutex_lock(&LOCK_open));
+ wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ error= table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
+ /* COND_refresh will be signaled in close_thread_tables() */
+ break;
+ }
+
+ if (error == HA_ERR_WRONG_COMMAND)
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
+ table->table_name);
+ error= 0;
+ }
+
+ if (!error && (new_name != table_name || new_db != db))
{
thd->proc_info="rename";
+ VOID(pthread_mutex_lock(&LOCK_open));
/* Then do a 'simple' rename of the table */
error=0;
if (!access(new_name_buff,F_OK))
{
- my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name);
error= -1;
}
else
@@ -3318,47 +2994,25 @@ view_err:
close_cached_table(thd, table);
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias))
error= -1;
- else if (Table_triggers_list::change_table_name(thd, db, table_name,
- new_db, new_alias))
- {
- VOID(mysql_rename_table(old_db_type, new_db, new_alias, db,
- table_name));
- error= -1;
- }
- }
- }
-
- if (!error)
- {
- switch (alter_info->keys_onoff) {
- case LEAVE_AS_IS:
- break;
- case ENABLE:
- wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
- /* COND_refresh will be signaled in close_thread_tables() */
- break;
- case DISABLE:
- wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
- /* COND_refresh will be signaled in close_thread_tables() */
- break;
}
+ VOID(pthread_mutex_unlock(&LOCK_open));
}
if (error == HA_ERR_WRONG_COMMAND)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
- table->alias);
+ table->table_name);
error=0;
}
+
if (!error)
{
+ mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
if (do_send_ok)
@@ -3369,7 +3023,6 @@ view_err:
table->file->print_error(error, MYF(0));
error= -1;
}
- VOID(pthread_mutex_unlock(&LOCK_open));
table_list->table=0; // For query cache
query_cache_invalidate3(thd, table_list, 0);
DBUG_RETURN(error);
@@ -3377,17 +3030,17 @@ view_err:
/* Full alter table */
- /* Let new create options override the old ones */
+ /* let new create options override the old ones */
if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
- create_info->min_rows= table->s->min_rows;
+ create_info->min_rows=table->min_rows;
if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
- create_info->max_rows= table->s->max_rows;
+ create_info->max_rows=table->max_rows;
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
- create_info->avg_row_length= table->s->avg_row_length;
+ create_info->avg_row_length=table->avg_row_length;
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
- create_info->default_table_charset= table->s->table_charset;
+ create_info->default_table_charset= table->table_charset;
- restore_record(table, s->default_values); // Empty record for DEFAULT
+ restore_record(table,default_values); // Empty record for DEFAULT
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
List_iterator<create_field> def_it(fields);
List_iterator<Alter_column> alter_it(alter_info->alter_list);
@@ -3402,8 +3055,6 @@ view_err:
Field **f_ptr,*field;
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
{
- if (field->type() == MYSQL_TYPE_STRING)
- varchar= TRUE;
/* Check if field should be dropped */
Alter_drop *drop;
drop_it.rewind();
@@ -3458,13 +3109,10 @@ view_err:
{
if (def->sql_type == FIELD_TYPE_BLOB)
{
- my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
- DBUG_RETURN(TRUE);
+ my_error(ER_BLOB_CANT_HAVE_DEFAULT,MYF(0),def->change);
+ DBUG_RETURN(-1);
}
- if ((def->def=alter->def)) // Use new default
- def->flags&= ~NO_DEFAULT_VALUE_FLAG;
- else
- def->flags|= NO_DEFAULT_VALUE_FLAG;
+ def->def=alter->def; // Use new default
alter_it.remove();
}
}
@@ -3475,8 +3123,8 @@ view_err:
{
if (def->change && ! def->field)
{
- my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table_name);
- DBUG_RETURN(TRUE);
+ my_error(ER_BAD_FIELD_ERROR,MYF(0),def->change,table_name);
+ DBUG_RETURN(-1);
}
if (!def->after)
create_list.push_back(def);
@@ -3493,23 +3141,22 @@ view_err:
}
if (!find)
{
- my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table_name);
- DBUG_RETURN(TRUE);
+ my_error(ER_BAD_FIELD_ERROR,MYF(0),def->after,table_name);
+ DBUG_RETURN(-1);
}
find_it.after(def); // Put element after this
}
}
if (alter_info->alter_list.elements)
{
- my_error(ER_BAD_FIELD_ERROR, MYF(0),
- alter_info->alter_list.head()->name, table_name);
- DBUG_RETURN(TRUE);
+ my_error(ER_BAD_FIELD_ERROR,MYF(0),alter_info->alter_list.head()->name,
+ table_name);
+ DBUG_RETURN(-1);
}
if (!create_list.elements)
{
- my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
- MYF(0));
- DBUG_RETURN(TRUE);
+ my_error(ER_CANT_REMOVE_ALL_FIELDS,MYF(0));
+ DBUG_RETURN(-1);
}
/*
@@ -3522,7 +3169,7 @@ view_err:
List<key_part_spec> key_parts;
KEY *key_info=table->key_info;
- for (uint i=0 ; i < table->s->keys ; i++,key_info++)
+ for (uint i=0 ; i < table->keys ; i++,key_info++)
{
char *key_name= key_info->name;
Alter_drop *drop;
@@ -3564,26 +3211,12 @@ view_err:
continue; // Field is removed
uint key_part_length=key_part->length;
if (cfield->field) // Not new field
- {
- /*
- If the field can't have only a part used in a key according to its
- new type, or should not be used partially according to its
- previous type, or the field length is less than the key part
- length, unset the key part length.
-
- We also unset the key part length if it is the same as the
- old field's length, so the whole new field will be used.
-
- BLOBs may have cfield->length == 0, which is why we test it before
- checking whether cfield->length < key_part_length (in chars).
- */
- if (!Field::type_can_have_key_part(cfield->field->type()) ||
- !Field::type_can_have_key_part(cfield->sql_type) ||
- (cfield->field->field_length == key_part_length &&
- !f_is_blob(key_part->key_type)) ||
- (cfield->length && (cfield->length < key_part_length /
- key_part->field->charset()->mbmaxlen)))
- key_part_length= 0; // Use whole field
+ { // Check if sub key
+ if (cfield->field->type() != FIELD_TYPE_BLOB &&
+ (cfield->field->pack_length() == key_part_length ||
+ cfield->length <= key_part_length /
+ key_part->field->charset()->mbmaxlen))
+ key_part_length=0; // Use whole field
}
key_part_length /= key_part->field->charset()->mbmaxlen;
key_parts.push_back(new key_part_spec(cfield->field_name,
@@ -3612,25 +3245,25 @@ view_err:
!my_strcasecmp(system_charset_info,key->name,primary_key_name))
{
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
- DBUG_RETURN(TRUE);
+ DBUG_RETURN(-1);
}
}
}
if (alter_info->drop_list.elements)
{
- my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
- alter_info->drop_list.head()->name);
+ my_error(ER_CANT_DROP_FIELD_OR_KEY,MYF(0),
+ alter_info->drop_list.head()->name);
goto err;
}
if (alter_info->alter_list.elements)
{
- my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
- alter_info->alter_list.head()->name);
+ my_error(ER_CANT_DROP_FIELD_OR_KEY,MYF(0),
+ alter_info->alter_list.head()->name);
goto err;
}
- db_create_options= table->s->db_create_options & ~(HA_OPTION_PACK_RECORD);
+ db_create_options=table->db_create_options & ~(HA_OPTION_PACK_RECORD);
my_snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
current_pid, thd->thread_id);
/* Safety fix for innodb */
@@ -3641,11 +3274,8 @@ view_err:
goto err;
}
create_info->db_type=new_db_type;
- if (!create_info->comment.str)
- {
- create_info->comment.str= table->s->comment.str;
- create_info->comment.length= table->s->comment.length;
- }
+ if (!create_info->comment)
+ create_info->comment=table->comment;
table->file->update_create_info(create_info);
if ((create_info->table_options &
@@ -3661,37 +3291,10 @@ view_err:
HA_OPTION_NO_DELAY_KEY_WRITE);
create_info->table_options|= db_create_options;
- if (table->s->tmp_table)
+ if (table->tmp_table)
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
/*
- better have a negative test here, instead of positive, like
- alter_info->flags & ALTER_ADD_COLUMN|ALTER_ADD_INDEX|...
- so that ALTER TABLE won't break when somebody will add new flag
-
- MySQL uses frm version to determine the type of the data fields and
- their layout. See Field_string::type() for details.
- Thus, if the table is too old we may have to rebuild the data to
- update the layout.
-
- There was a bug prior to mysql-4.0.25. Number of null fields was
- calculated incorrectly. As a result frm and data files gets out of
- sync after fast alter table. There is no way to determine by which
- mysql version (in 4.0 and 4.1 branches) table was created, thus we
- disable fast alter table for all tables created by mysql versions
- prior to 5.0 branch.
- See BUG#6236.
- */
- need_copy_table= (alter_info->flags &
- ~(ALTER_CHANGE_COLUMN_DEFAULT|ALTER_OPTIONS) ||
- (create_info->used_fields &
- ~(HA_CREATE_USED_COMMENT|HA_CREATE_USED_PASSWORD)) ||
- table->s->tmp_table ||
- !table->s->mysql_version ||
- (table->s->frm_version < FRM_VER_TRUE_VARCHAR &&
varchar));
- create_info->frm_only= !need_copy_table;
-
- /*
Handling of symlinked tables:
If no rename:
Create new data file and index file on the same disk as the
@@ -3737,9 +3340,8 @@ view_err:
}
else
create_info->data_file_name=create_info->index_file_name=0;
-
- /* We don't log the statement, it will be logged later. */
{
+ /* We don't log the statement, it will be logged later. */
tmp_disable_binlog(thd);
error= mysql_create_table(thd, new_db, tmp_name,
create_info,create_list,key_list,1,0);
@@ -3747,49 +3349,37 @@ view_err:
if (error)
DBUG_RETURN(error);
}
- if (need_copy_table)
+ if (table->tmp_table)
+ new_table=open_table(thd,new_db,tmp_name,tmp_name,0);
+ else
{
- if (table->s->tmp_table)
- {
- TABLE_LIST tbl;
- bzero((void*) &tbl, sizeof(tbl));
- tbl.db= new_db;
- tbl.table_name= tbl.alias= tmp_name;
- new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
- MYSQL_LOCK_IGNORE_FLUSH);
- }
- else
- {
- char path[FN_REFLEN];
- my_snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home,
- new_db, tmp_name);
- fn_format(path,path,"","",4);
- new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
- }
- if (!new_table)
- {
- VOID(quick_rm_table(new_db_type,new_db,tmp_name));
- goto err;
- }
+ char path[FN_REFLEN];
+ build_table_path(path, sizeof(path), new_db, tmp_name, "");
+ new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
}
+ if (!new_table)
+ {
+ VOID(quick_rm_table(new_db_type,new_db,tmp_name));
+ goto err;
+ }
+
/* We don't want update TIMESTAMP fields during ALTER TABLE. */
+ new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+ new_table->next_number_field=new_table->found_next_number_field;
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
thd->cuted_fields=0L;
thd->proc_info="copy to tmp table";
- next_insert_id=thd->next_insert_id; // Remember for logging
+ next_insert_id=thd->next_insert_id; // Remember for loggin
copied=deleted=0;
- if (new_table && !new_table->s->is_view)
- {
- new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
- new_table->next_number_field=new_table->found_next_number_field;
- error=copy_data_between_tables(table, new_table, create_list, ignore,
+ if (!new_table->is_view)
+ error=copy_data_between_tables(table,new_table,create_list,
+ handle_duplicates, ignore,
order_num, order, &copied, &deleted);
- }
thd->last_insert_id=next_insert_id; // Needed for correct log
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
- if (table->s->tmp_table)
+ if (table->tmp_table)
{
/* We changed a temporary table */
if (error)
@@ -3808,7 +3398,7 @@ view_err:
thd->lock=0;
}
/* Remove link to old table and rename the new one */
- close_temporary_table(thd, table->s->db, table_name);
+ close_temporary_table(thd,table->table_cache_key,table_name);
/* Should pass the 'new_name' as we store table name in the cache */
if (rename_temporary_table(thd, new_table, new_db, new_name))
{ // Fatal error
@@ -3816,24 +3406,18 @@ view_err:
my_free((gptr) new_table,MYF(0));
goto err;
}
- /*
- Writing to the binlog does not need to be synchronized for temporary tables,
- which are thread-specific.
- */
+ mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
goto end_temporary;
}
- if (new_table)
- {
- intern_close_table(new_table); /* close temporary table */
- my_free((gptr) new_table,MYF(0));
- }
+ intern_close_table(new_table); /* close temporary table */
+ my_free((gptr) new_table,MYF(0));
VOID(pthread_mutex_lock(&LOCK_open));
if (error)
{
@@ -3845,7 +3429,7 @@ view_err:
/*
Data is copied. Now we rename the old table to a temp name,
rename the new one to the old name, remove all entries from the old table
- from the cache, free all locks, close the old table and remove it.
+ from the cash, free all locks, close the old table and remove it.
*/
thd->proc_info="rename result table";
@@ -3858,7 +3442,7 @@ view_err:
if (!access(new_name_buff,F_OK))
{
error=1;
- my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff);
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
@@ -3873,9 +3457,14 @@ view_err:
Win32 and InnoDB can't drop a table that is in use, so we must
close the original table at before doing the rename
*/
- close_cached_table(thd, table);
+ table_name=thd->strdup(table_name); // must be saved
+ if (close_cached_table(thd, table))
+ { // Aborted
+ VOID(quick_rm_table(new_db_type,new_db,tmp_name));
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ goto err;
+ }
table=0; // Marker that table is closed
- no_table_reopen= TRUE;
}
#if (!defined( __WIN__) && !defined( __EMX__) && !defined( OS2))
else
@@ -3884,19 +3473,13 @@ view_err:
error=0;
- if (!need_copy_table)
- new_db_type=old_db_type=DB_TYPE_UNKNOWN; // this type cannot happen in regular ALTER
if (mysql_rename_table(old_db_type,db,table_name,db,old_name))
{
error=1;
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
}
else if (mysql_rename_table(new_db_type,new_db,tmp_name,new_db,
- new_alias) ||
- (new_name != table_name || new_db != db) && // we also do rename
- Table_triggers_list::change_table_name(thd, db, table_name,
- new_db, new_alias))
-
+ new_alias))
{ // Try to get everything back
error=1;
VOID(quick_rm_table(new_db_type,new_db,new_alias));
@@ -3914,7 +3497,7 @@ view_err:
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
- if (thd->lock || new_name != table_name || no_table_reopen) // True if WIN32
+ if (thd->lock || new_name != table_name) // True if WIN32
{
/*
Not table locking or alter table with rename
@@ -3956,17 +3539,18 @@ view_err:
if (error)
{
VOID(pthread_mutex_unlock(&LOCK_open));
- broadcast_refresh();
+ VOID(pthread_cond_broadcast(&COND_refresh));
goto err;
}
thd->proc_info="end";
+ mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
- broadcast_refresh();
+ VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open));
#ifdef HAVE_BERKELEY_DB
if (old_db_type == DB_TYPE_BERKELEY_DB)
@@ -4000,16 +3584,17 @@ end_temporary:
if (do_send_ok)
send_ok(thd,copied+deleted,0L,tmp_name);
thd->some_tables_deleted=0;
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(0);
-err:
- DBUG_RETURN(TRUE);
+ err:
+ DBUG_RETURN(-1);
}
static int
copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create,
+ enum enum_duplicates handle_duplicates,
bool ignore,
uint order_num, ORDER *order,
ha_rows *copied,
@@ -4040,18 +3625,11 @@ copy_data_between_tables(TABLE *from,TAB
if (error)
DBUG_RETURN(-1);
- if (!(copy= new Copy_field[to->s->fields]))
+ if (!(copy= new Copy_field[to->fields]))
DBUG_RETURN(-1); /* purecov: inspected */
if (to->file->external_lock(thd, F_WRLCK))
DBUG_RETURN(-1);
-
- /* We can abort alter table for any table type */
- thd->no_trans_update= 0;
- thd->abort_on_warning= !ignore && test(thd->variables.sql_mode &
- (MODE_STRICT_TRANS_TABLES |
- MODE_STRICT_ALL_TABLES));
-
from->file->info(HA_STATUS_VARIABLE);
to->file->start_bulk_insert(from->file->records);
@@ -4089,38 +3667,36 @@ copy_data_between_tables(TABLE *from,TAB
from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL));
bzero((char*) &tables,sizeof(tables));
- tables.table= from;
- tables.alias= tables.table_name= (char*) from->s->table_name;
- tables.db= (char*) from->s->db;
+ tables.table = from;
+ tables.alias = tables.real_name= from->real_name;
+ tables.db = from->table_cache_key;
error=1;
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
&tables, fields, all_fields, order) ||
- !(sortorder=make_unireg_sortorder(order, &length, NULL)) ||
+ !(sortorder=make_unireg_sortorder(order, &length)) ||
(from->sort.found_records = filesort(thd, from, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR,
- &examined_rows)) ==
- HA_POS_ERROR)
+ &examined_rows))
+ == HA_POS_ERROR)
goto err;
};
- /*
- Handler must be told explicitly to retrieve all columns, because
- this function does not set field->query_id in the columns to the
- current query id
- */
+ /* Handler must be told explicitly to retrieve all columns, because
+ this function does not set field->query_id in the columns to the
+ current query id */
from->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
- if (ignore)
+ if (ignore ||
+ handle_duplicates == DUP_REPLACE)
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
thd->row_count= 0;
- restore_record(to, s->default_values); // Create empty record
while (!(error=info.read_record(&info)))
{
if (thd->killed)
{
- thd->send_kill_message();
+ my_error(ER_SERVER_SHUTDOWN,MYF(0));
error= 1;
break;
}
@@ -4132,21 +3708,20 @@ copy_data_between_tables(TABLE *from,TAB
else
to->next_number_field->reset();
}
-
for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
{
copy_ptr->do_copy(copy_ptr);
}
if ((error=to->file->write_row((byte*) to->record[0])))
{
- if (!ignore ||
+ if ((!ignore &&
+ handle_duplicates != DUP_REPLACE) ||
(error != HA_ERR_FOUND_DUPP_KEY &&
error != HA_ERR_FOUND_DUPP_UNIQUE))
{
to->file->print_error(error,MYF(0));
break;
}
- to->file->restore_auto_increment();
delete_count++;
}
else
@@ -4156,7 +3731,7 @@ copy_data_between_tables(TABLE *from,TAB
free_io_cache(from);
delete [] copy; // This is never 0
- if (to->file->end_bulk_insert() && error <= 0)
+ if (to->file->end_bulk_insert() && !error)
{
to->file->print_error(my_errno,MYF(0));
error=1;
@@ -4176,7 +3751,6 @@ copy_data_between_tables(TABLE *from,TAB
err:
thd->variables.sql_mode= save_sql_mode;
- thd->abort_on_warning= 0;
free_io_cache(from);
*copied= found_count;
*deleted=delete_count;
@@ -4198,8 +3772,8 @@ copy_data_between_tables(TABLE *from,TAB
RETURN
Like mysql_alter_table().
*/
-bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
- bool do_send_ok)
+int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
+ bool do_send_ok)
{
DBUG_ENTER("mysql_recreate_table");
LEX *lex= thd->lex;
@@ -4208,20 +3782,19 @@ bool mysql_recreate_table(THD *thd, TABL
lex->key_list.empty();
lex->col_list.empty();
lex->alter_info.reset();
+ lex->alter_info.is_simple= 0; // Force full recreate
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
- create_info.row_type=ROW_TYPE_NOT_USED;
+ create_info.row_type=ROW_TYPE_DEFAULT;
create_info.default_table_charset=default_charset_info;
- /* Force alter table to recreate table */
- lex->alter_info.flags= ALTER_CHANGE_COLUMN;
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
table_list, lex->create_list,
lex->key_list, 0, (ORDER *) 0,
- 0, &lex->alter_info, do_send_ok));
+ DUP_ERROR, 0, &lex->alter_info, do_send_ok));
}
-bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
+int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
{
TABLE_LIST *table;
List<Item> field_list;
@@ -4233,18 +3806,17 @@ bool mysql_checksum_table(THD *thd, TABL
item->maybe_null= 1;
field_list.push_back(item=new Item_int("Checksum",(longlong) 1,21));
item->maybe_null= 1;
- if (protocol->send_fields(&field_list,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(TRUE);
+ if (protocol->send_fields(&field_list, 1))
+ DBUG_RETURN(-1);
- for (table= tables; table; table= table->next_local)
+ for (table= tables; table; table= table->next)
{
char table_name[NAME_LEN*2+2];
TABLE *t;
- strxmov(table_name, table->db ,".", table->table_name, NullS);
+ strxmov(table_name, table->db ,".", table->real_name, NullS);
- t= table->table= open_ltable(thd, table, TL_READ);
+ t= table->table= open_ltable(thd, table, TL_READ_NO_INSERT);
thd->clear_error(); // these errors shouldn't get client
protocol->prepare_for_resend();
@@ -4254,7 +3826,7 @@ bool mysql_checksum_table(THD *thd, TABL
{
/* Table didn't exist */
protocol->store_null();
- thd->clear_error();
+ thd->net.last_error[0]=0;
}
else
{
@@ -4270,7 +3842,6 @@ bool mysql_checksum_table(THD *thd, TABL
{
/* calculating table's checksum */
ha_checksum crc= 0;
- uchar null_mask=256 - (1 << t->s->last_null_bit_pos);
/* InnoDB must be told explicitly to retrieve all columns, because
this function does not set field->query_id in the columns to the
@@ -4291,21 +3862,14 @@ bool mysql_checksum_table(THD *thd, TABL
continue;
break;
}
- if (t->s->null_bytes)
- {
- /* fix undefined null bits */
- t->record[0][t->s->null_bytes-1] |= null_mask;
- if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
- t->record[0][0] |= 1;
-
- row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
- }
+ if (t->record[0] != (byte*) t->field[0]->ptr)
+ row_crc= my_checksum(row_crc, t->record[0],
+ ((byte*) t->field[0]->ptr) - t->record[0]);
- for (uint i= 0; i < t->s->fields; i++ )
+ for (uint i= 0; i < t->fields; i++ )
{
Field *f= t->field[i];
- if ((f->type() == FIELD_TYPE_BLOB) ||
- (f->type() == MYSQL_TYPE_VARCHAR))
+ if (f->type() == FIELD_TYPE_BLOB)
{
String tmp;
f->val_str(&tmp);
@@ -4331,32 +3895,11 @@ bool mysql_checksum_table(THD *thd, TABL
}
send_eof(thd);
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(0);
err:
close_thread_tables(thd); // Shouldn't be needed
if (table)
table->table=0;
- DBUG_RETURN(TRUE);
-}
-
-static bool check_engine(THD *thd, const char *table_name,
- enum db_type *new_engine)
-{
- enum db_type req_engine= *new_engine;
- bool no_substitution=
- test(thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION);
- if ((*new_engine=
- ha_checktype(thd, req_engine, no_substitution, 1)) == DB_TYPE_UNKNOWN)
- return TRUE;
-
- if (req_engine != *new_engine)
- {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_USING_OTHER_HANDLER,
- ER(ER_WARN_USING_OTHER_HANDLER),
- ha_get_storage_engine(*new_engine),
- table_name);
- }
- return FALSE;
+ DBUG_RETURN(-1);
}
--- 1.56/mysql-test/r/alter_table.result 2006-11-16 13:31:47 +01:00
+++ 1.57/mysql-test/r/alter_table.result 2006-11-16 13:31:47 +01:00
@@ -428,42 +428,42 @@ t1 MyISAM 10 Fixed 1 37 X X X X X X X X
drop table t1;
set names koi8r;
create table t1 (a char(10) character set koi8r);
-insert into t1 values ('ΤΕΣΤ');
+insert into t1 values ('ÔÅÓÔ');
select a,hex(a) from t1;
a hex(a)
-ΤΕΣΤ D4C5D3D4
+ÔÅÓÔ D4C5D3D4
alter table t1 change a a char(10) character set cp1251;
select a,hex(a) from t1;
a hex(a)
-ΤΕΣΤ F2E5F1F2
+ÔÅÓÔ F2E5F1F2
alter table t1 change a a binary(4);
select a,hex(a) from t1;
a hex(a)
-ςερς F2E5F1F2
+òåñò F2E5F1F2
alter table t1 change a a char(10) character set cp1251;
select a,hex(a) from t1;
a hex(a)
-ΤΕΣΤ F2E5F1F2
+ÔÅÓÔ F2E5F1F2
alter table t1 change a a char(10) character set koi8r;
select a,hex(a) from t1;
a hex(a)
-ΤΕΣΤ D4C5D3D4
+ÔÅÓÔ D4C5D3D4
alter table t1 change a a varchar(10) character set cp1251;
select a,hex(a) from t1;
a hex(a)
-ΤΕΣΤ F2E5F1F2
+ÔÅÓÔ F2E5F1F2
alter table t1 change a a char(10) character set koi8r;
select a,hex(a) from t1;
a hex(a)
-ΤΕΣΤ D4C5D3D4
+ÔÅÓÔ D4C5D3D4
alter table t1 change a a text character set cp1251;
select a,hex(a) from t1;
a hex(a)
-ΤΕΣΤ F2E5F1F2
+ÔÅÓÔ F2E5F1F2
alter table t1 change a a char(10) character set koi8r;
select a,hex(a) from t1;
a hex(a)
-ΤΕΣΤ D4C5D3D4
+ÔÅÓÔ D4C5D3D4
delete from t1;
show create table t1;
Table Create Table
@@ -528,7 +528,7 @@ ALTER TABLE T12207 DISCARD TABLESPACE;
ERROR HY000: Table storage engine for 'T12207' doesn't have this option
DROP TABLE T12207;
create table t1 (a text) character set koi8r;
-insert into t1 values (_koi8r'ΤΕΣΤ');
+insert into t1 values (_koi8r'ÔÅÓÔ');
select hex(a) from t1;
hex(a)
D4C5D3D4
@@ -566,3 +566,14 @@ create table t1 (t varchar(255) default
engine=myisam default charset=latin1;
alter table t1 change t t text;
drop table t1;
+DROP TABLE IF EXISTS bug24219;
+DROP TABLE IF EXISTS bug24219_2;
+CREATE TABLE bug24219 (a INT, INDEX(a));
+SHOW INDEX FROM bug24219;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+bug24219 1 a 1 a A NULL NULL NULL YES BTREE
+ALTER TABLE bug24219 RENAME TO bug24219_2, DISABLE KEYS;
+SHOW INDEX FROM bug24219_2;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+bug24219_2 1 a 1 a A NULL NULL NULL YES BTREE disabled
+DROP TABLE bug24219_2;
--- 1.44/mysql-test/t/alter_table.test 2006-11-16 13:31:47 +01:00
+++ 1.45/mysql-test/t/alter_table.test 2006-11-16 13:31:47 +01:00
@@ -274,7 +274,7 @@ drop table t1;
#
set names koi8r;
create table t1 (a char(10) character set koi8r);
-insert into t1 values ('ΤΕΣΤ');
+insert into t1 values ('ÔÅÓÔ');
select a,hex(a) from t1;
alter table t1 change a a char(10) character set cp1251;
select a,hex(a) from t1;
@@ -354,7 +354,7 @@ DROP TABLE T12207;
# modified. In other words, the values were reinterpreted
# as UTF8 instead of being converted.
create table t1 (a text) character set koi8r;
-insert into t1 values (_koi8r'ΤΕΣΤ');
+insert into t1 values (_koi8r'ÔÅÓÔ');
select hex(a) from t1;
alter table t1 convert to character set cp1251;
select hex(a) from t1;
@@ -402,8 +402,6 @@ alter table test.t1 rename test.t1;
use test;
drop table t1;
-# End of 4.1 tests
-
#
# Bug #14693 (ALTER SET DEFAULT doesn't work)
#
@@ -422,3 +420,24 @@ create table t1 (t varchar(255) default
engine=myisam default charset=latin1;
alter table t1 change t t text;
drop table t1;
+
+#
+# Bug#24219 - ALTER TABLE ... RENAME TO ... , DISABLE KEYS leads to crash
+#
+--disable_warnings
+DROP TABLE IF EXISTS bug24219;
+DROP TABLE IF EXISTS bug24219_2;
+--enable_warnings
+
+CREATE TABLE bug24219 (a INT, INDEX(a));
+
+SHOW INDEX FROM bug24219;
+
+ALTER TABLE bug24219 RENAME TO bug24219_2, DISABLE KEYS;
+
+SHOW INDEX FROM bug24219_2;
+
+DROP TABLE bug24219_2;
+
+# End of 4.1 tests
+
| Thread |
|---|
| • bk commit into 5.0 tree (andrey:1.2335) | ahristov | 16 Nov |