summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am10
-rw-r--r--sql/field.cc42
-rw-r--r--sql/field.h1
-rw-r--r--sql/field_conv.cc55
-rw-r--r--sql/filesort.cc39
-rw-r--r--sql/ha_heap.cc35
-rw-r--r--sql/ha_heap.h5
-rw-r--r--sql/ha_innodb.cc33
-rw-r--r--sql/ha_myisam.cc4
-rw-r--r--sql/init.cc1
-rw-r--r--sql/item.cc85
-rw-r--r--sql/item.h5
-rw-r--r--sql/item_subselect.cc71
-rw-r--r--sql/item_subselect.h27
-rw-r--r--sql/item_sum.cc4
-rw-r--r--sql/key.cc5
-rw-r--r--sql/log.cc5
-rw-r--r--sql/mysql_priv.h22
-rw-r--r--sql/mysqld.cc44
-rw-r--r--sql/net_pkg.cc4
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/set_var.cc2
-rw-r--r--sql/sql_base.cc105
-rw-r--r--sql/sql_cache.cc33
-rw-r--r--sql/sql_class.cc65
-rw-r--r--sql/sql_class.h12
-rw-r--r--sql/sql_db.cc7
-rw-r--r--sql/sql_delete.cc6
-rw-r--r--sql/sql_lex.cc4
-rw-r--r--sql/sql_lex.h6
-rw-r--r--sql/sql_parse.cc110
-rw-r--r--sql/sql_prepare.cc1
-rw-r--r--sql/sql_select.cc194
-rw-r--r--sql/sql_show.cc17
-rw-r--r--sql/sql_string.cc2
-rw-r--r--sql/sql_table.cc4
-rw-r--r--sql/sql_test.cc4
-rw-r--r--sql/sql_union.cc21
-rw-r--r--sql/sql_update.cc6
-rw-r--r--sql/sql_yacc.yy165
-rw-r--r--sql/table.cc7
41 files changed, 856 insertions, 414 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 5e023a68de9..606cc3ec7c0 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -98,16 +98,6 @@ BUILT_SOURCES = sql_yacc.cc sql_yacc.h
EXTRA_DIST = udf_example.cc $(BUILT_SOURCES)
YFLAGS = -d
-OMIT_DEPENDENCIES = pthread.h stdio.h __stdio.h stdlib.h __stdlib.h math.h\
- __math.h time.h __time.h unistd.h __unistd.h types.h \
- xtypes.h ac-types.h posix.h string.h __string.h \
- errno.h socket.h inet.h dirent.h netdb.h \
- cleanup.h cond.h debug_out.h fd.h kernel.h mutex.h \
- prio_queue.h pthread_attr.h pthread_once.h queue.h\
- sleep.h specific.h version.h pwd.h timers.h uio.h \
- cdefs.h machdep.h signal.h __signal.h util.h lex.h \
- wait.h
-
link_sources:
rm -f mini_client_errors.c
@LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c
diff --git a/sql/field.cc b/sql/field.cc
index ba84de07afb..205e98698fe 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -3831,7 +3831,9 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr)
if (binary_flag)
return memcmp(a_ptr,b_ptr,field_length);
else
- return my_sortcmp(field_charset,a_ptr,b_ptr,field_length);
+ return my_strnncoll(field_charset,
+ (const uchar*)a_ptr,field_length,
+ (const uchar*)b_ptr,field_length);
}
void Field_string::sort_string(char *to,uint length)
@@ -3841,7 +3843,7 @@ void Field_string::sort_string(char *to,uint length)
else
{
#ifdef USE_STRCOLL
- if (use_strcoll(field_charset)) {
+ if (use_strnxfrm(field_charset)) {
uint tmp=my_strnxfrm(field_charset,
(unsigned char *)to, length,
(unsigned char *) ptr, field_length);
@@ -3907,7 +3909,9 @@ int Field_string::pack_cmp(const char *a, const char *b, uint length)
int cmp= memcmp(a,b,min(a_length,b_length));
return cmp ? cmp : (int) (a_length - b_length);
}
- return my_sortncmp(field_charset, a,a_length, b,b_length);
+ return my_strnncoll(field_charset,
+ (const uchar*)a,a_length,
+ (const uchar*)b,b_length);
}
@@ -3924,7 +3928,9 @@ int Field_string::pack_cmp(const char *b, uint length)
int cmp= memcmp(ptr,b,min(a_length,b_length));
return cmp ? cmp : (int) (a_length - b_length);
}
- return my_sortncmp(field_charset, ptr,a_length, b, b_length);
+ return my_strnncoll(field_charset,
+ (const uchar*)ptr,a_length,
+ (const uchar*)b, b_length);
}
@@ -4033,7 +4039,9 @@ int Field_varstring::cmp(const char *a_ptr, const char *b_ptr)
if (binary_flag)
diff=memcmp(a_ptr+2,b_ptr+2,min(a_length,b_length));
else
- diff=my_sortcmp(field_charset, a_ptr+2,b_ptr+2,min(a_length,b_length));
+ diff=my_strnncoll(field_charset,
+ (const uchar*)a_ptr+2,min(a_length,b_length),
+ (const uchar*)b_ptr+2,min(a_length,b_length));
return diff ? diff : (int) (a_length - b_length);
}
@@ -4045,7 +4053,7 @@ void Field_varstring::sort_string(char *to,uint length)
else
{
#ifdef USE_STRCOLL
- if (use_strcoll(field_charset))
+ if (use_strnxfrm(field_charset))
tot_length=my_strnxfrm(field_charset,
(unsigned char *) to, length,
(unsigned char *)ptr+2, tot_length);
@@ -4134,7 +4142,9 @@ int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length)
int cmp= memcmp(a,b,min(a_length,b_length));
return cmp ? cmp : (int) (a_length - b_length);
}
- return my_sortncmp(field_charset, a,a_length, b,b_length);
+ return my_strnncoll(field_charset,
+ (const uchar *)a,a_length,
+ (const uchar *)b,b_length);
}
int Field_varstring::pack_cmp(const char *b, uint key_length)
@@ -4155,7 +4165,9 @@ int Field_varstring::pack_cmp(const char *b, uint key_length)
int cmp= memcmp(a,b,min(a_length,b_length));
return cmp ? cmp : (int) (a_length - b_length);
}
- return my_sortncmp(field_charset, a,a_length, b,b_length);
+ return my_strnncoll(field_charset,
+ (const uchar *)a,a_length,
+ (const uchar *)b,b_length);
}
uint Field_varstring::packed_col_length(const char *ptr, uint length)
@@ -4382,7 +4394,9 @@ int Field_blob::cmp(const char *a,uint32 a_length, const char *b,
if (binary_flag)
diff=memcmp(a,b,min(a_length,b_length));
else
- diff=my_sortcmp(field_charset, a,b,min(a_length,b_length));
+ diff=my_strnncoll(field_charset,
+ (const uchar*)a,min(a_length,b_length),
+ (const uchar*)b,min(a_length,b_length));
return diff ? diff : (int) (a_length - b_length);
}
@@ -4543,7 +4557,7 @@ void Field_blob::sort_string(char *to,uint length)
else
{
#ifdef USE_STRCOLL
- if (use_strcoll(field_charset))
+ if (use_strnxfrm(field_charset))
{
blob_length=my_strnxfrm(field_charset,
(unsigned char *)to, length,
@@ -4638,7 +4652,9 @@ int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
int cmp= memcmp(a,b,min(a_length,b_length));
return cmp ? cmp : (int) (a_length - b_length);
}
- return my_sortncmp(field_charset, a,a_length, b,b_length);
+ return my_strnncoll(field_charset,
+ (const uchar *)a,a_length,
+ (const uchar *)b,b_length);
}
@@ -4664,7 +4680,9 @@ int Field_blob::pack_cmp(const char *b, uint key_length)
int cmp= memcmp(a,b,min(a_length,b_length));
return cmp ? cmp : (int) (a_length - b_length);
}
- return my_sortncmp(field_charset, a,a_length, b,b_length);
+ return my_strnncoll(field_charset,
+ (const uchar *)a,a_length,
+ (const uchar *)b,b_length);
}
/* Create a packed key that will be used for storage from a MySQL row */
diff --git a/sql/field.h b/sql/field.h
index 127b3a069cb..8d63b0ef3f1 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1096,6 +1096,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 da7a1187a47..efb7401779c 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/filesort.cc b/sql/filesort.cc
index 4d877c92dba..e1c673aca0b 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -63,24 +63,21 @@ static uint sortlength(SORT_FIELD *sortorder,uint length);
table->record_pointers
*/
-ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
- SQL_SELECT *select, ha_rows special, ha_rows max_rows,
- ha_rows *examined_rows)
+ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
+ SQL_SELECT *select, ha_rows max_rows, ha_rows *examined_rows)
{
int error;
ulong memavl;
uint maxbuffer;
+ uint i;
BUFFPEK *buffpek;
ha_rows records;
uchar **sort_keys;
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
SORTPARAM param;
- THD *thd= current_thd;
-
- DBUG_ENTER("filesort");
- DBUG_EXECUTE("info",TEST_filesort(sortorder,s_length,special););
CHARSET_INFO *charset=table->table_charset;
- uint i;
+ DBUG_ENTER("filesort");
+ DBUG_EXECUTE("info",TEST_filesort(sortorder,s_length););
#ifdef SKIP_DBUG_IN_FILESORT
DBUG_PUSH(""); /* No DBUG here */
#endif
@@ -111,27 +108,15 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
{
statistic_increment(filesort_scan_count, &LOCK_status);
}
- if (select && my_b_inited(&select->file))
- {
- records=special=select->records; /* purecov: deadcode */
- selected_records_file= &select->file; /* purecov: deadcode */
- reinit_io_cache(selected_records_file,READ_CACHE,0L,0,0); /* purecov: deadcode */
- }
- else if (special)
- {
- records=special; /* purecov: deadcode */
- selected_records_file= outfile; /* purecov: deadcode */
- reinit_io_cache(selected_records_file,READ_CACHE,0L,0,0); /* purecov: deadcode */
- }
#ifdef CAN_TRUST_RANGE
- else if (select && select->quick && select->quick->records > 0L)
+ if (select && select->quick && select->quick->records > 0L)
{
records=min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
table->file->records)+EXTRA_RECORDS;
selected_records_file=0;
}
-#endif
else
+#endif
{
records=table->file->estimate_number_of_rows();
selected_records_file= 0;
@@ -140,7 +125,7 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
records=param.max_rows; /* purecov: inspected */
#ifdef USE_STRCOLL
- if (use_strcoll(charset) &&
+ if (use_strnxfrm(charset) &&
!(param.tmp_buffer=my_malloc(param.sort_length,MYF(MY_WME))))
goto err;
#endif
@@ -511,7 +496,7 @@ static void make_sortkey(register SORTPARAM *param,
length=sort_field->length;
}
#ifdef USE_STRCOLL
- if(use_strcoll(cs))
+ if(use_strnxfrm(cs))
{
if (item->binary)
{
@@ -541,7 +526,7 @@ static void make_sortkey(register SORTPARAM *param,
memcpy(to,res->ptr(),length);
bzero((char *)to+length,diff);
if (!item->binary)
- case_sort(cs, (char*) to,length);
+ my_tosort(cs, (char*) to,length);
#ifdef USE_STRCOLL
}
#endif
@@ -946,7 +931,7 @@ sortlength(SORT_FIELD *sortorder, uint s_length)
if (!sortorder->field->binary())
{
CHARSET_INFO *cs=((Field_str*)(sortorder->field))->charset();
- if (use_strcoll(cs))
+ if (use_strnxfrm(cs))
sortorder->length= sortorder->length*cs->strxfrm_multiply;
}
#endif
@@ -966,7 +951,7 @@ sortlength(SORT_FIELD *sortorder, uint s_length)
if (!sortorder->item->binary)
{
CHARSET_INFO *cs=sortorder->item->str_value.charset();
- if (use_strcoll(cs))
+ if (use_strnxfrm(cs))
sortorder->length= sortorder->length*cs->strxfrm_multiply;
}
#endif
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index 5c314462666..6cfd3c881cc 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -35,7 +35,9 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
{
if (!(file= heap_open(name, mode)) && my_errno == ENOENT)
{
- if (!create(name, table, NULL))
+ HA_CREATE_INFO create_info;
+ bzero(&create_info, sizeof(create_info));
+ if (!create(name, table, &create_info))
file= heap_open(name, mode);
}
return (file ? 0 : 1);
@@ -51,6 +53,8 @@ int ha_heap::write_row(byte * buf)
statistic_increment(ha_write_count,&LOCK_status);
if (table->time_stamp)
update_timestamp(buf+table->time_stamp-1);
+ if (table->next_number_field && buf == table->record[0])
+ update_auto_increment();
return heap_write(file,buf);
}
@@ -161,6 +165,8 @@ void ha_heap::info(uint flag)
index_file_length=info.index_length;
max_data_file_length= info.max_records* info.reclength;
delete_length= info.deleted * info.reclength;
+ if (flag & HA_STATUS_AUTO)
+ auto_increment_value= info.auto_increment;
}
int ha_heap::extra(enum ha_extra_function operation)
@@ -234,11 +240,11 @@ ha_rows ha_heap::records_in_range(int inx,
}
}
-
int ha_heap::create(const char *name, TABLE *table,
HA_CREATE_INFO *create_info)
{
uint key, parts, mem_per_row= 0;
+ uint auto_key= 0, auto_key_type= 0;
ulong max_rows;
HP_KEYDEF *keydef;
HA_KEYSEG *seg;
@@ -296,19 +302,42 @@ int ha_heap::create(const char *name, TABLE *table,
seg->null_bit= 0;
seg->null_pos= 0;
}
+ if (field->flags & AUTO_INCREMENT_FLAG)
+ {
+ auto_key= key + 1;
+ auto_key_type= field->key_type();
+ }
}
}
mem_per_row+= MY_ALIGN(table->reclength + 1, sizeof(char*));
max_rows = (ulong) (current_thd->variables.max_heap_table_size /
mem_per_row);
+ HP_CREATE_INFO hp_create_info;
+ hp_create_info.auto_key= auto_key;
+ hp_create_info.auto_key_type= auto_key_type;
+ hp_create_info.auto_increment= (create_info->auto_increment_value ?
+ create_info->auto_increment_value - 1 : 0);
error= heap_create(fn_format(buff,name,"","",4+2),
table->keys,keydef, table->reclength,
((table->max_rows < max_rows && table->max_rows) ?
table->max_rows : max_rows),
- table->min_rows);
+ table->min_rows, &hp_create_info);
my_free((gptr) keydef, MYF(0));
if (file)
info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
ref_length= sizeof(HEAP_PTR);
return (error);
}
+
+void ha_heap::update_create_info(HA_CREATE_INFO *create_info)
+{
+ table->file->info(HA_STATUS_AUTO);
+ if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
+ create_info->auto_increment_value= auto_increment_value;
+}
+
+longlong ha_heap::get_auto_increment()
+{
+ ha_heap::info(HA_STATUS_AUTO);
+ return auto_increment_value;
+}
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index 504f5262bf3..f82a1a460d8 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -40,8 +40,7 @@ class ha_heap: public handler
ulong table_flags() const
{
return (HA_READ_RND_SAME | HA_NO_INDEX | HA_KEYPOS_TO_RNDPOS |
- HA_NO_BLOBS | HA_NULL_KEY | HA_REC_NOT_IN_SEQ |
- HA_NO_AUTO_INCREMENT);
+ HA_NO_BLOBS | HA_NULL_KEY | HA_REC_NOT_IN_SEQ);
}
ulong index_flags(uint inx) const
{
@@ -63,6 +62,7 @@ class ha_heap: public handler
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf);
+ longlong get_auto_increment();
int index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag);
int index_read_idx(byte * buf, uint idx, const byte * key,
@@ -87,6 +87,7 @@ class ha_heap: public handler
int delete_table(const char *from);
int rename_table(const char * from, const char * to);
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
+ void update_create_info(HA_CREATE_INFO *create_info);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index b684d9dd4dd..2a7990a18ee 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -1366,9 +1366,9 @@ innobase_mysql_cmp(
case FIELD_TYPE_VAR_STRING:
// BAR TODO: Discuss with heikki.tuuri@innodb.com
// so that he sends CHARSET_INFO for the field to this function.
- ret = my_sortncmp(default_charset_info,
- (const char*) a, a_length,
- (const char*) b, b_length);
+ ret = my_strnncoll(default_charset_info,
+ a, a_length,
+ b, b_length);
if (ret < 0) {
return(-1);
} else if (ret > 0) {
@@ -2181,16 +2181,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 */
@@ -3155,8 +3147,8 @@ innobase_drop_database(
memcpy(namebuf, ptr, len);
namebuf[len] = '/';
namebuf[len + 1] = '\0';
-#ifdef __WIN__
- casedn_str(namebuf);
+#ifdef FN_NO_CASE_SENCE
+ my_casedn_str(system_charset_info, namebuf);
#endif
trx = trx_allocate_for_mysql();
@@ -3264,7 +3256,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;
@@ -3649,6 +3641,7 @@ 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,
@@ -3787,6 +3780,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/ha_myisam.cc b/sql/ha_myisam.cc
index a26c2e02db8..43a351101b3 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -559,7 +559,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
param.tmpfile_createflag = O_RDWR | O_TRUNC;
param.using_global_keycache = 1;
param.thd=thd;
- param.tmpdir=mysql_tmpdir;
+ param.tmpdir=&mysql_tmpdir_list;
param.out_flag=0;
strmov(fixed_name,file->filename);
@@ -718,7 +718,7 @@ bool ha_myisam::activate_all_index(THD *thd)
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;
+ param.tmpdir=&mysql_tmpdir_list;
error=repair(thd,param,0) != HA_ADMIN_OK;
thd->proc_info=save_proc_info;
}
diff --git a/sql/init.cc b/sql/init.cc
index 052ee16925e..8834fd3a89c 100644
--- a/sql/init.cc
+++ b/sql/init.cc
@@ -24,7 +24,6 @@ void unireg_init(ulong options)
{
uint i;
double nr;
- CHARSET_INFO *cs;
DBUG_ENTER("unireg_init");
MYSYS_PROGRAM_DONT_USE_CURSES();
diff --git a/sql/item.cc b/sql/item.cc
index 394833b396a..38ec7e80898 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -432,7 +432,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (!field) // If field is not checked
{
Field *tmp;
- if (!(tmp=find_field_in_tables(thd, this, tables, 0)))
+ if ((tmp= find_field_in_tables(thd, this, tables, 0)) == not_found_field)
{
/*
We can't find table field in table list of current select,
@@ -448,14 +448,18 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
thd->net.last_errno= 0;
#endif
for (SELECT_LEX *sl= thd->lex.select->outer_select();
- sl && !tmp;
+ sl;
sl= sl->outer_select())
- tmp=find_field_in_tables(thd, this,
- (TABLE_LIST*)(last= sl)->table_list.first,
- 0);
+ if ((tmp= find_field_in_tables(thd, this,
+ (TABLE_LIST*)
+ (last= sl)->table_list.first,
+ 0)) != not_found_field)
+ break;
if (!tmp)
+ return -1;
+ else if (tmp == not_found_field)
{
- // Call to produce appropriate error message
+ // call to return error code
find_field_in_tables(thd, this, tables, 1);
return -1;
}
@@ -481,7 +485,10 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
tbl->shared= 1;
}
}
- }
+ }
+ else if (!tmp)
+ return -1;
+
set_field(tmp);
}
else if (thd && thd->set_query_id && field->query_id != thd->query_id)
@@ -591,7 +598,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
{
@@ -606,7 +613,7 @@ int 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
{
@@ -618,8 +625,42 @@ int Item_field::save_in_field(Field *to)
}
+/*
+ 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'
+*/
+
int 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
+*/
+
+int Item_null::save_safe_in_field(Field *field)
+{
return set_field_to_null(field);
}
@@ -637,7 +678,7 @@ int Item::save_in_field(Field *field)
str_value.set_quick(buff,sizeof(buff),cs);
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();
error=field->store(result->ptr(),result->length(),cs);
str_value.set_quick(0, 0, cs);
@@ -654,7 +695,7 @@ int 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();
error=field->store(nr);
}
@@ -789,7 +830,9 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
if (!ref)
{
- if (!(ref= find_item_in_list(this, thd->lex.select->item_list, 0)))
+ if ((ref= find_item_in_list(this, thd->lex.select->item_list,
+ REPORT_EXCEPT_NOT_FOUND)) ==
+ (Item **)not_found_item)
{
/*
We can't find table field in table list of current select,
@@ -798,17 +841,25 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
of view rules. For example if both tables (outer & current) have
field 'field' it is not mistake to refer to this field without
mention of table name, but if we join tables in one list it will
- cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
+ cause error ER_NON_UNIQ_ERROR in find_item_in_list.
*/
SELECT_LEX *last=0;
for (SELECT_LEX *sl= thd->lex.select->outer_select();
- sl && !ref;
+ sl;
sl= sl->outer_select())
- ref= find_item_in_list(this, (last= sl)->item_list, 0);
+ if((ref= find_item_in_list(this, (last= sl)->item_list,
+ REPORT_EXCEPT_NOT_FOUND)) !=
+ (Item **)not_found_item)
+ break;
+
if (!ref)
{
+ return 1;
+ }
+ else if (ref == (Item **)not_found_item)
+ {
// Call to report error
- find_item_in_list(this, thd->lex.select->item_list, 1);
+ find_item_in_list(this, thd->lex.select->item_list, REPORT_ALL_ERRORS);
return 1;
}
else
@@ -834,6 +885,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
}
}
}
+ else if (!ref)
+ return 1;
max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals;
diff --git a/sql/item.h b/sql/item.h
index 84182203d4c..115e9426691 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -56,6 +56,8 @@ public:
virtual int save_in_field(Field *field);
virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field); }
+ virtual int 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; }
@@ -153,7 +155,8 @@ public:
longlong val_int();
String *val_str(String *str);
void make_field(Send_field *field);
- int save_in_field(Field *field);
+ int save_in_field(Field *field);
+ int 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/item_subselect.cc b/sql/item_subselect.cc
index 99fc0bcdb67..456ce5f22ba 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -32,11 +32,22 @@ SUBSELECT TODO:
#include "mysql_priv.h"
#include "sql_select.h"
-Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex,
- select_subselect *result):
+Item_subselect::Item_subselect():
Item(), engine_owner(1), value_assigned(0)
{
- DBUG_ENTER("Item_subselect::Item_subselect");
+ assign_null();
+ /*
+ item value is NULL if select_subselect not changed this value
+ (i.e. some rows will be found returned)
+ */
+ null_value= 1;
+}
+
+void Item_subselect::init(THD *thd, st_select_lex *select_lex,
+ select_subselect *result)
+{
+
+ DBUG_ENTER("Item_subselect::init");
DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex));
if (select_lex->next_select())
@@ -45,12 +56,6 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex,
else
engine= new subselect_single_select_engine(thd, select_lex, result,
this);
- assign_null();
- /*
- item value is NULL if select_subselect not changed this value
- (i.e. some rows will be found returned)
- */
- null_value= 1;
DBUG_VOID_RETURN;
}
@@ -76,14 +81,17 @@ void Item_subselect::make_field (Send_field *tmp_field)
bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
- // Is it one field subselect?
- if (engine->cols() > max_columns)
- {
- my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0));
- return 1;
- }
int res= engine->prepare();
- fix_length_and_dec();
+ if (!res)
+ {
+ // Is it one field subselect?
+ if (engine->cols() > max_columns)
+ {
+ my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0));
+ return 1;
+ }
+ fix_length_and_dec();
+ }
return res;
}
@@ -99,8 +107,9 @@ inline table_map Item_subselect::used_tables() const
Item_singleval_subselect::Item_singleval_subselect(THD *thd,
st_select_lex *select_lex):
- Item_subselect(thd, select_lex, new select_singleval_subselect(this))
+ Item_subselect()
{
+ init(thd, select_lex, new select_singleval_subselect(this));
max_columns= 1;
maybe_null= 1;
}
@@ -119,28 +128,38 @@ Item::Type Item_subselect::type() const
double Item_singleval_subselect::val ()
{
if (engine->exec())
+ {
+ assign_null();
return 0;
+ }
return real_value;
}
longlong Item_singleval_subselect::val_int ()
{
if (engine->exec())
+ {
+ assign_null();
return 0;
+ }
return int_value;
}
String *Item_singleval_subselect::val_str (String *str)
{
if (engine->exec() || null_value)
+ {
+ assign_null();
return 0;
- return &str_value;
+ }
+ return &string_value;
}
Item_exists_subselect::Item_exists_subselect(THD *thd,
st_select_lex *select_lex):
- Item_subselect(thd, select_lex, new select_exists_subselect(this))
+ Item_subselect()
{
+ init(thd, select_lex, new select_exists_subselect(this));
max_columns= UINT_MAX;
null_value= 0; //can't be NULL
maybe_null= 0; //can't be NULL
@@ -157,21 +176,30 @@ void Item_exists_subselect::fix_length_and_dec()
double Item_exists_subselect::val ()
{
if (engine->exec())
+ {
+ assign_null();
return 0;
+ }
return (double) value;
}
longlong Item_exists_subselect::val_int ()
{
if (engine->exec())
+ {
+ assign_null();
return 0;
+ }
return value;
}
String *Item_exists_subselect::val_str(String *str)
{
if (engine->exec())
+ {
+ assign_null();
return 0;
+ }
str->set(value);
return str;
}
@@ -182,7 +210,7 @@ subselect_single_select_engine::subselect_single_select_engine(THD *thd,
select_subselect *result,
Item_subselect *item):
subselect_engine(thd, item, result),
- executed(0), optimized(0)
+ prepared(0), optimized(0), executed(0)
{
select_lex= select;
SELECT_LEX_UNIT *unit= select_lex->master_unit();
@@ -221,6 +249,9 @@ subselect_union_engine::subselect_union_engine(THD *thd,
int subselect_single_select_engine::prepare()
{
+ if (prepared)
+ return 0;
+ prepared= 1;
SELECT_LEX *save_select= thd->lex.select;
thd->lex.select= select_lex;
if(join->prepare((TABLE_LIST*) select_lex->table_list.first,
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 92839eb0e5f..33f82982708 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -39,8 +39,7 @@ protected:
uint max_columns;
public:
- Item_subselect(THD *thd, st_select_lex *select_lex,
- select_subselect* result);
+ Item_subselect();
Item_subselect(Item_subselect *item)
{
null_value= item->null_value;
@@ -50,6 +49,14 @@ public:
engine_owner= 0;
name= item->name;
}
+
+ /*
+ We need this method, because some compilers do not allow 'this'
+ pointer in constructor initialization list, but we need pass pointer
+ to subselect Item class to select_subselect classes constructor.
+ */
+ void init (THD *thd, st_select_lex *select_lex, select_subselect *result);
+
~Item_subselect();
virtual void assign_null()
{
@@ -73,10 +80,16 @@ public:
class Item_singleval_subselect :public Item_subselect
{
protected:
- longlong int_value; /* here stored integer value of this item */
- double real_value; /* here stored real value of this item */
+ longlong int_value; /* Here stored integer value of this item */
+ double real_value; /* Here stored real value of this item */
+ /*
+ Here stored string value of this item.
+ (str_value used only as temporary buffer, because it can be changed
+ by Item::save_field)
+ */
+ String string_value;
enum Item_result res_type; /* type of results */
-
+
public:
Item_singleval_subselect(THD *thd, st_select_lex *select_lex);
Item_singleval_subselect(Item_singleval_subselect *item):
@@ -84,6 +97,7 @@ public:
{
int_value= item->int_value;
real_value= item->real_value;
+ string_value.set(item->string_value, 0, item->string_value.length());
max_length= item->max_length;
decimals= item->decimals;
res_type= item->res_type;
@@ -165,8 +179,9 @@ public:
class subselect_single_select_engine: public subselect_engine
{
- my_bool executed; /* simple subselect is executed */
+ my_bool prepared; /* simple subselect is prepared */
my_bool optimized; /* simple subselect is optimized */
+ my_bool executed; /* simple subselect is executed */
st_select_lex *select_lex; /* corresponding select_lex */
JOIN * join; /* corresponding JOIN structure */
public:
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 93ced79005f..4d25098bb88 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -866,7 +866,9 @@ static int simple_raw_key_cmp(void* arg, byte* key1, byte* key2)
static int simple_str_key_cmp(void* arg, byte* key1, byte* key2)
{
/* BAR TODO: remove default_charset_info */
- return my_sortcmp(default_charset_info,(char*) key1, (char*) key2, *(uint*) arg);
+ return my_strnncoll(default_charset_info,
+ (const uchar*) key1, *(uint*) arg,
+ (const uchar*) key2, *(uint*) arg);
}
/*
diff --git a/sql/key.cc b/sql/key.cc
index fa09a0a6d44..84669808b92 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -193,8 +193,9 @@ int key_cmp(TABLE *table,const byte *key,uint idx,uint key_length)
FIELDFLAG_PACK)))
{
/* BAR TODO: I'm not sure this should be system_charset_info */
- if (my_sortcmp(system_charset_info,(char*) key,
- (char*) table->record[0]+key_part->offset,length))
+ if (my_strnncoll(system_charset_info,
+ (const uchar*) key, length,
+ (const uchar*) table->record[0]+key_part->offset,length))
return 1;
}
else if (memcmp(key,table->record[0]+key_part->offset,length))
diff --git a/sql/log.cc b/sql/log.cc
index 59f99e3460e..91ef42e1381 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -942,8 +942,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;
@@ -973,7 +973,6 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
last_time=skr;
struct tm tm_tmp;
struct tm *start;
- ulong length;
localtime_r(&skr,&tm_tmp);
start=&tm_tmp;
/* Note that my_b_write() assumes it knows the length for this */
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 8077d600643..bd6914363e2 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -392,6 +392,8 @@ int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
bool fake_select_lex);
void fix_tables_pointers(SELECT_LEX *select_lex);
+int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
+ select_result *result);
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
select_result *result);
int mysql_union(THD *thd, LEX *lex,select_result *result);
@@ -456,6 +458,7 @@ bool wait_for_tables(THD *thd);
bool table_is_used(TABLE *table, bool wait_for_name_lock);
bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
void abort_locked_tables(THD *thd,const char *db, const char *table_name);
+extern const Field *not_found_field;
Field *find_field_in_tables(THD *thd, Item_field *item, TABLE_LIST *tables,
bool report_error);
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
@@ -545,7 +548,11 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds, int *error);
-Item ** find_item_in_list(Item *item, List<Item> &items, bool report_error);
+enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
+ IGNORE_ERRORS};
+extern const Item **not_found_item;
+Item ** find_item_in_list(Item *item, List<Item> &items,
+ find_item_error_report_type report_error);
bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name,
List_iterator<Item> *it);
@@ -606,7 +613,7 @@ pthread_handler_decl(handle_manager, arg);
#ifndef DBUG_OFF
void print_where(COND *cond,const char *info);
void print_cached_tables(void);
-void TEST_filesort(SORT_FIELD *sortorder,uint s_length, ha_rows special);
+void TEST_filesort(SORT_FIELD *sortorder,uint s_length);
#endif
void mysql_print_status(THD *thd);
/* key.cc */
@@ -635,8 +642,9 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
extern time_t start_time;
extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH],
- mysql_real_data_home[], *charsets_list;
-extern my_string mysql_tmpdir;
+ mysql_real_data_home[], *charsets_list, *opt_mysql_tmpdir;
+#define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list))
+extern MY_TMPDIR mysql_tmpdir_list;
extern const char *command_name[];
extern const char *first_keyword, *localhost, *delayed_user;
extern const char **errmesg; /* Error messages */
@@ -786,9 +794,9 @@ void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
SQL_SELECT *select,
int use_record_cache, bool print_errors);
void end_read_record(READ_RECORD *info);
-ha_rows filesort(TABLE *form,struct st_sort_field *sortorder, uint s_length,
- SQL_SELECT *select, ha_rows special,ha_rows max_rows,
- ha_rows *examined_rows);
+ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder,
+ uint s_length, SQL_SELECT *select,
+ ha_rows max_rows, ha_rows *examined_rows);
void change_double_for_sort(double nr,byte *to);
int get_quick_record(SQL_SELECT *select);
int calc_weekday(long daynr,bool sunday_first_day_of_week);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index a3a82d96b2e..e6c2c198722 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -395,7 +395,8 @@ const char *myisam_recover_options_str="OFF";
const char *sql_mode_str="OFF";
ulong rpl_recovery_rank=0;
-my_string mysql_unix_port=NULL, opt_mysql_tmpdir=NULL, mysql_tmpdir=NULL;
+my_string mysql_unix_port=NULL, opt_mysql_tmpdir=NULL;
+MY_TMPDIR mysql_tmpdir_list;
ulong my_bind_addr; /* the address we bind to */
char *my_bind_addr_str;
DATE_FORMAT dayord;
@@ -852,7 +853,7 @@ void clean_up(bool print_message)
if (defaults_argv)
free_defaults(defaults_argv);
my_free(charsets_list, MYF(MY_ALLOW_ZERO_PTR));
- my_free(mysql_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
+ free_tmpdir(&mysql_tmpdir_list);
my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR));
x_free(opt_bin_logname);
x_free(opt_relay_logname);
@@ -1834,17 +1835,6 @@ int main(int argc, char **argv)
load_defaults(MYSQL_CONFIG_NAME,load_default_groups,&argc,&argv);
defaults_argv=argv;
- /* Get default temporary directory */
- opt_mysql_tmpdir=getenv("TMPDIR"); /* Use this if possible */
-#if defined( __WIN__) || defined(OS2)
- if (!opt_mysql_tmpdir)
- opt_mysql_tmpdir=getenv("TEMP");
- if (!opt_mysql_tmpdir)
- opt_mysql_tmpdir=getenv("TMP");
-#endif
- if (!opt_mysql_tmpdir || !opt_mysql_tmpdir[0])
- opt_mysql_tmpdir=(char*) P_tmpdir; /* purecov: inspected */
-
set_options();
get_options(argc,argv);
if (opt_log || opt_update_log || opt_slow_log || opt_bin_log)
@@ -2941,13 +2931,13 @@ struct my_option my_long_options[] =
#endif /* HAVE_BERKELEY_DB */
{"skip-bdb", OPT_BDB_SKIP, "Don't use berkeley db (will save memory)",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"big-tables", OPT_BIG_TABLES,
+ {"big-tables", OPT_BIG_TABLES,
"Allow big result sets by saving all temporary sets on file (Solves most 'table full' errors)",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"binlog-do-db", OPT_BINLOG_DO_DB,
"Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
+ {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
"Tells the master that updates to the given database should not be logged tothe binary log",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"bind-address", OPT_BIND_ADDRESS, "IP address to bind to",
@@ -3316,16 +3306,23 @@ struct my_option my_long_options[] =
#ifdef HAVE_OPENSSL
#include "sslopt-longopts.h"
#endif
- {"temp-pool", OPT_TEMP_POOL,
+ {"temp-pool", OPT_TEMP_POOL,
"Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.",
(gptr*) &use_temp_pool, (gptr*) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
0, 0, 0, 0, 0},
- {"tmpdir", 't', "Path for temporary files", (gptr*) &opt_mysql_tmpdir,
+ {"tmpdir", 't',
+ "Path for temporary files. Several paths may be specified, separated by a "
+#if defined( __WIN__) || defined(OS2)
+ "semicolon (;)"
+#else
+ "colon (:)"
+#endif
+ ", in this case they are used in a round-robin fashion.",
+ (gptr*) &opt_mysql_tmpdir,
(gptr*) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"transaction-isolation", OPT_TX_ISOLATION,
- "Default transaction isolation level", 0, 0, 0, GET_NO_ARG, REQUIRED_ARG, 0,
- 0, 0, 0,
- 0, 0},
+ "Default transaction isolation level", 0, 0, 0, GET_STR, REQUIRED_ARG, 0,
+ 0, 0, 0, 0, 0},
{"external-locking", OPT_USE_LOCKING, "Use system (external) locking. With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running",
(gptr*) &opt_external_locking, (gptr*) &opt_external_locking,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -3378,7 +3375,7 @@ struct my_option my_long_options[] =
(gptr*) &connect_timeout, (gptr*) &connect_timeout,
0, GET_ULONG, REQUIRED_ARG, CONNECT_TIMEOUT, 2, LONG_TIMEOUT, 0, 1, 0 },
{"delayed_insert_timeout", OPT_DELAYED_INSERT_TIMEOUT,
- "Ho wlong a INSERT DELAYED thread should wait for INSERT statements before terminating.",
+ "How long a INSERT DELAYED thread should wait for INSERT statements before terminating.",
(gptr*) &delayed_insert_timeout, (gptr*) &delayed_insert_timeout, 0,
GET_ULONG, REQUIRED_ARG, DELAYED_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
{"delayed_insert_limit", OPT_DELAYED_INSERT_LIMIT,
@@ -4174,7 +4171,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:
@@ -4498,9 +4494,7 @@ static void fix_paths(void)
charsets_dir=mysql_charsets_dir;
}
- char *end=convert_dirname(buff, opt_mysql_tmpdir, NullS);
- if (!(mysql_tmpdir= my_memdup((byte*) buff,(uint) (end-buff)+1,
- MYF(MY_FAE))))
+ if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
exit(1);
if (!slave_load_tmpdir)
{
diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc
index 980f8b090a1..0fc2347bebd 100644
--- a/sql/net_pkg.cc
+++ b/sql/net_pkg.cc
@@ -286,12 +286,12 @@ send_eof(THD *thd, bool no_flush)
{
if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41))
{
- char buff[5];
+ uchar buff[5];
uint tmp= min(thd->total_warn_count, 65535);
buff[0]=254;
int2store(buff+1, tmp);
int2store(buff+3, 0); // No flags yet
- VOID(my_net_write(net,buff,5));
+ VOID(my_net_write(net,(char*) buff,5));
VOID(net_flush(net));
}
else
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index ed5b2b0a230..2b0ac08fe95 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -978,7 +978,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
{
CHARSET_INFO *charset=((Field_str*)(field))->charset();
#ifdef USE_STRCOLL
- if (use_strcoll(charset))
+ if (use_strnxfrm(charset))
like_error= my_like_range(charset,
res->ptr(),res->length(),wild_prefix,
field_length, min_str+maybe_null,
diff --git a/sql/set_var.cc b/sql/set_var.cc
index b221a3f98ff..72579664a3e 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -541,7 +541,7 @@ struct show_var_st init_vars[]= {
{"timezone", time_zone, SHOW_CHAR},
#endif
{sys_tmp_table_size.name, (char*) &sys_tmp_table_size, SHOW_SYS},
- {"tmpdir", (char*) &mysql_tmpdir, SHOW_CHAR_PTR},
+ {"tmpdir", (char*) &opt_mysql_tmpdir, SHOW_CHAR_PTR},
{"version", server_version, SHOW_CHAR},
{sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS},
{NullS, NullS, SHOW_LONG}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 3773eca43e1..40a11d54f10 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1783,9 +1783,29 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
return field;
}
+// Special Field pointer for find_field_in_tables returning
+const Field *not_found_field= (Field*) 0x1;
+/*
+ Find field in table list.
+
+ SYNOPSIS
+ find_field_in_tables()
+ thd - pointer to current thread structure
+ item - field item that should be found
+ tables - tables for scaning
+ report_error - if FALSE then do not report error if item not found and
+ return not_found_field;
+
+ RETURN VALUES
+ 0 - field is not found or field is not unique, error message is
+ reported
+ not_found_field - function was called with report_error == FALSE and
+ field if not found, no error message reported
+ found field
+*/
Field *
-find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
+find_field_in_tables(THD *thd, Item_field *item, TABLE_LIST *tables,
bool report_error)
{
Field *found=0;
@@ -1831,13 +1851,18 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS);
table_name=buff;
}
- my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),table_name,
- thd->where);
+ if (report_error)
+ my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
+ table_name, thd->where);
+ else
+ return (Field*) not_found_field;
}
else
if (report_error)
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
item->full_name(),thd->where);
+ else
+ return (Field*) not_found_field;
return (Field*) 0;
}
bool allow_rowid= tables && !tables->next; // Only one table
@@ -1852,11 +1877,10 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
return (Field*) 0;
if (found)
{
- if (!report_error) // Returns first found
+ if (!thd->where) // Returns first found
break;
- if (report_error)
- my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
- name,thd->where);
+ my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
+ name,thd->where);
return (Field*) 0;
}
found=field;
@@ -1867,11 +1891,39 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables,
if (report_error)
my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR),
MYF(0), item->full_name(), thd->where);
+ else
+ return (Field*) not_found_field;
return (Field*) 0;
}
+// Special Item pointer for find_item_in_list returning
+const Item **not_found_item= (const Item**) 0x1;
+
+/*
+ Find Item in list of items (find_field_in_tables analog)
+
+ SYNOPSIS
+ find_item_in_list()
+ find - item to find
+ items - list of items
+ report_error
+ REPORT_ALL_ERRORS - report errors, return 0 if error
+ REPORT_EXCEPT_NOT_FOUND - do not report 'not found' error and return not_ found_item, report other errors, return 0
+ IGNORE_ERRORS - do not report errors, return 0 if error
+
+ RETURN VALUES
+ 0 - item is not found or item is not unique, error message is
+ reported
+ not_found_item - function was called with report_error ==
+ REPORT_EXCEPT_NOT_FOUND and item if not found, no error
+ message reported
+ found field
+
+*/
+
Item **
-find_item_in_list(Item *find, List<Item> &items, bool report_error)
+find_item_in_list(Item *find, List<Item> &items,
+ find_item_error_report_type report_error)
{
List_iterator<Item> li(items);
Item **found=0,*item;
@@ -1896,7 +1948,7 @@ find_item_in_list(Item *find, List<Item> &items, bool report_error)
{
if ((*found)->eq(item,0))
continue; // Same field twice (Access?)
- if (report_error)
+ if (report_error != IGNORE_ERRORS)
my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
find->full_name(), current_thd->where);
return (Item**) 0;
@@ -1919,10 +1971,17 @@ find_item_in_list(Item *find, List<Item> &items, bool report_error)
break;
}
}
- if (!found && report_error)
- my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0),
- find->full_name(), current_thd->where);
- return found;
+ if (found)
+ return found;
+ else if (report_error != REPORT_EXCEPT_NOT_FOUND)
+ {
+ if (report_error == REPORT_ALL_ERRORS)
+ my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0),
+ find->full_name(), current_thd->where);
+ return (Item **) 0;
+ }
+ else
+ return (Item **) not_found_item;
}
/****************************************************************************
@@ -2229,30 +2288,32 @@ fill_record(Field **ptr,List<Item> &values)
static void mysql_rm_tmp_tables(void)
{
- uint idx;
- char filePath[FN_REFLEN];
+ uint i, idx;
+ char filePath[FN_REFLEN], *tmpdir;
MY_DIR *dirp;
FILEINFO *file;
DBUG_ENTER("mysql_rm_tmp_tables");
+ for (i=0; i<=mysql_tmpdir_list.max; i++)
+ {
+ tmpdir=mysql_tmpdir_list.list[i];
/* See if the directory exists */
- if (!(dirp = my_dir(mysql_tmpdir,MYF(MY_WME | MY_DONT_SORT))))
- DBUG_VOID_RETURN; /* purecov: inspected */
+ if (!(dirp = my_dir(tmpdir,MYF(MY_WME | MY_DONT_SORT))))
+ continue;
- /*
- ** Remove all SQLxxx tables from directory
- */
+ /* Remove all SQLxxx tables from directory */
for (idx=2 ; idx < (uint) dirp->number_off_files ; idx++)
{
file=dirp->dir_entry+idx;
if (!bcmp(file->name,tmp_file_prefix,tmp_file_prefix_length))
{
- sprintf(filePath,"%s%s",mysql_tmpdir,file->name); /* purecov: inspected */
- VOID(my_delete(filePath,MYF(MY_WME))); /* purecov: inspected */
+ sprintf(filePath,"%s%s",tmpdir,file->name);
+ VOID(my_delete(filePath,MYF(MY_WME)));
}
}
my_dirend(dirp);
+ }
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 7c51cac0f3a..5bdefbaaa30 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -357,6 +357,12 @@ TODO list:
#define DUMP(C)
#endif
+#ifdef FN_NO_CASE_SENCE
+#define DB_NAME_PREPROCESS(C) tolower(C)
+#else
+#define DB_NAME_PREPROCESS(C) (C)
+#endif
+
const char *query_cache_type_names[]= { "OFF", "ON", "DEMAND",NullS };
TYPELIB query_cache_type_typelib=
{
@@ -1394,14 +1400,15 @@ ulong Query_cache::init_cache()
VOID(hash_init(&queries,system_charset_info,def_query_hash_size, 0, 0,
query_cache_query_get_key, 0, 0));
- /*
- On windows we have to compare names case insensitive as for the OS
- A.frm and a.frm are the same file.
- */
+#ifndef FN_NO_CASE_SENCE
+ VOID(hash_init(&tables,system_charset_info,def_table_hash_size, 0, 0,
+ query_cache_table_get_key, 0, 0));
+#else
+ // windows, OS/2 or other case insensitive file names work around
VOID(hash_init(&tables,system_charset_info,def_table_hash_size, 0, 0,
- query_cache_table_get_key, 0,
- IF_WIN((lower_case_table_names ? 0: HASH_CASE_INSENSITIVE),
- 0)));
+ query_cache_table_get_key, 0,
+ (lower_case_table_names?0:HASH_CASE_INSENSITIVE)));
+#endif
queries_in_cache = 0;
queries_blocks = 0;
@@ -2447,7 +2454,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
lex->select->options,
(int) thd->variables.query_cache_type));
- for (; tables_used; tables_used=tables_used->next)
+ for (; tables_used; tables_used= tables_used->next)
{
tables++;
DBUG_PRINT("qcache", ("table %s, db %s, type %u",
@@ -2457,10 +2464,16 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
tables_used->table->file->has_transactions());
if (tables_used->table->db_type == DB_TYPE_MRG_ISAM ||
- tables_used->table->tmp_table != NO_TMP_TABLE)
+ tables_used->table->tmp_table != NO_TMP_TABLE ||
+ (tables_used->db_length == 5 &&
+ DB_NAME_PREPROCESS(tables_used->db[0])=='m' &&
+ DB_NAME_PREPROCESS(tables_used->db[1])=='y' &&
+ DB_NAME_PREPROCESS(tables_used->db[2])=='s' &&
+ DB_NAME_PREPROCESS(tables_used->db[3])=='q' &&
+ DB_NAME_PREPROCESS(tables_used->db[4])=='l'))
{
DBUG_PRINT("qcache",
- ("select not cacheable: used MRG_ISAM or temporary table(s)"));
+ ("select not cacheable: used MRG_ISAM, temporary or system table(s)"));
DBUG_RETURN(0);
}
if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 763484dbba8..c4966ff1326 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -887,9 +887,14 @@ bool select_singleval_subselect::send_data(List<Item> &items)
it->decimals= val_item->decimals;
it->binary= val_item->binary;
it->int_value= val_item->val_int();
- String *s= val_item->val_str(&it->str_value);
- if (s != &it->str_value)
- it->str_value.set(*s, 0, s->length());
+ String *s= val_item->val_str(&it->string_value);
+ if (s != &it->string_value)
+ {
+ it->string_value.set(*s, 0, s->length());
+ }
+ // TODO: remove when correct charset handling appeared for Item
+ it->str_value.set(*s, 0, s->length()); // store charset
+
it->res_type= val_item->result_type();
}
it->assigned(1);
@@ -910,3 +915,57 @@ bool select_exists_subselect::send_data(List<Item> &items)
DBUG_RETURN(0);
}
+
+/***************************************************************************
+** Dump of select to variables
+***************************************************************************/
+int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
+{
+ List_iterator_fast<Item> li(list);
+ List_iterator_fast<LEX_STRING> gl(var_list);
+ Item *item;
+ LEX_STRING *ls;
+ if (var_list.elements != list.elements)
+ {
+ my_error(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, MYF(0));
+ return 1;
+ }
+ while ((item=li++))
+ {
+ ls= gl++;
+ Item_func_set_user_var *xx = new Item_func_set_user_var(*ls,item);
+ xx->fix_fields(current_thd,(TABLE_LIST*) current_thd->lex.select_lex.table_list.first,&item);
+ xx->fix_length_and_dec();
+ vars.push_back(xx);
+ }
+ return 0;
+}
+bool select_dumpvar::send_data(List<Item> &items)
+{
+ List_iterator_fast<Item_func_set_user_var> li(vars);
+ Item_func_set_user_var *xx;
+ DBUG_ENTER("send_data");
+
+ if (row_count++)
+ {
+ my_error(ER_TOO_MANY_ROWS, MYF(0));
+ DBUG_RETURN(1);
+ }
+ while ((xx=li++))
+ xx->update();
+ DBUG_RETURN(0);
+}
+
+bool select_dumpvar::send_eof()
+{
+ if (row_count)
+ {
+ ::send_ok(thd,row_count);
+ return 0;
+ }
+ else
+ {
+ my_error(ER_EMPTY_QUERY,MYF(0));
+ return 1;
+ }
+}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 3983405e039..b625a78b867 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -973,3 +973,15 @@ public:
bool send_eof();
};
+class select_dumpvar :public select_result {
+ ha_rows row_count;
+public:
+ List<LEX_STRING> var_list;
+ List<Item_func_set_user_var> vars;
+ select_dumpvar(void) { var_list.empty(); vars.empty(); row_count=0;}
+ ~select_dumpvar() {}
+ int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
+ bool send_fields(List<Item> &list, uint flag) {return 0;}
+ bool send_data(List<Item> &items);
+ bool send_eof();
+};
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 1d843b78d4e..58b12bca00d 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -69,7 +69,6 @@ static bool write_db_opt(const char *path, HA_CREATE_INFO *create)
error=0;
my_close(file,MYF(0));
}
-exit:
return error;
}
@@ -104,7 +103,7 @@ static bool load_db_opt(const char *path, HA_CREATE_INFO *create)
IO_CACHE cache;
init_io_cache(&cache, file, IO_SIZE, READ_CACHE, 0, 0, MYF(0));
- while ((int) (nbytes= my_b_gets(&cache, (byte*) buf, sizeof(buf))) > 0)
+ while ((int) (nbytes= my_b_gets(&cache, (char*) buf, sizeof(buf))) > 0)
{
char *pos= buf+nbytes-1;
/* Remove end space and control characters */
@@ -251,10 +250,8 @@ exit2:
int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
{
char path[FN_REFLEN+16];
- MY_DIR *dirp;
long result=1;
int error = 0;
- register File file;
uint create_options = create_info ? create_info->options : 0;
DBUG_ENTER("mysql_alter_db");
@@ -602,7 +599,7 @@ bool mysql_change_db(THD *thd, const char *name)
int mysqld_show_create_db(THD *thd, const char *dbname)
{
- int length, db_length;
+ int length;
char path[FN_REFLEN], *to;
uint db_access;
bool found_libchar;
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 0581e0b5a3b..cb1a9db70cd 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -117,8 +117,8 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
MYF(MY_FAE | MY_ZEROFILL));
if (setup_order(thd, &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) ||
- (table->found_records = filesort(table, sortorder, length,
- (SQL_SELECT *) 0, 0L, HA_POS_ERROR,
+ (table->found_records = filesort(thd, table, sortorder, length,
+ (SQL_SELECT *) 0, HA_POS_ERROR,
&examined_rows))
== HA_POS_ERROR)
{
@@ -330,7 +330,7 @@ bool multi_delete::send_data(List<Item> &values)
table->status|= STATUS_DELETED;
if (!(error=table->file->delete_row(table->record[0])))
deleted++;
- else
+ else if (!table_being_deleted->next)
{
table->file->print_error(error,MYF(0));
DBUG_RETURN(1);
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 122ceeedc54..9f09afc78a6 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -944,7 +944,7 @@ void st_select_lex_unit::init_query()
global_parameters= this;
select_limit_cnt= HA_POS_ERROR;
offset_limit_cnt= 0;
- optimized= 0;
+ prepared= optimized= 0;
item= 0;
}
@@ -955,6 +955,7 @@ void st_select_lex::init_query()
table_list.first= 0;
table_list.next= (byte**) &table_list.first;
item_list.empty();
+ join= 0;
}
void st_select_lex::init_select()
@@ -973,7 +974,6 @@ void st_select_lex::init_select()
ftfunc_list= &ftfunc_list_alloc;
linkage= UNSPECIFIED_TYPE;
depended= having_fix_field= 0;
-
}
/*
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index acf73f34d5d..de57e9f77a8 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -210,7 +210,7 @@ private:
SELECT_LEX_UNIT - unit of selects (UNION, INTERSECT, ...) group
SELECT_LEXs
*/
-class st_lex;
+struct st_lex;
class st_select_lex;
class THD;
class select_result;
@@ -227,6 +227,7 @@ protected:
select_result *result;
int res;
bool describe, found_rows_for_union,
+ prepared, //prepare phase already performed for UNION (unit)
optimized; // optimize phase already performed for UNION (unit)
public:
/*
@@ -333,6 +334,7 @@ typedef struct st_lex
enum SSL_type ssl_type; /* defined in violite.h */
String *wild;
sql_exchange *exchange;
+ select_result *result;
List<key_part_spec> col_list;
List<key_part_spec> ref_list;
@@ -376,7 +378,7 @@ typedef struct st_lex
uint param_count;
bool drop_primary, drop_if_exists, local_file, olap;
bool in_comment, ignore_space, verbose, simple_alter;
- bool derived_tables;
+ bool derived_tables, describe;
uint slave_thd_opt;
CHARSET_INFO *charset;
} LEX;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 595df6b7b7d..96b48ebd1fd 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1289,6 +1289,7 @@ mysql_execute_command(THD *thd)
int res= 0;
LEX *lex= &thd->lex;
TABLE_LIST *tables= (TABLE_LIST*) lex->select_lex.table_list.first;
+ TABLE_LIST *cursor;
SELECT_LEX *select_lex= &lex->select_lex;
SELECT_LEX_UNIT *unit= &lex->unit;
DBUG_ENTER("mysql_execute_command");
@@ -1336,8 +1337,7 @@ mysql_execute_command(THD *thd)
TODO: solve problem with depended derived tables in subselects
*/
if (lex->sql_command == SQLCOM_SELECT &&
- (select_lex->options & SELECT_DESCRIBE) &&
- lex->derived_tables)
+ lex->describe && lex->derived_tables)
{
if (!(explain_result= new select_send()))
{
@@ -1345,7 +1345,7 @@ mysql_execute_command(THD *thd)
DBUG_VOID_RETURN;
}
//check rights
- for (TABLE_LIST *cursor= tables;
+ for (cursor= tables;
cursor;
cursor= cursor->next)
if (cursor->derived)
@@ -1363,7 +1363,7 @@ mysql_execute_command(THD *thd)
}
thd->send_explain_fields(explain_result);
// EXPLAIN derived tables
- for (TABLE_LIST *cursor= tables;
+ for (cursor= tables;
cursor;
cursor= cursor->next)
if (cursor->derived)
@@ -1405,9 +1405,7 @@ mysql_execute_command(THD *thd)
switch (lex->sql_command) {
case SQLCOM_SELECT:
{
- select_result *result;
- if (select_lex->options & SELECT_DESCRIBE)
- lex->exchange=0;
+ select_result *result=lex->result;
if (tables)
{
res=check_table_access(thd,
@@ -1432,51 +1430,10 @@ mysql_execute_command(THD *thd)
if (unit->select_limit_cnt == HA_POS_ERROR)
select_lex->options&= ~OPTION_FOUND_ROWS;
- if (lex->exchange)
- {
- if (lex->exchange->dumpfile)
- {
- if (!(result=new select_dump(lex->exchange)))
- {
- res= -1;
- break;
- }
- }
- else
- {
- if (!(result=new select_export(lex->exchange)))
- {
- res= -1;
- break;
- }
- }
- }
- else if (!(result=new select_send()))
- {
- res= -1;
-#ifdef DELETE_ITEMS
- delete select_lex->having;
- delete select_lex->where;
-#endif
- break;
- }
- else
- {
- /*
- Normal select:
- Change lock if we are using SELECT HIGH PRIORITY,
- FOR UPDATE or IN SHARE MODE
- */
- TABLE_LIST *table;
- for (table = tables ; table ; table=table->next)
- table->lock_type= lex->lock_option;
- }
-
if (!(res=open_and_lock_tables(thd,tables)))
{
- if (select_lex->options & SELECT_DESCRIBE)
+ if (lex->describe)
{
- delete result; // we do not need it for explain
if (!explain_result)
if (!(explain_result= new select_send()))
{
@@ -1486,24 +1443,7 @@ mysql_execute_command(THD *thd)
else
thd->send_explain_fields(explain_result);
fix_tables_pointers(select_lex);
- for ( SELECT_LEX *sl= select_lex;
- sl && res == 0;
- sl= sl->next_select_in_list())
- {
- SELECT_LEX *first= sl->master_unit()->first_select();
- res= mysql_explain_select(thd, sl,
- ((select_lex==sl)?
- ((sl->next_select_in_list())?"PRIMARY":
- "SIMPLE"):
- ((sl == first)?
- ((sl->depended)?"DEPENDENT SUBSELECT":
- "SUBSELECT"):
- ((sl->depended)?"DEPENDENT UNION":
- "UNION"))),
- explain_result);
- }
- if (res > 0)
- res= -res; // mysql_explain_select do not report error
+ res= mysql_explain_union(thd, &thd->lex.unit, explain_result);
MYSQL_LOCK *save_lock= thd->lock;
thd->lock= (MYSQL_LOCK *)0;
explain_result->send_eof();
@@ -1511,12 +1451,33 @@ mysql_execute_command(THD *thd)
}
else
{
+ if (!result)
+ {
+ if ((result=new select_send()))
+ {
+ /*
+ Normal select:
+ Change lock if we are using SELECT HIGH PRIORITY,
+ FOR UPDATE or IN SHARE MODE
+ */
+ TABLE_LIST *table;
+ for (table = tables ; table ; table=table->next)
+ table->lock_type= lex->lock_option;
+ }
+ else
+ {
+ res= -1;
+#ifdef DELETE_ITEMS
+ delete select_lex->having;
+ delete select_lex->where;
+#endif
+ break;
+ }
+ }
query_cache_store_query(thd, tables);
res=handle_select(thd, lex, result);
}
}
- else
- delete result;
break;
}
case SQLCOM_DO:
@@ -2947,7 +2908,7 @@ mysql_init_query(THD *thd)
thd->free_list= 0;
thd->lex.union_option= 0;
thd->lex.select= &thd->lex.select_lex;
- thd->lex.olap=0;
+ thd->lex.olap=thd->lex.describe=0;
thd->lex.select->olap= UNSPECIFIED_OLAP_TYPE;
thd->fatal_error= 0; // Safety
thd->total_warn_count=0; // Warnings for this query
@@ -2967,6 +2928,7 @@ mysql_init_select(LEX *lex)
lex->thd->variables.select_limit;
select_lex->olap= UNSPECIFIED_OLAP_TYPE;
lex->exchange= 0;
+ lex->result= 0;
lex->proc_list.first= 0;
}
@@ -3570,10 +3532,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(1);
+ mysql_update_log.new_file(1);
+ mysql_bin_log.new_file(1);
+ mysql_slow_log.new_file(1);
if (ha_flush_logs())
result=1;
}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index a085795fa76..bd115f0fc1e 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -634,7 +634,6 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
{
MEM_ROOT thd_root = thd->mem_root;
PREP_STMT stmt;
- bool error;
DBUG_ENTER("mysql_stmt_prepare");
bzero((char*) &stmt, sizeof(stmt));
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index f850134190d..84ffa9c6663 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -112,7 +112,10 @@ static Item* part_of_refkey(TABLE *form,Field *field);
static uint find_shortest_key(TABLE *table, key_map usable_keys);
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
ha_rows select_limit, bool no_changes);
-static int create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows select_limit);
+static int create_sort_index(THD *thd, JOIN_TAB *tab,ORDER *order,
+ ha_rows filesort_limit, ha_rows select_limit);
+static int create_sort_index(THD *thd, JOIN_TAB *tab,ORDER *order,
+ ha_rows select_limit);
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
Item *having);
static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
@@ -171,7 +174,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
result->abort();
if (res || thd->net.report_error)
{
- send_error(thd, 0, MYF(0));
+ send_error(thd, 0, NullS);
res= 1;
}
delete result;
@@ -213,7 +216,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
SELECT_LEX_UNIT *unit, bool fake_select_lex)
{
DBUG_ENTER("JOIN::prepare");
-
+
conds= conds_init;
order= order_init;
group_list= group_init;
@@ -348,7 +351,7 @@ int
JOIN::optimize()
{
DBUG_ENTER("JOIN::optimize");
-
+
#ifdef HAVE_REF_TO_FIELDS // Not done yet
/* Add HAVING to WHERE if possible */
if (having && !group_list && ! sum_func_count)
@@ -748,8 +751,8 @@ JOIN::exec()
{
DBUG_PRINT("info",("Sorting for group"));
thd->proc_info="Sorting for group";
- if (create_sort_index(&join_tab[const_tables], group_list,
- HA_POS_ERROR) ||
+ if (create_sort_index(thd, &join_tab[const_tables], group_list,
+ HA_POS_ERROR, HA_POS_ERROR) ||
make_sum_func_list(this, all_fields) ||
alloc_group_fields(this, group_list))
DBUG_VOID_RETURN;
@@ -763,8 +766,8 @@ JOIN::exec()
{
DBUG_PRINT("info",("Sorting for order"));
thd->proc_info="Sorting for order";
- if (create_sort_index(&join_tab[const_tables], order,
- HA_POS_ERROR))
+ if (create_sort_index(thd, &join_tab[const_tables], order,
+ HA_POS_ERROR, HA_POS_ERROR))
DBUG_VOID_RETURN;
order=0;
}
@@ -866,7 +869,8 @@ JOIN::exec()
if (group_list)
{
thd->proc_info="Creating sort index";
- if (create_sort_index(join_tab, group_list, HA_POS_ERROR) ||
+ if (create_sort_index(thd, join_tab, group_list, HA_POS_ERROR,
+ HA_POS_ERROR) ||
alloc_group_fields(this, group_list))
{
free_tmp_table(thd,tmp_table2); /* purecov: inspected */
@@ -962,12 +966,33 @@ JOIN::exec()
DBUG_EXECUTE("where",print_where(conds,"having after sort"););
}
}
- if (create_sort_index(&join_tab[const_tables],
- group_list ? group_list : order,
- (having_list || group_list ||
- (select_options & OPTION_FOUND_ROWS)) ?
- HA_POS_ERROR : unit->select_limit_cnt))
- DBUG_VOID_RETURN;
+ {
+ ha_rows select_limit= unit->select_limit_cnt;
+ if (having || group || (select_options & OPTION_FOUND_ROWS))
+ select_limit= HA_POS_ERROR;
+ else
+ {
+ /*
+ We can abort sorting after thd->select_limit rows if we there is no
+ WHERE clause for any tables after the sorted one.
+ */
+ JOIN_TAB *table= &join_tab[const_tables+1];
+ JOIN_TAB *end_table= &join_tab[tables];
+ for (; table < end_table ; table++)
+ {
+ if (table->select_cond)
+ {
+ /* We have to sort all rows */
+ select_limit= HA_POS_ERROR;
+ break;
+ }
+ }
+ }
+ if (create_sort_index(thd, &join_tab[const_tables],
+ group_list ? group_list : order,
+ select_limit, unit->select_limit_cnt))
+ DBUG_VOID_RETURN;
+ }
}
having=having_list; // Actually a parameter
thd->proc_info="Sending data";
@@ -1018,36 +1043,60 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
bool fake_select_lex)
{
- JOIN *join = new JOIN(thd, fields, select_options, result);
-
DBUG_ENTER("mysql_select");
- thd->proc_info="init";
- thd->used_tables=0; // Updated by setup_fields
- if (join->prepare(tables, conds, order, group, having, proc_param,
- select_lex, unit, fake_select_lex))
+ bool free_join= 1;
+ JOIN *join;
+ if (!fake_select_lex && select_lex->join != 0)
{
- DBUG_RETURN(-1);
+ //here is EXPLAIN of subselect or derived table
+ join= select_lex->join;
+ join->result= result;
+ if (!join->procedure && result->prepare(join->fields_list, unit))
+ {
+ DBUG_RETURN(-1);
+ }
+ join->select_options= select_options;
+ free_join= 0;
+ }
+ else
+ {
+ join= new JOIN(thd, fields, select_options, result);
+ thd->proc_info="init";
+ thd->used_tables=0; // Updated by setup_fields
+
+ if (join->prepare(tables, conds, order, group, having, proc_param,
+ select_lex, unit, fake_select_lex))
+ {
+ DBUG_RETURN(-1);
+ }
}
- switch (join->optimize()) {
+
+ switch (join->optimize())
+ {
case 1:
DBUG_RETURN(join->error);
case -1:
goto err;
- }
+ }
- if (join->global_optimize())
+ if (free_join && join->global_optimize())
goto err;
join->exec();
err:
- thd->limit_found_rows = join->send_records;
- thd->examined_row_count = join->examined_rows;
- thd->proc_info="end";
- int error= (fake_select_lex?0:join->cleanup(thd)) || thd->net.report_error;
- delete join;
- DBUG_RETURN(error);
+ if (free_join)
+ {
+ thd->limit_found_rows = join->send_records;
+ thd->examined_row_count = join->examined_rows;
+ thd->proc_info="end";
+ int error= (fake_select_lex?0:join->cleanup(thd)) || thd->net.report_error;
+ delete join;
+ DBUG_RETURN(error);
+ }
+ else
+ DBUG_RETURN(0);
}
/*****************************************************************************
@@ -3605,6 +3654,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case Item::COND_ITEM:
case Item::FIELD_AVG_ITEM:
case Item::FIELD_STD_ITEM:
+ case Item::SUBSELECT_ITEM:
/* The following can only happen with 'CREATE TABLE ... SELECT' */
case Item::INT_ITEM:
case Item::REAL_ITEM:
@@ -3663,7 +3713,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;
@@ -3708,8 +3758,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,
@@ -3738,8 +3789,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;
@@ -3748,7 +3803,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
table->derived_select_number= 0;
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 */
@@ -3795,7 +3850,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);
}
}
@@ -3818,7 +3876,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++;
@@ -3831,6 +3892,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 ||
@@ -4088,10 +4150,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 */
@@ -4236,6 +4305,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();
@@ -5797,7 +5867,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
*****************************************************************************/
static int
-create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows select_limit)
+create_sort_index(THD *thd, JOIN_TAB *tab, ORDER *order,
+ ha_rows filesort_limit, ha_rows select_limit)
{
SORT_FIELD *sortorder;
uint length;
@@ -5841,8 +5912,8 @@ create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows select_limit)
}
if (table->tmp_table)
table->file->info(HA_STATUS_VARIABLE); // Get record count
- table->found_records=filesort(table,sortorder,length,
- select, 0L, select_limit, &examined_rows);
+ table->found_records=filesort(thd, table,sortorder, length,
+ select, filesort_limit, &examined_rows);
tab->records=table->found_records; // For SQL_CALC_ROWS
delete select; // filesort did select
tab->select=0;
@@ -5940,7 +6011,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
int error;
ulong reclength,offset;
uint field_count;
- THD *thd= current_thd;
+ THD *thd= join->thd;
DBUG_ENTER("remove_duplicates");
entry->reginfo.lock_type=TL_WRITE;
@@ -6490,7 +6561,7 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
order->in_field_list=1;
return 0;
}
- Item **item=find_item_in_list(*order->item, fields, 0);
+ Item **item= find_item_in_list(*order->item, fields, IGNORE_ERRORS);
if (item)
{
order->item=item; // use it
@@ -6590,7 +6661,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
thd->set_query_id=1; // Not really needed, but...
for (; new_field ; new_field= new_field->next)
{
- if ((item= find_item_in_list(*new_field->item, fields, 0)))
+ if ((item= find_item_in_list(*new_field->item, fields, IGNORE_ERRORS)))
new_field->item=item; /* Change to shared Item */
else
{
@@ -7179,7 +7250,6 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
bool distinct,const char *message)
{
List<Item> field_list;
- Item *item;
List<Item> item_list;
THD *thd=join->thd;
SELECT_LEX *select_lex = &(join->thd->lex.select_lex);
@@ -7193,7 +7263,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
if (message)
{
- item_list.push_back(new Item_int((int)thd->lex.select->select_number));
+ item_list.push_back(new Item_int((int32) thd->lex.select->select_number));
item_list.push_back(new Item_string(thd->lex.select->type,
strlen(thd->lex.select->type),
default_charset_info));
@@ -7220,7 +7290,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
tmp2.length(0);
item_list.empty();
- item_list.push_back(new Item_int((int)thd->lex.select->select_number));
+ item_list.push_back(new Item_int((int32) thd->lex.select->select_number));
item_list.push_back(new Item_string(thd->lex.select->type,
strlen(thd->lex.select->type),
default_charset_info));
@@ -7368,9 +7438,43 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
result->send_error(0,NullS);
}
}
+ for (SELECT_LEX_UNIT *unit= join->select_lex->first_inner_unit();
+ unit;
+ unit= unit->next_unit())
+ {
+ if (mysql_explain_union(thd, unit, result))
+ DBUG_VOID_RETURN;
+ }
DBUG_VOID_RETURN;
}
+int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
+{
+ int res= 0;
+ SELECT_LEX *first= unit->first_select();
+ for (SELECT_LEX *sl= first;
+ sl;
+ sl= sl->next_select())
+ {
+ res= mysql_explain_select(thd, sl,
+ (((&thd->lex.select_lex)==sl)?
+ ((sl->next_select_in_list())?"PRIMARY":
+ "SIMPLE"):
+ ((sl == first)?
+ ((sl->depended)?"DEPENDENT SUBSELECT":
+ "SUBSELECT"):
+ ((sl->depended)?"DEPENDENT UNION":
+ "UNION"))),
+ result);
+ if (res)
+ break;
+
+ }
+ if (res > 0)
+ res= -res; // mysql_explain_select do not report error
+ return res;
+}
+
int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
select_result *result)
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 93c7c07a347..eca86a60887 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -230,7 +230,7 @@ int mysqld_show_table_types(THD *thd)
const char *option_name= show_comp_option_name[(int) *types->value];
if (*types->value == SHOW_OPTION_YES &&
- !strcasecmp(default_type_name, types->type))
+ !my_strcasecmp(system_charset_info, default_type_name, types->type))
option_name= "DEFAULT";
net_store_data(packet, option_name);
net_store_data(packet, types->comment);
@@ -1401,12 +1401,11 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
int mysqld_show_charsets(THD *thd, const char *wild)
{
- uint i;
char buff[8192];
String packet2(buff,sizeof(buff),default_charset_info);
List<Item> field_list;
CONVERT *convert=thd->variables.convert_set;
- CHARSET_INFO *cs;
+ CHARSET_INFO **cs;
DBUG_ENTER("mysqld_show_charsets");
field_list.push_back(new Item_empty_string("Name",30));
@@ -1419,16 +1418,16 @@ int mysqld_show_charsets(THD *thd, const char *wild)
for (cs=all_charsets ; cs < all_charsets+255 ; cs++ )
{
- if (!cs->name)
+ if (!cs[0])
continue;
if (!(wild && wild[0] &&
- wild_case_compare(system_charset_info,cs->name,wild)))
+ wild_case_compare(system_charset_info,cs[0]->name,wild)))
{
packet2.length(0);
- net_store_data(&packet2,convert,cs->name);
- net_store_data(&packet2,(uint32) cs->number);
- net_store_data(&packet2,(uint32) cs->strxfrm_multiply);
- net_store_data(&packet2,(uint32) cs->mbmaxlen ? cs->mbmaxlen : 1);
+ net_store_data(&packet2,convert,cs[0]->name);
+ net_store_data(&packet2,(uint32) cs[0]->number);
+ net_store_data(&packet2,(uint32) cs[0]->strxfrm_multiply);
+ net_store_data(&packet2,(uint32) (cs[0]->mbmaxlen ? cs[0]->mbmaxlen : 1));
if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length()))
goto err;
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 6a42078cbcd..d2d14d4e7a2 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -505,7 +505,7 @@ int sortcmp(const String *x,const String *y)
uint32 x_len=x->length(),y_len=y->length(),len=min(x_len,y_len);
#ifdef USE_STRCOLL
- if (use_strcoll(x->str_charset))
+ if (use_strnxfrm(x->str_charset))
{
#ifndef CMP_ENDSPACE
while (x_len && my_isspace(x->str_charset,s[x_len-1]))
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index ccb7b5e5a9a..803d4102563 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2114,8 +2114,8 @@ copy_data_between_tables(TABLE *from,TABLE *to,
if (setup_order(thd, &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) ||
- (from->found_records = filesort(from, sortorder, length,
- (SQL_SELECT *) 0, 0L, HA_POS_ERROR,
+ (from->found_records = filesort(thd, from, sortorder, length,
+ (SQL_SELECT *) 0, HA_POS_ERROR,
&examined_rows))
== HA_POS_ERROR)
goto err;
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index ef26a1f45fe..538417f43ea 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -97,7 +97,7 @@ void print_cached_tables(void)
}
-void TEST_filesort(SORT_FIELD *sortorder,uint s_length, ha_rows special)
+void TEST_filesort(SORT_FIELD *sortorder,uint s_length)
{
char buff[256],buff2[256];
String str(buff,sizeof(buff),default_charset_info);
@@ -131,8 +131,6 @@ void TEST_filesort(SORT_FIELD *sortorder,uint s_length, ha_rows special)
out.append('\0'); // Purify doesn't like c_ptr()
DBUG_LOCK_FILE;
VOID(fputs("\nInfo about FILESORT\n",DBUG_FILE));
- if (special)
- fprintf(DBUG_FILE,"Records to sort: %ld\n",special);
fprintf(DBUG_FILE,"Sortorder: %s\n",out.ptr());
DBUG_UNLOCK_FILE;
DBUG_VOID_RETURN;
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 1a18759eb5b..eaeec2c1e68 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -104,14 +104,19 @@ bool select_union::flush()
typedef JOIN * JOIN_P;
int st_select_lex_unit::prepare(THD *thd, select_result *result)
{
+ DBUG_ENTER("st_select_lex_unit::prepare");
+
+ if (prepared)
+ DBUG_RETURN(0);
+ prepared= 1;
+ union_result=0;
describe=(first_select()->options & SELECT_DESCRIBE) ? 1 : 0;
res= 0;
found_rows_for_union= false;
TMP_TABLE_PARAM tmp_table_param;
- DBUG_ENTER("st_select_lex_unit::prepare");
this->thd= thd;
this->result= result;
- SELECT_LEX *lex_select_save= thd->lex.select;
+ SELECT_LEX *lex_select_save= thd->lex.select, *sl;
/* Global option */
if (((void*)(global_parameters)) == ((void*)this))
@@ -179,7 +184,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
// prepare selects
joins.empty();
- for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
+ for (sl= first_select(); sl; sl= sl->next_select())
{
JOIN *join= new JOIN(thd, sl->item_list,
sl->options | thd->options | SELECT_NO_UNLOCK |
@@ -304,10 +309,12 @@ int st_select_lex_unit::exec()
int st_select_lex_unit::cleanup()
{
DBUG_ENTER("st_select_lex_unit::cleanup");
- delete union_result;
- free_tmp_table(thd,table);
- table= 0; // Safety
-
+ if (union_result)
+ {
+ delete union_result;
+ free_tmp_table(thd,table);
+ table= 0; // Safety
+ }
List_iterator<JOIN*> j(joins);
JOIN** join;
while ((join= j++))
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 5d94b54f347..c146b07284f 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -190,8 +190,8 @@ int mysql_update(THD *thd,
MYF(MY_FAE | MY_ZEROFILL));
if (setup_order(thd, &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) ||
- (table->found_records = filesort(table, sortorder, length,
- (SQL_SELECT *) 0, 0L,
+ (table->found_records = filesort(thd, table, sortorder, length,
+ (SQL_SELECT *) 0,
HA_POS_ERROR, &examined_rows))
== HA_POS_ERROR)
{
@@ -776,7 +776,7 @@ bool multi_update::send_eof()
thd->proc_info="updating the reference tables";
/* Does updates for the last n - 1 tables, returns 0 if ok */
- int error = do_updates(false); /* do_updates returns 0 if success */
+ int error = (num_updated > 1) ? do_updates(false) : 0; /* do_updates returns 0 if success */
/* reset used flags */
#ifndef NOT_USED
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index f7ab07b2da3..4f75716ff56 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -520,10 +520,15 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%left '^'
%right NOT
%right BINARY COLLATE_SYM
+/* These don't actually affect the way the query is really evaluated, but
+ they silence a few warnings for shift/reduce conflicts. */
+%left ','
+%left STRAIGHT_JOIN JOIN_SYM
+%nonassoc CROSS INNER_SYM NATURAL LEFT RIGHT
%type <lex_str>
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
- ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET
+ ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET
%type <lex_str_ptr>
opt_table_alias
@@ -632,7 +637,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
handler_rkey_function handler_read_or_scan
single_multi table_wild_list table_wild_one opt_wild union union_list
precision union_option opt_on_delete_item subselect_start opt_and
- subselect_end
+ subselect_end select_var_list select_var_list_init
END_OF_INPUT
%type <NONE>
@@ -754,7 +759,8 @@ master_def:
RELAY_LOG_POS_SYM EQ ULONG_NUM
{
Lex->mi.relay_log_pos = $3;
- };
+ }
+ ;
/* create a table */
@@ -819,11 +825,13 @@ create:
LEX *lex=Lex;
lex->udf.returns=(Item_result) $7;
lex->udf.dl=$9.str;
- };
+ }
+ ;
create2:
'(' field_list ')' opt_create_table_options create3 {}
- | opt_create_table_options create3 {};
+ | opt_create_table_options create3 {}
+ ;
create3:
/* empty */ {}
@@ -833,7 +841,8 @@ create3:
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex);
}
- select_options select_item_list opt_select_from union {};
+ select_options select_item_list opt_select_from union {}
+ ;
opt_as:
/* empty */ {}
@@ -1544,6 +1553,7 @@ select_part2:
select_into:
limit_clause {}
| select_from
+ | opt_into
| opt_into select_from
| select_from opt_into;
@@ -2209,11 +2219,12 @@ opt_pad:
join_table_list:
'(' join_table_list ')' { $$=$2; }
| join_table { $$=$1; }
- | join_table_list normal_join join_table { $$=$3; }
- | join_table_list STRAIGHT_JOIN join_table { $$=$3 ; $$->straight=1; }
- | join_table_list INNER_SYM JOIN_SYM join_table ON expr
+ | join_table_list normal_join join_table_list { $$=$3; }
+ | join_table_list STRAIGHT_JOIN join_table_list
+ { $$=$3 ; $$->straight=1; }
+ | join_table_list INNER_SYM JOIN_SYM join_table_list ON expr
{ add_join_on($4,$6); $$=$4; }
- | join_table_list INNER_SYM JOIN_SYM join_table
+ | join_table_list INNER_SYM JOIN_SYM join_table_list
{
SELECT_LEX *sel=Select;
sel->db1=$1->db; sel->table1=$1->alias;
@@ -2221,9 +2232,9 @@ join_table_list:
}
USING '(' using_list ')'
{ add_join_on($4,$8); $$=$4; }
- | join_table_list LEFT opt_outer JOIN_SYM join_table ON expr
+ | join_table_list LEFT opt_outer JOIN_SYM join_table_list ON expr
{ add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
- | join_table_list LEFT opt_outer JOIN_SYM join_table
+ | join_table_list LEFT opt_outer JOIN_SYM join_table_list
{
SELECT_LEX *sel=Select;
sel->db1=$1->db; sel->table1=$1->alias;
@@ -2231,11 +2242,11 @@ join_table_list:
}
USING '(' using_list ')'
{ add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
- | join_table_list NATURAL LEFT opt_outer JOIN_SYM join_table
+ | join_table_list NATURAL LEFT opt_outer JOIN_SYM join_table_list
{ add_join_natural($1,$6); $6->outer_join|=JOIN_TYPE_LEFT; $$=$6; }
- | join_table_list RIGHT opt_outer JOIN_SYM join_table ON expr
+ | join_table_list RIGHT opt_outer JOIN_SYM join_table_list ON expr
{ add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
- | join_table_list RIGHT opt_outer JOIN_SYM join_table
+ | join_table_list RIGHT opt_outer JOIN_SYM join_table_list
{
SELECT_LEX *sel=Select;
sel->db1=$1->db; sel->table1=$1->alias;
@@ -2243,9 +2254,9 @@ join_table_list:
}
USING '(' using_list ')'
{ add_join_on($1,$9); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
- | join_table_list NATURAL RIGHT opt_outer JOIN_SYM join_table
+ | join_table_list NATURAL RIGHT opt_outer JOIN_SYM join_table_list
{ add_join_natural($6,$1); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
- | join_table_list NATURAL JOIN_SYM join_table
+ | join_table_list NATURAL JOIN_SYM join_table_list
{ add_join_natural($1,$4); $$=$4; };
normal_join:
@@ -2287,11 +2298,11 @@ select_part3:
mysql_init_select(lex);
lex->select->linkage= DERIVED_TABLE_TYPE;
}
- select_options select_item_list select_intoto
+ select_options select_item_list select_intoto;
select_intoto:
limit_clause {}
- | select_from
+ | select_from;
opt_outer:
/* empty */ {}
@@ -2542,20 +2553,61 @@ procedure_item:
YYABORT;
if (!$2->name)
$2->set_name($1,(uint) ((char*) Lex->tok_end - $1));
- };
+ }
+ ;
+
+
+select_var_list_init:
+ {
+ LEX *lex=Lex;
+ if (!lex->describe && (!(lex->result= new select_dumpvar())))
+ YYABORT;
+ }
+ select_var_list
+ ;
+
+select_var_list:
+ select_var_list ',' select_var_ident
+ | select_var_ident {}
+ ;
+
+select_var_ident: '@' ident_or_text
+ {
+ LEX *lex=Lex;
+ if (lex->result && ((select_dumpvar *)lex->result)->var_list.push_back((LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING))))
+ YYABORT;
+ }
+ ;
opt_into:
- INTO OUTFILE TEXT_STRING
+ INTO OUTFILE TEXT_STRING
{
- if (!(Lex->exchange= new sql_exchange($3.str,0)))
- YYABORT;
+ LEX *lex=Lex;
+ if (!lex->describe)
+ {
+ if (!(lex->exchange= new sql_exchange($3.str,0)))
+ YYABORT;
+ if (!(lex->result= new select_export(lex->exchange)))
+ YYABORT;
+ }
}
opt_field_term opt_line_term
| INTO DUMPFILE TEXT_STRING
{
- if (!(Lex->exchange= new sql_exchange($3.str,1)))
- YYABORT;
- };
+ LEX *lex=Lex;
+ if (!lex->describe)
+ {
+ if (!(lex->exchange= new sql_exchange($3.str,1)))
+ YYABORT;
+ if (!(lex->result= new select_dump(lex->exchange)))
+ YYABORT;
+ }
+ }
+ | INTO select_var_list_init
+ {
+ current_thd->safe_to_cache_query=0;
+ }
+ ;
/*
DO statement
@@ -3019,7 +3071,11 @@ describe:
}
opt_describe_column
| describe_command select
- { Lex->select_lex.options|= SELECT_DESCRIBE; };
+ {
+ LEX *lex=Lex;
+ lex->select_lex.options|= SELECT_DESCRIBE;
+ lex->describe=1;
+ };
describe_command:
@@ -3225,7 +3281,7 @@ param_marker:
yyerror("You have an error in your SQL syntax");
YYABORT;
}
- }
+ };
literal:
text_literal { $$ = $1; }
| NUM { $$ = new Item_int($1.str, (longlong) atol($1.str),$1.length); }
@@ -3566,6 +3622,7 @@ option_value:
{
Lex->var_list.push_back(new set_var_password($3,$5));
}
+ ;
internal_variable_name:
ident
@@ -3575,6 +3632,7 @@ internal_variable_name:
YYABORT;
$$=tmp;
}
+ ;
isolation_types:
READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; }
@@ -3595,7 +3653,8 @@ text_or_password:
make_scrambled_password(buff,$3.str);
$$=buff;
}
- };
+ }
+ ;
set_expr_or_default:
@@ -3625,16 +3684,19 @@ table_lock_list:
table_lock:
table_ident opt_table_alias lock_option
- { if (!add_table_to_list($1,$2,0,(thr_lock_type) $3)) YYABORT; };
+ { if (!add_table_to_list($1,$2,0,(thr_lock_type) $3)) YYABORT; }
+ ;
lock_option:
READ_SYM { $$=TL_READ_NO_INSERT; }
| WRITE_SYM { $$=current_thd->update_lock_default; }
| LOW_PRIORITY WRITE_SYM { $$=TL_WRITE_LOW_PRIORITY; }
- | READ_SYM LOCAL_SYM { $$= TL_READ; };
+ | READ_SYM LOCAL_SYM { $$= TL_READ; }
+ ;
unlock:
- UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; };
+ UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; }
+ ;
/*
@@ -3664,15 +3726,18 @@ handler:
if (!add_table_to_list($2,0,0))
YYABORT;
}
- handler_read_or_scan where_clause limit_clause { };
+ handler_read_or_scan where_clause limit_clause { }
+ ;
handler_read_or_scan:
handler_scan_function { Lex->backup_dir= 0; }
- | ident handler_rkey_function { Lex->backup_dir= $1.str; };
+ | ident handler_rkey_function { Lex->backup_dir= $1.str; }
+ ;
handler_scan_function:
FIRST_SYM { Lex->ha_read_mode = RFIRST; }
- | NEXT_SYM { Lex->ha_read_mode = RNEXT; };
+ | NEXT_SYM { Lex->ha_read_mode = RNEXT; }
+ ;
handler_rkey_function:
FIRST_SYM { Lex->ha_read_mode = RFIRST; }
@@ -3686,14 +3751,16 @@ handler_rkey_function:
lex->ha_rkey_mode=$1;
if (!(lex->insert_list = new List_item))
YYABORT;
- } '(' values ')' { };
+ } '(' values ')' { }
+ ;
handler_rkey_mode:
EQ { $$=HA_READ_KEY_EXACT; }
| GE { $$=HA_READ_KEY_OR_NEXT; }
| LE { $$=HA_READ_KEY_OR_PREV; }
| GT_SYM { $$=HA_READ_AFTER_KEY; }
- | LT { $$=HA_READ_BEFORE_KEY; };
+ | LT { $$=HA_READ_BEFORE_KEY; }
+ ;
/* GRANT / REVOKE */
@@ -3731,7 +3798,8 @@ grant:
grant_privileges:
grant_privilege_list {}
| ALL PRIVILEGES { Lex->grant = GLOBAL_ACLS;}
- | ALL { Lex->grant = GLOBAL_ACLS;};
+ | ALL { Lex->grant = GLOBAL_ACLS;}
+ ;
grant_privilege_list:
grant_privilege
@@ -3850,7 +3918,8 @@ opt_table:
YYABORT;
if (lex->grant == GLOBAL_ACLS)
lex->grant = TABLE_ACLS & ~GRANT_ACL;
- };
+ }
+ ;
user_list:
@@ -3881,7 +3950,8 @@ grant_user:
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
{ $$=$1; $1->password=$5 ; }
| user
- { $$=$1; $1->password.str=NullS; };
+ { $$=$1; $1->password.str=NullS; }
+ ;
opt_column_list:
@@ -3914,7 +3984,8 @@ column_list_id:
point->rights |= lex->which_columns;
else
lex->columns.push_back(new LEX_COLUMN (*new_str,lex->which_columns));
- };
+ }
+ ;
require_clause: /* empty */
@@ -3934,6 +4005,7 @@ require_clause: /* empty */
{
Lex->ssl_type=SSL_TYPE_NONE;
}
+ ;
grant_options:
/* empty */ {}
@@ -3941,7 +4013,8 @@ grant_options:
grant_option_list:
grant_option_list grant_option {}
- | grant_option {};
+ | grant_option {}
+ ;
grant_option:
GRANT OPTION { Lex->grant |= GRANT_ACL;}
@@ -3959,14 +4032,16 @@ grant_option:
{
Lex->mqh.connections=$2;
Lex->mqh.bits |= 4;
- };
+ }
+ ;
begin:
BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN;} opt_work;
opt_work:
/* empty */ {}
- | WORK_SYM {;};
+ | WORK_SYM {;}
+ ;
commit:
COMMIT_SYM { Lex->sql_command = SQLCOM_COMMIT;};
@@ -4076,4 +4151,4 @@ subselect_end:
{
LEX *lex=Lex;
lex->select = lex->select->outer_select();
- }
+ };
diff --git a/sql/table.cc b/sql/table.cc
index 2cdd62001f1..122cce160b6 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -527,6 +527,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