summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/derror.cc4
-rw-r--r--sql/field.cc49
-rw-r--r--sql/field.h14
-rw-r--r--sql/field_conv.cc10
-rw-r--r--sql/filesort.cc15
-rw-r--r--sql/ha_berkeley.cc1
-rw-r--r--sql/ha_berkeley.h3
-rw-r--r--sql/ha_heap.cc5
-rw-r--r--sql/ha_heap.h4
-rw-r--r--sql/ha_innodb.cc23
-rw-r--r--sql/ha_innodb.h4
-rw-r--r--sql/ha_isam.cc5
-rw-r--r--sql/ha_isam.h1
-rw-r--r--sql/ha_isammrg.cc5
-rw-r--r--sql/ha_isammrg.h1
-rw-r--r--sql/ha_myisam.cc141
-rw-r--r--sql/ha_myisam.h11
-rw-r--r--sql/ha_myisammrg.cc6
-rw-r--r--sql/ha_myisammrg.h1
-rw-r--r--sql/handler.h39
-rw-r--r--sql/init.cc2
-rw-r--r--sql/item.cc3
-rw-r--r--sql/item_cmpfunc.cc4
-rw-r--r--sql/item_func.cc3
-rw-r--r--sql/item_geofunc.cc16
-rw-r--r--sql/item_sum.cc330
-rw-r--r--sql/item_sum.h82
-rw-r--r--sql/key.cc2
-rw-r--r--sql/lex.h2
-rw-r--r--sql/log.cc1
-rw-r--r--sql/log_event.cc4
-rw-r--r--sql/mysql_priv.h28
-rw-r--r--sql/mysqld.cc21
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/protocol.cc9
-rw-r--r--sql/records.cc2
-rw-r--r--sql/repl_failsafe.cc2
-rw-r--r--sql/set_var.cc5
-rw-r--r--sql/slave.cc33
-rw-r--r--sql/sql_acl.cc23
-rw-r--r--sql/sql_base.cc51
-rw-r--r--sql/sql_cache.cc5
-rw-r--r--sql/sql_derived.cc1
-rw-r--r--sql/sql_help.cc3
-rw-r--r--sql/sql_insert.cc62
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_lex.h11
-rw-r--r--sql/sql_load.cc10
-rw-r--r--sql/sql_parse.cc30
-rw-r--r--sql/sql_prepare.cc9
-rw-r--r--sql/sql_select.cc38
-rw-r--r--sql/sql_show.cc17
-rw-r--r--sql/sql_table.cc1467
-rw-r--r--sql/sql_yacc.yy139
-rw-r--r--sql/table.cc7
-rw-r--r--sql/table.h2
-rw-r--r--sql/unireg.cc29
57 files changed, 1651 insertions, 1148 deletions
diff --git a/sql/derror.cc b/sql/derror.cc
index 53d0dc5b7e5..09f43d20044 100644
--- a/sql/derror.cc
+++ b/sql/derror.cc
@@ -50,7 +50,7 @@ static bool read_texts(const char *file_name,const char ***point,
char name[FN_REFLEN];
const char *buff;
uchar head[32],*pos;
- CHARSET_INFO *cset;
+ CHARSET_INFO *cset; // For future
DBUG_ENTER("read_texts");
*point=0; // If something goes wrong
@@ -137,7 +137,7 @@ err1:
if (file != FERR)
VOID(my_close(file,MYF(MY_WME)));
unireg_abort(1);
- DBUG_RETURN(1); // Impossible
+ DBUG_RETURN(1); // keep compiler happy
} /* read_texts */
diff --git a/sql/field.cc b/sql/field.cc
index 238d5e36147..2da84ba1316 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -161,13 +161,6 @@ static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
}
#endif
-static inline uint field_length_without_space(const char *ptr, uint length)
-{
- const char *end= ptr+length;
- while (end > ptr && end[-1] == ' ')
- end--;
- return (uint) (end-ptr);
-}
/*
Tables of filed type compatibility.
@@ -306,7 +299,7 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
field_name(field_name_arg),
query_id(0), key_start(0), part_of_key(0), part_of_sortkey(0),
unireg_check(unireg_check_arg),
- field_length(length_arg),null_bit(null_bit_arg),abs_offset(0)
+ field_length(length_arg),null_bit(null_bit_arg)
{
flags=null_ptr ? 0: NOT_NULL_FLAG;
comment.str= (char*) "";
@@ -334,7 +327,7 @@ bool Field::send_binary(Protocol *protocol)
{
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff),charset());
- val_str(&tmp,&tmp);
+ val_str(&tmp);
return protocol->store(tmp.ptr(), tmp.length(), tmp.charset());
}
@@ -403,8 +396,8 @@ uint Field::fill_cache_field(CACHE_FIELD *copy)
bool Field::get_date(TIME *ltime,uint fuzzydate)
{
char buff[40];
- String tmp(buff,sizeof(buff),&my_charset_bin),tmp2,*res;
- if (!(res=val_str(&tmp,&tmp2)) ||
+ String tmp(buff,sizeof(buff),&my_charset_bin),*res;
+ if (!(res=val_str(&tmp)) ||
str_to_TIME(res->ptr(),res->length(),ltime,fuzzydate) <=
TIMESTAMP_DATETIME_ERROR)
return 1;
@@ -414,8 +407,8 @@ bool Field::get_date(TIME *ltime,uint fuzzydate)
bool Field::get_time(TIME *ltime)
{
char buff[40];
- String tmp(buff,sizeof(buff),&my_charset_bin),tmp2,*res;
- if (!(res=val_str(&tmp,&tmp2)) ||
+ String tmp(buff,sizeof(buff),&my_charset_bin),*res;
+ if (!(res=val_str(&tmp)) ||
str_to_time(res->ptr(),res->length(),ltime))
return 1;
return 0;
@@ -2789,14 +2782,8 @@ int Field_double::cmp(const char *a_ptr, const char *b_ptr)
else
#endif
{
-/* could this ALWAYS be 2 calls to doubleget() ?? */
-#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
doubleget(a, a_ptr);
doubleget(b, b_ptr);
-#else
- memcpy_fixed(&a,a_ptr,sizeof(double));
- memcpy_fixed(&b,b_ptr,sizeof(double));
-#endif
}
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
@@ -2816,12 +2803,7 @@ void Field_double::sort_string(char *to,uint length __attribute__((unused)))
}
else
#endif
-/* could this ALWAYS be 2 calls to doubleget() ?? */
-#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
doubleget(nr,ptr);
-#else
- memcpy_fixed(&nr,ptr,sizeof(nr));
-#endif
change_double_for_sort(nr, (byte*) to);
}
@@ -3105,8 +3087,7 @@ longlong Field_timestamp::val_int(void)
}
-String *Field_timestamp::val_str(String *val_buffer,
- String *val_ptr __attribute__((unused)))
+String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
{
uint32 temp, temp2;
time_t time_arg;
@@ -5597,7 +5578,7 @@ uint32 calc_pack_length(enum_field_types type,uint32 length)
case FIELD_TYPE_ENUM: abort(); return 0; // This shouldn't happen
default: return 0;
}
- return 0; // This shouldn't happen
+ return 0; // Keep compiler happy
}
@@ -5630,6 +5611,18 @@ Field *make_field(char *ptr, uint32 field_length,
null_pos=0;
null_bit=0;
}
+
+ switch (field_type)
+ {
+ case FIELD_TYPE_DATE:
+ case FIELD_TYPE_NEWDATE:
+ case FIELD_TYPE_TIME:
+ case FIELD_TYPE_DATETIME:
+ case FIELD_TYPE_TIMESTAMP:
+ field_charset= &my_charset_bin;
+ default: break;
+ }
+
if (f_is_alpha(pack_flag))
{
if (!f_is_packed(pack_flag))
@@ -5795,7 +5788,7 @@ create_field::create_field(Field *old_field,Field *orig_field)
my_ptrdiff_t diff= (my_ptrdiff_t) (orig_field->table->rec_buff_length*2);
orig_field->move_field(diff); // Points now at default_values
bool is_null=orig_field->is_real_null();
- orig_field->val_str(&tmp,&tmp);
+ orig_field->val_str(&tmp);
orig_field->move_field(-diff); // Back to record[0]
if (!is_null)
{
diff --git a/sql/field.h b/sql/field.h
index 258c18257f0..8ebc7412c35 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -87,7 +87,6 @@ public:
uint32 field_length; // Length of field
uint16 flags;
uchar null_bit; // Bit used to test null bit
- uint abs_offset; // use only in group_concat
Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uchar null_bit_arg,
utype unireg_check_arg, const char *field_name_arg,
@@ -99,6 +98,19 @@ public:
virtual void store_time(TIME *ltime,timestamp_type t_type);
virtual double val_real(void)=0;
virtual longlong val_int(void)=0;
+ inline String *val_str(String *str) { return val_str(str, str); }
+ /*
+ val_str(buf1, buf2) gets two buffers and should use them as follows:
+ if it needs a temp buffer to convert result to string - use buf1
+ example Field_tiny::val_str()
+ if the value exists as a string already - use buf2
+ example Field_string::val_str()
+ consequently, buf2 may be created as 'String buf;' - no memory
+ will be allocated for it. buf1 will be allocated to hold a
+ value if it's too small. Using allocated buffer for buf2 may result in
+ an unnecessary free (and later, may be an alloc).
+ This trickery is used to decrease a number of malloc calls.
+ */
virtual String *val_str(String*,String *)=0;
virtual Item_result result_type () const=0;
virtual Item_result cmp_type () const { return result_type(); }
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 5632c63c521..0974c552364 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -274,7 +274,7 @@ static void do_copy_blob(Copy_field *copy)
static void do_conv_blob(Copy_field *copy)
{
- copy->from_field->val_str(&copy->tmp,&copy->tmp);
+ copy->from_field->val_str(&copy->tmp);
((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
copy->tmp.length(),
copy->tmp.charset());
@@ -286,7 +286,7 @@ static void do_save_blob(Copy_field *copy)
{
char buff[MAX_FIELD_WIDTH];
String res(buff,sizeof(buff),copy->tmp.charset());
- copy->from_field->val_str(&res,&res);
+ copy->from_field->val_str(&res);
copy->tmp.copy(res);
((Field_blob *) copy->to_field)->store(copy->tmp.ptr(),
copy->tmp.length(),
@@ -298,7 +298,7 @@ static void do_field_string(Copy_field *copy)
{
char buff[MAX_FIELD_WIDTH];
copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
- copy->from_field->val_str(&copy->tmp,&copy->tmp);
+ copy->from_field->val_str(&copy->tmp);
copy->to_field->store(copy->tmp.c_ptr_quick(),copy->tmp.length(),copy->tmp.charset());
}
@@ -559,7 +559,7 @@ void field_conv(Field *to,Field *from)
if (to->type() == FIELD_TYPE_BLOB)
{ // Be sure the value is stored
Field_blob *blob=(Field_blob*) to;
- from->val_str(&blob->value,&blob->value);
+ from->val_str(&blob->value);
if (!blob->value.is_alloced() &&
from->real_type() != FIELD_TYPE_STRING)
blob->value.copy();
@@ -574,7 +574,7 @@ void field_conv(Field *to,Field *from)
{
char buff[MAX_FIELD_WIDTH];
String result(buff,sizeof(buff),from->charset());
- from->val_str(&result,&result);
+ from->val_str(&result);
to->store(result.c_ptr_quick(),result.length(),from->charset());
}
else if (from->result_type() == REAL_RESULT)
diff --git a/sql/filesort.cc b/sql/filesort.cc
index a15ffb43f6f..8699a517661 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -663,9 +663,22 @@ static void make_sortkey(register SORTPARAM *param,
for ( ; (field= addonf->field) ; addonf++)
{
if (addonf->null_bit && field->is_null())
+ {
nulls[addonf->null_offset]|= addonf->null_bit;
+#ifdef HAVE_purify
+ bzero(to, addonf->length);
+#endif
+ }
else
- field->pack((char *) to, field->ptr);
+ {
+ uchar *end= (uchar*) field->pack((char *) to, field->ptr);
+#ifdef HAVE_purify
+ uint length= (uint) ((to + addonf->length) - end);
+ DBUG_ASSERT((int) length >= 0);
+ if (length)
+ bzero(end, length);
+#endif
+ }
to+= addonf->length;
}
}
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index f13261ef52d..593b9575fb6 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -1709,6 +1709,7 @@ int ha_berkeley::extra(enum ha_extra_function operation)
int ha_berkeley::reset(void)
{
+ ha_berkeley::extra(HA_EXTRA_RESET);
key_read=0; // Reset to state after open
return 0;
}
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index 581b50501e8..88af2326eac 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -88,7 +88,7 @@ class ha_berkeley: public handler
public:
ha_berkeley(TABLE *table): handler(table), alloc_ptr(0),rec_buff(0), file(0),
int_table_flags(HA_REC_NOT_IN_SEQ |
- HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER |
+ HA_KEYPOS_TO_RNDPOS | HA_LASTKEY_ORDER | HA_FAST_KEY_READ |
HA_NULL_KEY | HA_BLOB_KEY | HA_NOT_EXACT_COUNT |
HA_PRIMARY_KEY_IN_READ_INDEX | HA_DROP_BEFORE_CREATE |
HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX |
@@ -107,7 +107,6 @@ class ha_berkeley: public handler
uint max_key_length() const { return MAX_KEY_LENGTH; }
uint extra_rec_buf_length() { return BDB_HIDDEN_PRIMARY_KEY_LENGTH; }
ha_rows estimate_number_of_rows();
- bool fast_key_read() { return 1;}
const key_map *keys_to_use_for_scanning() { return &key_map_full; }
bool has_transactions() { return 1;}
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index 94105fb9409..47978d647ec 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -196,11 +196,6 @@ int ha_heap::extra(enum ha_extra_function operation)
return heap_extra(file,operation);
}
-int ha_heap::reset(void)
-{
- return heap_extra(file,HA_EXTRA_RESET);
-}
-
int ha_heap::delete_all_rows()
{
heap_clear(file);
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index feadc0c3c0f..68406202c76 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -40,7 +40,7 @@ class ha_heap: public handler
const char **bas_ext() const;
ulong table_flags() const
{
- return (HA_READ_RND_SAME | HA_NO_INDEX | HA_KEYPOS_TO_RNDPOS |
+ return (HA_READ_RND_SAME | HA_FAST_KEY_READ | HA_KEYPOS_TO_RNDPOS |
HA_NO_BLOBS | HA_NULL_KEY | HA_REC_NOT_IN_SEQ);
}
ulong index_flags(uint inx) const
@@ -58,7 +58,6 @@ class ha_heap: public handler
double scan_time() { return (double) (records+deleted) / 20.0+10; }
double read_time(uint index, uint ranges, ha_rows rows)
{ return (double) rows / 20.0+1; }
- virtual bool fast_key_read() { return 1;}
int open(const char *name, int mode, uint test_if_locked);
int close(void);
@@ -81,7 +80,6 @@ class ha_heap: public handler
void position(const byte *record);
void info(uint);
int extra(enum ha_extra_function operation);
- int reset(void);
int external_lock(THD *thd, int lock_type);
int delete_all_rows(void);
ha_rows records_in_range(int inx, const byte *start_key,uint start_key_len,
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 307bd13885c..a5dc6719182 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -134,7 +134,6 @@ static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length,
my_bool not_used __attribute__((unused)));
static INNOBASE_SHARE *get_share(const char *table_name);
static void free_share(INNOBASE_SHARE *share);
-static void innobase_print_error(const char* db_errpfx, char* buffer);
/* General functions */
@@ -1292,18 +1291,6 @@ innobase_close_connection(
return(0);
}
-/**********************************************************************
-Prints an error message. */
-static
-void
-innobase_print_error(
-/*=================*/
- const char* db_errpfx, /* in: error prefix text */
- char* buffer) /* in: error text */
-{
- sql_print_error("%s: %s", db_errpfx, buffer);
-}
-
/*****************************************************************************
** InnoDB database tables
@@ -4554,16 +4541,6 @@ ha_innobase::extra(
}
/**********************************************************************
-????????????? */
-
-int
-ha_innobase::reset(void)
-/*====================*/
-{
- return(0);
-}
-
-/**********************************************************************
MySQL calls this function at the start of each SQL statement inside LOCK
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
mark SQL statement borders. Note also a special case: if a temporary table
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index a9e8c146d69..e5f1c66e23a 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -89,7 +89,7 @@ class ha_innobase: public handler
int_table_flags(HA_REC_NOT_IN_SEQ |
HA_KEYPOS_TO_RNDPOS |
HA_LASTKEY_ORDER |
- HA_NULL_KEY |
+ HA_NULL_KEY | HA_FAST_KEY_READ |
HA_BLOB_KEY |
HA_CAN_SQL_HANDLER |
HA_NOT_EXACT_COUNT |
@@ -123,7 +123,6 @@ class ha_innobase: public handler
whose size is > MAX_KEY_LENGTH */
uint max_key_length() const { return((MAX_KEY_LENGTH <= 3500) ?
MAX_KEY_LENGTH : 3500);}
- bool fast_key_read() { return 1;}
const key_map *keys_to_use_for_scanning() { return &key_map_full; }
bool has_transactions() { return 1;}
@@ -161,7 +160,6 @@ class ha_innobase: public handler
int optimize(THD* thd,HA_CHECK_OPT* check_opt);
int discard_or_import_tablespace(my_bool discard);
int extra(enum ha_extra_function operation);
- int reset(void);
int external_lock(THD *thd, int lock_type);
int start_stmt(THD *thd);
diff --git a/sql/ha_isam.cc b/sql/ha_isam.cc
index 52fea2f7a15..09c2aeceafc 100644
--- a/sql/ha_isam.cc
+++ b/sql/ha_isam.cc
@@ -237,11 +237,6 @@ int ha_isam::extra(enum ha_extra_function operation)
return nisam_extra(file,operation);
}
-int ha_isam::reset(void)
-{
- return nisam_extra(file,HA_EXTRA_RESET);
-}
-
int ha_isam::external_lock(THD *thd, int lock_type)
{
if (!table->tmp_table)
diff --git a/sql/ha_isam.h b/sql/ha_isam.h
index 129777e68e5..2c8ec274145 100644
--- a/sql/ha_isam.h
+++ b/sql/ha_isam.h
@@ -69,7 +69,6 @@ class ha_isam: public handler
my_off_t row_position() { return nisam_position(file); }
void info(uint);
int extra(enum ha_extra_function operation);
- int reset(void);
int external_lock(THD *thd, int lock_type);
ha_rows records_in_range(int inx,
const byte *start_key,uint start_key_len,
diff --git a/sql/ha_isammrg.cc b/sql/ha_isammrg.cc
index 8f7056a15fa..20e2b4db423 100644
--- a/sql/ha_isammrg.cc
+++ b/sql/ha_isammrg.cc
@@ -171,11 +171,6 @@ int ha_isammrg::extra(enum ha_extra_function operation)
return !mrg_extra(file,operation) ? 0 : my_errno ? my_errno : -1;
}
-int ha_isammrg::reset(void)
-{
- return !mrg_extra(file,HA_EXTRA_RESET) ? 0 : my_errno ? my_errno : -1;
-}
-
int ha_isammrg::external_lock(THD *thd, int lock_type)
{
return !mrg_lock_database(file,lock_type) ? 0 : my_errno ? my_errno : -1;
diff --git a/sql/ha_isammrg.h b/sql/ha_isammrg.h
index e5846d20212..05c1d862eb3 100644
--- a/sql/ha_isammrg.h
+++ b/sql/ha_isammrg.h
@@ -63,7 +63,6 @@ class ha_isammrg: public handler
my_off_t row_position() { return mrg_position(file); }
void info(uint);
int extra(enum ha_extra_function operation);
- int reset(void);
int external_lock(THD *thd, int lock_type);
uint lock_count(void) const;
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 6ac3c52fe40..c56009dc0aa 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -811,81 +811,92 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt)
}
/*
- Deactive all not unique index that can be recreated fast
+ disable indexes, making it persistent if requested
+ SYNOPSIS
+ disable_indexes(all, save)
+ all disable all indexes
+ if not set only non-unique indexes will be disabled
+ [all=1 is NOT IMPLEMENTED YET]
+ save save the disabled state, so that it will persist
+ between queries/threads/reboots
+ [save=0 is NOT IMPLEMENTED YET]
+*/
+int ha_myisam::disable_indexes(bool all, bool save)
+{
+ mi_extra(file, HA_EXTRA_NO_KEYS, 0);
+ info(HA_STATUS_CONST); // Read new key info
+ return 0;
+}
+
+int ha_myisam::enable_indexes()
+{
+ if (file->s->state.key_map == set_bits(ulonglong, file->s->base.keys))
+ return 0;
+
+ int error=0;
+ THD *thd=current_thd;
+ MI_CHECK param;
+ const char *save_proc_info=thd->proc_info;
+ thd->proc_info="Creating index";
+ myisamchk_init(&param);
+ param.op_name = (char*) "recreating_index";
+ param.testflag = (T_SILENT | T_REP_BY_SORT | T_QUICK |
+ T_CREATE_MISSING_KEYS);
+ param.myf_rw&= ~MY_WAIT_IF_FULL;
+ param.sort_buffer_length= thd->variables.myisam_sort_buff_size;
+ param.tmpdir=&mysql_tmpdir_list;
+ error=repair(thd,param,0) != HA_ADMIN_OK;
+ info(HA_STATUS_CONST);
+ thd->proc_info=save_proc_info;
+ return error;
+}
+
+/*
+ prepare for a many-rows insert operation
+ e.g. - disable indexes (if they can be recreated fast) or
+ activate special bulk-insert optimizations
SYNOPSIS
- deactivate_non_unique_index()
- rows Rows to be inserted
- 0 if we don't know
- HA_POS_ERROR if we want to force disabling
- and make it permanent (save on disk)
+ start_bulk_insert(rows)
+ rows Rows to be inserted
+ 0 if we don't know
*/
-void ha_myisam::deactivate_non_unique_index(ha_rows rows)
+void ha_myisam::start_bulk_insert(ha_rows rows)
{
- MYISAM_SHARE* share = file->s;
- if (share->state.key_map == ((ulonglong) 1L << share->base.keys)-1)
+ THD *thd=current_thd;
+ ulong size= min(thd->variables.read_buff_size, table->avg_row_length*rows);
+
+ mi_extra(file, HA_EXTRA_WRITE_CACHE, (void*)&size);
+
+ can_enable_indexes= (file->s->state.key_map ==
+ set_bits(ulonglong, file->s->base.keys));
+
+ if (!(specialflag & SPECIAL_SAFE_MODE))
{
- if (!(specialflag & SPECIAL_SAFE_MODE))
+ /*
+ Only disable old index if the table was empty and we are inserting
+ a lot of rows.
+ We should not do this for only a few rows as this is slower and
+ we don't want to update the key statistics based of only a few rows.
+ */
+ if (file->state->records == 0 && can_enable_indexes &&
+ (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES))
+ mi_disable_non_unique_index(file,rows);
+ else
+ if (!file->bulk_insert &&
+ (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT))
{
- if (rows == HA_POS_ERROR) // force disable and save it on disk!
- mi_extra(file, HA_EXTRA_NO_KEYS, 0);
- else
- {
- /*
- Only disable old index if the table was empty and we are inserting
- a lot of rows.
- We should not do this for only a few rows as this is slower and
- we don't want to update the key statistics based of only a few rows.
- */
- if (file->state->records == 0 &&
- (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES))
- mi_disable_non_unique_index(file,rows);
- else
- if (!file->bulk_insert &&
- (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT))
- {
- mi_init_bulk_insert(file,
- current_thd->variables.bulk_insert_buff_size,
- rows);
- }
- }
+ mi_init_bulk_insert(file, thd->variables.bulk_insert_buff_size, rows);
}
- enable_activate_all_index=1;
- info(HA_STATUS_CONST); // Read new key info
}
- else
- enable_activate_all_index=0;
}
-
-bool ha_myisam::activate_all_index(THD *thd)
+int ha_myisam::end_bulk_insert()
{
- int error=0;
- MI_CHECK param;
- MYISAM_SHARE* share = file->s;
- DBUG_ENTER("activate_all_index");
-
mi_end_bulk_insert(file);
- if (enable_activate_all_index &&
- share->state.key_map != set_bits(ulonglong, share->base.keys))
- {
- const char *save_proc_info=thd->proc_info;
- thd->proc_info="Creating index";
- myisamchk_init(&param);
- param.op_name = (char*) "recreating_index";
- param.testflag = (T_SILENT | T_REP_BY_SORT | T_QUICK |
- T_CREATE_MISSING_KEYS);
- param.myf_rw&= ~MY_WAIT_IF_FULL;
- param.sort_buffer_length= thd->variables.myisam_sort_buff_size;
- param.tmpdir=&mysql_tmpdir_list;
- error=repair(thd,param,0) != HA_ADMIN_OK;
- info(HA_STATUS_CONST);
- thd->proc_info=save_proc_info;
- }
- else
- enable_activate_all_index=1;
- DBUG_RETURN(error);
+ int err=mi_extra(file, HA_EXTRA_NO_CACHE, 0);
+ return err ? err : can_enable_indexes ? enable_indexes() : 0;
}
@@ -1118,12 +1129,6 @@ int ha_myisam::extra_opt(enum ha_extra_function operation, ulong cache_size)
return mi_extra(file, operation, (void*) &cache_size);
}
-
-int ha_myisam::reset(void)
-{
- return mi_extra(file, HA_EXTRA_RESET, 0);
-}
-
int ha_myisam::delete_all_rows()
{
return mi_delete_all_rows(file);
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index 4d66639690d..ca318b02778 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -39,7 +39,7 @@ class ha_myisam: public handler
MI_INFO *file;
ulong int_table_flags;
char *data_file_name, *index_file_name;
- bool enable_activate_all_index;
+ bool can_enable_indexes;
int repair(THD *thd, MI_CHECK &param, bool optimize);
public:
@@ -48,7 +48,7 @@ class ha_myisam: public handler
HA_NULL_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
HA_DUPP_POS | HA_BLOB_KEY | HA_AUTO_PART_KEY |
HA_FILE_BASED | HA_HAS_GEOMETRY),
- enable_activate_all_index(1)
+ can_enable_indexes(1)
{}
~ha_myisam() {}
const char *table_type() const { return "MyISAM"; }
@@ -103,11 +103,12 @@ class ha_myisam: public handler
void info(uint);
int extra(enum ha_extra_function operation);
int extra_opt(enum ha_extra_function operation, ulong cache_size);
- int reset(void);
int external_lock(THD *thd, int lock_type);
int delete_all_rows(void);
- void deactivate_non_unique_index(ha_rows rows);
- bool activate_all_index(THD *thd);
+ int disable_indexes(bool all, bool save);
+ int enable_indexes();
+ void start_bulk_insert(ha_rows rows);
+ int end_bulk_insert();
ha_rows records_in_range(int inx,
const byte *start_key,uint start_key_len,
enum ha_rkey_function start_search_flag,
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 7c36f6c6e0e..041d9eaead3 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -271,12 +271,6 @@ int ha_myisammrg::extra_opt(enum ha_extra_function operation, ulong cache_size)
return myrg_extra(file, operation, (void*) &cache_size);
}
-
-int ha_myisammrg::reset(void)
-{
- return myrg_extra(file,HA_EXTRA_RESET,0);
-}
-
int ha_myisammrg::external_lock(THD *thd, int lock_type)
{
return myrg_lock_database(file,lock_type);
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index ea53b40739d..c0f81a77a1e 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -79,7 +79,6 @@ class ha_myisammrg: public handler
void info(uint);
int extra(enum ha_extra_function operation);
int extra_opt(enum ha_extra_function operation, ulong cache_size);
- int reset(void);
int external_lock(THD *thd, int lock_type);
uint lock_count(void) const;
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
diff --git a/sql/handler.h b/sql/handler.h
index 26fb762a9b5..80a3c2e7f1b 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -51,7 +51,7 @@
#define HA_REC_NOT_IN_SEQ 8 /* ha_info don't return recnumber;
It returns a position to ha_r_rnd */
#define HA_HAS_GEOMETRY (1 << 4)
-#define HA_NO_INDEX (1 << 5) /* No index needed for next/prev */
+#define HA_FAST_KEY_READ (1 << 5) /* no need for a record cache in filesort */
#define HA_KEY_READ_WRONG_STR (1 << 6) /* keyread returns converted strings */
#define HA_NULL_KEY (1 << 7) /* One can have keys with NULL */
#define HA_DUPP_POS (1 << 8) /* ha_position() gives dupp row */
@@ -90,6 +90,20 @@
#define HA_NOT_READ_PREFIX_LAST 32 /* No support for index_read_last() */
#define HA_KEY_READ_ONLY 64 /* Support HA_EXTRA_KEYREAD */
+
+/*
+ Bits in index_ddl_flags(KEY *wanted_index)
+ for what ddl you can do with index
+ If none is set, the wanted type of index is not supported
+ by the handler at all. See WorkLog 1563.
+*/
+#define HA_DDL_SUPPORT 1 /* Supported by handler */
+#define HA_DDL_WITH_LOCK 2 /* Can create/drop with locked table */
+#define HA_DDL_ONLINE 4 /* Can create/drop without lock */
+
+/* Return value for ddl methods */
+#define HA_DDL_NOT_IMPLEMENTED -1
+
/*
Parameters for open() (in register form->filestat)
HA_GET_INFO does an implicit HA_ABORT_IF_LOCKED
@@ -256,7 +270,6 @@ public:
{ return ulonglong2double(data_file_length) / IO_SIZE + 2; }
virtual double read_time(uint index, uint ranges, ha_rows rows)
{ return rows2double(ranges+rows); }
- virtual bool fast_key_read() { return 0;}
virtual const key_map *keys_to_use_for_scanning() { return &key_map_empty; }
virtual bool has_transactions(){ return 0;}
virtual uint extra_rec_buf_length() { return 0; }
@@ -310,7 +323,7 @@ public:
{
return extra(operation);
}
- virtual int reset()=0;
+ virtual int reset() { return extra(HA_EXTRA_RESET); }
virtual int external_lock(THD *thd, int lock_type)=0;
virtual void unlock_row() {}
virtual int start_stmt(THD *thd) {return 0;}
@@ -331,8 +344,10 @@ public:
*/
virtual int restore(THD* thd, HA_CHECK_OPT* check_opt);
virtual int dump(THD* thd, int fd = -1) { return ER_DUMP_NOT_IMPLEMENTED; }
- virtual void deactivate_non_unique_index(ha_rows rows) {}
- virtual bool activate_all_index(THD *thd) {return 0;}
+ virtual int disable_indexes(bool all, bool save) { return HA_ERR_WRONG_COMMAND; }
+ virtual int enable_indexes() { return HA_ERR_WRONG_COMMAND; }
+ virtual void start_bulk_insert(ha_rows rows) {}
+ virtual int end_bulk_insert() {return 0; }
virtual int discard_or_import_tablespace(my_bool discard) {return -1;}
// not implemented by default
virtual int net_read_dump(NET* net)
@@ -355,6 +370,20 @@ public:
{
return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_KEY_READ_ONLY);
}
+ virtual ulong index_ddl_flags(KEY *wanted_index) const
+ {
+ return (HA_DDL_SUPPORT);
+ }
+ virtual int add_index(TABLE *table, KEY *key_info, uint num_of_keys)
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "online add index");
+ return (HA_DDL_NOT_IMPLEMENTED);
+ }
+ virtual int drop_index(TABLE *table, uint *key_num, uint num_of_keys)
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "online drop index");
+ return (HA_DDL_NOT_IMPLEMENTED);
+ }
virtual uint max_record_length() const =0;
virtual uint max_keys() const =0;
virtual uint max_key_parts() const =0;
diff --git a/sql/init.cc b/sql/init.cc
index 084db57f8aa..4beb8db0c6f 100644
--- a/sql/init.cc
+++ b/sql/init.cc
@@ -46,7 +46,5 @@ void unireg_init(ulong options)
log_10[i]= nr ; nr*= 10.0;
}
specialflag|=options; /* Set options from argv */
-
- thread_stack_min=thread_stack - STACK_MIN_SIZE;
DBUG_VOID_RETURN;
}
diff --git a/sql/item.cc b/sql/item.cc
index 1efed78799a..65e1e67c7c6 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -771,7 +771,6 @@ String *Item_param::query_val_str(String* str)
case INT_RESULT:
case REAL_RESULT:
return val_str(str);
- break;
default:
str->set("'", 1, default_charset());
@@ -1972,7 +1971,7 @@ bool field_is_equal_to_item(Field *field,Item *item)
item_result=item->val_str(&item_tmp);
if (item->null_value)
return 1; // This must be true
- field->val_str(&field_tmp,&field_tmp);
+ field->val_str(&field_tmp);
return !stringcmp(&field_tmp,item_result);
}
if (res_type == INT_RESULT)
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index d5842189f07..8da517a8d99 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1474,16 +1474,12 @@ cmp_item* cmp_item::get_comparator(Item *item)
switch (item->result_type()) {
case STRING_RESULT:
return new cmp_item_sort_string(item->collation.collation);
- break;
case INT_RESULT:
return new cmp_item_int;
- break;
case REAL_RESULT:
return new cmp_item_real;
- break;
case ROW_RESULT:
return new cmp_item_row;
- break;
default:
DBUG_ASSERT(0);
break;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index fdc0ee9d6a0..d7e778171a0 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1143,7 +1143,6 @@ String *Item_func_min_max::val_str(String *str)
// This case should never be choosen
DBUG_ASSERT(0);
return 0;
-
}
return 0; // Keep compiler happy
}
@@ -2442,7 +2441,6 @@ Item_func_set_user_var::check()
save_result.vint= args[0]->val_int();
break;
}
- break;
case STRING_RESULT:
{
save_result.vstr= args[0]->val_str(&value);
@@ -2494,7 +2492,6 @@ Item_func_set_user_var::update()
INT_RESULT, &my_charset_bin, DERIVATION_NONE);
break;
}
- break;
case STRING_RESULT:
{
if (!save_result.vstr) // Null value
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index a1305e0b1d9..555c1a74eaf 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -66,7 +66,6 @@ String *Item_func_geometry_from_wkb::val_str(String *str)
String arg_val;
String *wkb= args[0]->val_str(&arg_val);
Geometry_buffer buffer;
- Geometry *geom;
uint32 srid= 0;
if ((arg_count == 2) && !args[1]->null_value)
@@ -78,7 +77,7 @@ String *Item_func_geometry_from_wkb::val_str(String *str)
str->q_append(srid);
if ((null_value=
(args[0]->null_value ||
- !(geom= Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length())) ||
+ !Geometry::create_from_wkb(&buffer, wkb->ptr(), wkb->length()) ||
str->append(*wkb))))
return 0;
return str;
@@ -126,12 +125,11 @@ String *Item_func_as_wkb::val_str(String *str)
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
Geometry_buffer buffer;
- Geometry *geom;
if ((null_value=
(args[0]->null_value ||
- !(geom= Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE)))))
+ !(Geometry::create_from_wkb(&buffer, swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE)))))
return 0;
str->copy(swkb->ptr() + SRID_SIZE, swkb->length() - SRID_SIZE,
@@ -701,10 +699,10 @@ longlong Item_func_srid::val_int()
Geometry_buffer buffer;
Geometry *geom;
- null_value= !swkb ||
- !(geom= Geometry::create_from_wkb(&buffer,
- swkb->ptr() + SRID_SIZE,
- swkb->length() - SRID_SIZE));
+ null_value= (!swkb ||
+ !Geometry::create_from_wkb(&buffer,
+ swkb->ptr() + SRID_SIZE,
+ swkb->length() - SRID_SIZE));
if (null_value)
return 0;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 26b859c8aba..eac8d31b256 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -41,7 +41,11 @@ Item_sum::Item_sum(List<Item> &list)
list.empty(); // Fields are used
}
-// Constructor used in processing select with temporary tebles
+
+/*
+ Constructor used in processing select with temporary tebles
+*/
+
Item_sum::Item_sum(THD *thd, Item_sum *item):
Item_result_field(thd, item), arg_count(item->arg_count),
quick_group(item->quick_group)
@@ -937,7 +941,7 @@ Item_sum_hybrid::min_max_update_str_field()
if (!args[0]->null_value)
{
res_str->strip_sp();
- result_field->val_str(&tmp_value,&tmp_value);
+ result_field->val_str(&tmp_value);
if (result_field->is_null() ||
(cmp_sign * sortcmp(res_str,&tmp_value,cmp_charset)) < 0)
@@ -1538,10 +1542,17 @@ String *Item_sum_udf_str::val_str(String *str)
/*****************************************************************************
GROUP_CONCAT function
- Syntax:
- GROUP_CONCAT([DISTINCT] expr,... [ORDER BY col [ASC|DESC],...]
- [SEPARATOR str_const])
+
+ SQL SYNTAX:
+ GROUP_CONCAT([DISTINCT] expr,... [ORDER BY col [ASC|DESC],...]
+ [SEPARATOR str_const])
+
concat of values from "group by" operation
+
+ BUGS
+ DISTINCT and ORDER BY only works if ORDER BY uses all fields and only fields
+ in expression list
+ Blobs doesn't work with DISTINCT or ORDER BY
*****************************************************************************/
/*
@@ -1552,25 +1563,28 @@ String *Item_sum_udf_str::val_str(String *str)
int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
byte* key2)
{
- Item_func_group_concat* item= (Item_func_group_concat*)arg;
+ Item_func_group_concat* grp_item= (Item_func_group_concat*)arg;
+ Item **field_item, **end;
+ char *record= (char*) grp_item->table->record[0];
- for (uint i= 0; i < item->arg_count_field; i++)
+ for (field_item= grp_item->args, end= field_item + grp_item->arg_count_field;
+ field_item < end;
+ field_item++)
{
- Item *field_item= item->args[i];
- Field *field= field_item->real_item()->get_tmp_table_field();
+ /*
+ We have to use get_tmp_table_field() instead of
+ real_item()->get_tmp_table_field() because we want the field in
+ the temporary table, not the original field
+ */
+ Field *field= (*field_item)->get_tmp_table_field();
if (field)
{
- uint offset= field->abs_offset;
-
- int res= field->key_cmp(key1 + offset, key2 + offset);
- /*
- if key1 and key2 is not equal than field->key_cmp return offset. This
- function must return value 1 for this case.
- */
- if (res)
- return 1;
+ int res;
+ uint offset= (uint) (field->ptr - record);
+ if ((res= field->key_cmp(key1 + offset, key2 + offset)))
+ return res;
}
- }
+ }
return 0;
}
@@ -1582,26 +1596,34 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
{
- Item_func_group_concat* item= (Item_func_group_concat*)arg;
+ Item_func_group_concat* grp_item= (Item_func_group_concat*) arg;
+ ORDER **order_item, **end;
+ char *record= (char*) grp_item->table->record[0];
- for (uint i=0; i < item->arg_count_order; i++)
+ for (order_item= grp_item->order, end=order_item+ grp_item->arg_count_order;
+ order_item < end;
+ order_item++)
{
- ORDER *order_item= item->order[i];
- Item *item= *order_item->item;
- Field *field= item->real_item()->get_tmp_table_field();
+ Item *item= *(*order_item)->item;
+ /*
+ We have to use get_tmp_table_field() instead of
+ real_item()->get_tmp_table_field() because we want the field in
+ the temporary table, not the original field
+ */
+ Field *field= item->get_tmp_table_field();
if (field)
{
- uint offset= field->abs_offset;
-
- bool dir= order_item->asc;
- int res= field->key_cmp(key1 + offset, key2 + offset);
- if (res)
- return dir ? res : -res;
+ int res;
+ uint offset= (uint) (field->ptr - record);
+ if ((res= field->key_cmp(key1 + offset, key2 + offset)))
+ return (*order_item)->asc ? res : -res;
}
- }
+ }
/*
- We can't return 0 because tree class remove this item as double value.
- */
+ We can't return 0 because in that case the tree class would remove this
+ item as double value. This would cause problems for case-changes and
+ if the the returned values are not the same we do the sort on.
+ */
return 1;
}
@@ -1609,6 +1631,11 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
/*
function of sort for syntax:
GROUP_CONCAT(DISTINCT expr,... ORDER BY col,... )
+
+ BUG:
+ This doesn't work in the case when the order by contains data that
+ is not part of the field list because tree-insert will not notice
+ the duplicated values when inserting things sorted by ORDER BY
*/
int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1,
@@ -1621,58 +1648,60 @@ int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1,
/*
- create result
- item is pointer to Item_func_group_concat
+ Append data from current leaf to item->result
*/
int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
- Item_func_group_concat *group_concat_item)
+ Item_func_group_concat *item)
{
char buff[MAX_FIELD_WIDTH];
- String tmp((char *)&buff,sizeof(buff),default_charset_info);
- String tmp2((char *)&buff,sizeof(buff),default_charset_info);
-
+ String tmp((char *)&buff,sizeof(buff),default_charset_info), tmp2;
+ char *record= (char*) item->table->record[0];
+
tmp.length(0);
- for (uint i= 0; i < group_concat_item->arg_show_fields; i++)
+ for (uint i= 0; i < item->arg_count_field; i++)
{
- Item *show_item= group_concat_item->args[i];
+ Item *show_item= item->args[i];
if (!show_item->const_item())
{
- Field *f= show_item->real_item()->get_tmp_table_field();
- char *sv= f->ptr;
- f->ptr= (char *)key + f->abs_offset;
- String *res= f->val_str(&tmp,&tmp2);
- group_concat_item->result.append(*res);
- f->ptr= sv;
+ /*
+ We have to use get_tmp_table_field() instead of
+ real_item()->get_tmp_table_field() because we want the field in
+ the temporary table, not the original field
+ */
+ Field *field= show_item->get_tmp_table_field();
+ String *res;
+ char *save_ptr= field->ptr;
+ uint offset= (uint) (save_ptr - record);
+ DBUG_ASSERT(offset < item->table->reclength);
+ field->ptr= (char *) key + offset;
+ res= field->val_str(&tmp,&tmp2);
+ item->result.append(*res);
+ field->ptr= save_ptr;
}
else
{
String *res= show_item->val_str(&tmp);
if (res)
- group_concat_item->result.append(*res);
+ item->result.append(*res);
}
}
- if (group_concat_item->tree_mode) // Last item of tree
+ if (item->tree_mode) // Last item of tree
{
- group_concat_item->show_elements++;
- if (group_concat_item->show_elements <
- group_concat_item->tree->elements_in_tree)
- group_concat_item->result.append(*group_concat_item->separator);
+ item->show_elements++;
+ if (item->show_elements < item->tree->elements_in_tree)
+ item->result.append(*item->separator);
}
else
+ item->result.append(*item->separator);
+
+ /* stop if length of result more than group_concat_max_len */
+ if (item->result.length() > item->group_concat_max_len)
{
- group_concat_item->result.append(*group_concat_item->separator);
- }
- /*
- if length of result more than group_concat_max_len - stop !
- */
- if (group_concat_item->result.length() >
- group_concat_item->group_concat_max_len)
- {
- group_concat_item->count_cut_values++;
- group_concat_item->result.length(group_concat_item->group_concat_max_len);
- group_concat_item->warning_for_row= TRUE;
+ item->count_cut_values++;
+ item->result.length(item->group_concat_max_len);
+ item->warning_for_row= TRUE;
return 1;
}
return 0;
@@ -1692,56 +1721,86 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
SQL_LIST *is_order,
String *is_separator)
:Item_sum(), tmp_table_param(0), max_elements_in_tree(0), warning(0),
- warning_available(0), key_length(0), rec_offset(0),
+ warning_available(0), key_length(0),
tree_mode(0), distinct(is_distinct), warning_for_row(0),
separator(is_separator), tree(&tree_base), table(0),
order(0), tables_list(0),
show_elements(0), arg_count_order(0), arg_count_field(0),
- arg_show_fields(0), count_cut_values(0)
-
+ count_cut_values(0)
{
+ Item *item_select;
+ Item **arg_ptr;
+
original= 0;
quick_group= 0;
mark_as_sum_func();
order= 0;
group_concat_max_len= current_thd->variables.group_concat_max_len;
-
- arg_show_fields= arg_count_field= is_select->elements;
+ arg_count_field= is_select->elements;
arg_count_order= is_order ? is_order->elements : 0;
- arg_count= arg_count_field;
+ arg_count= arg_count_field + arg_count_order;
/*
We need to allocate:
- args - arg_count+arg_count_order (for possible order items in temporare
- tables)
+ args - arg_count_field+arg_count_order
+ (for possible order items in temporare tables)
order - arg_count_order
*/
- args= (Item**) sql_alloc(sizeof(Item*)*(arg_count+arg_count_order)+
- sizeof(ORDER*)*arg_count_order);
- if (!args)
+ if (!(args= (Item**) sql_alloc(sizeof(Item*) * arg_count +
+ sizeof(ORDER*)*arg_count_order)))
return;
+ order= (ORDER**)(args + arg_count);
+
/* fill args items of show and sort */
- int i= 0;
List_iterator_fast<Item> li(*is_select);
- Item *item_select;
- for ( ; (item_select= li++) ; i++)
- args[i]= item_select;
+ for (arg_ptr=args ; (item_select= li++) ; arg_ptr++)
+ *arg_ptr= item_select;
if (arg_count_order)
{
- i= 0;
- order= (ORDER**)(args + arg_count + arg_count_order);
+ ORDER **order_ptr= order;
for (ORDER *order_item= (ORDER*) is_order->first;
- order_item != NULL;
- order_item= order_item->next)
+ order_item != NULL;
+ order_item= order_item->next)
{
- order[i++]= order_item;
+ (*order_ptr++)= order_item;
+ *arg_ptr= *order_item->item;
+ order_item->item= arg_ptr++;
}
}
}
+
+
+Item_func_group_concat::Item_func_group_concat(THD *thd,
+ Item_func_group_concat *item)
+ :Item_sum(thd, item),item_thd(thd),
+ tmp_table_param(item->tmp_table_param),
+ max_elements_in_tree(item->max_elements_in_tree),
+ warning(item->warning),
+ warning_available(item->warning_available),
+ key_length(item->key_length),
+ tree_mode(item->tree_mode),
+ distinct(item->distinct),
+ warning_for_row(item->warning_for_row),
+ separator(item->separator),
+ tree(item->tree),
+ table(item->table),
+ order(item->order),
+ tables_list(item->tables_list),
+ group_concat_max_len(item->group_concat_max_len),
+ show_elements(item->show_elements),
+ arg_count_order(item->arg_count_order),
+ arg_count_field(item->arg_count_field),
+ field_list_offset(item->field_list_offset),
+ count_cut_values(item->count_cut_values),
+ original(item)
+{
+ quick_group= item->quick_group;
+}
+
void Item_func_group_concat::cleanup()
@@ -1785,12 +1844,11 @@ Item_func_group_concat::~Item_func_group_concat()
*/
if (!original)
{
- THD *thd= current_thd;
if (warning_available)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff, ER(ER_CUT_VALUE_GROUP_CONCAT), count_cut_values);
- warning->set_msg(thd, warn_buff);
+ warning->set_msg(current_thd, warn_buff);
}
}
}
@@ -1826,33 +1884,31 @@ bool Item_func_group_concat::add()
copy_fields(tmp_table_param);
copy_funcs(tmp_table_param->items_to_copy);
- bool record_is_null= TRUE;
- for (uint i= 0; i < arg_show_fields; i++)
+ for (uint i= 0; i < arg_count_field; i++)
{
Item *show_item= args[i];
if (!show_item->const_item())
{
+ /*
+ Here we use real_item as we want the original field data that should
+ be written to table->record[0]
+ */
Field *f= show_item->real_item()->get_tmp_table_field();
- if (!f->is_null())
- {
- record_is_null= FALSE;
- break;
- }
+ if (f->is_null())
+ return 0; // Skip row if it contains null
}
}
- if (record_is_null)
- return 0;
+
null_value= FALSE;
if (tree_mode)
{
- if (!tree_insert(tree, table->record[0] + rec_offset, 0, tree->custom_arg))
+ if (!tree_insert(tree, table->record[0], 0, tree->custom_arg))
return 1;
}
else
{
if (result.length() <= group_concat_max_len && !warning_for_row)
- dump_leaf_key(table->record[0] + rec_offset, 1,
- (Item_func_group_concat*)this);
+ dump_leaf_key(table->record[0], 1, this);
}
return 0;
}
@@ -1884,24 +1940,19 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
thd->allow_sum_func= 0;
maybe_null= 0;
item_thd= thd;
- for (i= 0 ; i < arg_count ; i++)
- {
- if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
- return 1;
- maybe_null |= args[i]->maybe_null;
- }
+
/*
- Fix fields for order clause in function:
- GROUP_CONCAT(expr,... ORDER BY col,... )
+ Fix fields for select list and ORDER clause
*/
- for (i= 0 ; i < arg_count_order ; i++)
+
+ for (i= 0 ; i < arg_count ; i++)
{
- // order_item->item can be changed by fix_fields() call
- ORDER *order_item= order[i];
- if ((*order_item->item)->fix_fields(thd, tables, order_item->item) ||
- (*order_item->item)->check_cols(1))
+ if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
return 1;
+ if (i < arg_count_field && args[i]->maybe_null)
+ maybe_null= 0;
}
+
result_field= 0;
null_value= 1;
max_length= group_concat_max_len;
@@ -1916,23 +1967,29 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
bool Item_func_group_concat::setup(THD *thd)
{
- DBUG_ENTER("Item_func_group_concat::setup");
List<Item> list;
SELECT_LEX *select_lex= thd->lex->current_select;
+ uint const_fields;
+ byte *record;
+ qsort_cmp2 compare_key;
+ DBUG_ENTER("Item_func_group_concat::setup");
if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
DBUG_RETURN(1);
+
/*
push all not constant fields to list and create temp table
*/
+ const_fields= 0;
always_null= 0;
- for (uint i= 0; i < arg_count; i++)
+ for (uint i= 0; i < arg_count_field; i++)
{
Item *item= args[i];
if (list.push_back(item))
DBUG_RETURN(1);
if (item->const_item())
{
+ const_fields++;
(void) item->val_int();
if (item->null_value)
always_null= 1;
@@ -1952,12 +2009,19 @@ bool Item_func_group_concat::setup(THD *thd)
count_field_types(tmp_table_param,all_fields,0);
if (table)
{
+ /*
+ We come here when we are getting the result from a temporary table,
+ not the original tables used in the query
+ */
free_tmp_table(thd, table);
tmp_table_param->cleanup();
}
/*
- We have to create a temporary table for that we get descriptions of fields
+ We have to create a temporary table to get descriptions of fields
(types, sizes and so on).
+
+ Note that in the table, we first have the ORDER BY fields, then the
+ field list.
*/
if (!(table=create_tmp_table(thd, tmp_table_param, all_fields, 0,
0, 0, 0,select_lex->options | thd->options,
@@ -1966,27 +2030,17 @@ bool Item_func_group_concat::setup(THD *thd)
table->file->extra(HA_EXTRA_NO_ROWS);
table->no_rows= 1;
+ key_length= table->reclength;
+ record= table->record[0];
- Field** field, **field_end;
- field_end = (field = table->field) + table->fields;
- uint offset = 0;
- for (key_length = 0; field < field_end; ++field)
- {
- uint32 length= (*field)->pack_length();
- (*field)->abs_offset= offset;
- offset+= length;
- key_length += length;
- }
- rec_offset = table->reclength - key_length;
-
+ /* Offset to first result field in table */
+ field_list_offset= table->fields - (list.elements - const_fields);
if (tree_mode)
delete_tree(tree);
- /*
- choise function of sort
- */
+
+ /* choose function of sort */
tree_mode= distinct || arg_count_order;
- qsort_cmp2 compare_key;
if (tree_mode)
{
if (arg_count_order)
@@ -1998,21 +2052,20 @@ bool Item_func_group_concat::setup(THD *thd)
}
else
{
+ compare_key= NULL;
if (distinct)
compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct;
- else
- compare_key= NULL;
}
/*
- Create a tree of sort. Tree is used for a sort and a remove dubl
- values (according with syntax of the function). If function does't
+ Create a tree of sort. Tree is used for a sort and a remove double
+ values (according with syntax of the function). If function doesn't
contain DISTINCT and ORDER BY clauses, we don't create this tree.
*/
init_tree(tree, min(thd->variables.max_heap_table_size,
- thd->variables.sortbuff_size/16), 0,
+ thd->variables.sortbuff_size/16), 0,
key_length, compare_key, 0, NULL, (void*) this);
- max_elements_in_tree= ((key_length) ?
- thd->variables.max_heap_table_size/key_length : 1);
+ max_elements_in_tree= (key_length ?
+ thd->variables.max_heap_table_size/key_length : 1);
};
/*
@@ -2027,6 +2080,7 @@ bool Item_func_group_concat::setup(THD *thd)
DBUG_RETURN(0);
}
+
/* This is used by rollup to create a separate usable copy of the function */
void Item_func_group_concat::make_unique()
@@ -2069,7 +2123,7 @@ void Item_func_group_concat::print(String *str)
str->append("group_concat(", 13);
if (distinct)
str->append("distinct ", 9);
- for (uint i= 0; i < arg_count; i++)
+ for (uint i= 0; i < arg_count_field; i++)
{
if (i)
str->append(',');
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 8a51a7e5a7c..107c19b7d85 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -197,18 +197,24 @@ class Item_sum_count_distinct :public Item_sum_int
uint key_length;
CHARSET_INFO *key_charset;
- // calculated based on max_heap_table_size. If reached,
- // walk the tree and dump it into MyISAM table
+ /*
+ Calculated based on max_heap_table_size. If reached,
+ walk the tree and dump it into MyISAM table
+ */
uint max_elements_in_tree;
- // the first few bytes of record ( at least one)
- // are just markers for deleted and NULLs. We want to skip them since
- // they will just bloat the tree without providing any valuable info
+ /*
+ The first few bytes of record ( at least one)
+ are just markers for deleted and NULLs. We want to skip them since
+ they will just bloat the tree without providing any valuable info
+ */
int rec_offset;
- // If there are no blobs, we can use a tree, which
- // is faster than heap table. In that case, we still use the table
- // to help get things set up, but we insert nothing in it
+ /*
+ If there are no blobs, we can use a tree, which
+ is faster than heap table. In that case, we still use the table
+ to help get things set up, but we insert nothing in it
+ */
bool use_tree;
bool always_null; // Set to 1 if the result is always NULL
@@ -312,18 +318,17 @@ public:
void fix_length_and_dec() {}
};
-/*
-
-variance(a) =
-
-= sum (ai - avg(a))^2 / count(a) )
-= sum (ai^2 - 2*ai*avg(a) + avg(a)^2) / count(a)
-= (sum(ai^2) - sum(2*ai*avg(a)) + sum(avg(a)^2))/count(a) =
-= (sum(ai^2) - 2*avg(a)*sum(a) + count(a)*avg(a)^2)/count(a) =
-= (sum(ai^2) - 2*sum(a)*sum(a)/count(a) + count(a)*sum(a)^2/count(a)^2 )/count(a) =
-= (sum(ai^2) - 2*sum(a)^2/count(a) + sum(a)^2/count(a) )/count(a) =
-= (sum(ai^2) - sum(a)^2/count(a))/count(a)
+/*
+ variance(a) =
+
+ = sum (ai - avg(a))^2 / count(a) )
+ = sum (ai^2 - 2*ai*avg(a) + avg(a)^2) / count(a)
+ = (sum(ai^2) - sum(2*ai*avg(a)) + sum(avg(a)^2))/count(a) =
+ = (sum(ai^2) - 2*avg(a)*sum(a) + count(a)*avg(a)^2)/count(a) =
+ = (sum(ai^2) - 2*sum(a)*sum(a)/count(a) + count(a)*sum(a)^2/count(a)^2 )/count(a) =
+ = (sum(ai^2) - 2*sum(a)^2/count(a) + sum(a)^2/count(a) )/count(a) =
+ = (sum(ai^2) - sum(a)^2/count(a))/count(a)
*/
class Item_sum_variance : public Item_sum_num
@@ -509,8 +514,9 @@ class Item_sum_xor :public Item_sum_bit
/*
-** user defined aggregates
+ User defined aggregates
*/
+
#ifdef HAVE_DLOPEN
class Item_udf_sum : public Item_sum
@@ -668,7 +674,6 @@ class Item_func_group_concat : public Item_sum
MYSQL_ERROR *warning;
bool warning_available;
uint key_length;
- int rec_offset;
bool tree_mode;
bool distinct;
bool warning_for_row;
@@ -676,12 +681,13 @@ class Item_func_group_concat : public Item_sum
friend int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
byte* key2);
- friend int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2);
+ friend int group_concat_key_cmp_with_order(void* arg, byte* key1,
+ byte* key2);
friend int group_concat_key_cmp_with_distinct_and_order(void* arg,
byte* key1,
byte* key2);
friend int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
- Item_func_group_concat *group_concat_item);
+ Item_func_group_concat *group_concat_item);
public:
String result;
@@ -695,7 +701,7 @@ class Item_func_group_concat : public Item_sum
uint show_elements;
uint arg_count_order;
uint arg_count_field;
- uint arg_show_fields;
+ uint field_list_offset;
uint count_cut_values;
/*
Following is 0 normal object and pointer to original one for copy
@@ -706,38 +712,12 @@ class Item_func_group_concat : public Item_sum
Item_func_group_concat(bool is_distinct,List<Item> *is_select,
SQL_LIST *is_order,String *is_separator);
- Item_func_group_concat(THD *thd, Item_func_group_concat *item)
- :Item_sum(thd, item),item_thd(thd),
- tmp_table_param(item->tmp_table_param),
- max_elements_in_tree(item->max_elements_in_tree),
- warning(item->warning),
- warning_available(item->warning_available),
- key_length(item->key_length),
- rec_offset(item->rec_offset),
- tree_mode(item->tree_mode),
- distinct(item->distinct),
- warning_for_row(item->warning_for_row),
- separator(item->separator),
- tree(item->tree),
- table(item->table),
- order(item->order),
- tables_list(item->tables_list),
- group_concat_max_len(item->group_concat_max_len),
- show_elements(item->show_elements),
- arg_count_order(item->arg_count_order),
- arg_count_field(item->arg_count_field),
- arg_show_fields(item->arg_show_fields),
- count_cut_values(item->count_cut_values),
- original(item)
- {
- quick_group= item->quick_group;
- };
+ Item_func_group_concat(THD *thd, Item_func_group_concat *item);
~Item_func_group_concat();
void cleanup();
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
const char *func_name() const { return "group_concat"; }
- enum Type type() const { return SUM_FUNC_ITEM; }
virtual Item_result result_type () const { return STRING_RESULT; }
void clear();
bool add();
diff --git a/sql/key.cc b/sql/key.cc
index d4499573e8e..a2c3b2c8989 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -233,7 +233,7 @@ void key_unpack(String *to,TABLE *table,uint idx)
}
if ((field=key_part->field))
{
- field->val_str(&tmp,&tmp);
+ field->val_str(&tmp);
if (key_part->length < field->pack_length())
tmp.length(min(tmp.length(),key_part->length));
to->append(tmp);
diff --git a/sql/lex.h b/sql/lex.h
index ceef140b5f7..94ea0295f05 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -122,6 +122,7 @@ static SYMBOL symbols[] = {
{ "CURRENT_DATE", SYM(CURDATE)},
{ "CURRENT_TIME", SYM(CURTIME)},
{ "CURRENT_TIMESTAMP", SYM(NOW_SYM)},
+ { "CURRENT_USER", SYM(CURRENT_USER)},
{ "DATA", SYM(DATA_SYM)},
{ "DATABASE", SYM(DATABASE)},
{ "DATABASES", SYM(DATABASES)},
@@ -481,7 +482,6 @@ static SYMBOL sql_functions[] = {
{ "CAST", SYM(CAST_SYM)},
{ "CEIL", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)},
{ "CEILING", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)},
- { "CURRENT_USER", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_current_user)},
{ "BIT_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_length)},
{ "CENTROID", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_centroid)},
{ "CHAR_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
diff --git a/sql/log.cc b/sql/log.cc
index 6b091484a82..0cd9e7172c3 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -507,7 +507,6 @@ int MYSQL_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name,
RETURN VALUES
0 ok
LOG_INFO_EOF End of log-index-file found
- LOG_INFO_SEEK Could not allocate IO cache
LOG_INFO_IO Got IO error while reading file
*/
diff --git a/sql/log_event.cc b/sql/log_event.cc
index cd0324a72ca..3b92e0956ba 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -83,7 +83,7 @@ inline int ignored_error_code(int err_code)
pretty_print_str()
*/
-#ifndef MYSQL_CLIENT
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
static char *pretty_print_str(char *packet, char *str, int len)
{
char *end= str + len;
@@ -1698,7 +1698,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
tables.alias = tables.real_name = (char*)table_name;
tables.lock_type = TL_WRITE;
tables.updating= 1;
- tables.non_cachable_table= 1; // just safety for table on stack
+
// the table will be opened in mysql_load
if (table_rules_on && !tables_ok(thd, &tables))
{
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 44e241b9d4c..78e0efa7ceb 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -495,6 +495,11 @@ int mysql_handle_derived(LEX *lex);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field,
bool group,bool modify_item);
+int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
+ List<create_field> &fields,
+ List<Key> &keys, uint &db_options,
+ handler *file, KEY *&key_info_buffer,
+ uint &key_count, int 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,
@@ -511,11 +516,23 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list,
- uint order_num, ORDER *order,
+ uint order_num, ORDER *order, int alter_flags,
enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
enum tablespace_op_type tablespace_op=NO_TABLESPACE_OP,
bool simple_alter=0);
+int real_alter_table(THD *thd, char *new_db, char *new_name,
+ HA_CREATE_INFO *create_info,
+ TABLE_LIST *table_list,
+ TABLE *table,
+ List<create_field> &fields,
+ List<Key> &keys,List<Alter_drop> &drop_list,
+ List<Alter_column> &alter_list,
+ uint order_num, ORDER *order, int alter_flags,
+ enum enum_duplicates handle_duplicates,
+ enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
+ enum tablespace_op_type tablespace_op=NO_TABLESPACE_OP,
+ bool simple_alter=0);
int mysql_create_like_table(THD *thd, TABLE_LIST *table,
HA_CREATE_INFO *create_info,
Table_ident *src_table);
@@ -527,6 +544,10 @@ bool mysql_rename_table(enum db_type base,
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list);
+int mysql_add_column(THD *thd, TABLE_LIST *table_list,
+ List<create_field> &fields);
+int mysql_drop_column(THD *thd, TABLE_LIST *table_list,
+ List<Alter_drop> &drop_list);
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds,
uint order_num, ORDER *order, ha_rows limit,
@@ -777,7 +798,7 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create);
extern time_t start_time;
extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH],
mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[],
- opt_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
+ def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
#define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list))
extern MY_TMPDIR mysql_tmpdir_list;
extern const char *command_name[];
@@ -930,6 +951,9 @@ void unlock_table_names(THD *thd, TABLE_LIST *table_list,
void unireg_init(ulong options);
void unireg_end(void);
+int mysql_create_frm(THD *thd, my_string file_name,HA_CREATE_INFO *create_info,
+ List<create_field> &create_field,
+ uint key_count,KEY *key_info,handler *db_type);
int rea_create_table(THD *thd, my_string file_name,HA_CREATE_INFO *create_info,
List<create_field> &create_field,
uint key_count,KEY *key_info);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 0f75c7d14ef..5176ee33a17 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -326,7 +326,7 @@ char mysql_real_data_home[FN_REFLEN],
language[LIBLEN],reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file,
*opt_init_connect, *opt_init_slave,
- opt_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
+ def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
const char *opt_date_time_formats[3];
@@ -2105,13 +2105,11 @@ static int init_common_variables(const char *conf_file_name, int argc,
strmov(fn_ext(pidfile_name),".pid"); // Add proper extension
#ifndef DBUG_OFF
- if (*(MYSQL_SERVER_SUFFIX))
- strxmov(strend(server_version),MYSQL_SERVER_SUFFIX,"-debug",NullS);
+ if (!*(MYSQL_SERVER_SUFFIX))
+ strmov(strend(server_version),"-debug");
else
- strmov(strend(server_version),"--debug");
-#else
- strmov(strend(server_version),MYSQL_SERVER_SUFFIX);
#endif
+ strmov(strend(server_version),MYSQL_SERVER_SUFFIX);
load_defaults(conf_file_name, groups, &argc, &argv);
defaults_argv=argv;
@@ -2364,9 +2362,8 @@ Now disabling --log-slave-updates.");
{
if (global_system_variables.log_warnings)
sql_print_error("Warning: Failed to lock memory. Errno: %d\n",errno);
+ locked_in_memory= 0;
}
- else
- locked_in_memory=1;
}
#else
locked_in_memory=0;
@@ -2530,6 +2527,8 @@ int main(int argc, char **argv)
}
}
#endif
+ thread_stack_min=thread_stack - STACK_MIN_SIZE;
+
(void) thr_setconcurrency(concurrency); // 10 by default
/*
@@ -5652,7 +5651,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
fprintf(stderr, "Invalid ft-boolean-syntax string: %s\n", argument);
exit(1);
}
- strmake(opt_ft_boolean_syntax, argument, sizeof(ft_boolean_syntax)-1);
+ strmake(ft_boolean_syntax, argument, sizeof(ft_boolean_syntax)-1);
break;
case OPT_SKIP_SAFEMALLOC:
#ifdef SAFEMALLOC
@@ -5702,7 +5701,7 @@ static void get_options(int argc,char **argv)
int ho_error;
my_getopt_register_get_addr(mysql_getopt_value);
- strmake(opt_ft_boolean_syntax, ft_boolean_syntax,
+ strmake(def_ft_boolean_syntax, ft_boolean_syntax,
sizeof(ft_boolean_syntax)-1);
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
exit(ho_error);
@@ -5759,8 +5758,6 @@ static void get_options(int argc,char **argv)
table_alias_charset= (lower_case_table_names ?
files_charset_info :
&my_charset_bin);
- strmake(ft_boolean_syntax, opt_ft_boolean_syntax,
- sizeof(ft_boolean_syntax)-1);
if (opt_short_log_format)
opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index b6ac0eab53b..38ff7f14c40 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2968,7 +2968,7 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
((field->type() == FIELD_TYPE_BLOB) ?
HA_KEY_BLOB_LENGTH : 0),
field->charset());
- field->val_str(&tmp,&tmp);
+ field->val_str(&tmp);
fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE);
}
}
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 40adc9e8961..a5944af829d 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -166,10 +166,10 @@ net_printf(THD *thd, uint errcode, ...)
const char *format;
#ifndef EMBEDDED_LIBRARY
const char *text_pos;
+ int head_length= NET_HEADER_SIZE;
#else
char text_pos[1024];
#endif
- int head_length= NET_HEADER_SIZE;
NET *net= &thd->net;
DBUG_ENTER("net_printf");
@@ -530,7 +530,10 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
/* Store fixed length fields */
pos= (char*) local_packet->ptr()+local_packet->length();
*pos++= 12; // Length of packed fields
- int2store(pos, field.charsetnr);
+ if (item->collation.collation == &my_charset_bin || thd_charset == NULL)
+ int2store(pos, field.charsetnr);
+ else
+ int2store(pos, thd_charset->number);
int4store(pos+2, field.length);
pos[6]= field.type;
int2store(pos+7,field.flags);
@@ -822,7 +825,7 @@ bool Protocol_simple::store(Field *field)
String str(buff,sizeof(buff), &my_charset_bin);
CHARSET_INFO *tocs= this->thd->variables.character_set_results;
- field->val_str(&str,&str);
+ field->val_str(&str);
if (tocs && !my_charset_same(field->charset(), tocs) &&
(field->charset() != &my_charset_bin) &&
(tocs != &my_charset_bin))
diff --git a/sql/records.cc b/sql/records.cc
index 0feb873a6af..ca00658cdae 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -80,7 +80,7 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
if (!table->sort.addon_field &&
! (specialflag & SPECIAL_SAFE_MODE) &&
thd->variables.read_rnd_buff_size &&
- !table->file->fast_key_read() &&
+ !(table->file->table_flags() & HA_FAST_KEY_READ) &&
(table->db_stat & HA_READ_ONLY ||
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
(ulonglong) table->reclength*(table->file->records+
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index f8b0cf31621..f254ffb3df3 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -736,7 +736,7 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db,
table.db= (char*) db;
table.real_name= (char*) table_name;
table.updating= 1;
- table.non_cachable_table= 1; // just safety for table on stack
+
if (!tables_ok(thd, &table))
continue;
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index b357c0c96f2..54f2d75d6a8 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -839,7 +839,8 @@ bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex,
{
char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
uint new_length= (var ? var->value->str_value.length() : 0);
- if (!old_value) old_value="";
+ if (!old_value)
+ old_value= (char*) "";
if (!(res= my_strdup_with_length(old_value, new_length, MYF(0))))
return 1;
/*
@@ -900,7 +901,7 @@ static bool sys_update_ftb_syntax(THD *thd, set_var * var)
static void sys_default_ftb_syntax(THD *thd, enum_var_type type)
{
- strmake(ft_boolean_syntax, opt_ft_boolean_syntax,
+ strmake(ft_boolean_syntax, def_ft_boolean_syntax,
sizeof(ft_boolean_syntax)-1);
}
diff --git a/sql/slave.cc b/sql/slave.cc
index d8bb9359727..67b9c7515e1 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -285,8 +285,9 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
In this case, we will use the same IO_CACHE pointer to
read data as the IO thread is using to write data.
*/
- if (my_b_tell((rli->cur_log=rli->relay_log.get_log_file())) == 0 &&
- check_binlog_magic(rli->cur_log,errmsg))
+ rli->cur_log= rli->relay_log.get_log_file();
+ if (my_b_tell(rli->cur_log) == 0 &&
+ check_binlog_magic(rli->cur_log, errmsg))
goto err;
rli->cur_log_old_open_count=rli->relay_log.get_open_count();
}
@@ -1216,7 +1217,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
bzero((char*) &tables,sizeof(tables));
tables.db = (char*)db;
tables.alias= tables.real_name= (char*)table_name;
- tables.non_cachable_table= 1; // just safety for table on stack
+
/* Drop the table if 'overwrite' is true */
if (overwrite && mysql_rm_table(thd,&tables,1,0)) /* drop if exists */
{
@@ -1673,7 +1674,18 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
DBUG_ENTER("init_master_info");
if (mi->inited)
+ {
+ /*
+ We have to reset read position of relay-log-bin as we may have
+ already been reading from 'hotlog' when the slave was stopped
+ last time. If this case pos_in_file would be set and we would
+ get a crash when trying to read the signature for the binary
+ relay log.
+ */
+ my_b_seek(mi->rli.cur_log, (my_off_t) 0);
DBUG_RETURN(0);
+ }
+
mi->mysql=0;
mi->file_id=1;
fn_format(fname, master_info_fname, mysql_data_home, "", 4+32);
@@ -3617,13 +3629,16 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
mi->master_log_pos+= inc_pos;
DBUG_PRINT("info", ("master_log_pos: %d, event originating from the same server, ignored", (ulong) mi->master_log_pos));
}
- else /* write the event to the relay log */
+ else
+ {
+ /* write the event to the relay log */
if (likely(!(error= rli->relay_log.appendv(buf,event_len,0))))
{
mi->master_log_pos+= inc_pos;
DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
}
+ }
err:
pthread_mutex_unlock(&mi->data_lock);
@@ -4091,8 +4106,9 @@ Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s",
if (rli->relay_log.is_active(rli->linfo.log_file_name))
{
#ifdef EXTRA_DEBUG
- sql_print_error("next log '%s' is currently active",
- rli->linfo.log_file_name);
+ if (global_system_variables.log_warnings)
+ sql_print_error("next log '%s' is currently active",
+ rli->linfo.log_file_name);
#endif
rli->cur_log= cur_log= rli->relay_log.get_log_file();
rli->cur_log_old_open_count= rli->relay_log.get_open_count();
@@ -4120,8 +4136,9 @@ Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s",
from hot to cold, but not from cold to hot). No need for LOCK_log.
*/
#ifdef EXTRA_DEBUG
- sql_print_error("next log '%s' is not active",
- rli->linfo.log_file_name);
+ if (global_system_variables.log_warnings)
+ sql_print_error("next log '%s' is not active",
+ rli->linfo.log_file_name);
#endif
// open_binlog() will check the magic header
if ((rli->cur_log_fd=open_binlog(cur_log,rli->linfo.log_file_name,
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index ee049b619ea..4b287ea9a8d 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -172,9 +172,6 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
tables[1].next=tables+2;
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ;
tables[0].db=tables[1].db=tables[2].db=thd->db;
- // just safety for table on stack
- tables[0].non_cachable_table= tables[1].non_cachable_table=
- tables[2].non_cachable_table= 1;
uint counter;
if (open_tables(thd, tables, &counter))
@@ -508,7 +505,7 @@ static ulong get_access(TABLE *form, uint fieldnr)
((Field_enum*) (*pos))->typelib->count == 2 ;
pos++ , bit<<=1)
{
- (*pos)->val_str(&res,&res);
+ (*pos)->val_str(&res);
if (my_toupper(&my_charset_latin1, res[0]) == 'Y')
access_bits|= bit;
}
@@ -1328,7 +1325,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
bzero((char*) &tables,sizeof(tables));
tables.alias=tables.real_name=(char*) "user";
tables.db=(char*) "mysql";
- tables.non_cachable_table= 1; // just safety for table on stack
+
#ifdef HAVE_REPLICATION
/*
GRANT and REVOKE are applied the slave in/exclusion rules as they are
@@ -1386,7 +1383,7 @@ static bool test_if_create_new_users(THD *thd)
bzero((char*) &tl,sizeof(tl));
tl.db= (char*) "mysql";
tl.real_name= (char*) "user";
- tl.non_cachable_table= 1; // just safety for table on stack
+
db_access=acl_get(thd->host, thd->ip,
thd->priv_user, tl.db, 0);
if (!(db_access & INSERT_ACL))
@@ -1792,7 +1789,7 @@ public:
String *res,column_name;
GRANT_COLUMN *mem_check;
/* As column name is a string, we don't have to supply a buffer */
- res=col_privs->field[4]->val_str(&column_name,&column_name);
+ res=col_privs->field[4]->val_str(&column_name);
ulong priv= (ulong) col_privs->field[6]->val_int();
if (!(mem_check = new GRANT_COLUMN(*res,
fix_rights_for_column(priv))))
@@ -1995,7 +1992,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
privileges&= ~rights;
table->field[6]->store((longlong)
get_rights_for_column(privileges));
- table->field[4]->val_str(&column_name,&column_name);
+ table->field[4]->val_str(&column_name);
grant_column = column_hash_search(g_t,
column_name.ptr(),
column_name.length());
@@ -2238,9 +2235,6 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
? tables+2 : 0);
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_WRITE;
tables[0].db=tables[1].db=tables[2].db=(char*) "mysql";
- // just safety for table on stack
- tables[0].non_cachable_table= tables[1].non_cachable_table=
- tables[2].non_cachable_table= 1;
#ifdef HAVE_REPLICATION
/*
@@ -2415,8 +2409,6 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
tables[0].lock_type=tables[1].lock_type=TL_WRITE;
tables[0].db=tables[1].db=(char*) "mysql";
tables[0].table=tables[1].table=0;
- // just safety for table on stack
- tables[0].non_cachable_table= tables[1].non_cachable_table= 1;
#ifdef HAVE_REPLICATION
/*
@@ -2536,8 +2528,6 @@ my_bool grant_init(THD *org_thd)
tables[0].next=tables+1;
tables[0].lock_type=tables[1].lock_type=TL_READ;
tables[0].db=tables[1].db=thd->db;
- // just safety for table on stack
- tables[0].non_cachable_table= tables[1].non_cachable_table= 1;
uint counter;
if (open_tables(thd, tables, &counter))
@@ -3375,9 +3365,6 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables)
tables->lock_type= (tables+1)->lock_type=
(tables+2)->lock_type= (tables+3)->lock_type= TL_WRITE;
tables->db= (tables+1)->db= (tables+2)->db= (tables+3)->db=(char*) "mysql";
- // just safety for table on stack
- tables[0].non_cachable_table= tables[1].non_cachable_table=
- tables[2].non_cachable_table= tables[3].non_cachable_table=1;
#ifdef HAVE_REPLICATION
/*
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index f70feb8dc9c..8c4571dd540 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -156,7 +156,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
table_list.db= (char*) entry->table_cache_key;
table_list.real_name= entry->real_name;
table_list.grant.privilege=0;
- table_list.non_cachable_table= 1; // just safety for table on stack
+
if (check_table_access(thd,SELECT_ACL | EXTRA_ACL,&table_list,1))
continue;
/* need to check if we haven't already listed it */
@@ -444,7 +444,7 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
else
{
// Free memory and reset for next loop
- table->file->extra(HA_EXTRA_RESET);
+ table->file->reset();
}
table->in_use=0;
if (unused_tables)
@@ -1333,7 +1333,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
bzero((char*) &table_list, sizeof(table_list)); // just for safe
table_list.db=(char*) db;
table_list.real_name=(char*) name;
- table_list.non_cachable_table= 1; // just safety for table on stack
+
safe_mutex_assert_owner(&LOCK_open);
if ((error=lock_table_name(thd,&table_list)))
@@ -1807,7 +1807,7 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
if (cached_field_index < table->fields &&
!my_strcasecmp(system_charset_info,
table->field[cached_field_index]->field_name, name))
- field_ptr= table->field + cached_field_index;
+ field_ptr= table->field + cached_field_index;
else if (table->name_hash.records)
field_ptr= (Field**)hash_search(&table->name_hash,(byte*) name,
length);
@@ -1941,7 +1941,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
if (find)
{
(*where)= item->cached_table= tables;
- if (tables->non_cachable_table)
+ if (!tables->cacheable_table)
item->cached_table= 0;
if (find == WRONG_GRANT)
return (Field*) 0;
@@ -2002,7 +2002,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
if (field == WRONG_GRANT)
return (Field*) 0;
(*where)= item->cached_table= tables;
- if (tables->non_cachable_table)
+ if (!tables->cacheable_table)
item->cached_table= 0;
if (found)
{
@@ -2604,45 +2604,6 @@ static void mysql_rm_tmp_tables(void)
}
-/*
- CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
- the proper arguments. This isn't very fast but it should work for most
- cases.
- One should normally create all indexes with CREATE TABLE or ALTER TABLE.
-*/
-
-int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
-{
- List<create_field> fields;
- List<Alter_drop> drop;
- List<Alter_column> alter;
- HA_CREATE_INFO create_info;
- DBUG_ENTER("mysql_create_index");
- bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
- create_info.default_table_charset= thd->variables.collation_database;
- DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
- &create_info, table_list,
- fields, keys, drop, alter, 0, (ORDER*)0,
- DUP_ERROR));
-}
-
-
-int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
-{
- List<create_field> fields;
- List<Key> keys;
- List<Alter_column> alter;
- HA_CREATE_INFO create_info;
- DBUG_ENTER("mysql_drop_index");
- bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
- create_info.default_table_charset= thd->variables.collation_database;
- DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
- &create_info, table_list,
- fields, keys, drop, alter, 0, (ORDER*)0,
- DUP_ERROR));
-}
/*****************************************************************************
unireg support functions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 985dac7d613..e1a15eff475 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1022,7 +1022,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
Query_cache_table *table = block_table->parent;
table_list.db = table->db();
table_list.alias= table_list.real_name= table->table();
- table_list.non_cachable_table= 1; // just safety for table on stack
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_table_access(thd,SELECT_ACL,&table_list,1))
{
@@ -1861,11 +1860,11 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block,
{
// It is success (nobody can prevent us write data)
STRUCT_UNLOCK(&structure_guard_mutex);
- byte *rest = (byte*) data;
- Query_cache_block *block = *result_block;
uint headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_result)));
#ifndef EMBEDDED_LIBRARY
+ Query_cache_block *block= *result_block;
+ byte *rest= (byte*) data;
// Now fill list of blocks that created by allocate_data_chain
do
{
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index ea47ca9f71d..81269a8cbcf 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -115,7 +115,6 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
TABLE *table;
int res;
select_union *derived_result;
- TABLE_LIST *tables= (TABLE_LIST *)first_select->table_list.first;
bool is_union= first_select->next_select() &&
first_select->next_select()->linkage == UNION_TYPE;
bool is_subsel= first_select->first_inner_unit() ? 1: 0;
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 29dab51839d..44293b8214f 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -670,9 +670,6 @@ int mysqld_help(THD *thd, const char *mask)
tables[3].lock_type= TL_READ;
tables[3].next= 0;
tables[0].db= tables[1].db= tables[2].db= tables[3].db= (char*) "mysql";
- // just safety for table on stack
- tables[0].non_cachable_table= tables[1].non_cachable_table=
- tables[2].non_cachable_table= tables[3].non_cachable_table= 1;
List<String> topics_list, categories_list, subcategories_list;
String name, description, example;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 3f943b3a4c6..c6aff403f5b 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -21,12 +21,14 @@
#include "sql_acl.h"
static int check_null_fields(THD *thd,TABLE *entry);
+#ifndef EMBEDDED_LIBRARY
static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list);
static int write_delayed(THD *thd,TABLE *table, enum_duplicates dup,
char *query, uint query_length, int log_on);
static void end_delayed_insert(THD *thd);
extern "C" pthread_handler_decl(handle_delayed_insert,arg);
static void unlink_blobs(register TABLE *table);
+#endif
/* Define to force use of my_malloc() if the allocated memory block is big */
@@ -82,7 +84,6 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
table_list.real_name= table_list.alias= table->table_name;
table_list.table=table;
table_list.grant=table->grant;
- table_list.non_cachable_table= 1;
thd->dupp_field=0;
if (setup_tables(&table_list) ||
@@ -128,7 +129,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
TABLE *table;
List_iterator_fast<List_item> its(values_list);
List_item *values;
- char *query=thd->query;
+#ifndef EMBEDDED_LIBRARY
+ char *query= thd->query;
+#endif
thr_lock_type lock_type = table_list->lock_type;
TABLE_LIST *insert_table_list= (TABLE_LIST*)
thd->lex->select_lex.table_list.first;
@@ -257,17 +260,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->proc_info="update";
if (duplic != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- if ((lock_type != TL_WRITE_DELAYED && !(specialflag & SPECIAL_SAFE_MODE)) &&
- values_list.elements >= MIN_ROWS_TO_USE_BULK_INSERT)
- {
- table->file->extra_opt(HA_EXTRA_WRITE_CACHE,
- min(thd->variables.read_buff_size,
- table->avg_row_length*values_list.elements));
- table->file->deactivate_non_unique_index(values_list.elements);
- bulk_insert=1;
- }
- else
- bulk_insert=0;
+ if (lock_type != TL_WRITE_DELAYED)
+ table->file->start_bulk_insert(values_list.elements);
while ((values= its++))
{
@@ -345,24 +339,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
else
#endif
{
- if (bulk_insert)
+ if (table->file->end_bulk_insert() && !error)
{
- if (table->file->extra(HA_EXTRA_NO_CACHE))
- {
- if (!error)
- {
- table->file->print_error(my_errno,MYF(0));
- error=1;
- }
- }
- if (table->file->activate_all_index(thd))
- {
- if (!error)
- {
- table->file->print_error(my_errno,MYF(0));
- error=1;
- }
- }
+ table->file->print_error(my_errno,MYF(0));
+ error=1;
}
if (id && values_list.elements != 1)
thd->insert_id(id); // For update log
@@ -380,7 +360,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
transactional_table= table->file->has_transactions();
log_delayed= (transactional_table || table->tmp_table);
- if ((info.copied || info.deleted || info.updated) &&
+ if ((info.copied || info.deleted || info.updated) &&
(error <= 0 || !transactional_table))
{
mysql_update_log.write(thd, thd->query, thd->query_length);
@@ -1432,12 +1412,10 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
table->next_number_field=table->found_next_number_field;
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
thd->cuted_fields=0;
- if (info.handle_duplicates != DUP_REPLACE)
- table->file->extra(HA_EXTRA_WRITE_CACHE);
if (info.handle_duplicates == DUP_IGNORE ||
info.handle_duplicates == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- table->file->deactivate_non_unique_index((ha_rows) 0);
+ table->file->start_bulk_insert((ha_rows) 0);
DBUG_RETURN(0);
}
@@ -1446,7 +1424,7 @@ select_insert::~select_insert()
if (table)
{
table->next_number_field=0;
- table->file->extra(HA_EXTRA_RESET);
+ table->file->reset();
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
}
@@ -1490,15 +1468,14 @@ void select_insert::send_error(uint errcode,const char *err)
*/
DBUG_VOID_RETURN;
}
- table->file->extra(HA_EXTRA_NO_CACHE);
- table->file->activate_all_index(thd);
+ table->file->end_bulk_insert();
/*
If at least one row has been inserted/modified and will stay in the table
(the table doesn't have transactions) (example: we got a duplicate key
error while inserting into a MyISAM table) we must write to the binlog (and
the error code will make the slave stop).
*/
- if ((info.copied || info.deleted || info.updated) &&
+ if ((info.copied || info.deleted || info.updated) &&
!table->file->has_transactions())
{
if (last_insert_id)
@@ -1511,7 +1488,7 @@ void select_insert::send_error(uint errcode,const char *err)
mysql_bin_log.write(&qinfo);
}
if (!table->tmp_table)
- thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
+ thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
if (info.copied || info.deleted || info.updated)
query_cache_invalidate3(thd, table, 1);
@@ -1525,8 +1502,7 @@ bool select_insert::send_eof()
int error,error2;
DBUG_ENTER("select_insert::send_eof");
- if (!(error=table->file->extra(HA_EXTRA_NO_CACHE)))
- error=table->file->activate_all_index(thd);
+ error=table->file->end_bulk_insert();
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
/*
@@ -1602,7 +1578,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
/* Don't set timestamp if used */
table->timestamp_default_now= table->timestamp_on_update_now= 0;
-
+
table->next_number_field=table->found_next_number_field;
restore_record(table,default_values); // Get empty record
@@ -1611,7 +1587,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
if (info.handle_duplicates == DUP_IGNORE ||
info.handle_duplicates == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- table->file->deactivate_non_unique_index((ha_rows) 0);
+ table->file->start_bulk_insert((ha_rows) 0);
DBUG_RETURN(0);
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 7ff2fb4643a..7fa0591ddc8 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1389,7 +1389,7 @@ create_total_list_n_last_return(THD *thd_arg,
}
}
}
-end:
+
if (slave_list_first)
{
*new_table_list= slave_list_first;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index d5fbbd8803e..ea1accabf37 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -396,6 +396,7 @@ public:
SQL_LIST order_list; /* ORDER clause */
List<List_item> expr_list;
List<List_item> when_list; /* WHEN clause (expression) */
+ SQL_LIST *gorder_list;
ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
// Arrays of pointers to top elements of all_fields list
Item **ref_pointer_array;
@@ -508,6 +509,14 @@ public:
};
typedef class st_select_lex SELECT_LEX;
+#define ALTER_ADD_COLUMN 1
+#define ALTER_DROP_COLUMN 2
+#define ALTER_CHANGE_COLUMN 4
+#define ALTER_ADD_INDEX 8
+#define ALTER_DROP_INDEX 16
+#define ALTER_RENAME 32
+#define ALTER_ORDER 64
+#define ALTER_OPTIONS 128
/* The state of the lex parsing. This is saved in the THD struct */
@@ -538,7 +547,6 @@ typedef struct st_lex
gptr yacc_yyss,yacc_yyvs;
THD *thd;
CHARSET_INFO *charset;
- SQL_LIST *gorder_list;
List<key_part_spec> col_list;
List<key_part_spec> ref_list;
@@ -578,6 +586,7 @@ typedef struct st_lex
uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option;
uint slave_thd_opt;
+ uint alter_flags;
uint8 describe;
bool drop_if_exists, drop_temporary, local_file;
bool in_comment, ignore_space, verbose, simple_alter, no_write_to_binlog;
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 7b7ed2e96d0..3d9299ca05c 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -276,14 +276,12 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{
if (use_timestamp)
table->timestamp_default_now= table->timestamp_on_update_now= 0;
-
+
table->next_number_field=table->found_next_number_field;
- VOID(table->file->extra_opt(HA_EXTRA_WRITE_CACHE,
- thd->variables.read_buff_size));
if (handle_duplicates == DUP_IGNORE ||
handle_duplicates == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- table->file->deactivate_non_unique_index((ha_rows) 0);
+ table->file->start_bulk_insert((ha_rows) 0);
table->copy_blobs=1;
if (!field_term->length() && !enclosed->length())
error=read_fixed_length(thd,info,table,fields,read_info,
@@ -291,9 +289,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
else
error=read_sep_field(thd,info,table,fields,read_info,*enclosed,
skip_lines);
- if (table->file->extra(HA_EXTRA_NO_CACHE))
- error=1; /* purecov: inspected */
- if (table->file->activate_all_index(thd))
+ if (table->file->end_bulk_insert())
error=1; /* purecov: inspected */
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->next_number_field=0;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 147f576d03e..0a501dd86c2 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -48,7 +48,9 @@
extern "C" int gethostname(char *name, int namelen);
#endif
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
+#endif
static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
static void remove_escape(char *name);
@@ -423,6 +425,8 @@ void init_max_user_conn(void)
1 error
*/
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+
static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
{
int error=0;
@@ -453,7 +457,7 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
(void) pthread_mutex_unlock(&LOCK_user_conn);
DBUG_RETURN(error);
}
-
+#endif /* NO_EMBEDDED_ACCESS_CHECKS */
/*
Decrease user connection count
@@ -542,15 +546,15 @@ bool is_update_query(enum enum_sql_command command)
static bool check_mqh(THD *thd, uint check_command)
{
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+ return(0);
+#else
bool error=0;
time_t check_time = thd->start_time ? thd->start_time : time(NULL);
USER_CONN *uc=thd->user_connect;
DBUG_ENTER("check_mqh");
DBUG_ASSERT(uc != 0);
-#ifdef NO_EMBEDDED_ACCESS_CHECKS
- DBUG_RETURN(0);
-#else
/* If more than a hour since last check, reset resource checking */
if (check_time - uc->intime >= 3600)
{
@@ -2362,6 +2366,7 @@ unsent_create_error:
lex->key_list, lex->drop_list, lex->alter_list,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
+ lex->alter_flags,
lex->duplicates,
lex->alter_keys_onoff,
lex->tablespace_op,
@@ -2512,7 +2517,7 @@ unsent_create_error:
res= mysql_alter_table(thd, NullS, NullS, &create_info,
tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list,
- 0, (ORDER *) 0,
+ 0, (ORDER *) 0, 0,
DUP_ERROR);
}
else
@@ -3071,7 +3076,7 @@ unsent_create_error:
net_printf(thd,ER_WRONG_DB_NAME, lex->name);
break;
}
- if (check_access(thd,DROP_ACL,lex->name,0,1,0))
+ if (check_access(thd,SELECT_ACL,lex->name,0,1,0))
break;
if (thd->locked_tables || thd->active_transaction())
{
@@ -3460,7 +3465,10 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
DBUG_ENTER("check_access");
DBUG_PRINT("enter",("want_access: %lu master_access: %lu", want_access,
thd->master_access));
- ulong db_access,dummy;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ ulong db_access;
+#endif
+ ulong dummy;
if (save_priv)
*save_priv=0;
else
@@ -3652,6 +3660,10 @@ static bool check_db_used(THD *thd,TABLE_LIST *tables)
#define used_stack(A,B) (long) (B - A)
#endif
+#ifndef DBUG_OFF
+long max_stack_used;
+#endif
+
#ifndef EMBEDDED_LIBRARY
bool check_stack_overrun(THD *thd,char *buf __attribute__((unused)))
{
@@ -3664,6 +3676,9 @@ bool check_stack_overrun(THD *thd,char *buf __attribute__((unused)))
thd->fatal_error();
return 1;
}
+#ifndef DBUG_OFF
+ max_stack_used= max(max_stack_used, stack_used);
+#endif
return 0;
}
#endif /* EMBEDDED_LIBRARY */
@@ -4466,6 +4481,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
ptr->derived= table->sel;
+ ptr->cacheable_table= 1;
if (use_index_arg)
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index_arg,
sizeof(*use_index_arg));
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index b4580ca5a60..395adcf974c 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -828,7 +828,7 @@ static int mysql_test_select_fields(Prepared_statement *stmt,
if (check_table_access(thd, privilege, tables,0))
DBUG_RETURN(1);
}
- else if (check_access(thd, privilege, "*any*",0,0,0))
+ else if (check_access(thd, privilege, any_db,0,0,0))
DBUG_RETURN(1);
#endif
@@ -1325,7 +1325,7 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
int error;
DBUG_ENTER("mysql_stmt_prepare");
- DBUG_PRINT("pquery", ("%s", packet));
+ DBUG_PRINT("prep_query", ("%s", packet));
if (stmt == 0)
{
@@ -1461,9 +1461,10 @@ static void reset_stmt_for_execute(Prepared_statement *stmt)
void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
{
ulong stmt_id= uint4korr(packet);
+#ifndef EMBEDDED_LIBRARY
uchar *packet_end= (uchar *) packet + packet_length - 1;
+#endif
Prepared_statement *stmt;
-
DBUG_ENTER("mysql_stmt_execute");
packet+= 9; /* stmt_id + 5 bytes of flags */
@@ -1471,7 +1472,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
if (!(stmt= find_prepared_statement(thd, stmt_id, "execute", SEND_ERROR)))
DBUG_VOID_RETURN;
- DBUG_PRINT("equery:", ("%s", stmt->query));
+ DBUG_PRINT("exec_query:", ("%s", stmt->query));
/* Check if we got an error when sending long data */
if (stmt->get_longdata_error)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 03b6d9b6bbb..c634dd0ab0e 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3610,7 +3610,6 @@ static void
make_join_readinfo(JOIN *join, uint options)
{
uint i;
- SELECT_LEX *select_lex= &join->thd->lex->select_lex;
bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
DBUG_ENTER("make_join_readinfo");
@@ -3880,9 +3879,7 @@ JOIN::join_free(bool full)
else
{
for (tab= join_tab, end= tab+tables; tab != end; tab++)
- {
tab->cleanup();
- }
table= 0;
}
}
@@ -4789,7 +4786,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
else
return new Field_double(item_sum->max_length,maybe_null,
item->name, table, item_sum->decimals);
- case Item_sum::VARIANCE_FUNC: /* Place for sum & count */
+ case Item_sum::VARIANCE_FUNC: /* Place for sum & count */
case Item_sum::STD_FUNC:
if (group)
return new Field_string(sizeof(double)*2+sizeof(longlong),
@@ -4817,17 +4814,19 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
default:
// This case should never be choosen
DBUG_ASSERT(0);
+ thd->fatal_error();
return 0;
}
}
- thd->fatal_error();
- return 0; // Error
+ /* We never come here */
}
case Item::FIELD_ITEM:
case Item::DEFAULT_VALUE_ITEM:
- return create_tmp_field_from_field(thd, (*from_field=
- ((Item_field*) item)->field),
+ {
+ Item_field *field= (Item_field*) item;
+ return create_tmp_field_from_field(thd, (*from_field= field->field),
item, table, modify_item);
+ }
case Item::FUNC_ITEM:
case Item::COND_ITEM:
case Item::FIELD_AVG_ITEM:
@@ -8405,12 +8404,11 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
Item *pos;
List_iterator_fast<Item> li(all_fields);
Copy_field *copy;
- DBUG_ENTER("setup_copy_fields");
res_selected_fields.empty();
res_all_fields.empty();
List_iterator_fast<Item> itr(res_all_fields);
-
uint i, border= all_fields.elements - elements;
+ DBUG_ENTER("setup_copy_fields");
if (!(copy=param->copy_field= new Copy_field[param->field_count]))
goto err2;
@@ -8545,6 +8543,23 @@ bool JOIN::alloc_func_list()
}
+/*
+ Initialize 'sum_funcs' array with all Item_sum objects
+
+ SYNOPSIS
+ make_sum_func_list()
+ field_list All items
+ send_fields Items in select list
+ before_group_by Set to 1 if this is called before GROUP BY handling
+
+ NOTES
+ Calls ::setup() for all item_sum objects in field_list
+
+ RETURN
+ 0 ok
+ 1 error
+*/
+
bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
bool before_group_by)
{
@@ -8581,7 +8596,7 @@ bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
/*
- Change all funcs and sum_funcs to fields in tmp table, and create
+ Change all funcs and sum_funcs to fields in tmp table, and create
new list of all items.
change_to_use_tmp_fields()
@@ -9081,7 +9096,6 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
List<Item> field_list;
List<Item> item_list;
THD *thd=join->thd;
- SELECT_LEX *select_lex= &join->thd->lex->select_lex;
select_result *result=join->result;
Item *item_null= new Item_null();
CHARSET_INFO *cs= &my_charset_latin1;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index f93004976f2..c3c4124db1c 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -31,9 +31,11 @@ static const char *grant_names[]={
"select","insert","update","delete","create","drop","reload","shutdown",
"process","file","grant","references","index","alter"};
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
"grant_types",
grant_names};
+#endif
static int mysql_find_files(THD *thd,List<char> *files, const char *db,
const char *path, const char *wild, bool dir);
@@ -367,7 +369,9 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
char *ext;
MY_DIR *dirp;
FILEINFO *file;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint col_access=thd->col_access;
+#endif
TABLE_LIST table_list;
DBUG_ENTER("mysql_find_files");
@@ -731,11 +735,11 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
*/
protocol->store("CURRENT_TIMESTAMP", system_charset_info);
}
- else if (field->unireg_check != Field::NEXT_NUMBER &&
+ else if (field->unireg_check != Field::NEXT_NUMBER &&
!field->is_null())
{ // Not null by default
type.set(tmp, sizeof(tmp), field->charset());
- field->val_str(&type,&type);
+ field->val_str(&type);
protocol->store(type.ptr(),type.length(),type.charset());
}
else if (field->unireg_check == Field::NEXT_NUMBER ||
@@ -829,7 +833,9 @@ int mysqld_show_create_db(THD *thd, char *dbname,
char path[FN_REFLEN];
char buff[2048];
String buffer(buff, sizeof(buff), system_charset_info);
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint db_access;
+#endif
bool found_libchar;
HA_CREATE_INFO create;
uint create_options = create_info ? create_info->options : 0;
@@ -1138,7 +1144,6 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
{
const char *name_end;
char quote_char;
- uint part_len;
if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
quote_char= '\"';
@@ -1274,7 +1279,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
/*
- Again we are using CURRENT_TIMESTAMP instead of NOW becaus eit is
+ Again we are using CURRENT_TIMESTAMP instead of NOW because it is
more standard
*/
has_now_default= table->timestamp_field == field &&
@@ -1293,10 +1298,10 @@ store_create_info(THD *thd, TABLE *table, String *packet)
else if (!field->is_null())
{ // Not null by default
type.set(tmp, sizeof(tmp), field->charset());
- field->val_str(&type,&type);
+ field->val_str(&type);
if (type.length())
{
- String def_val;
+ String def_val;
/* convert to system_charset_info == utf8 */
def_val.copy(type.ptr(), type.length(), field->charset(),
system_charset_info);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 5e358f76d3f..17ea4cd540e 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -34,19 +34,19 @@ 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,
- enum enum_duplicates handle_duplicates,
+ List<create_field> &create,
+ enum enum_duplicates handle_duplicates,
uint order_num, ORDER *order,
- ha_rows *copied,ha_rows *deleted);
+ ha_rows *copied,ha_rows *deleted);
/*
delete (drop) tables.
SYNOPSIS
mysql_rm_table()
- thd Thread handle
- tables List of tables to delete
- if_exists If 1, don't give error if one table doesn't exists
+ thd Thread handle
+ tables List of tables to delete
+ if_exists If 1, don't give error if one table doesn't exists
NOTES
Will delete all tables that can be deleted and give a compact error
@@ -57,13 +57,13 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set.
RETURN
- 0 ok. In this case ok packet is sent to user
- -1 Error (Error message given but not sent to user)
+ 0 ok. In this case ok packet is sent to user
+ -1 Error (Error message given but not sent to user)
*/
int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
- my_bool drop_temporary)
+ my_bool drop_temporary)
{
int error= 0;
DBUG_ENTER("mysql_rm_table");
@@ -79,7 +79,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
if (thd->global_read_lock)
{
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0),
- tables->real_name);
+ tables->real_name);
error= 1;
goto err;
}
@@ -111,23 +111,23 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
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
+ 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
global_read_lock and don't send_ok packet to server.
RETURN
- 0 ok
- 1 error
+ 0 ok
+ 1 error
*/
int mysql_rm_table_part2_with_lock(THD *thd,
- TABLE_LIST *tables, bool if_exists,
- bool drop_temporary, bool dont_log_query)
+ TABLE_LIST *tables, bool if_exists,
+ bool drop_temporary, bool dont_log_query)
{
int error;
thd->mysys_var->current_mutex= &LOCK_open;
@@ -135,7 +135,7 @@ int mysql_rm_table_part2_with_lock(THD *thd,
VOID(pthread_mutex_lock(&LOCK_open));
error=mysql_rm_table_part2(thd,tables, if_exists, drop_temporary,
- dont_log_query);
+ dont_log_query);
pthread_mutex_unlock(&LOCK_open);
@@ -152,12 +152,12 @@ int mysql_rm_table_part2_with_lock(THD *thd,
SYNOPSIS
mysql_rm_table_part2()
- thd Thread handler
- tables Tables to drop
- 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
- dont_log_query Don't log the query
+ thd Thread handler
+ tables Tables to drop
+ 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
+ dont_log_query Don't log the query
TODO:
When logging to the binary log, we should log
@@ -170,16 +170,16 @@ int mysql_rm_table_part2_with_lock(THD *thd,
not all.
RETURN
- 0 ok
- 1 Error
- -1 Thread was killed
+ 0 ok
+ 1 Error
+ -1 Thread was killed
*/
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
- bool drop_temporary, bool dont_log_query)
+ bool drop_temporary, bool dont_log_query)
{
TABLE_LIST *table;
- char path[FN_REFLEN], *alias;
+ char path[FN_REFLEN], *alias;
String wrong_tables;
int error;
bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
@@ -195,7 +195,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
if (!close_temporary_table(thd, db, table->real_name))
{
tmp_table_deleted=1;
- continue; // removed temporary table
+ continue; // removed temporary table
}
error=0;
@@ -204,13 +204,13 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
abort_locked_tables(thd,db,table->real_name);
while (remove_table_from_cache(thd,db,table->real_name) && !thd->killed)
{
- dropping_tables++;
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- dropping_tables--;
+ dropping_tables++;
+ (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+ dropping_tables--;
}
drop_locked_tables(thd,db,table->real_name);
if (thd->killed)
- DBUG_RETURN(-1);
+ DBUG_RETURN(-1);
alias= (lower_case_table_names == 2) ? table->alias : table->real_name;
/* remove form file and isam files */
strxmov(path, mysql_data_home, "/", db, "/", alias, reg_ext, NullS);
@@ -219,9 +219,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
if (drop_temporary || access(path,F_OK))
{
if (if_exists)
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
- ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
- table->real_name);
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
+ table->real_name);
else
error= 1;
}
@@ -229,27 +229,27 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
{
char *end;
db_type table_type= get_table_type(path);
- *(end=fn_ext(path))=0; // Remove extension for delete
+ *(end=fn_ext(path))=0; // Remove extension for delete
error=ha_delete_table(table_type, path);
if (error == ENOENT && if_exists)
- error = 0;
+ error = 0;
if (error == HA_ERR_ROW_IS_REFERENCED)
{
- /* the table is referenced by a foreign key constraint */
+ /* the table is referenced by a foreign key constraint */
foreign_key_error=1;
}
if (!error || error == ENOENT)
{
- /* Delete the table definition file */
- strmov(end,reg_ext);
- if (!(error=my_delete(path,MYF(MY_WME))))
- some_tables_deleted=1;
+ /* Delete the table definition file */
+ strmov(end,reg_ext);
+ if (!(error=my_delete(path,MYF(MY_WME))))
+ some_tables_deleted=1;
}
}
if (error)
{
if (wrong_tables.length())
- wrong_tables.append(',');
+ wrong_tables.append(',');
wrong_tables.append(String(table->real_name,system_charset_info));
}
}
@@ -263,9 +263,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length,
- tmp_table_deleted && !some_tables_deleted);
- mysql_bin_log.write(&qinfo);
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ tmp_table_deleted && !some_tables_deleted);
+ mysql_bin_log.write(&qinfo);
}
}
}
@@ -285,15 +285,19 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
int quick_rm_table(enum db_type base,const char *db,
- const char *table_name)
+ const char *table_name)
{
char path[FN_REFLEN];
int error=0;
- (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,db,table_name,reg_ext);
+ if (snprintf(path, sizeof(path), "%s/%s/%s%s",
+ mysql_data_home, db, table_name, reg_ext)>= (int)sizeof(path))
+ return 1;
unpack_filename(path,path);
if (my_delete(path,MYF(0)))
error=1; /* purecov: inspected */
- sprintf(path,"%s/%s/%s",mysql_data_home,db,table_name);
+ if (snprintf(path, sizeof(path), "%s/%s/%s",
+ mysql_data_home, db, table_name)>= (int)sizeof(path))
+ return 1;
unpack_filename(path,path);
return ha_delete_table(base,path) || error;
}
@@ -327,7 +331,7 @@ static int sort_keys(KEY *a, KEY *b)
return 1;
}
else if (b->flags & HA_NOSAME)
- return 1; // Prefer b
+ return 1; // Prefer b
if ((a->flags ^ b->flags) & HA_FULLTEXT)
{
@@ -338,8 +342,8 @@ static int sort_keys(KEY *a, KEY *b)
the original key position.
*/
return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
- (a->usable_key_parts > b->usable_key_parts) ? 1 :
- 0);
+ (a->usable_key_parts > b->usable_key_parts) ? 1 :
+ 0);
}
/*
@@ -360,7 +364,7 @@ static int sort_keys(KEY *a, KEY *b)
*/
void check_duplicates_in_interval(const char *set_or_name,
- const char *name, TYPELIB *typelib)
+ const char *name, TYPELIB *typelib)
{
unsigned int old_count= typelib->count;
const char **old_type_names= typelib->type_names;
@@ -375,9 +379,9 @@ void check_duplicates_in_interval(const char *set_or_name,
if (find_type((char*)*cur_value,typelib,1))
{
push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE,
- ER_DUPLICATED_VALUE_IN_TYPE,
- ER(ER_DUPLICATED_VALUE_IN_TYPE),
- name,*cur_value,set_or_name);
+ ER_DUPLICATED_VALUE_IN_TYPE,
+ ER(ER_DUPLICATED_VALUE_IN_TYPE),
+ name,*cur_value,set_or_name);
}
}
typelib->count= old_count;
@@ -385,85 +389,43 @@ void check_duplicates_in_interval(const char *set_or_name,
}
/*
- Create a table
+ Preparation for table creation
SYNOPSIS
- mysql_create_table()
- thd Thread object
- db Database
- table_name Table name
- create_info Create information (like MAX_ROWS)
- fields List of fields to create
- keys List of keys to create
- tmp_table Set to 1 if this is an internal temporary table
- (From ALTER TABLE)
- no_log Don't log the query to binary log.
+ mysql_prepare_table()
+ thd Thread object
+ create_info Create information (like MAX_ROWS)
+ fields List of fields to create
+ keys List of keys to create
DESCRIPTION
- 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
- select_field_count is also used for CREATE ... SELECT,
- and must be zero for standard create of table.
+ Prepares the table and key structures for table creation.
RETURN VALUES
- 0 ok
- -1 error
+ 0 ok
+ -1 error
*/
-int mysql_create_table(THD *thd,const char *db, const char *table_name,
- HA_CREATE_INFO *create_info,
- List<create_field> &fields,
- List<Key> &keys,bool tmp_table,bool no_log,
- uint 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)
{
- char path[FN_REFLEN];
- const char *key_name, *alias;
- create_field *sql_field,*dup_field;
- int error= -1;
- uint db_options,field,null_fields,blob_columns;
- ulong pos;
- KEY *key_info,*key_info_buffer;
+ const char *key_name;
+ create_field *sql_field,*dup_field;
+ uint field,null_fields,blob_columns;
+ ulong pos;
+ KEY *key_info;
KEY_PART_INFO *key_part_info;
- int auto_increment=0;
int timestamps= 0, timestamps_with_niladic= 0;
- handler *file;
int field_no,dup_no;
- enum db_type new_db_type;
- DBUG_ENTER("mysql_create_table");
+ int select_field_pos,auto_increment=0;
+ DBUG_ENTER("mysql_prepare_table");
- /* Check for duplicate fields and check type of table to create */
- if (!fields.elements)
- {
- my_error(ER_TABLE_MUST_HAVE_COLUMNS,MYF(0));
- DBUG_RETURN(-1);
- }
List_iterator<create_field> it(fields),it2(fields);
- int select_field_pos=fields.elements - select_field_count;
+ select_field_pos=fields.elements - select_field_count;
null_fields=blob_columns=0;
- 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, create_info->db_type);
-
- 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(-1);
- }
for (field_no=0; (sql_field=it++) ; field_no++)
{
@@ -493,8 +455,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
/* 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)
+ sql_field->sql_type == FIELD_TYPE_VAR_STRING &&
+ create_info->row_type != ROW_TYPE_FIXED)
{
db_options|=HA_OPTION_PACK_RECORD;
}
@@ -514,10 +476,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
sql_field->field_name,
dup_field->field_name) == 0)
{
- /*
- If this was a CREATE ... SELECT statement, accept a field
- redefinition if we are changing a field in the SELECT part
- */
+ /*
+ If this was a CREATE ... SELECT statement, accept a field
+ redefinition if we are changing a field in the SELECT part
+ */
if (field_no < select_field_pos || dup_no >= select_field_pos)
{
my_error(ER_DUP_FIELDNAME,MYF(0),sql_field->field_name);
@@ -525,20 +487,20 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
else
{
- /* Field redefined */
- sql_field->sql_type= dup_field->sql_type;
- sql_field->charset= (dup_field->charset ?
- dup_field->charset :
- create_info->default_table_charset);
- sql_field->length= dup_field->length;
- sql_field->pack_length= dup_field->pack_length;
- sql_field->create_length_to_internal_length();
- sql_field->decimals= dup_field->decimals;
- sql_field->flags= dup_field->flags;
- sql_field->unireg_check= dup_field->unireg_check;
- it2.remove(); // Remove first (create) definition
- select_field_pos--;
- break;
+ /* Field redefined */
+ sql_field->sql_type= dup_field->sql_type;
+ sql_field->charset= (dup_field->charset ?
+ dup_field->charset :
+ create_info->default_table_charset);
+ sql_field->length= dup_field->length;
+ sql_field->pack_length= dup_field->pack_length;
+ sql_field->create_length_to_internal_length();
+ sql_field->decimals= dup_field->decimals;
+ sql_field->flags= dup_field->flags;
+ sql_field->unireg_check= dup_field->unireg_check;
+ it2.remove(); // Remove first (create) definition
+ select_field_pos--;
+ break;
}
}
}
@@ -560,11 +522,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
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);
+ 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->pack_flag|=FIELDFLAG_BINARY;
+ sql_field->length=8; // Unireg field length
sql_field->unireg_check=Field::BLOB_FIELD;
blob_columns++;
break;
@@ -572,49 +534,49 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
#ifdef HAVE_SPATIAL
if (!(file->table_flags() & HA_HAS_GEOMETRY))
{
- my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
- MYF(0), "GEOMETRY");
- DBUG_RETURN(-1);
+ 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);
+ 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->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);
+ sym_group_geom.name, sym_group_geom.needed_define);
DBUG_RETURN(-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;
+ 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;
+ FIELDFLAG_INTERVAL;
if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
+ 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->interval);
break;
case FIELD_TYPE_SET:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
- FIELDFLAG_BITFIELD;
+ FIELDFLAG_BITFIELD;
if (sql_field->charset->state & MY_CS_BINSORT)
- sql_field->pack_flag|=FIELDFLAG_BINARY;
+ 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->interval);
break;
- case FIELD_TYPE_DATE: // Rest of string types
+ case FIELD_TYPE_DATE: // Rest of string types
case FIELD_TYPE_NEWDATE:
case FIELD_TYPE_TIME:
case FIELD_TYPE_DATETIME:
@@ -628,24 +590,24 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (!timestamps)
{
sql_field->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
- ++timestamps_with_niladic;
+ timestamps_with_niladic++;
}
else
sql_field->unireg_check= Field::NONE;
}
- else if(sql_field->unireg_check != Field::NONE)
- ++timestamps_with_niladic;
+ else if (sql_field->unireg_check != Field::NONE)
+ timestamps_with_niladic++;
- ++timestamps;
+ 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));
+ (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))
@@ -681,13 +643,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
/* Create keys */
List_iterator<Key> key_iterator(keys);
- uint key_parts=0, key_count=0, fk_key_count=0;
- List<Key> keys_in_order; // Add new keys here
+ uint key_parts=0, fk_key_count=0;
+ List<Key> keys_in_order; // Add new keys here
bool primary_key=0,unique_key=0;
Key *key;
uint tmp, key_number;
/* Calculate number of key segements */
+ key_count=0;
while ((key=key_iterator++))
{
@@ -696,12 +659,12 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
fk_key_count++;
foreign_key *fk_key= (foreign_key*) key;
if (fk_key->ref_columns.elements &&
- fk_key->ref_columns.elements != fk_key->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));
- DBUG_RETURN(-1);
+ 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;
}
@@ -719,7 +682,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
key_parts+=key->columns.elements;
if (key->name && !tmp_table &&
- !my_strcasecmp(system_charset_info,key->name,primary_key_name))
+ !my_strcasecmp(system_charset_info,key->name,primary_key_name))
{
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
DBUG_RETURN(-1);
@@ -735,7 +698,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
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)
- DBUG_RETURN(-1); // Out of memory
+ DBUG_RETURN(-1); // Out of memory
key_iterator.rewind();
key_number=0;
@@ -756,12 +719,12 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
key_info->flags = HA_SPATIAL;
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);
+ 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:
- key_number--; // Skip this key
+ key_number--; // Skip this key
continue;
default:
key_info->flags = HA_NOSAME;
@@ -804,17 +767,17 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
#ifdef HAVE_RTREE_KEYS
if ((key_info->key_parts & 1) == 1)
{
- my_printf_error(ER_WRONG_ARGUMENTS,
- ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX");
- DBUG_RETURN(-1);
+ my_printf_error(ER_WRONG_ARGUMENTS,
+ ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX");
+ DBUG_RETURN(-1);
}
/* TODO: To be deleted */
my_printf_error(ER_NOT_SUPPORTED_YET, ER(ER_NOT_SUPPORTED_YET),
- MYF(0), "RTREE INDEX");
+ MYF(0), "RTREE INDEX");
DBUG_RETURN(-1);
#else
my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0),
- sym_group_rtree.name, sym_group_rtree.needed_define);
+ sym_group_rtree.name, sym_group_rtree.needed_define);
DBUG_RETURN(-1);
#endif
}
@@ -826,16 +789,16 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
it.rewind();
field=0;
while ((sql_field=it++) &&
- my_strcasecmp(system_charset_info,
+ my_strcasecmp(system_charset_info,
column->field_name,
sql_field->field_name))
- field++;
+ field++;
if (!sql_field)
{
- my_printf_error(ER_KEY_COLUMN_DOES_NOT_EXITS,
- ER(ER_KEY_COLUMN_DOES_NOT_EXITS),MYF(0),
- column->field_name);
- DBUG_RETURN(-1);
+ my_printf_error(ER_KEY_COLUMN_DOES_NOT_EXITS,
+ ER(ER_KEY_COLUMN_DOES_NOT_EXITS),MYF(0),
+ column->field_name);
+ DBUG_RETURN(-1);
}
/* for fulltext keys keyseg length is 1 for blobs (it's ignored in
ft code anyway, and 0 (set to column width later) for char's.
@@ -924,7 +887,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
{
if (column_nr == 0 || (file->table_flags() & HA_AUTO_PART_KEY))
- auto_increment--; // Field is used
+ auto_increment--; // Field is used
}
}
@@ -934,17 +897,19 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
uint length=sql_field->pack_length;
if (column->length)
{
- if (f_is_blob(sql_field->pack_flag))
- {
- if ((length=column->length) > file->max_key_length() ||
- length > file->max_key_part_length())
+ if (f_is_blob(sql_field->pack_flag))
+ {
+ if ((length=column->length) > file->max_key_length() ||
+ 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 */
char warn_buff[MYSQL_ERRMSG_SIZE];
- sprintf(warn_buff,ER(ER_TOO_LONG_KEY),length);
+ if (snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
+ length)>= (int)sizeof(warn_buff))
+ DBUG_RETURN(-1);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_KEY, warn_buff);
}
@@ -954,8 +919,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
DBUG_RETURN(-1);
}
}
- }
- else if (!f_is_geom(sql_field->pack_flag) &&
+ }
+ else if (!f_is_geom(sql_field->pack_flag) &&
(column->length > length ||
((f_is_packed(sql_field->pack_flag) ||
((file->table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
@@ -970,9 +935,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
else if (length == 0)
{
- my_printf_error(ER_WRONG_KEY_COLUMN, ER(ER_WRONG_KEY_COLUMN), MYF(0),
- column->field_name);
- DBUG_RETURN(-1);
+ 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())
{
@@ -981,7 +946,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{
/* not a critical problem */
char warn_buff[MYSQL_ERRMSG_SIZE];
- sprintf(warn_buff,ER(ER_TOO_LONG_KEY),length);
+ if (snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_KEY),
+ length)>= (int)sizeof(warn_buff))
+ DBUG_RETURN(-1);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_LONG_KEY, warn_buff);
}
@@ -994,15 +961,15 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
key_part_info->length=(uint16) length;
/* Use packed keys for long strings on the first column */
if (!(db_options & HA_OPTION_NO_PACK_KEYS) &&
- (length >= KEY_DEFAULT_PACK_LENGTH &&
- (sql_field->sql_type == FIELD_TYPE_STRING ||
- sql_field->sql_type == FIELD_TYPE_VAR_STRING ||
- sql_field->pack_flag & FIELDFLAG_BLOB)))
+ (length >= KEY_DEFAULT_PACK_LENGTH &&
+ (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))
- key_info->flags|= HA_BINARY_PACK_KEY;
- else
- key_info->flags|= HA_PACK_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;
}
key_length+=length;
key_part_info++;
@@ -1010,25 +977,25 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
/* Create the key name based on the first column (if not given) */
if (column_nr == 0)
{
- if (key->type == Key::PRIMARY)
- {
- if (primary_key)
- {
- my_error(ER_MULTIPLE_PRI_KEY,MYF(0));
- DBUG_RETURN(-1);
- }
- key_name=primary_key_name;
- primary_key=1;
- }
- 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))
- {
- my_error(ER_DUP_KEYNAME,MYF(0),key_name);
- DBUG_RETURN(-1);
- }
- key_info->name=(char*) key_name;
+ if (key->type == Key::PRIMARY)
+ {
+ if (primary_key)
+ {
+ my_error(ER_MULTIPLE_PRI_KEY,MYF(0));
+ DBUG_RETURN(-1);
+ }
+ key_name=primary_key_name;
+ primary_key=1;
+ }
+ 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))
+ {
+ my_error(ER_DUP_KEYNAME,MYF(0),key_name);
+ DBUG_RETURN(-1);
+ }
+ key_info->name=(char*) key_name;
}
}
if (!key_info->name || check_column_name(key_info->name))
@@ -1061,15 +1028,100 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
/* Sort keys in optimized order */
qsort((gptr) key_info_buffer, key_count, sizeof(KEY), (qsort_cmp) sort_keys);
+ DBUG_RETURN(0);
+}
+
+/*
+ Create a table
+
+ SYNOPSIS
+ mysql_create_table()
+ thd Thread object
+ db Database
+ table_name Table name
+ create_info Create information (like MAX_ROWS)
+ fields List of fields to create
+ keys List of keys to create
+ tmp_table Set to 1 if this is an internal temporary table
+ (From ALTER TABLE)
+ no_log Don't log the query to binary log.
+
+ DESCRIPTION
+ 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
+ select_field_count is also used for CREATE ... SELECT,
+ and must be zero for standard create of table.
+
+ RETURN VALUES
+ 0 ok
+ -1 error
+*/
+
+int mysql_create_table(THD *thd,const char *db, const char *table_name,
+ HA_CREATE_INFO *create_info,
+ List<create_field> &fields,
+ List<Key> &keys,bool tmp_table,bool no_log,
+ 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;
+ 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_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, create_info->db_type);
+
+ 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(-1);
+ }
+
+ if (mysql_prepare_table(thd, create_info, fields,
+ keys, tmp_table, db_options, file,
+ key_info_buffer, key_count,
+ select_field_count))
+ DBUG_RETURN(-1);
+
/* Check if table exists */
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
{
- sprintf(path,"%s%s%lx_%lx_%x%s",mysql_tmpdir,tmp_file_prefix,
- current_pid, thd->thread_id, thd->tmp_table++,reg_ext);
+ if (snprintf(path, sizeof(path), "%s%s%lx_%lx_%x%s",
+ mysql_tmpdir, tmp_file_prefix, current_pid, thd->thread_id,
+ thd->tmp_table++, reg_ext)>= (int)sizeof(path))
+ DBUG_RETURN(-1);
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
}
else
- (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,db,alias,reg_ext);
+ if (snprintf(path, sizeof(path), "%s/%s/%s%s", mysql_data_home, db,
+ alias, reg_ext)>= (int)sizeof(path))
+ DBUG_RETURN(-1);
unpack_filename(path,path);
/* Check if table already exists */
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE)
@@ -1077,7 +1129,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
{
- create_info->table_existed= 1; // Mark that table existed
+ create_info->table_existed= 1; // Mark that table existed
DBUG_RETURN(0);
}
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
@@ -1092,8 +1144,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
{
- create_info->table_existed= 1; // Mark that table existed
- error= 0;
+ create_info->table_existed= 1; // Mark that table existed
+ error= 0;
}
else
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
@@ -1102,14 +1154,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
thd->proc_info="creating table";
- create_info->table_existed= 0; // Mark that table is created
+ create_info->table_existed= 0; // Mark that table is created
if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)
create_info->data_file_name= create_info->index_file_name= 0;
create_info->table_options=db_options;
if (rea_create_table(thd, path, create_info, fields, key_count,
- key_info_buffer))
+ key_info_buffer))
{
/* my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,my_errno); */
goto end;
@@ -1132,8 +1184,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- test(create_info->options &
- HA_LEX_CREATE_TMP_TABLE));
+ test(create_info->options &
+ HA_LEX_CREATE_TMP_TABLE));
mysql_bin_log.write(&qinfo);
}
}
@@ -1163,17 +1215,23 @@ static char *
make_unique_key_name(const char *field_name,KEY *start,KEY *end)
{
char buff[MAX_FIELD_NAME],*buff_end;
+ int remain;
if (!check_if_keyname_exists(field_name,start,end) &&
my_strcasecmp(system_charset_info,field_name,primary_key_name))
- return (char*) field_name; // Use fieldname
+ return (char*) field_name; // Use fieldname
buff_end=strmake(buff,field_name,MAX_FIELD_NAME-4);
- for (uint i=2 ; ; i++)
+ /*ingo 2004-04-07 only 3 chars + '\0' left, so need to limit to 2 digit*/
+ for (uint i=2 ; i< 100; i++)
{
- sprintf(buff_end,"_%d",i);
+ remain= (int)sizeof(buff)- (buff_end- buff);
+ if (snprintf(buff_end, remain, "_%d", i)>= remain)
+ return NULL;
if (!check_if_keyname_exists(buff,start,end))
return sql_strdup(buff);
}
+ /*ingo 2004-04-07 dedicated return is inevitable*/
+ return NULL;
}
/****************************************************************************
@@ -1181,13 +1239,13 @@ make_unique_key_name(const char *field_name,KEY *start,KEY *end)
****************************************************************************/
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)
+ 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 tmp_table; // Used during 'create_field()'
TABLE *table;
tmp_table.table_name=0;
uint select_field_count= items->elements;
@@ -1201,7 +1259,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
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);
+ create_info->db_type == DB_TYPE_HEAP);
while ((item=it++))
{
@@ -1211,18 +1269,18 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
field=item->tmp_table_field(&tmp_table);
else
field=create_tmp_field(thd, &tmp_table, item, item->type(),
- (Item ***) 0, &tmp_field,0,0);
+ (Item ***) 0, &tmp_field,0,0);
if (!field ||
- !(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ?
- ((Item_field *)item)->field :
- (Field*) 0))))
+ !(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: This should be done atomic ! */
if (mysql_create_table(thd,db,name,create_info,*extra_fields,
- *keys,0,1,select_field_count)) // no logging
+ *keys,0,1,select_field_count)) // no logging
DBUG_RETURN(0);
if (!(table=open_table(thd,db,name,name,(bool*) 0)))
{
@@ -1249,10 +1307,10 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
bool
mysql_rename_table(enum db_type base,
- const char *old_db,
- const char *old_name,
- const char *new_db,
- const char *new_name)
+ const char *old_db,
+ const char *old_name,
+ const char *new_db,
+ const char *new_name)
{
char from[FN_REFLEN], to[FN_REFLEN];
char tmp_from[NAME_LEN+1], tmp_to[NAME_LEN+1];
@@ -1271,8 +1329,12 @@ mysql_rename_table(enum db_type base,
my_casedn_str(system_charset_info, tmp_to);
new_name= tmp_to;
}
- (void) sprintf(from,"%s/%s/%s",mysql_data_home,old_db,old_name);
- (void) sprintf(to,"%s/%s/%s",mysql_data_home,new_db,new_name);
+ if (snprintf(from, sizeof(from), "%s/%s/%s",
+ mysql_data_home, old_db, old_name)>= (int)sizeof(from))
+ DBUG_RETURN(1);
+ if (snprintf(to, sizeof(to), "%s/%s/%s",
+ mysql_data_home, new_db, new_name)>= (int)sizeof(to))
+ DBUG_RETURN(1);
fn_format(from,from,"","",4);
fn_format(to,to, "","",4);
@@ -1297,10 +1359,10 @@ mysql_rename_table(enum db_type base,
SYNOPSIS
wait_while_table_is_used()
- thd Thread handler
- table Table to remove from cache
- function HA_EXTRA_PREPARE_FOR_DELETE if table is to be deleted
- HA_EXTRA_FORCE_REOPEN if table is not be used
+ thd Thread handler
+ table Table to remove from cache
+ function HA_EXTRA_PREPARE_FOR_DELETE if table is to be deleted
+ HA_EXTRA_FORCE_REOPEN if table is not be used
NOTES
When returning, the table will be unusable for other threads until
the table is closed.
@@ -1311,7 +1373,7 @@ mysql_rename_table(enum db_type base,
*/
static void wait_while_table_is_used(THD *thd,TABLE *table,
- enum ha_extra_function function)
+ enum ha_extra_function function)
{
DBUG_PRINT("enter",("table: %s", table->real_name));
DBUG_ENTER("wait_while_table_is_used");
@@ -1319,11 +1381,11 @@ static void wait_while_table_is_used(THD *thd,TABLE *table,
VOID(table->file->extra(function));
/* Mark all tables that are in use as 'old' */
- mysql_lock_abort(thd, table); // end threads waiting on lock
+ mysql_lock_abort(thd, table); // end threads waiting on lock
/* Wait until all there are no other threads that has this table open */
while (remove_table_from_cache(thd,table->table_cache_key,
- table->real_name))
+ table->real_name))
{
dropping_tables++;
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
@@ -1337,8 +1399,8 @@ static void wait_while_table_is_used(THD *thd,TABLE *table,
SYNOPSIS
close_cached_table()
- thd Thread handler
- table Table to remove from cache
+ thd Thread handler
+ table Table to remove from cache
NOTES
Function ends by signaling threads waiting for the table to try to
@@ -1358,7 +1420,7 @@ static bool close_cached_table(THD *thd, TABLE *table)
if (thd->lock)
{
mysql_unlock_tables(thd, thd->lock);
- thd->lock=0; // Start locked threads
+ thd->lock=0; // Start locked threads
}
/* Close all copies of 'table'. This also frees all LOCK TABLES lock */
thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
@@ -1369,7 +1431,7 @@ static bool close_cached_table(THD *thd, TABLE *table)
}
static int send_check_errmsg(THD *thd, TABLE_LIST* table,
- const char* operator_name, const char* errmsg)
+ const char* operator_name, const char* errmsg)
{
Protocol *protocol= thd->protocol;
@@ -1386,15 +1448,15 @@ static int send_check_errmsg(THD *thd, TABLE_LIST* table,
static int prepare_for_restore(THD* thd, TABLE_LIST* table,
- HA_CHECK_OPT *check_opt)
+ HA_CHECK_OPT *check_opt)
{
DBUG_ENTER("prepare_for_restore");
if (table->table) // do not overwrite existing tables on restore
{
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
- "table exists, will not overwrite on restore"
- ));
+ "table exists, will not overwrite on restore"
+ ));
}
else
{
@@ -1404,23 +1466,25 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
char* db = thd->db ? thd->db : table->db;
if (fn_format_relative_to_data_home(src_path, table_name, backup_dir,
- reg_ext))
+ reg_ext))
DBUG_RETURN(-1); // protect buffer overflow
- sprintf(dst_path, "%s/%s/%s", mysql_real_data_home, db, table_name);
+ if (snprintf(dst_path, sizeof(dst_path), "%s/%s/%s",
+ mysql_real_data_home, db, table_name)>= (int)sizeof(dst_path))
+ DBUG_RETURN(-1);
if (lock_and_wait_for_table_name(thd,table))
DBUG_RETURN(-1);
if (my_copy(src_path,
- fn_format(dst_path, dst_path,"", reg_ext, 4),
- MYF(MY_WME)))
+ fn_format(dst_path, dst_path,"", reg_ext, 4),
+ MYF(MY_WME)))
{
pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table);
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
- "Failed copying .frm file"));
+ "Failed copying .frm file"));
}
if (mysql_truncate(thd, table, 1))
{
@@ -1428,7 +1492,7 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
unlock_table_name(thd, table);
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
- "Failed generating table from .frm file"));
+ "Failed generating table from .frm file"));
}
}
@@ -1447,7 +1511,7 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
- HA_CHECK_OPT *check_opt)
+ HA_CHECK_OPT *check_opt)
{
int error= 0;
TABLE tmp_table, *table;
@@ -1456,13 +1520,13 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
if (!(check_opt->sql_flags & TT_USEFRM))
DBUG_RETURN(0);
- if (!(table= table_list->table)) /* if open_ltable failed */
+ if (!(table= table_list->table)) /* if open_ltable failed */
{
char name[FN_REFLEN];
strxmov(name, mysql_data_home, "/", table_list->db, "/",
- table_list->real_name, NullS);
+ table_list->real_name, NullS);
if (openfrm(name, "", 0, 0, 0, &tmp_table))
- DBUG_RETURN(0); // Can't open frm file
+ DBUG_RETURN(0); // Can't open frm file
table= &tmp_table;
}
@@ -1485,13 +1549,18 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
like ISAM or MyISAM
*/
if (!ext[0] || !ext[1])
- goto end; // No data file
+ goto end; // No data file
- strxmov(from, table->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
+ goto end; // Can't use USE_FRM flag
- sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
+ if (snprintf(tmp, sizeof(tmp), "%s-%lx_%lx",
+ from, current_pid, thd->thread_id)>= (int)sizeof(tmp))
+ {
+ error= -1;
+ goto end;
+ }
/* If we could open the table, close it */
if (table_list->table)
@@ -1511,7 +1580,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
unlock_table_name(thd, table_list);
pthread_mutex_unlock(&LOCK_open);
error= send_check_errmsg(thd, table_list, "repair",
- "Failed renaming data file");
+ "Failed renaming data file");
goto end;
}
if (mysql_truncate(thd, table_list, 1))
@@ -1520,7 +1589,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
unlock_table_name(thd, table_list);
pthread_mutex_unlock(&LOCK_open);
error= send_check_errmsg(thd, table_list, "repair",
- "Failed generating table from .frm file");
+ "Failed generating table from .frm file");
goto end;
}
if (my_rename(tmp, from, MYF(MY_WME)))
@@ -1529,7 +1598,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
unlock_table_name(thd, table_list);
pthread_mutex_unlock(&LOCK_open);
error= send_check_errmsg(thd, table_list, "repair",
- "Failed restoring .MYD file");
+ "Failed restoring .MYD file");
goto end;
}
@@ -1546,21 +1615,21 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
end:
if (table == &tmp_table)
- closefrm(table); // Free allocated memory
+ closefrm(table); // Free allocated memory
DBUG_RETURN(error);
}
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 *))
+ 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;
List<Item> field_list;
@@ -1611,11 +1680,11 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->store(operator_name, 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);
+ err_msg=ER(ER_CHECK_NO_SUCH_TABLE);
protocol->store(err_msg, system_charset_info);
thd->net.last_error[0]=0;
if (protocol->write())
- goto err;
+ goto err;
continue;
}
table->table->pos_in_table_list= table;
@@ -1626,12 +1695,14 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
protocol->store("error", 5, system_charset_info);
- sprintf(buff, ER(ER_OPEN_AS_READONLY), table_name);
+ if (snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
+ table_name)>= (int)sizeof(buff))
+ goto err;
protocol->store(buff, system_charset_info);
close_thread_tables(thd);
- table->table=0; // For query cache
+ table->table=0; // For query cache
if (protocol->write())
- goto err;
+ goto err;
continue;
}
@@ -1640,20 +1711,20 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
{
pthread_mutex_lock(&LOCK_open);
const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
- "Waiting to get writelock");
+ "Waiting to get writelock");
mysql_lock_abort(thd,table->table);
while (remove_table_from_cache(thd, table->table->table_cache_key,
- table->table->real_name) &&
- ! thd->killed)
+ table->table->real_name) &&
+ ! thd->killed)
{
- dropping_tables++;
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- dropping_tables--;
+ dropping_tables++;
+ (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+ dropping_tables--;
}
thd->exit_cond(old_message);
pthread_mutex_unlock(&LOCK_open);
if (thd->killed)
- goto err;
+ goto err;
open_for_modify=0;
}
@@ -1670,7 +1741,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
{
char buf[ERRMSGSIZE+20];
uint length=my_snprintf(buf, ERRMSGSIZE,
- ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
+ ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
protocol->store("error", 5, system_charset_info);
protocol->store(buf, length, system_charset_info);
}
@@ -1708,26 +1779,26 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->store("Invalid argument",16, system_charset_info);
break;
- default: // Probably HA_ADMIN_INTERNAL_ERROR
+ default: // Probably HA_ADMIN_INTERNAL_ERROR
protocol->store("error", 5, system_charset_info);
protocol->store("Unknown - internal error during operation", 41
- , system_charset_info);
+ , system_charset_info);
fatal_error=1;
break;
}
if (fatal_error)
- table->table->version=0; // Force close of table
+ table->table->version=0; // Force close of table
else if (open_for_modify)
{
pthread_mutex_lock(&LOCK_open);
remove_table_from_cache(thd, table->table->table_cache_key,
- table->table->real_name);
+ table->table->real_name);
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);
- table->table=0; // For query cache
+ table->table=0; // For query cache
if (protocol->write())
goto err;
}
@@ -1735,7 +1806,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
send_eof(thd);
DBUG_RETURN(0);
err:
- close_thread_tables(thd); // Shouldn't be needed
+ close_thread_tables(thd); // Shouldn't be needed
if (table)
table->table=0;
DBUG_RETURN(-1);
@@ -1746,8 +1817,8 @@ 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,
- &handler::backup));
+ "backup", TL_READ, 0, 0, 0,
+ &handler::backup));
}
@@ -1755,9 +1826,9 @@ 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, 0,
+ "restore", TL_WRITE, 1, 0,
&prepare_for_restore,
- &handler::restore));
+ &handler::restore));
}
@@ -1765,9 +1836,9 @@ 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, HA_OPEN_FOR_REPAIR,
+ "repair", TL_WRITE, 1, HA_OPEN_FOR_REPAIR,
&prepare_for_repair,
- &handler::repair));
+ &handler::repair));
}
@@ -1775,8 +1846,8 @@ 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,
- &handler::optimize));
+ "optimize", TL_WRITE, 1,0,0,
+ &handler::optimize));
}
@@ -1785,16 +1856,16 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
SYNOPSIS
mysql_assign_to_keycache()
- thd Thread object
+ thd Thread object
tables Table list (one table only)
RETURN VALUES
- 0 ok
- -1 error
+ 0 ok
+ -1 error
*/
int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
- LEX_STRING *key_cache_name)
+ LEX_STRING *key_cache_name)
{
HA_CHECK_OPT check_opt;
KEY_CACHE *key_cache;
@@ -1811,7 +1882,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
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,
+ "assign_to_keycache", TL_READ_NO_INSERT, 0,
0, 0, &handler::assign_to_keycache));
}
@@ -1821,7 +1892,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
SYNOPSIS
reassign_keycache_tables()
- thd Thread object
+ thd Thread object
src_cache Reference to the key cache to clean up
dest_cache New key cache
@@ -1838,7 +1909,7 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
to it for a while after this function returns.
RETURN VALUES
- 0 ok
+ 0 ok
*/
int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache,
@@ -1848,7 +1919,7 @@ int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache,
DBUG_ASSERT(src_cache != dst_cache);
DBUG_ASSERT(src_cache->in_init);
- src_cache->param_buff_size= 0; // Free key cache
+ src_cache->param_buff_size= 0; // Free key cache
ha_resize_key_cache(src_cache);
ha_change_key_cache(src_cache, dst_cache);
DBUG_RETURN(0);
@@ -1860,20 +1931,20 @@ int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache,
SYNOPSIS
mysql_preload_keys()
- thd Thread object
+ thd Thread object
tables Table list (one table only)
RETURN VALUES
- 0 ok
- -1 error
+ 0 ok
+ -1 error
*/
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,
- &handler::preload_keys));
+ "preload_keys", TL_READ, 0, 0, 0,
+ &handler::preload_keys));
}
@@ -1882,14 +1953,14 @@ int mysql_preload_keys(THD* thd, TABLE_LIST* tables)
SYNOPSIS
mysql_create_like_table()
- thd Thread object
+ thd Thread object
table Table list (one table only)
create_info Create info
table_ident Src table_ident
RETURN VALUES
- 0 ok
- -1 error
+ 0 ok
+ -1 error
*/
int mysql_create_like_table(THD* thd, TABLE_LIST* table,
@@ -1948,8 +2019,11 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
{
if (find_temporary_table(thd, db, table_name))
goto table_exists;
- sprintf(dst_path,"%s%s%lx_%lx_%x%s",mysql_tmpdir,tmp_file_prefix,
- current_pid, thd->thread_id, thd->tmp_table++,reg_ext);
+ if (snprintf(dst_path, sizeof(dst_path), "%s%s%lx_%lx_%x%s",
+ mysql_tmpdir, tmp_file_prefix, current_pid,
+ thd->thread_id, thd->tmp_table++, reg_ext)>=
+ (int)sizeof(dst_path))
+ DBUG_RETURN(-1);
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
}
else
@@ -1963,11 +2037,6 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
/*
Create a new table by copying from source table
*/
-#ifndef DBUG_OFF
- // The code stated below is for test synchronization.test Bug #2385
- if (test_flags & TEST_SYNCHRONIZATION)
- sleep(3);
-#endif
if (my_copy(src_path, dst_path, MYF(MY_WME|MY_DONT_OVERWRITE_FILE)))
goto err;
@@ -2001,8 +2070,8 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
{
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- test(create_info->options &
- HA_LEX_CREATE_TMP_TABLE));
+ test(create_info->options &
+ HA_LEX_CREATE_TMP_TABLE));
mysql_bin_log.write(&qinfo);
}
res= 0;
@@ -2012,7 +2081,9 @@ table_exists:
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
- sprintf(warn_buff,ER(ER_TABLE_EXISTS_ERROR),table_name);
+ if (snprintf(warn_buff, sizeof(warn_buff),
+ ER(ER_TABLE_EXISTS_ERROR), table_name)>= (int)sizeof(warn_buff))
+ DBUG_RETURN(-1);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TABLE_EXISTS_ERROR,warn_buff);
res= 0;
@@ -2038,8 +2109,8 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
DBUG_ENTER("mysql_analyze_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
- "analyze", lock_type, 1,0,0,
- &handler::analyze));
+ "analyze", lock_type, 1,0,0,
+ &handler::analyze));
}
@@ -2053,15 +2124,15 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
DBUG_ENTER("mysql_check_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
- "check", lock_type,
- 0, HA_OPEN_FOR_REPAIR, 0,
- &handler::check));
+ "check", lock_type,
+ 0, HA_OPEN_FOR_REPAIR, 0,
+ &handler::check));
}
/* table_list should contain just one table */
int mysql_discard_or_import_tablespace(THD *thd,
- TABLE_LIST *table_list,
- enum tablespace_op_type tablespace_op)
+ TABLE_LIST *table_list,
+ enum tablespace_op_type tablespace_op)
{
TABLE *table;
my_bool discard;
@@ -2079,8 +2150,8 @@ int mysql_discard_or_import_tablespace(THD *thd,
discard = FALSE;
thd->tablespace_op=TRUE; /* we set this flag so that ha_innobase::open
- and ::external_lock() do not complain when we
- lock the table */
+ and ::external_lock() do not complain when we
+ lock the table */
mysql_ha_closeall(thd, table_list);
if (!(table=open_ltable(thd,table_list,TL_WRITE)))
@@ -2123,28 +2194,317 @@ err:
DBUG_RETURN(error);
}
+/*
+ CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
+ the proper arguments. This isn't very fast but it should work for most
+ cases.
+ One should normally create all indexes with CREATE TABLE or ALTER TABLE.
+*/
+
+int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
+{
+ List<create_field> fields;
+ List<Alter_drop> drop;
+ List<Alter_column> alter;
+ HA_CREATE_INFO create_info;
+ int rc;
+ uint idx;
+ uint db_options;
+ uint key_count;
+ TABLE *table;
+ Field **f_ptr;
+ KEY *key_info_buffer;
+ char path[FN_REFLEN];
+ DBUG_ENTER("mysql_create_index");
+
+ /*
+ Try to use online generation of index.
+ This requires that all indexes can be created online.
+ Otherwise, the old alter table procedure is executed.
+
+ Open the table to have access to the correct table handler.
+ */
+ if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
+ DBUG_RETURN(-1);
+
+ /*
+ The add_index method takes an array of KEY structs for the new indexes.
+ Preparing a new table structure generates this array.
+ It needs a list with all fields of the table, which does not need to
+ be correct in every respect. The field names are important.
+ */
+ for (f_ptr= table->field; *f_ptr; f_ptr++)
+ {
+ create_field *c_fld= new create_field(*f_ptr, *f_ptr);
+ c_fld->unireg_check= Field::NONE; /*avoid multiple auto_increments*/
+ fields.push_back(c_fld);
+ }
+ bzero((char*) &create_info,sizeof(create_info));
+ 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,
+ /*select_field_count*/ 0))
+ DBUG_RETURN(-1);
+
+ /*
+ Check if all keys can be generated with the add_index method.
+ If anyone cannot, then take the old way.
+ */
+ for (idx=0; idx< key_count; idx++)
+ {
+ DBUG_PRINT("info", ("creating index %s", key_info_buffer[idx].name));
+ if (!(table->file->index_ddl_flags(key_info_buffer+idx)&
+ (HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
+ break ;
+ }
+ if ((idx < key_count)|| !key_count)
+ {
+ /* Re-initialize the create_info, which was changed by prepare table. */
+ bzero((char*) &create_info,sizeof(create_info));
+ create_info.db_type=DB_TYPE_DEFAULT;
+ 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->real_name,
+ &create_info, table_list, table,
+ fields, keys, drop, alter, 0, (ORDER*)0,
+ ALTER_ADD_INDEX, DUP_ERROR))
+ /*don't need to free((gptr) key_info_buffer);*/
+ DBUG_RETURN(-1);
+ }
+ else
+ {
+ if (table->file->add_index(table, key_info_buffer, key_count)||
+ (snprintf(path, sizeof(path), "%s/%s/%s%s", mysql_data_home,
+ table_list->db, (lower_case_table_names == 2)?
+ table_list->alias: table_list->real_name, reg_ext)>=
+ (int)sizeof(path))||
+ ! unpack_filename(path, path)||
+ mysql_create_frm(thd, path, &create_info,
+ fields, key_count, key_info_buffer, table->file))
+ /*don't need to free((gptr) key_info_buffer);*/
+ DBUG_RETURN(-1);
+ }
+
+ /*don't need to free((gptr) key_info_buffer);*/
+ DBUG_RETURN(0);
+}
+
+
+int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
+{
+ List<create_field> fields;
+ List<Key> keys;
+ List<Alter_column> alter;
+ HA_CREATE_INFO create_info;
+ uint idx;
+ uint db_options;
+ uint key_count;
+ uint *key_numbers;
+ TABLE *table;
+ Field **f_ptr;
+ KEY *key_info;
+ KEY *key_info_buffer;
+ char path[FN_REFLEN];
+ DBUG_ENTER("mysql_drop_index");
+
+ /*
+ Try to use online generation of index.
+ This requires that all indexes can be created online.
+ Otherwise, the old alter table procedure is executed.
+
+ Open the table to have access to the correct table handler.
+ */
+ if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
+ DBUG_RETURN(-1);
+
+ /*
+ The drop_index method takes an array of key numbers.
+ It cannot get more entries than keys in the table.
+ */
+ key_numbers= (uint*) thd->alloc(sizeof(uint*)*table->keys);
+ key_count= 0;
+
+ /*
+ Get the number of each key and check if it can be created online.
+ */
+ List_iterator<Alter_drop> drop_it(drop);
+ Alter_drop *drop_key;
+ while ((drop_key= drop_it++))
+ {
+ /* Find the key in the table. */
+ key_info=table->key_info;
+ for (idx=0; idx< table->keys; idx++, key_info++)
+ {
+ if (!my_strcasecmp(system_charset_info, key_info->name, drop_key->name))
+ break;
+ }
+ if (idx>= table->keys)
+ {
+ my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop_key->name);
+ /*don't need to free((gptr) key_numbers);*/
+ DBUG_RETURN(-1);
+ }
+ /*
+ Check if the key can be generated with the add_index method.
+ If anyone cannot, then take the old way.
+ */
+ DBUG_PRINT("info", ("dropping index %s", table->key_info[idx].name));
+ if (!(table->file->index_ddl_flags(table->key_info+idx)&
+ (HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
+ break ;
+ key_numbers[key_count++]= idx;
+ }
+
+ bzero((char*) &create_info,sizeof(create_info));
+ create_info.db_type=DB_TYPE_DEFAULT;
+ create_info.default_table_charset= thd->variables.collation_database;
+
+ if ((drop_key)|| (drop.elements<= 0))
+ {
+ 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))
+ /*don't need to free((gptr) key_numbers);*/
+ DBUG_RETURN(-1);
+ }
+ else
+ {
+ 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,
+ /*select_field_count*/ 0)||
+ (snprintf(path, sizeof(path), "%s/%s/%s%s", mysql_data_home,
+ table_list->db, (lower_case_table_names == 2)?
+ table_list->alias: table_list->real_name, reg_ext)>=
+ (int)sizeof(path))||
+ ! unpack_filename(path, path)||
+ mysql_create_frm(thd, path, &create_info,
+ fields, key_count, key_info_buffer, table->file))
+ /*don't need to free((gptr) key_numbers);*/
+ DBUG_RETURN(-1);
+ }
+
+ /*don't need to free((gptr) key_numbers);*/
+ DBUG_RETURN(0);
+}
+
+int mysql_add_column(THD *thd, TABLE_LIST *table_list,
+ List<create_field> &fields)
+{
+ List<Alter_drop> drop;
+ List<Key> keys;
+ List<Alter_column> alter;
+ HA_CREATE_INFO create_info;
+ DBUG_ENTER("mysql_add_column");
+ bzero((char*) &create_info,sizeof(create_info));
+ create_info.db_type=DB_TYPE_DEFAULT;
+ create_info.default_table_charset= thd->variables.collation_database;
+ TABLE *table;
+ if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
+ DBUG_RETURN(-1);
+
+ DBUG_RETURN(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_COLUMN, DUP_ERROR));
+}
+
+int mysql_drop_column(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
+{
+ List<create_field> fields;
+ List<Key> keys;
+ List<Alter_column> alter;
+ HA_CREATE_INFO create_info;
+ DBUG_ENTER("mysql_drop_column");
+ bzero((char*) &create_info,sizeof(create_info));
+ create_info.db_type=DB_TYPE_DEFAULT;
+ create_info.default_table_charset= thd->variables.collation_database;
+ TABLE *table;
+ if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
+ DBUG_RETURN(-1);
+
+ DBUG_RETURN(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_COLUMN, DUP_ERROR));
+}
+
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,List<Alter_drop> &drop_list,
- List<Alter_column> &alter_list,
- uint order_num, ORDER *order,
- enum enum_duplicates handle_duplicates,
- enum enum_enable_or_disable keys_onoff,
- enum tablespace_op_type tablespace_op,
+ HA_CREATE_INFO *create_info,
+ TABLE_LIST *table_list,
+ List<create_field> &fields,
+ List<Key> &keys,List<Alter_drop> &drop_list,
+ List<Alter_column> &alter_list,
+ uint order_num, ORDER *order, int alter_flags,
+ enum enum_duplicates handle_duplicates,
+ enum enum_enable_or_disable keys_onoff,
+ enum tablespace_op_type tablespace_op,
bool simple_alter)
{
- TABLE *table,*new_table;
+ DBUG_ENTER("mysql_alter_table");
+
+ mysql_ha_closeall(thd, table_list);
+
+ /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
+ if (tablespace_op != NO_TABLESPACE_OP)
+ DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
+ tablespace_op));
+
+ if (alter_flags == ALTER_ADD_INDEX)
+ DBUG_RETURN(mysql_create_index(thd, table_list, keys));
+
+ if (alter_flags == ALTER_DROP_INDEX)
+ DBUG_RETURN(mysql_drop_index(thd, table_list, drop_list));
+
+ if (alter_flags == ALTER_ADD_COLUMN)
+ DBUG_RETURN(mysql_add_column(thd, table_list, fields));
+
+ if (alter_flags == ALTER_DROP_COLUMN)
+ DBUG_RETURN(mysql_drop_column(thd, table_list, drop_list));
+
+ TABLE *table;
+ if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
+ DBUG_RETURN(-1);
+
+ DBUG_RETURN(real_alter_table(thd, new_db, new_name,
+ create_info, table_list, table, fields,
+ keys, drop_list, alter_list,
+ order_num, order, alter_flags,
+ handle_duplicates, keys_onoff,
+ tablespace_op, simple_alter));
+}
+
+int real_alter_table(THD *thd,char *new_db, char *new_name,
+ HA_CREATE_INFO *create_info,
+ TABLE_LIST *table_list,
+ TABLE *table,
+ List<create_field> &fields,
+ List<Key> &keys,List<Alter_drop> &drop_list,
+ List<Alter_column> &alter_list,
+ uint order_num, ORDER *order, int alter_flags,
+ enum enum_duplicates handle_duplicates,
+ enum enum_enable_or_disable keys_onoff,
+ enum tablespace_op_type tablespace_op,
+ bool simple_alter)
+{
+ 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;
char index_file[FN_REFLEN], data_file[FN_REFLEN];
+ bool use_timestamp=0;
ha_rows copied,deleted;
ulonglong next_insert_id;
uint db_create_options, used_fields;
enum db_type old_db_type,new_db_type;
- DBUG_ENTER("mysql_alter_table");
+ DBUG_ENTER("real_alter_table");
thd->proc_info="init";
table_name=table_list->real_name;
@@ -2157,15 +2517,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
used_fields=create_info->used_fields;
- mysql_ha_closeall(thd, table_list);
-
- /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
- if (tablespace_op != NO_TABLESPACE_OP)
- DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
- tablespace_op));
- if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
- DBUG_RETURN(-1);
-
/* Check that we are not trying to rename to an existing table */
if (new_name)
{
@@ -2175,13 +2526,13 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
if (lower_case_table_names != 2)
{
- my_casedn_str(system_charset_info, new_name_buff);
- new_alias= new_name; // Create lower case table name
+ my_casedn_str(system_charset_info, new_name_buff);
+ new_alias= new_name; // Create lower case table name
}
my_casedn_str(system_charset_info, new_name);
}
if (new_db == db &&
- !my_strcasecmp(table_alias_charset, new_name_buff, table_name))
+ !my_strcasecmp(table_alias_charset, new_name_buff, table_name))
{
/*
Source and destination table names are equal: make later check
@@ -2193,21 +2544,21 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
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(-1);
- }
+ if (find_temporary_table(thd,new_db,new_name_buff))
+ {
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff);
+ DBUG_RETURN(-1);
+ }
}
else
{
- if (!access(fn_format(new_name_buff,new_name_buff,new_db,reg_ext,0),
- F_OK))
- {
- /* Table will be closed in do_command() */
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0), new_alias);
- DBUG_RETURN(-1);
- }
+ if (!access(fn_format(new_name_buff,new_name_buff,new_db,reg_ext,0),
+ F_OK))
+ {
+ /* Table will be closed in do_command() */
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0), new_alias);
+ DBUG_RETURN(-1);
+ }
}
}
}
@@ -2222,10 +2573,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
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);
+ 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->row_type;
@@ -2250,7 +2601,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
*fn_ext(new_name)=0;
close_cached_table(thd, table);
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias))
- error= -1;
+ error= -1;
}
VOID(pthread_mutex_unlock(&LOCK_open));
}
@@ -2259,42 +2610,47 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
switch (keys_onoff) {
case LEAVE_AS_IS:
- break;
+ 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->activate_all_index(thd);
+ error= table->file->enable_indexes();
/* COND_refresh will be signaled in close_thread_tables() */
break;
case DISABLE:
- if (table->db_type == DB_TYPE_MYISAM)
- {
- VOID(pthread_mutex_lock(&LOCK_open));
- wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- VOID(pthread_mutex_unlock(&LOCK_open));
- table->file->deactivate_non_unique_index(HA_POS_ERROR);
+ 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(0, 1);
/* COND_refresh will be signaled in close_thread_tables() */
- }
- else
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_ILLEGAL_HA,
- ER(ER_ILLEGAL_HA), table->table_name);
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)
{
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, 0);
- mysql_bin_log.write(&qinfo);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ mysql_bin_log.write(&qinfo);
}
send_ok(thd);
}
- table_list->table=0; // For query cache
+ else
+ {
+ table->file->print_error(error, MYF(0));
+ error=-1;
+ }
+ table_list->table=0; // For query cache
query_cache_invalidate3(thd, table_list, 0);
DBUG_RETURN(error);
}
@@ -2311,12 +2667,12 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
create_info->default_table_charset= table->table_charset;
- restore_record(table,default_values); // Empty record for DEFAULT
+ restore_record(table,default_values); // Empty record for DEFAULT
List_iterator<Alter_drop> drop_it(drop_list);
List_iterator<create_field> def_it(fields);
List_iterator<Alter_column> alter_it(alter_list);
- List<create_field> create_list; // Add new fields here
- List<Key> key_list; // Add new keys here
+ List<create_field> create_list; // Add new fields here
+ List<Key> key_list; // Add new keys here
create_field *def;
/*
@@ -2332,16 +2688,16 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
while ((drop=drop_it++))
{
if (drop->type == Alter_drop::COLUMN &&
- !my_strcasecmp(system_charset_info,field->field_name, drop->name))
+ !my_strcasecmp(system_charset_info,field->field_name, drop->name))
{
- /* Reset auto_increment value if it was dropped */
- if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
- !(used_fields & HA_CREATE_USED_AUTO))
- {
- create_info->auto_increment_value=0;
- create_info->used_fields|=HA_CREATE_USED_AUTO;
- }
- break;
+ /* Reset auto_increment value if it was dropped */
+ if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
+ !(used_fields & HA_CREATE_USED_AUTO))
+ {
+ create_info->auto_increment_value=0;
+ create_info->used_fields|=HA_CREATE_USED_AUTO;
+ }
+ break;
}
}
if (drop)
@@ -2355,26 +2711,30 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
if (def->change &&
!my_strcasecmp(system_charset_info,field->field_name, def->change))
- break;
+ break;
}
if (def)
- { // Field is changed
+ { // Field is changed
def->field=field;
+ if (def->sql_type == FIELD_TYPE_TIMESTAMP)
+ use_timestamp=1;
if (!def->after)
{
- create_list.push_back(def);
- def_it.remove();
+ create_list.push_back(def);
+ def_it.remove();
}
}
else
- { // Use old field value
+ { // Use old field value
create_list.push_back(def=new create_field(field,field));
- alter_it.rewind(); // Change default if ALTER
+ if (def->sql_type == FIELD_TYPE_TIMESTAMP)
+ use_timestamp=1;
+ alter_it.rewind(); // Change default if ALTER
Alter_column *alter;
while ((alter=alter_it++))
{
- if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
- break;
+ if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
+ break;
}
if (alter)
{
@@ -2383,14 +2743,14 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
my_error(ER_BLOB_CANT_HAVE_DEFAULT,MYF(0),def->change);
DBUG_RETURN(-1);
}
- def->def=alter->def; // Use new default
- alter_it.remove();
+ def->def=alter->def; // Use new default
+ alter_it.remove();
}
}
}
def_it.rewind();
List_iterator<create_field> find_it(create_list);
- while ((def=def_it++)) // Add new columns
+ while ((def=def_it++)) // Add new columns
{
if (def->change && ! def->field)
{
@@ -2405,17 +2765,17 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
create_field *find;
find_it.rewind();
- while ((find=find_it++)) // Add new columns
+ while ((find=find_it++)) // Add new columns
{
- if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
- break;
+ if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
+ break;
}
if (!find)
{
- my_error(ER_BAD_FIELD_ERROR,MYF(0),def->after,table_name);
- DBUG_RETURN(-1);
+ my_error(ER_BAD_FIELD_ERROR,MYF(0),def->after,table_name);
+ DBUG_RETURN(-1);
}
- find_it.after(def); // Put element after this
+ find_it.after(def); // Put element after this
}
}
if (alter_list.elements)
@@ -2447,8 +2807,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
while ((drop=drop_it++))
{
if (drop->type == Alter_drop::KEY &&
- !my_strcasecmp(system_charset_info,key_name, drop->name))
- break;
+ !my_strcasecmp(system_charset_info,key_name, drop->name))
+ break;
}
if (drop)
{
@@ -2461,60 +2821,60 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{
if (!key_part->field)
- continue; // Wrong field (from UNIREG)
+ continue; // Wrong field (from UNIREG)
const char *key_part_name=key_part->field->field_name;
create_field *cfield;
field_it.rewind();
while ((cfield=field_it++))
{
- if (cfield->change)
- {
- if (!my_strcasecmp(system_charset_info, key_part_name,
- cfield->change))
- break;
- }
- else if (!my_strcasecmp(system_charset_info,
+ if (cfield->change)
+ {
+ if (!my_strcasecmp(system_charset_info, key_part_name,
+ cfield->change))
+ break;
+ }
+ else if (!my_strcasecmp(system_charset_info,
key_part_name, cfield->field_name))
- break;
+ break;
}
if (!cfield)
- continue; // Field is removed
+ continue; // Field is removed
uint key_part_length=key_part->length;
- if (cfield->field) // Not new 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
+ if (cfield->field) // Not new 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,
- key_part_length));
+ key_part_length));
}
if (key_parts.elements)
key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL :
(key_info->flags & HA_NOSAME ?
- (!my_strcasecmp(system_charset_info,
+ (!my_strcasecmp(system_charset_info,
key_name, primary_key_name) ?
- Key::PRIMARY : Key::UNIQUE) :
- (key_info->flags & HA_FULLTEXT ?
- Key::FULLTEXT : Key::MULTIPLE)),
- key_name,
+ Key::PRIMARY : Key::UNIQUE) :
+ (key_info->flags & HA_FULLTEXT ?
+ Key::FULLTEXT : Key::MULTIPLE)),
+ key_name,
key_info->algorithm,
- key_parts));
+ key_parts));
}
{
Key *key;
- while ((key=key_it++)) // Add new keys
+ while ((key=key_it++)) // Add new keys
{
if (key->type != Key::FOREIGN_KEY)
- key_list.push_back(key);
+ key_list.push_back(key);
if (key->name &&
- !my_strcasecmp(system_charset_info,key->name,primary_key_name))
+ !my_strcasecmp(system_charset_info,key->name,primary_key_name))
{
- my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
- DBUG_RETURN(-1);
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
+ DBUG_RETURN(-1);
}
}
}
@@ -2531,8 +2891,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
db_create_options=table->db_create_options & ~(HA_OPTION_PACK_RECORD);
- (void) sprintf(tmp_name,"%s-%lx_%lx", tmp_file_prefix, current_pid,
- thd->thread_id);
+ if (snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
+ current_pid, thd->thread_id)>= (int)sizeof(tmp_name))
+ goto err;
create_info->db_type=new_db_type;
if (!create_info->comment)
create_info->comment=table->comment;
@@ -2548,7 +2909,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (create_info->table_options &
(HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
- HA_OPTION_NO_DELAY_KEY_WRITE);
+ HA_OPTION_NO_DELAY_KEY_WRITE);
create_info->table_options|= db_create_options;
if (table->tmp_table)
@@ -2579,31 +2940,31 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
Remove old table and symlinks.
*/
- if (!strcmp(db, new_db)) // Ignore symlink if db changed
+ if (!strcmp(db, new_db)) // Ignore symlink if db changed
{
if (create_info->index_file_name)
{
/* Fix index_file_name to have 'tmp_name' as basename */
strmov(index_file, tmp_name);
create_info->index_file_name=fn_same(index_file,
- create_info->index_file_name,
- 1);
+ create_info->index_file_name,
+ 1);
}
if (create_info->data_file_name)
{
/* Fix data_file_name to have 'tmp_name' as basename */
strmov(data_file, tmp_name);
create_info->data_file_name=fn_same(data_file,
- create_info->data_file_name,
- 1);
+ create_info->data_file_name,
+ 1);
}
}
else
create_info->data_file_name=create_info->index_file_name=0;
if ((error=mysql_create_table(thd, new_db, tmp_name,
- create_info,
- create_list,key_list,1,1,0))) // no logging
+ create_info,
+ create_list,key_list,1,1,0))) // no logging
DBUG_RETURN(error);
if (table->tmp_table)
@@ -2611,7 +2972,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
else
{
char path[FN_REFLEN];
- (void) sprintf(path,"%s/%s/%s",mysql_data_home,new_db,tmp_name);
+ if (snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home,
+ new_db, tmp_name)>= (int)sizeof(path))
+ goto err;
fn_format(path,path,"","",4);
new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
}
@@ -2629,16 +2992,16 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
*/
new_table->timestamp_default_now= 0;
new_table->next_number_field=new_table->found_next_number_field;
- thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
+ 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 loggin
+ next_insert_id=thd->next_insert_id; // Remember for loggin
copied=deleted=0;
if (!new_table->is_view)
error=copy_data_between_tables(table,new_table,create_list,
- handle_duplicates,
- order_num, order, &copied, &deleted);
- thd->last_insert_id=next_insert_id; // Needed for correct log
+ handle_duplicates,
+ 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->tmp_table)
@@ -2647,8 +3010,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (error)
{
/*
- The following function call will free the new_table pointer,
- in close_temporary_table(), so we can safely directly jump to err
+ The following function call will free the new_table pointer,
+ in close_temporary_table(), so we can safely directly jump to err
*/
close_temporary_table(thd,new_db,tmp_name);
goto err;
@@ -2662,7 +3025,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
/* Remove link to old table and rename the new one */
close_temporary_table(thd,table->table_cache_key,table_name);
if (rename_temporary_table(thd, new_table, new_db, new_alias))
- { // Fatal error
+ { // Fatal error
close_temporary_table(thd,new_db,tmp_name);
my_free((gptr) new_table,MYF(0));
goto err;
@@ -2677,7 +3040,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto end_temporary;
}
- intern_close_table(new_table); /* close temporary table */
+ intern_close_table(new_table); /* close temporary table */
my_free((gptr) new_table,MYF(0));
VOID(pthread_mutex_lock(&LOCK_open));
if (error)
@@ -2694,8 +3057,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
*/
thd->proc_info="rename result table";
- sprintf(old_name,"%s2-%lx-%lx", tmp_file_prefix, current_pid,
- thd->thread_id);
+ if (snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
+ current_pid, thd->thread_id)>= (int)sizeof(old_name))
+ goto err;
if (new_name != table_name || new_db != db)
{
if (!access(new_name_buff,F_OK))
@@ -2716,18 +3080,18 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
Win32 and InnoDB can't drop a table that is in use, so we must
close the original table at before doing the rename
*/
- table_name=thd->strdup(table_name); // must be saved
+ table_name=thd->strdup(table_name); // must be saved
if (close_cached_table(thd, table))
- { // Aborted
+ { // 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
+ table=0; // Marker that table is closed
}
#if (!defined( __WIN__) && !defined( __EMX__) && !defined( OS2))
else
- table->file->extra(HA_EXTRA_FORCE_REOPEN); // Don't use this file anymore
+ table->file->extra(HA_EXTRA_FORCE_REOPEN); // Don't use this file anymore
#endif
@@ -2738,8 +3102,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
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))
- { // Try to get everything back
+ new_alias))
+ { // Try to get everything back
error=1;
VOID(quick_rm_table(new_db_type,new_db,new_alias));
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
@@ -2756,7 +3120,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
- if (thd->lock || new_name != table_name) // True if WIN32
+ if (thd->lock || new_name != table_name) // True if WIN32
{
/*
Not table locking or alter table with rename
@@ -2777,14 +3141,14 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Use new file
remove_table_from_cache(thd,db,table_name); // Mark all in-use copies old
- mysql_lock_abort(thd,table); // end threads waiting on lock
+ mysql_lock_abort(thd,table); // end threads waiting on lock
}
VOID(quick_rm_table(old_db_type,db,old_name));
if (close_data_tables(thd,db,table_name) ||
- reopen_tables(thd,1,0))
- { // This shouldn't happen
+ reopen_tables(thd,1,0))
+ { // This shouldn't happen
if (table)
- close_cached_table(thd,table); // Remove lock for table
+ close_cached_table(thd,table); // Remove lock for table
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
@@ -2818,7 +3182,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
shutdown.
*/
char path[FN_REFLEN];
- (void) sprintf(path,"%s/%s/%s",mysql_data_home,new_db,table_name);
+ if (snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home,
+ new_db, table_name)>= (int)sizeof(path))
+ goto err;
fn_format(path,path,"","",4);
table=open_temporary_table(thd, path, new_db, tmp_name,0);
if (table)
@@ -2828,16 +3194,18 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
else
sql_print_error("Warning: Could not open BDB table %s.%s after rename\n",
- new_db,table_name);
+ new_db,table_name);
(void) berkeley_flush_logs();
}
#endif
- table_list->table=0; // For query cache
+ table_list->table=0; // For query cache
query_cache_invalidate3(thd, table_list, 0);
end_temporary:
- sprintf(tmp_name, ER(ER_INSERT_INFO), (ulong) (copied + deleted),
- (ulong) deleted, (ulong) thd->cuted_fields);
+ if (snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
+ (ulong) (copied + deleted), (ulong) deleted,
+ (ulong) thd->cuted_fields)>= (int)sizeof(tmp_name))
+ goto err;
send_ok(thd,copied+deleted,0L,tmp_name);
thd->some_tables_deleted=0;
DBUG_RETURN(0);
@@ -2850,9 +3218,9 @@ end_temporary:
static int
copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create,
- enum enum_duplicates handle_duplicates,
+ enum enum_duplicates handle_duplicates,
uint order_num, ORDER *order,
- ha_rows *copied,
+ ha_rows *copied,
ha_rows *deleted)
{
int error;
@@ -2870,12 +3238,11 @@ copy_data_between_tables(TABLE *from,TABLE *to,
DBUG_ENTER("copy_data_between_tables");
if (!(copy= new Copy_field[to->fields]))
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(-1); /* purecov: inspected */
to->file->external_lock(thd,F_WRLCK);
- to->file->extra(HA_EXTRA_WRITE_CACHE);
from->file->info(HA_STATUS_VARIABLE);
- to->file->deactivate_non_unique_index(from->file->records);
+ to->file->start_bulk_insert(from->file->records);
List_iterator<create_field> it(create);
create_field *def;
@@ -2896,12 +3263,12 @@ copy_data_between_tables(TABLE *from,TABLE *to,
bzero((char*) &tables,sizeof(tables));
tables.table = from;
tables.alias = tables.real_name= from->real_name;
- tables.db = from->table_cache_key;
+ 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) ||
+ setup_order(thd, thd->lex->select_lex.ref_pointer_array,
+ &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) ||
(from->sort.found_records = filesort(thd, from, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR,
@@ -2943,12 +3310,12 @@ copy_data_between_tables(TABLE *from,TABLE *to,
if ((error=to->file->write_row((byte*) to->record[0])))
{
if ((handle_duplicates != DUP_IGNORE &&
- handle_duplicates != DUP_REPLACE) ||
- (error != HA_ERR_FOUND_DUPP_KEY &&
- error != HA_ERR_FOUND_DUPP_UNIQUE))
+ 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->print_error(error,MYF(0));
+ break;
}
delete_count++;
}
@@ -2957,18 +3324,16 @@ copy_data_between_tables(TABLE *from,TABLE *to,
}
end_read_record(&info);
free_io_cache(from);
- delete [] copy; // This is never 0
- uint tmp_error;
- if ((tmp_error=to->file->extra(HA_EXTRA_NO_CACHE)))
+ delete [] copy; // This is never 0
+
+ if (to->file->end_bulk_insert() && !error)
{
- to->file->print_error(tmp_error,MYF(0));
+ to->file->print_error(my_errno,MYF(0));
error=1;
}
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
- if (to->file->activate_all_index(thd))
- error=1;
- tmp_error = ha_recovery_logging(thd,TRUE);
+ ha_recovery_logging(thd,TRUE);
/*
Ensure that the new table is saved properly to disk so that we
can do a rename
@@ -3010,7 +3375,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
strxmov(table_name, table->db ,".", table->real_name, NullS);
t= table->table= open_ltable(thd, table, TL_READ_NO_INSERT);
- thd->clear_error(); // these errors shouldn't get client
+ thd->clear_error(); // these errors shouldn't get client
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
@@ -3029,7 +3394,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
!(check_opt->flags & T_EXTEND))
protocol->store((ulonglong)t->file->checksum());
else if (!(t->file->table_flags() & HA_HAS_CHECKSUM) &&
- (check_opt->flags & T_QUICK))
+ (check_opt->flags & T_QUICK))
protocol->store_null();
else
{
@@ -3050,7 +3415,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
ha_checksum row_crc= 0;
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]);
+ ((byte*) t->field[0]->ptr) - t->record[0]);
for (uint i= 0; i < t->fields; i++ )
{
@@ -3058,12 +3423,12 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
if (f->type() == FIELD_TYPE_BLOB)
{
String tmp;
- f->val_str(&tmp,&tmp);
+ f->val_str(&tmp);
row_crc= my_checksum(row_crc, (byte*) tmp.ptr(), tmp.length());
}
else
row_crc= my_checksum(row_crc, (byte*) f->ptr,
- f->pack_length());
+ f->pack_length());
}
crc+= row_crc;
@@ -3073,7 +3438,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
}
thd->clear_error();
close_thread_tables(thd);
- table->table=0; // For query cache
+ table->table=0; // For query cache
}
if (protocol->write())
goto err;
@@ -3083,7 +3448,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
DBUG_RETURN(0);
err:
- close_thread_tables(thd); // Shouldn't be needed
+ close_thread_tables(thd); // Shouldn't be needed
if (table)
table->table=0;
DBUG_RETURN(-1);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 2d713ef5f5e..b87b0b29677 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -210,6 +210,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CONCURRENT
%token CONSTRAINT
%token CONVERT_SYM
+%token CURRENT_USER
%token DATABASES
%token DATA_SYM
%token DEFAULT
@@ -1438,10 +1439,29 @@ attribute:
{ Lex->on_update_value= new Item_func_now_local(); }
| AUTO_INC { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; }
| SERIAL_SYM DEFAULT VALUE_SYM
- { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG; }
- | opt_primary KEY_SYM { Lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG; }
- | UNIQUE_SYM { Lex->type|= UNIQUE_FLAG; }
- | UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; }
+ {
+ LEX *lex=Lex;
+ lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG;
+ lex->alter_flags|= ALTER_ADD_INDEX;
+ }
+ | opt_primary KEY_SYM
+ {
+ LEX *lex=Lex;
+ lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG;
+ lex->alter_flags|= ALTER_ADD_INDEX;
+ }
+ | UNIQUE_SYM
+ {
+ LEX *lex=Lex;
+ lex->type|= UNIQUE_FLAG;
+ lex->alter_flags|= ALTER_ADD_INDEX;
+ }
+ | UNIQUE_SYM KEY_SYM
+ {
+ LEX *lex=Lex;
+ lex->type|= UNIQUE_KEY_FLAG;
+ lex->alter_flags|= ALTER_ADD_INDEX;
+ }
| COMMENT_SYM TEXT_STRING_sys { Lex->comment= &$2; }
| BINARY { Lex->type|= BINCMP_FLAG; }
| COLLATE_SYM collation_name
@@ -1699,6 +1719,7 @@ alter:
lex->alter_keys_onoff=LEAVE_AS_IS;
lex->tablespace_op=NO_TABLESPACE_OP;
lex->simple_alter=1;
+ lex->alter_flags=0;
}
alter_list
{}
@@ -1717,16 +1738,28 @@ alter_list:
| alter_list ',' alter_list_item;
add_column:
- ADD opt_column { Lex->change=0; };
+ ADD opt_column
+ {
+ LEX *lex=Lex;
+ lex->change=0;
+ lex->alter_flags|= ALTER_ADD_COLUMN;
+ };
alter_list_item:
add_column column_def opt_place { Lex->simple_alter=0; }
- | ADD key_def { Lex->simple_alter=0; }
+ | ADD key_def
+ {
+ LEX *lex=Lex;
+ lex->simple_alter=0;
+ lex->alter_flags|= ALTER_ADD_INDEX;
+ }
| add_column '(' field_list ')' { Lex->simple_alter=0; }
| CHANGE opt_column field_ident
{
LEX *lex=Lex;
- lex->change= $3.str; lex->simple_alter=0;
+ lex->change= $3.str;
+ lex->simple_alter=0;
+ lex->alter_flags|= ALTER_CHANGE_COLUMN;
}
field_spec opt_place
| MODIFY_SYM opt_column field_ident
@@ -1737,6 +1770,7 @@ alter_list_item:
lex->comment=0;
lex->charset= NULL;
lex->simple_alter=0;
+ lex->alter_flags|= ALTER_CHANGE_COLUMN;
}
type opt_attribute
{
@@ -1755,7 +1789,9 @@ alter_list_item:
{
LEX *lex=Lex;
lex->drop_list.push_back(new Alter_drop(Alter_drop::COLUMN,
- $3.str)); lex->simple_alter=0;
+ $3.str));
+ lex->simple_alter=0;
+ lex->alter_flags|= ALTER_DROP_COLUMN;
}
| DROP FOREIGN KEY_SYM opt_ident { Lex->simple_alter=0; }
| DROP PRIMARY_SYM KEY_SYM
@@ -1764,6 +1800,7 @@ alter_list_item:
lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
primary_key_name));
lex->simple_alter=0;
+ lex->alter_flags|= ALTER_DROP_INDEX;
}
| DROP key_or_index field_ident
{
@@ -1771,6 +1808,7 @@ alter_list_item:
lex->drop_list.push_back(new Alter_drop(Alter_drop::KEY,
$3.str));
lex->simple_alter=0;
+ lex->alter_flags|= ALTER_DROP_INDEX;
}
| DISABLE_SYM KEYS { Lex->alter_keys_onoff=DISABLE; }
| ENABLE_SYM KEYS { Lex->alter_keys_onoff=ENABLE; }
@@ -1779,18 +1817,21 @@ alter_list_item:
LEX *lex=Lex;
lex->alter_list.push_back(new Alter_column($3.str,$6));
lex->simple_alter=0;
+ lex->alter_flags|= ALTER_CHANGE_COLUMN;
}
| ALTER opt_column field_ident DROP DEFAULT
{
LEX *lex=Lex;
lex->alter_list.push_back(new Alter_column($3.str,(Item*) 0));
lex->simple_alter=0;
+ lex->alter_flags|= ALTER_CHANGE_COLUMN;
}
| RENAME opt_to table_ident
{
LEX *lex=Lex;
lex->select_lex.db=$3->db.str;
lex->name= $3->table.str;
+ lex->alter_flags|= ALTER_RENAME;
}
| CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate
{
@@ -1813,8 +1854,18 @@ alter_list_item:
HA_CREATE_USED_DEFAULT_CHARSET);
lex->simple_alter= 0;
}
- | create_table_options_space_separated { Lex->simple_alter=0; }
- | order_clause { Lex->simple_alter=0; };
+ | create_table_options_space_separated
+ {
+ LEX *lex=Lex;
+ lex->simple_alter=0;
+ lex->alter_flags|= ALTER_OPTIONS;
+ }
+ | order_clause
+ {
+ LEX *lex=Lex;
+ lex->simple_alter=0;
+ lex->alter_flags|= ALTER_ORDER;
+ };
opt_column:
/* empty */ {}
@@ -2684,6 +2735,8 @@ simple_expr:
$$= new Item_func_curtime_local($3);
Lex->safe_to_cache_query=0;
}
+ | CURRENT_USER optional_braces
+ { $$= create_func_current_user(); }
| DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')'
{ $$= new Item_date_add_interval($3,$5,$6,0); }
| DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')'
@@ -3060,11 +3113,15 @@ sum_expr:
{ $$=new Item_sum_variance($3); }
| SUM_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_sum($3); }
- | GROUP_CONCAT_SYM '(' opt_distinct expr_list opt_gorder_clause
- opt_gconcat_separator ')'
+ | GROUP_CONCAT_SYM '(' opt_distinct
+ { Select->in_sum_expr++; }
+ expr_list opt_gorder_clause
+ opt_gconcat_separator
+ ')'
{
- $$=new Item_func_group_concat($3,$4,Lex->gorder_list,$6);
- $4->empty();
+ Select->in_sum_expr--;
+ $$=new Item_func_group_concat($3,$5,Select->gorder_list,$7);
+ $5->empty();
};
opt_distinct:
@@ -3079,16 +3136,15 @@ opt_gconcat_separator:
opt_gorder_clause:
/* empty */
{
- LEX *lex=Lex;
- lex->gorder_list = NULL;
+ Select->gorder_list = NULL;
}
| order_clause
{
- LEX *lex=Lex;
- lex->gorder_list=
- (SQL_LIST*) sql_memdup((char*) &lex->current_select->order_list,
+ SELECT_LEX *select= Select;
+ select->gorder_list=
+ (SQL_LIST*) sql_memdup((char*) &select->order_list,
sizeof(st_sql_list));
- lex->current_select->order_list.empty();
+ select->order_list.empty();
};
@@ -4170,6 +4226,29 @@ show_param:
{ Lex->sql_command= SQLCOM_SHOW_LOGS; WARN_DEPRECATED("SHOW BDB LOGS", "SHOW ENGINE BDB LOGS"); }
| LOGS_SYM
{ Lex->sql_command= SQLCOM_SHOW_LOGS; WARN_DEPRECATED("SHOW LOGS", "SHOW ENGINE BDB LOGS"); }
+ | GRANTS
+ {
+ LEX *lex=Lex;
+ lex->sql_command= SQLCOM_SHOW_GRANTS;
+ THD *thd= lex->thd;
+ LEX_USER *curr_user;
+ if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ YYABORT;
+ curr_user->user.str= thd->priv_user;
+ curr_user->user.length= strlen(thd->priv_user);
+ if (*thd->priv_host != 0)
+ {
+ curr_user->host.str= thd->priv_host;
+ curr_user->host.length= strlen(thd->priv_host);
+ }
+ else
+ {
+ curr_user->host.str= (char *) "%";
+ curr_user->host.length= 1;
+ }
+ curr_user->password.str=NullS;
+ lex->grant_user= curr_user;
+ }
| GRANTS FOR_SYM user
{
LEX *lex=Lex;
@@ -4760,7 +4839,25 @@ user:
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
YYABORT;
$$->user = $1; $$->host=$3;
- };
+ }
+ | CURRENT_USER optional_braces
+ {
+ THD *thd= YYTHD;
+ if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
+ YYABORT;
+ $$->user.str= thd->priv_user;
+ $$->user.length= strlen(thd->priv_user);
+ if (*thd->priv_host != 0)
+ {
+ $$->host.str= thd->priv_host;
+ $$->host.length= strlen(thd->priv_host);
+ }
+ else
+ {
+ $$->host.str= (char *) "%";
+ $$->host.length= 1;
+ }
+ };
/* Keyword that we allow for identifiers */
diff --git a/sql/table.cc b/sql/table.cc
index dcd0d39d855..f137abf2ef7 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -465,7 +465,6 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
goto err_not_open; /* purecov: inspected */
}
reg_field->comment=comment;
- reg_field->set_charset(charset);
if (!(reg_field->flags & NOT_NULL_FLAG))
{
if ((null_bit<<=1) == 256)
@@ -1229,7 +1228,7 @@ bool get_field(MEM_ROOT *mem, Field *field, String *res)
String str(buff,sizeof(buff),&my_charset_bin);
uint length;
- field->val_str(&str,&str);
+ field->val_str(&str);
if (!(length= str.length()))
return 1;
to= strmake_root(mem, str.ptr(), length);
@@ -1257,7 +1256,7 @@ char *get_field(MEM_ROOT *mem, Field *field)
String str(buff,sizeof(buff),&my_charset_bin);
uint length;
- field->val_str(&str,&str);
+ field->val_str(&str);
length= str.length();
if (!length || !(to= (char*) alloc_root(mem,length+1)))
return NullS;
@@ -1288,7 +1287,7 @@ bool check_db_name(char *name)
/* Used to catch empty names and names with end space */
bool last_char_is_space= TRUE;
- if (lower_case_table_names)
+ if (lower_case_table_names && name != any_db)
my_casedn_str(files_charset_info, name);
while (*name)
diff --git a/sql/table.h b/sql/table.h
index bbf22ae6725..46516c839a3 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -193,8 +193,8 @@ typedef struct st_table_list
bool updating; /* for replicate-do/ignore table */
bool force_index; /* Prefer index over table scan */
bool ignore_leaves; /* Preload only non-leaf nodes */
+ bool cacheable_table; /* stop PS caching */
bool checked; /* used in multi-upd privelege check */
- bool non_cachable_table; /* stop PS caching */
} TABLE_LIST;
typedef struct st_changed_table_list
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 0e4b449c6a3..4af1c832b57 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -47,10 +47,11 @@ static bool make_empty_rec(int file, enum db_type table_type,
uint reclength,uint null_fields);
-int rea_create_table(THD *thd, my_string file_name,
+int mysql_create_frm(THD *thd, my_string file_name,
HA_CREATE_INFO *create_info,
List<create_field> &create_fields,
- uint keys, KEY *key_info)
+ uint keys, KEY *key_info,
+ handler *db_file)
{
uint reclength,info_length,screens,key_info_length,maxlength,null_fields;
File file;
@@ -58,13 +59,13 @@ int rea_create_table(THD *thd, my_string file_name,
uchar fileinfo[64],forminfo[288],*keybuff;
TYPELIB formnames;
uchar *screen_buff;
- handler *db_file;
DBUG_ENTER("rea_create_table");
formnames.type_names=0;
if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0)))
DBUG_RETURN(1);
- db_file=get_new_handler((TABLE*) 0, create_info->db_type);
+ if (db_file == NULL)
+ db_file=get_new_handler((TABLE*) 0, create_info->db_type);
if (pack_header(forminfo, create_info->db_type,create_fields,info_length,
screens, create_info->table_options, db_file))
{
@@ -155,8 +156,7 @@ int rea_create_table(THD *thd, my_string file_name,
if (opt_sync_frm && !(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
my_sync(file, MYF(MY_WME)))
goto err2;
- if (my_close(file,MYF(MY_WME)) ||
- ha_create_table(file_name,create_info,0))
+ if (my_close(file,MYF(MY_WME)))
goto err3;
DBUG_RETURN(0);
@@ -166,6 +166,23 @@ err:
err2:
VOID(my_close(file,MYF(MY_WME)));
err3:
+ DBUG_RETURN(1);
+} /* mysql_create_frm */
+
+int rea_create_table(THD *thd, my_string file_name,
+ HA_CREATE_INFO *create_info,
+ List<create_field> &create_fields,
+ uint keys, KEY *key_info)
+{
+ DBUG_ENTER("rea_create_table");
+
+ if (mysql_create_frm(thd, file_name, create_info,
+ create_fields, keys, key_info, NULL) ||
+ ha_create_table(file_name,create_info,0))
+ goto err;
+ DBUG_RETURN(0);
+
+err:
my_delete(file_name,MYF(0));
DBUG_RETURN(1);
} /* rea_create_table */