diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.h | 1 | ||||
-rw-r--r-- | sql/field_conv.cc | 55 | ||||
-rw-r--r-- | sql/ha_innodb.cc | 63 | ||||
-rw-r--r-- | sql/item.cc | 42 | ||||
-rw-r--r-- | sql/item.h | 3 | ||||
-rw-r--r-- | sql/log.cc | 4 | ||||
-rw-r--r-- | sql/mysqld.cc | 1 | ||||
-rw-r--r-- | sql/sql_db.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 8 | ||||
-rw-r--r-- | sql/sql_select.cc | 30 | ||||
-rw-r--r-- | sql/table.cc | 7 |
11 files changed, 170 insertions, 46 deletions
diff --git a/sql/field.h b/sql/field.h index 0f0225da3d2..4290f99ea3e 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1056,6 +1056,7 @@ Field *make_field(char *ptr, uint32 field_length, uint pack_length_to_packflag(uint type); uint32 calc_pack_length(enum_field_types type,uint32 length); bool set_field_to_null(Field *field); +bool set_field_to_null_with_conversions(Field *field); uint find_enum(TYPELIB *typelib,const char *x, uint length); ulonglong find_set(TYPELIB *typelib,const char *x, uint length); bool test_if_int(const char *str,int length); diff --git a/sql/field_conv.cc b/sql/field_conv.cc index c7a6d778953..53b26920c14 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -112,35 +112,52 @@ static void do_outer_field_to_null_str(Copy_field *copy) bool set_field_to_null(Field *field) { - if (field->maybe_null()) + if (field->real_maybe_null()) { field->set_null(); field->reset(); + return 0; } - else + return 1; +} + + +bool +set_field_to_null_with_conversions(Field *field) +{ + if (field->real_maybe_null()) { - if (field->type() == FIELD_TYPE_TIMESTAMP) - { - ((Field_timestamp*) field)->set_time(); - return 0; // Ok to set time to NULL - } + field->set_null(); field->reset(); - if (field == field->table->next_number_field) - return 0; // field is set in handler.cc - if (current_thd->count_cuted_fields) - { - current_thd->cuted_fields++; // Increment error counter - return 0; - } - if (!current_thd->no_errors) - my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0), - field->field_name); - return 1; + return 0; + } + + /* + Check if this is a special type, which will get a special walue + when set to NULL + */ + if (field->type() == FIELD_TYPE_TIMESTAMP) + { + ((Field_timestamp*) field)->set_time(); + return 0; // Ok to set time to NULL + } + field->reset(); + if (field == field->table->next_number_field) + return 0; // field is set in handler.cc + if (current_thd->count_cuted_fields) + { + current_thd->cuted_fields++; // Increment error counter + return 0; } - return 0; + if (!current_thd->no_errors) + my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0), + field->field_name); + return 1; } + + static void do_skip(Copy_field *copy __attribute__((unused))) { } diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 2c27f565895..bb3f254bc03 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2179,16 +2179,8 @@ convert_search_mode_to_innobase( case HA_READ_AFTER_KEY: return(PAGE_CUR_G); case HA_READ_BEFORE_KEY: return(PAGE_CUR_L); case HA_READ_PREFIX: return(PAGE_CUR_GE); - case HA_READ_PREFIX_LAST: - /* ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Warning: Using HA_READ_PREFIX_LAST\n"); */ - return(PAGE_CUR_LE); - - /* InnoDB does not yet support ..PREFIX_LAST! - We have to add a new search flag - PAGE_CUR_LE_OR_PREFIX to InnoDB. */ - + case HA_READ_PREFIX_LAST: return(PAGE_CUR_LE); + /* HA_READ_PREFIX_LAST does not yet work in InnoDB! */ /* the above PREFIX flags mean that the last field in the key value may just be a prefix of the complete fixed length field */ @@ -3262,7 +3254,7 @@ ha_innobase::records_in_range( MYF(MY_WME)); dtuple_t* range_start; dtuple_t* range_end; - ulint n_rows; + ib_longlong n_rows; ulint mode1; ulint mode2; void* heap1; @@ -3647,6 +3639,47 @@ ha_innobase::reset(void) return(0); } + +/********************************************************************** +When we create a temporary table inside MySQL LOCK TABLES, MySQL will +not call external_lock for the temporary table when it uses it. Instead, +it will call this function. */ + +int +ha_innobase::start_stmt( +/*====================*/ + /* out: 0 or error code */ + THD* thd) /* in: handle to the user thread */ +{ + row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; + trx_t* trx; + + update_thd(thd); + + trx = prebuilt->trx; + + innobase_release_stat_resources(trx); + trx_mark_sql_stat_end(trx); + + auto_inc_counter_for_this_stat = 0; + prebuilt->sql_stat_start = TRUE; + prebuilt->hint_no_need_to_fetch_extra_cols = TRUE; + prebuilt->read_just_key = 0; + + if (prebuilt->select_lock_type == LOCK_NONE) { + /* This handle is for a temporary table created inside + this same LOCK TABLES; since MySQL does NOT call external_lock + in this case, we must use x-row locks inside InnoDB to be + prepared for an update of a row */ + + prebuilt->select_lock_type = LOCK_X; + } + + thd->transaction.all.innodb_active_trans = 1; + + return(0); +} + /********************************************************************** When we create a temporary table inside MySQL LOCK TABLES, MySQL will not call external_lock for the temporary table when it uses it. Instead, @@ -3785,6 +3818,14 @@ innodb_show_status( DBUG_ENTER("innodb_show_status"); + if (innodb_skip) { + + fprintf(stderr, + "Cannot call SHOW INNODB STATUS because skip-innodb is defined\n"); + + DBUG_RETURN(-1); + } + /* We let the InnoDB Monitor to output at most 100 kB of text, add a safety margin of 10 kB for buffer overruns */ diff --git a/sql/item.cc b/sql/item.cc index bb39a141e9f..b3b4e99e28a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -419,7 +419,7 @@ void Item_field::save_org_in_field(Field *to) if (field->is_null()) { null_value=1; - set_field_to_null(to); + set_field_to_null_with_conversions(to); } else { @@ -434,7 +434,7 @@ bool Item_field::save_in_field(Field *to) if (result_field->is_null()) { null_value=1; - return set_field_to_null(to); + return set_field_to_null_with_conversions(to); } else { @@ -445,9 +445,42 @@ bool Item_field::save_in_field(Field *to) return 0; } +/* + Store null in field + + SYNOPSIS + save_in_field() + field Field where we want to store NULL + + DESCRIPTION + This is used on INSERT. + Allow NULL to be inserted in timestamp and auto_increment values + + RETURN VALUES + 0 ok + 1 Field doesn't support NULL values and can't handle 'field = NULL' +*/ bool Item_null::save_in_field(Field *field) { + return set_field_to_null_with_conversions(field); +} + + +/* + Store null in field + + SYNOPSIS + save_safe_in_field() + field Field where we want to store NULL + + RETURN VALUES + 0 ok + 1 Field doesn't support NULL values +*/ + +bool Item_null::save_safe_in_field(Field *field) +{ return set_field_to_null(field); } @@ -463,7 +496,7 @@ bool Item::save_in_field(Field *field) str_value.set_quick(buff,sizeof(buff)); result=val_str(&str_value); if (null_value) - return set_field_to_null(field); + return set_field_to_null_with_conversions(field); field->set_notnull(); field->store(result->ptr(),result->length()); str_value.set_quick(0, 0); @@ -480,13 +513,14 @@ bool Item::save_in_field(Field *field) { longlong nr=val_int(); if (null_value) - return set_field_to_null(field); + return set_field_to_null_with_conversions(field); field->set_notnull(); field->store(nr); } return 0; } + bool Item_string::save_in_field(Field *field) { String *result; diff --git a/sql/item.h b/sql/item.h index 70729afe28e..246e1fbcbd6 100644 --- a/sql/item.h +++ b/sql/item.h @@ -56,6 +56,8 @@ public: virtual bool save_in_field(Field *field); virtual void save_org_in_field(Field *field) { (void) save_in_field(field); } + virtual bool save_safe_in_field(Field *field) + { return save_in_field(field); } virtual bool send(THD *thd, String *str); virtual bool eq(const Item *, bool binary_cmp) const; virtual Item_result result_type () const { return REAL_RESULT; } @@ -154,6 +156,7 @@ public: String *val_str(String *str); void make_field(Send_field *field); bool save_in_field(Field *field); + bool save_safe_in_field(Field *field); enum Item_result result_type () const { return STRING_RESULT; } bool send(THD *thd, String *str); diff --git a/sql/log.cc b/sql/log.cc index ccd3954e172..72e1b60f6b3 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -938,8 +938,8 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, int error=0; VOID(pthread_mutex_lock(&LOCK_log)); - /* Test if someone closed after the is_open test */ - if (log_type != LOG_CLOSED) + /* Test if someone closed between the is_open test and lock */ + if (is_open()) { time_t skr; ulong id; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c418ef34174..7e2bc9512cd 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4160,7 +4160,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case (int) OPT_SKIP_SHOW_DB: opt_skip_show_db=1; opt_specialflag|=SPECIAL_SKIP_SHOW_DB; - mysql_port=0; break; #ifdef ONE_THREAD case (int) OPT_ONE_THREAD: diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 6c2ba4b6429..287df717aec 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -382,6 +382,8 @@ bool mysql_change_db(THD *thd,const char *name) } send_ok(&thd->net); x_free(thd->db); + if (lower_case_table_names) + casedn_str(dbname); thd->db=dbname; thd->db_length=db_length; thd->db_access=db_access; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d6e40889eed..2642a27cfff 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3356,10 +3356,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables) } if (options & REFRESH_LOG) { - mysql_log.new_file(); - mysql_update_log.new_file(); - mysql_bin_log.new_file(); - mysql_slow_log.new_file(); + mysql_log.new_file(0); + mysql_update_log.new_file(0); + mysql_bin_log.new_file(0); + mysql_slow_log.new_file(0); if (ha_flush_logs()) result=1; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 042fb779ec2..fc5fe33288f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3527,7 +3527,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, char *tmpname,path[FN_REFLEN]; byte *pos,*group_buff; uchar *null_flags; - Field **reg_field,**from_field; + Field **reg_field, **from_field, **blob_field; Copy_field *copy=0; KEY *keyinfo; KEY_PART_INFO *key_part_info; @@ -3572,8 +3572,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, hidden_field_count=param->hidden_field_count; if (!my_multi_malloc(MYF(MY_WME), &table,sizeof(*table), - ®_field,sizeof(Field*)*(field_count+1), - &from_field,sizeof(Field*)*field_count, + ®_field, sizeof(Field*)*(field_count+1), + &blob_field, sizeof(Field*)*(field_count+1), + &from_field, sizeof(Field*)*field_count, ©_func,sizeof(*copy_func)*(param->func_count+1), ¶m->keyinfo,sizeof(*param->keyinfo), &key_part_info, @@ -3602,8 +3603,12 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, bzero((char*) reg_field,sizeof(Field*)*(field_count+1)); bzero((char*) from_field,sizeof(Field*)*field_count); table->field=reg_field; + table->blob_field= (Field_blob**) blob_field; table->real_name=table->path=tmpname; - table->table_name=base_name(tmpname); + /* + This must be "" as field may refer to it after tempory table is dropped + */ + table->table_name= (char*) ""; table->reginfo.lock_type=TL_WRITE; /* Will be updated */ table->db_stat=HA_OPEN_KEYFILE+HA_OPEN_RNDFILE; table->blob_ptr_size=mi_portable_sizeof_char_ptr; @@ -3611,7 +3616,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, table->tmp_table= TMP_TABLE; table->db_low_byte_first=1; // True for HEAP and MyISAM table->temp_pool_slot = temp_pool_slot; - + table->copy_blobs= 1; /* Calculate which type of fields we will store in the temporary table */ @@ -3658,7 +3663,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, if (!(new_field->flags & NOT_NULL_FLAG)) null_count++; if (new_field->flags & BLOB_FLAG) + { + *blob_field++= new_field; blob_count++; + } ((Item_sum*) item)->args[i]= new Item_field(new_field); } } @@ -3681,7 +3689,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, if (!(new_field->flags & NOT_NULL_FLAG)) null_count++; if (new_field->flags & BLOB_FLAG) + { + *blob_field++= new_field; blob_count++; + } if (item->marker == 4 && item->maybe_null) { group_null_items++; @@ -3694,6 +3705,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, } DBUG_ASSERT(field_count >= (uint) (reg_field - table->field)); field_count= (uint) (reg_field - table->field); + *blob_field= 0; // End marker /* If result table is small; use a heap */ if (blob_count || using_unique_constraint || group_null_items || @@ -3951,10 +3963,17 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, if (create_myisam_tmp_table(table,param,select_options)) goto err; } + /* Set table_name for easier debugging */ + table->table_name= base_name(tmpname); if (!open_tmp_table(table)) DBUG_RETURN(table); err: + /* + Hack to ensure that free_blobs() doesn't fail if blob_field is not yet + complete + */ + *table->blob_field= 0; free_tmp_table(thd,table); /* purecov: inspected */ bitmap_clear_bit(&temp_pool, temp_pool_slot); DBUG_RETURN(NULL); /* purecov: inspected */ @@ -4096,6 +4115,7 @@ free_tmp_table(THD *thd, TABLE *entry) save_proc_info=thd->proc_info; thd->proc_info="removing tmp table"; + free_blobs(entry); if (entry->db_stat && entry->file) { (void) entry->file->close(); diff --git a/sql/table.cc b/sql/table.cc index cc5666ff5fb..d3b719c553d 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -482,6 +482,13 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, field->field_length=key_part->length; } } + /* + If the field can be NULL, don't optimize away the test + key_part_column = expression from the WHERE clause + as we need to test for NULL = NULL. + */ + if (field->real_maybe_null()) + key_part->key_part_flag|= HA_PART_KEY; } else { // Error: shorten key |