diff options
Diffstat (limited to 'sql')
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(©->tmp,©->tmp); + copy->from_field->val_str(©->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(©->tmp,©->tmp); + copy->from_field->val_str(©->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(¶m); + 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(¶m); - 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 ¶m, 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 */ |