summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.h1
-rw-r--r--sql/field_conv.cc55
-rw-r--r--sql/ha_innodb.cc63
-rw-r--r--sql/item.cc42
-rw-r--r--sql/item.h3
-rw-r--r--sql/log.cc4
-rw-r--r--sql/mysqld.cc1
-rw-r--r--sql/sql_db.cc2
-rw-r--r--sql/sql_parse.cc8
-rw-r--r--sql/sql_select.cc30
-rw-r--r--sql/table.cc7
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),
- &reg_field,sizeof(Field*)*(field_count+1),
- &from_field,sizeof(Field*)*field_count,
+ &reg_field, sizeof(Field*)*(field_count+1),
+ &blob_field, sizeof(Field*)*(field_count+1),
+ &from_field, sizeof(Field*)*field_count,
&copy_func,sizeof(*copy_func)*(param->func_count+1),
&param->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