summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorHe Zhenxing <zhenxing.he@sun.com>2009-11-21 12:48:54 +0800
committerHe Zhenxing <zhenxing.he@sun.com>2009-11-21 12:48:54 +0800
commitb9268fc8ea2a2090b94aee6b2cef3cdd4d7aadd2 (patch)
tree821dc823aee6fd653afed43cbcce9dc52330f984 /sql
parentdd383cadec0fbfba626bba72051f2dc548171015 (diff)
parent34b11fb627df93e395158a27f48baa1c049ddf85 (diff)
downloadmariadb-git-b9268fc8ea2a2090b94aee6b2cef3cdd4d7aadd2.tar.gz
Auto merge
Diffstat (limited to 'sql')
-rw-r--r--sql/event_data_objects.cc2
-rw-r--r--sql/event_scheduler.cc1
-rw-r--r--sql/events.cc1
-rw-r--r--sql/field.cc350
-rw-r--r--sql/field.h42
-rw-r--r--sql/ha_ndbcluster.cc2
-rw-r--r--sql/ha_ndbcluster_binlog.cc1
-rw-r--r--sql/ha_partition.cc3
-rw-r--r--sql/item_cmpfunc.cc3
-rw-r--r--sql/item_func.cc81
-rw-r--r--sql/item_subselect.cc7
-rw-r--r--sql/item_timefunc.cc18
-rw-r--r--sql/mysql_priv.h4
-rw-r--r--sql/opt_sum.cc6
-rw-r--r--sql/share/errmsg.txt1
-rw-r--r--sql/slave.cc1
-rw-r--r--sql/sp.cc3
-rw-r--r--sql/sp_head.cc6
-rw-r--r--sql/sql_acl.cc2
-rw-r--r--sql/sql_base.cc3
-rw-r--r--sql/sql_cache.cc10
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_class.h48
-rw-r--r--sql/sql_insert.cc20
-rw-r--r--sql/sql_list.h2
-rw-r--r--sql/sql_parse.cc127
-rw-r--r--sql/sql_partition.cc178
-rw-r--r--sql/sql_plugin.cc1
-rw-r--r--sql/sql_select.cc8
-rw-r--r--sql/sql_servers.cc5
-rw-r--r--sql/sql_show.cc60
-rw-r--r--sql/sql_string.cc17
-rw-r--r--sql/sql_string.h4
-rw-r--r--sql/sql_trigger.cc4
-rw-r--r--sql/sql_udf.cc1
-rw-r--r--sql/sql_update.cc18
-rw-r--r--sql/sql_yacc.yy339
-rw-r--r--sql/table.cc3
-rw-r--r--sql/table.h6
-rw-r--r--sql/tztime.cc3
40 files changed, 561 insertions, 831 deletions
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc
index 23eec749a30..b2bbd340e14 100644
--- a/sql/event_data_objects.cc
+++ b/sql/event_data_objects.cc
@@ -196,7 +196,7 @@ Event_basic::Event_basic()
{
DBUG_ENTER("Event_basic::Event_basic");
/* init memory root */
- init_alloc_root(&mem_root, 256, 512);
+ init_sql_alloc(&mem_root, 256, 512);
dbname.str= name.str= NULL;
dbname.length= name.length= 0;
time_zone= NULL;
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
index ea20270b457..d9ca161f260 100644
--- a/sql/event_scheduler.cc
+++ b/sql/event_scheduler.cc
@@ -128,7 +128,6 @@ post_init_event_thread(THD *thd)
thd->cleanup();
return TRUE;
}
- lex_start(thd);
pthread_mutex_lock(&LOCK_thread_count);
threads.append(thd);
diff --git a/sql/events.cc b/sql/events.cc
index af40b31c80e..f5f837930c0 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -925,7 +925,6 @@ Events::init(my_bool opt_noacl_or_bootstrap)
*/
thd->thread_stack= (char*) &thd;
thd->store_globals();
- lex_start(thd);
/*
We will need Event_db_repository anyway, even if the scheduler is
diff --git a/sql/field.cc b/sql/field.cc
index dc32624db10..615d081918b 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -6819,86 +6819,6 @@ int Field_string::do_save_field_metadata(uchar *metadata_ptr)
}
-/*
- Compare two packed keys
-
- SYNOPSIS
- pack_cmp()
- a New key
- b Original key
- length Key length
- insert_or_update 1 if this is an insert or update
-
- RETURN
- < 0 a < b
- 0 a = b
- > 0 a > b
-*/
-
-int Field_string::pack_cmp(const uchar *a, const uchar *b, uint length,
- my_bool insert_or_update)
-{
- uint a_length, b_length;
- if (length > 255)
- {
- a_length= uint2korr(a);
- b_length= uint2korr(b);
- a+= 2;
- b+= 2;
- }
- else
- {
- a_length= (uint) *a++;
- b_length= (uint) *b++;
- }
- return field_charset->coll->strnncollsp(field_charset,
- a, a_length,
- b, b_length,
- insert_or_update);
-}
-
-
-/**
- Compare a packed key against row.
-
- @param key Original key
- @param length Key length. (May be less than field length)
- @param insert_or_update 1 if this is an insert or update
-
- @return
- < 0 row < key
- @return
- 0 row = key
- @return
- > 0 row > key
-*/
-
-int Field_string::pack_cmp(const uchar *key, uint length,
- my_bool insert_or_update)
-{
- uint row_length, local_key_length;
- uchar *end;
- if (length > 255)
- {
- local_key_length= uint2korr(key);
- key+= 2;
- }
- else
- local_key_length= (uint) *key++;
-
- /* Only use 'length' of key, not field_length */
- end= ptr + length;
- while (end > ptr && end[-1] == ' ')
- end--;
- row_length= (uint) (end - ptr);
-
- return field_charset->coll->strnncollsp(field_charset,
- ptr, row_length,
- key, local_key_length,
- insert_or_update);
-}
-
-
uint Field_string::packed_col_length(const uchar *data_ptr, uint length)
{
if (length > 255)
@@ -7258,90 +7178,6 @@ uchar *Field_varstring::pack(uchar *to, const uchar *from,
}
-uchar *
-Field_varstring::pack_key(uchar *to, const uchar *key, uint max_length,
- bool low_byte_first __attribute__((unused)))
-{
- uint length= length_bytes == 1 ? (uint) *key : uint2korr(key);
- uint local_char_length= ((field_charset->mbmaxlen > 1) ?
- max_length/field_charset->mbmaxlen : max_length);
- key+= length_bytes;
- if (length > local_char_length)
- {
- local_char_length= my_charpos(field_charset, key, key+length,
- local_char_length);
- set_if_smaller(length, local_char_length);
- }
- *to++= (char) (length & 255);
- if (max_length > 255)
- *to++= (char) (length >> 8);
- if (length)
- memcpy(to, key, length);
- return to+length;
-}
-
-
-/**
- Unpack a key into a record buffer.
-
- A VARCHAR key has a maximum size of 64K-1.
- In its packed form, the length field is one or two bytes long,
- depending on 'max_length'.
-
- @param to Pointer into the record buffer.
- @param key Pointer to the packed key.
- @param max_length Key length limit from key description.
-
- @return
- Pointer to end of 'key' (To the next key part if multi-segment key)
-*/
-
-const uchar *
-Field_varstring::unpack_key(uchar *to, const uchar *key, uint max_length,
- bool low_byte_first __attribute__((unused)))
-{
- /* get length of the blob key */
- uint32 length= *key++;
- if (max_length > 255)
- length+= (*key++) << 8;
-
- /* put the length into the record buffer */
- if (length_bytes == 1)
- *ptr= (uchar) length;
- else
- int2store(ptr, length);
- memcpy(ptr + length_bytes, key, length);
- return key + length;
-}
-
-/**
- Create a packed key that will be used for storage in the index tree.
-
- @param to Store packed key segment here
- @param from Key segment (as given to index_read())
- @param max_length Max length of key
-
- @return
- end of key storage
-*/
-
-uchar *
-Field_varstring::pack_key_from_key_image(uchar *to, const uchar *from, uint max_length,
- bool low_byte_first __attribute__((unused)))
-{
- /* Key length is always stored as 2 bytes */
- uint length= uint2korr(from);
- if (length > max_length)
- length= max_length;
- *to++= (char) (length & 255);
- if (max_length > 255)
- *to++= (char) (length >> 8);
- if (length)
- memcpy(to, from+HA_KEY_BLOB_LENGTH, length);
- return to+length;
-}
-
-
/**
Unpack a varstring field from row data.
@@ -7384,59 +7220,6 @@ Field_varstring::unpack(uchar *to, const uchar *from,
}
-int Field_varstring::pack_cmp(const uchar *a, const uchar *b,
- uint key_length_arg,
- my_bool insert_or_update)
-{
- uint a_length, b_length;
- if (key_length_arg > 255)
- {
- a_length=uint2korr(a); a+= 2;
- b_length=uint2korr(b); b+= 2;
- }
- else
- {
- a_length= (uint) *a++;
- b_length= (uint) *b++;
- }
- return field_charset->coll->strnncollsp(field_charset,
- a, a_length,
- b, b_length,
- insert_or_update);
-}
-
-
-int Field_varstring::pack_cmp(const uchar *b, uint key_length_arg,
- my_bool insert_or_update)
-{
- uchar *a= ptr+ length_bytes;
- uint a_length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
- uint b_length;
- uint local_char_length= ((field_charset->mbmaxlen > 1) ?
- key_length_arg / field_charset->mbmaxlen :
- key_length_arg);
-
- if (key_length_arg > 255)
- {
- b_length=uint2korr(b); b+= HA_KEY_BLOB_LENGTH;
- }
- else
- b_length= (uint) *b++;
-
- if (a_length > local_char_length)
- {
- local_char_length= my_charpos(field_charset, a, a+a_length,
- local_char_length);
- set_if_smaller(a_length, local_char_length);
- }
-
- return field_charset->coll->strnncollsp(field_charset,
- a, a_length,
- b, b_length,
- insert_or_update);
-}
-
-
uint Field_varstring::packed_col_length(const uchar *data_ptr, uint length)
{
if (length > 255)
@@ -8135,139 +7918,6 @@ const uchar *Field_blob::unpack(uchar *to,
DBUG_RETURN(from + master_packlength + length);
}
-/* Keys for blobs are like keys on varchars */
-
-int Field_blob::pack_cmp(const uchar *a, const uchar *b, uint key_length_arg,
- my_bool insert_or_update)
-{
- uint a_length, b_length;
- if (key_length_arg > 255)
- {
- a_length=uint2korr(a); a+=2;
- b_length=uint2korr(b); b+=2;
- }
- else
- {
- a_length= (uint) *a++;
- b_length= (uint) *b++;
- }
- return field_charset->coll->strnncollsp(field_charset,
- a, a_length,
- b, b_length,
- insert_or_update);
-}
-
-
-int Field_blob::pack_cmp(const uchar *b, uint key_length_arg,
- my_bool insert_or_update)
-{
- uchar *a;
- uint a_length, b_length;
- memcpy_fixed(&a,ptr+packlength,sizeof(char*));
- if (!a)
- return key_length_arg > 0 ? -1 : 0;
-
- a_length= get_length(ptr);
- if (key_length_arg > 255)
- {
- b_length= uint2korr(b); b+=2;
- }
- else
- b_length= (uint) *b++;
- return field_charset->coll->strnncollsp(field_charset,
- a, a_length,
- b, b_length,
- insert_or_update);
-}
-
-/** Create a packed key that will be used for storage from a MySQL row. */
-
-uchar *
-Field_blob::pack_key(uchar *to, const uchar *from, uint max_length,
- bool low_byte_first __attribute__((unused)))
-{
- uchar *save= ptr;
- ptr= (uchar*) from;
- uint32 length=get_length(); // Length of from string
- uint local_char_length= ((field_charset->mbmaxlen > 1) ?
- max_length/field_charset->mbmaxlen : max_length);
- if (length)
- get_ptr((uchar**) &from);
- if (length > local_char_length)
- local_char_length= my_charpos(field_charset, from, from+length,
- local_char_length);
- set_if_smaller(length, local_char_length);
- *to++= (uchar) length;
- if (max_length > 255) // 2 byte length
- *to++= (uchar) (length >> 8);
- memcpy(to, from, length);
- ptr=save; // Restore org row pointer
- return to+length;
-}
-
-
-/**
- Unpack a blob key into a record buffer.
-
- A blob key has a maximum size of 64K-1.
- In its packed form, the length field is one or two bytes long,
- depending on 'max_length'.
- Depending on the maximum length of a blob, its length field is
- put into 1 to 4 bytes. This is a property of the blob object,
- described by 'packlength'.
- Blobs are internally stored apart from the record buffer, which
- contains a pointer to the blob buffer.
-
-
- @param to Pointer into the record buffer.
- @param from Pointer to the packed key.
- @param max_length Key length limit from key description.
-
- @return
- Pointer into 'from' past the last byte copied from packed key.
-*/
-
-const uchar *
-Field_blob::unpack_key(uchar *to, const uchar *from, uint max_length,
- bool low_byte_first __attribute__((unused)))
-{
- /* get length of the blob key */
- uint32 length= *from++;
- if (max_length > 255)
- length+= *from++ << 8;
-
- /* put the length into the record buffer */
- put_length(to, length);
-
- /* put the address of the blob buffer or NULL */
- if (length)
- memcpy_fixed(to + packlength, &from, sizeof(from));
- else
- bzero(to + packlength, sizeof(from));
-
- /* point to first byte of next field in 'from' */
- return from + length;
-}
-
-
-/** Create a packed key that will be used for storage from a MySQL key. */
-
-uchar *
-Field_blob::pack_key_from_key_image(uchar *to, const uchar *from, uint max_length,
- bool low_byte_first __attribute__((unused)))
-{
- uint length=uint2korr(from);
- if (length > max_length)
- length=max_length;
- *to++= (char) (length & 255);
- if (max_length > 255)
- *to++= (char) (length >> 8);
- if (length)
- memcpy(to, from+HA_KEY_BLOB_LENGTH, length);
- return to+length;
-}
-
-
uint Field_blob::packed_col_length(const uchar *data_ptr, uint length)
{
if (length > 255)
diff --git a/sql/field.h b/sql/field.h
index 7235115a888..fb6ca34e88e 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -25,7 +25,6 @@
#pragma interface /* gcc class implementation */
#endif
-#define NOT_FIXED_DEC 31
#define DATETIME_DEC 6
const uint32 max_field_size= (uint32) 4294967295U;
@@ -410,32 +409,11 @@ public:
DBUG_RETURN(result);
}
- virtual uchar *pack_key(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first)
- {
- return pack(to, from, max_length, low_byte_first);
- }
- virtual uchar *pack_key_from_key_image(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first)
- {
- return pack(to, from, max_length, low_byte_first);
- }
- virtual const uchar *unpack_key(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first)
- {
- return unpack(to, from, max_length, low_byte_first);
- }
virtual uint packed_col_length(const uchar *to, uint length)
{ return length;}
virtual uint max_packed_col_length(uint max_length)
{ return max_length;}
- virtual int pack_cmp(const uchar *a,const uchar *b, uint key_length_arg,
- my_bool insert_or_update)
- { return cmp(a,b); }
- virtual int pack_cmp(const uchar *b, uint key_length_arg,
- my_bool insert_or_update)
- { return cmp(ptr,b); }
uint offset(uchar *record)
{
return (uint) (ptr - record);
@@ -1503,9 +1481,6 @@ public:
int compatible_field_size(uint field_metadata,
const Relay_log_info *rli);
uint row_pack_length() { return (field_length + 1); }
- int pack_cmp(const uchar *a,const uchar *b,uint key_length,
- my_bool insert_or_update);
- int pack_cmp(const uchar *b,uint key_length,my_bool insert_or_update);
uint packed_col_length(const uchar *to, uint length);
uint max_packed_col_length(uint max_length);
uint size_of() const { return sizeof(*this); }
@@ -1579,16 +1554,8 @@ public:
void sql_type(String &str) const;
virtual uchar *pack(uchar *to, const uchar *from,
uint max_length, bool low_byte_first);
- uchar *pack_key(uchar *to, const uchar *from, uint max_length, bool low_byte_first);
- uchar *pack_key_from_key_image(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first);
virtual const uchar *unpack(uchar* to, const uchar *from,
uint param_data, bool low_byte_first);
- const uchar *unpack_key(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first);
- int pack_cmp(const uchar *a, const uchar *b, uint key_length,
- my_bool insert_or_update);
- int pack_cmp(const uchar *b, uint key_length,my_bool insert_or_update);
int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0L);
int key_cmp(const uchar *,const uchar*);
int key_cmp(const uchar *str, uint length);
@@ -1764,17 +1731,8 @@ public:
}
virtual uchar *pack(uchar *to, const uchar *from,
uint max_length, bool low_byte_first);
- uchar *pack_key(uchar *to, const uchar *from,
- uint max_length, bool low_byte_first);
- uchar *pack_key_from_key_image(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first);
virtual const uchar *unpack(uchar *to, const uchar *from,
uint param_data, bool low_byte_first);
- const uchar *unpack_key(uchar* to, const uchar *from,
- uint max_length, bool low_byte_first);
- int pack_cmp(const uchar *a, const uchar *b, uint key_length,
- my_bool insert_or_update);
- int pack_cmp(const uchar *b, uint key_length,my_bool insert_or_update);
uint packed_col_length(const uchar *col_ptr, uint length);
uint max_packed_col_length(uint max_length);
void free() { value.free(); }
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 83cceb0da76..f83e40ec402 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -6952,7 +6952,6 @@ int ndb_create_table_from_engine(THD *thd, const char *db,
LEX *old_lex= thd->lex, newlex;
thd->lex= &newlex;
newlex.current_select= NULL;
- lex_start(thd);
int res= ha_create_table_from_engine(thd, db, table_name);
thd->lex= old_lex;
return res;
@@ -9272,7 +9271,6 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
thd->thread_stack= (char*)&thd; /* remember where our stack is */
if (thd->store_globals())
goto ndb_util_thread_fail;
- lex_start(thd);
thd->init_for_queries();
thd->version=refresh_version;
thd->main_security_ctx.host_or_ip= "";
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc
index e34a22cf9f4..a22ce976351 100644
--- a/sql/ha_ndbcluster_binlog.cc
+++ b/sql/ha_ndbcluster_binlog.cc
@@ -3669,7 +3669,6 @@ pthread_handler_t ndb_binlog_thread_func(void *arg)
pthread_exit(0);
return NULL; // Avoid compiler warnings
}
- lex_start(thd);
thd->init_for_queries();
thd->command= COM_DAEMON;
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 7e5eccb2374..0d5fc454a0c 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -1980,8 +1980,7 @@ partition_element *ha_partition::find_partition_element(uint part_id)
return part_elem;
}
DBUG_ASSERT(0);
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- current_thd->fatal_error(); // Abort
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
return NULL;
}
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index c6b88cd8188..981b4bf0b92 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -855,7 +855,8 @@ get_time_value(THD *thd, Item ***item_arg, Item **cache_arg,
else
{
*is_null= item->get_time(&ltime);
- value= !*is_null ? (longlong) TIME_to_ulonglong_datetime(&ltime) : 0;
+ value= !*is_null ? (longlong) TIME_to_ulonglong_datetime(&ltime) *
+ (ltime.neg ? -1 : 1) : 0;
}
/*
Do not cache GET_USER_VAR() function as its const_item() may return TRUE
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 23af528c256..ccb55feff81 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3474,6 +3474,48 @@ void debug_sync_point(const char* lock_name, uint lock_timeout)
#endif
+
+/**
+ Wait for a given condition to be signaled within the specified timeout.
+
+ @param cond the condition variable to wait on
+ @param lock the associated mutex
+ @param abstime the amount of time in seconds to wait
+
+ @retval return value from pthread_cond_timedwait
+*/
+
+#define INTERRUPT_INTERVAL (5 * ULL(1000000000))
+
+static int interruptible_wait(THD *thd, pthread_cond_t *cond,
+ pthread_mutex_t *lock, double time)
+{
+ int error;
+ struct timespec abstime;
+ ulonglong slice, timeout= (ulonglong) (time * 1000000000.0);
+
+ do
+ {
+ /* Wait for a fixed interval. */
+ if (timeout > INTERRUPT_INTERVAL)
+ slice= INTERRUPT_INTERVAL;
+ else
+ slice= timeout;
+
+ timeout-= slice;
+ set_timespec_nsec(abstime, slice);
+ error= pthread_cond_timedwait(cond, lock, &abstime);
+ if (error == ETIMEDOUT || error == ETIME)
+ {
+ /* Return error if timed out or connection is broken. */
+ if (!timeout || !thd->is_connected())
+ break;
+ }
+ } while (error && timeout);
+
+ return error;
+}
+
/**
Get a user level lock. If the thread has an old lock this is first released.
@@ -3489,8 +3531,7 @@ longlong Item_func_get_lock::val_int()
{
DBUG_ASSERT(fixed == 1);
String *res=args[0]->val_str(&value);
- longlong timeout=args[1]->val_int();
- struct timespec abstime;
+ double timeout= args[1]->val_real();
THD *thd=current_thd;
User_level_lock *ull;
int error;
@@ -3554,12 +3595,11 @@ longlong Item_func_get_lock::val_int()
thd->mysys_var->current_mutex= &LOCK_user_locks;
thd->mysys_var->current_cond= &ull->cond;
- set_timespec(abstime,timeout);
error= 0;
while (ull->locked && !thd->killed)
{
DBUG_PRINT("info", ("waiting on lock"));
- error= pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime);
+ error= interruptible_wait(thd, &ull->cond, &LOCK_user_locks, timeout);
if (error == ETIMEDOUT || error == ETIME)
{
DBUG_PRINT("info", ("lock wait timeout"));
@@ -3754,13 +3794,13 @@ void Item_func_benchmark::print(String *str, enum_query_type query_type)
longlong Item_func_sleep::val_int()
{
THD *thd= current_thd;
- struct timespec abstime;
pthread_cond_t cond;
+ double timeout;
int error;
DBUG_ASSERT(fixed == 1);
- double time= args[0]->val_real();
+ timeout= args[0]->val_real();
/*
On 64-bit OSX pthread_cond_timedwait() waits forever
if passed abstime time has already been exceeded by
@@ -3770,10 +3810,8 @@ longlong Item_func_sleep::val_int()
We assume that the lines between this test and the call
to pthread_cond_timedwait() will be executed in less than 0.00001 sec.
*/
- if (time < 0.00001)
+ if (timeout < 0.00001)
return 0;
-
- set_timespec_nsec(abstime, (ulonglong)(time * ULL(1000000000)));
pthread_cond_init(&cond, NULL);
pthread_mutex_lock(&LOCK_user_locks);
@@ -3785,7 +3823,7 @@ longlong Item_func_sleep::val_int()
error= 0;
while (!thd->killed)
{
- error= pthread_cond_timedwait(&cond, &LOCK_user_locks, &abstime);
+ error= interruptible_wait(thd, &cond, &LOCK_user_locks, timeout);
if (error == ETIMEDOUT || error == ETIME)
break;
error= 0;
@@ -3817,7 +3855,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
if (!my_hash_inited(hash))
return 0;
- if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME))))
+ if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME | ME_FATALERROR))))
return 0;
entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
extra_size;
@@ -3955,6 +3993,8 @@ bool Item_func_set_user_var::register_field_in_read_map(uchar *arg)
@param dv derivation for new value
@param unsigned_arg indiates if a value of type INT_RESULT is unsigned
+ @note Sets error and fatal error if allocation fails.
+
@retval
false success
@retval
@@ -3998,7 +4038,8 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
if (entry->value == pos)
entry->value=0;
entry->value= (char*) my_realloc(entry->value, length,
- MYF(MY_ALLOW_ZERO_PTR | MY_WME));
+ MYF(MY_ALLOW_ZERO_PTR | MY_WME |
+ ME_FATALERROR));
if (!entry->value)
return 1;
}
@@ -4035,7 +4076,6 @@ Item_func_set_user_var::update_hash(void *ptr, uint length,
if (::update_hash(entry, (null_value= args[0]->null_value),
ptr, length, res_type, cs, dv, unsigned_arg))
{
- current_thd->fatal_error(); // Probably end of memory
null_value= 1;
return 1;
}
@@ -4768,11 +4808,6 @@ void Item_func_get_user_var::fix_length_and_dec()
m_cached_result_type= STRING_RESULT;
max_length= MAX_BLOB_WIDTH;
}
-
- if (error)
- thd->fatal_error();
-
- return;
}
@@ -4843,18 +4878,16 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
{
- if (::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
- DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
- current_thd->fatal_error(); // Probably end of memory
+ ::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
+ DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
}
void Item_user_var_as_out_param::set_value(const char *str, uint length,
CHARSET_INFO* cs)
{
- if (::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
- DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
- current_thd->fatal_error(); // Probably end of memory
+ ::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
+ DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
}
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 0ce9c555fea..a619827b2d3 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1740,8 +1740,6 @@ subselect_union_engine::subselect_union_engine(st_select_lex_unit *u,
:subselect_engine(item_arg, result_arg)
{
unit= u;
- if (!result_arg) //out of memory
- current_thd->fatal_error();
unit->item= item_arg;
}
@@ -1753,10 +1751,7 @@ int subselect_single_select_engine::prepare()
join= new JOIN(thd, select_lex->item_list,
select_lex->options | SELECT_NO_UNLOCK, result);
if (!join || !result)
- {
- thd->fatal_error(); //out of memory
- return 1;
- }
+ return 1; /* Fatal error is set already. */
prepared= 1;
SELECT_LEX *save_select= thd->lex->current_select;
thd->lex->current_select= select_lex;
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 84ddc88487d..3009c48cac7 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -865,6 +865,8 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
{
const char *end=str+length;
uint i;
+ long msec_length= 0;
+
while (str != end && !my_isdigit(cs,*str))
str++;
@@ -874,12 +876,7 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
const char *start= str;
for (value=0; str != end && my_isdigit(cs,*str) ; str++)
value= value*LL(10) + (longlong) (*str - '0');
- if (transform_msec && i == count - 1) // microseconds always last
- {
- long msec_length= 6 - (uint) (str - start);
- if (msec_length > 0)
- value*= (long) log_10_int[msec_length];
- }
+ msec_length= 6 - (str - start);
values[i]= value;
while (str != end && !my_isdigit(cs,*str))
str++;
@@ -893,6 +890,10 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
break;
}
}
+
+ if (transform_msec && msec_length > 0)
+ values[count - 1] *= (long) log_10_int[msec_length];
+
return (str != end);
}
@@ -1854,7 +1855,7 @@ longlong Item_func_sec_to_time::val_int()
sec_to_time(arg_val, args[0]->unsigned_flag, &ltime);
return (ltime.neg ? -1 : 1) *
- ((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
+ (longlong) ((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
}
@@ -2666,7 +2667,8 @@ longlong Item_time_typecast::val_int()
null_value= 1;
return 0;
}
- return ltime.hour * 10000L + ltime.minute * 100 + ltime.second;
+ return (ltime.neg ? -1 : 1) *
+ (longlong) ((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
}
String *Item_time_typecast::val_str(String *str)
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index b3e614e0c7a..ad937144ab0 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1076,9 +1076,9 @@ inline bool check_access(THD *thd, ulong access, const char *db,
return false;
}
inline bool check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
- bool no_errors,
bool any_combination_of_privileges_will_do,
- uint number)
+ uint number,
+ bool no_errors)
{ return false; }
#endif /*NO_EMBEDDED_ACCESS_CHECKS*/
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 13b10ac2e8f..d85e976e9c8 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -175,8 +175,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
if(error)
{
- tl->table->file->print_error(error, MYF(0));
- tl->table->in_use->fatal_error();
+ tl->table->file->print_error(error, MYF(ME_FATALERROR));
return error;
}
count*= tl->table->file->stats.records;
@@ -427,8 +426,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
return HA_ERR_KEY_NOT_FOUND; // No rows matching WHERE
/* HA_ERR_LOCK_DEADLOCK or some other error */
- table->file->print_error(error, MYF(0));
- table->in_use->fatal_error();
+ table->file->print_error(error, MYF(ME_FATALERROR));
return(error);
}
removed_tables|= table->map;
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 034f987e0e7..b0ea4774a29 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -4880,6 +4880,7 @@ ER_ZLIB_Z_DATA_ERROR
spa "ZLIB: Dato de entrada fué corrompido para zlib"
ER_CUT_VALUE_GROUP_CONCAT
eng "Row %u was cut by GROUP_CONCAT()"
+ por "Linha %u foi cortada por GROUP_CONCAT()"
ER_WARN_TOO_FEW_RECORDS 01000
eng "Row %ld doesn't contain data for all columns"
ger "Zeile %ld enthält nicht für alle Felder Daten"
diff --git a/sql/slave.cc b/sql/slave.cc
index 8be17860c61..d49031ef066 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2121,7 +2121,6 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
thd->cleanup();
DBUG_RETURN(-1);
}
- lex_start(thd);
if (thd_type == SLAVE_THD_SQL)
thd_proc_info(thd, "Waiting for the next event in relay log");
diff --git a/sql/sp.cc b/sql/sp.cc
index 3e8ef5d4dc8..6e98dfdf4bc 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -1719,6 +1719,9 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
ret= SP_OK;
break;
default:
+ /* Query might have been killed, don't set error. */
+ if (thd->killed)
+ break;
/*
Any error when loading an existing routine is either some problem
with the mysql.proc table, or a parse error because the contents
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 19e6a9ffb72..33b487d9177 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1086,7 +1086,6 @@ sp_head::execute(THD *thd)
Item_change_list old_change_list;
String old_packet;
Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
-
Object_creation_ctx *saved_creation_ctx;
Warning_info *saved_warning_info, warning_info(thd->warning_info->warn_id());
@@ -4006,7 +4005,7 @@ sp_head::add_used_tables_to_table_list(THD *thd,
/**
- Simple function for adding an explicetly named (systems) table to
+ Simple function for adding an explicitly named (systems) table to
the global table list, e.g. "mysql", "proc".
*/
@@ -4018,10 +4017,7 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
TABLE_LIST *table;
if (!(table= (TABLE_LIST *)thd->calloc(sizeof(TABLE_LIST))))
- {
- thd->fatal_error();
return NULL;
- }
table->db_length= strlen(db);
table->db= thd->strmake(db, table->db_length);
table->table_name_length= strlen(name);
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 26eb3bf8a24..895cba93638 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -276,7 +276,6 @@ my_bool acl_init(bool dont_read_acl_tables)
DBUG_RETURN(1); /* purecov: inspected */
thd->thread_stack= (char*) &thd;
thd->store_globals();
- lex_start(thd);
/*
It is safe to call acl_reload() since acl_* arrays and hashes which
will be freed there are global static objects and thus are initialized
@@ -3525,7 +3524,6 @@ my_bool grant_init()
DBUG_RETURN(1); /* purecov: deadcode */
thd->thread_stack= (char*) &thd;
thd->store_globals();
- lex_start(thd);
return_val= grant_reload(thd);
delete thd;
/* Remember that we don't have a THD */
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 435bd053472..8cb35e3c447 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2536,9 +2536,6 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
HASH_SEARCH_STATE state;
DBUG_ENTER("open_table");
- /* Parsing of partitioning information from .frm needs thd->lex set up. */
- DBUG_ASSERT(thd->lex->is_lex_started);
-
/* find a unused table in the open table cache */
if (refresh)
*refresh=0;
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 35d2c886119..ed6f593cc2e 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1331,12 +1331,12 @@ end:
@param thd Pointer to the thread handler
@param sql A pointer to the sql statement *
@param query_length Length of the statement in characters
-
+
@return status code
- @retval 1 Query was not cached.
- @retval 0 The query was cached and user was sent the result.
- @retval -1 The query was cached but we didn't have rights to use it.
-
+ @retval 0 Query was not cached.
+ @retval 1 The query was cached and user was sent the result.
+ @retval -1 The query was cached but we didn't have rights to use it.
+
In case of -1, no error is sent to the client.
*) The buffer must be allocated memory of size:
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 60aed4ce53b..a944b65e74d 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1609,7 +1609,6 @@ void THD::rollback_item_tree_changes()
select_result::select_result()
{
thd=current_thd;
- nest_level= -1;
}
void select_result::send_error(uint errcode,const char *err)
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 0015a97e319..794f3d04310 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1982,9 +1982,15 @@ public:
DBUG_VOID_RETURN;
}
inline bool vio_ok() const { return net.vio != 0; }
+ /** Return FALSE if connection to client is broken. */
+ bool is_connected()
+ {
+ return vio_ok() ? vio_is_connected(net.vio) : FALSE;
+ }
#else
void clear_error();
- inline bool vio_ok() const { return true; }
+ inline bool vio_ok() const { return TRUE; }
+ inline bool is_connected() { return TRUE; }
#endif
/**
Mark the current error as fatal. Warning: this does not
@@ -1993,6 +1999,7 @@ public:
*/
inline void fatal_error()
{
+ DBUG_ASSERT(main_da.is_error());
is_fatal_error= 1;
DBUG_PRINT("error",("Fatal error set"));
}
@@ -2158,7 +2165,10 @@ public:
else
{
x_free(db);
- db= new_db ? my_strndup(new_db, new_db_len, MYF(MY_WME)) : NULL;
+ if (new_db)
+ db= my_strndup(new_db, new_db_len, MYF(MY_WME | ME_FATALERROR));
+ else
+ db= NULL;
}
db_length= db ? new_db_len : 0;
return new_db && !db;
@@ -2400,7 +2410,6 @@ class select_result :public Sql_alloc {
protected:
THD *thd;
SELECT_LEX_UNIT *unit;
- uint nest_level;
public:
select_result();
virtual ~select_result() {};
@@ -2437,12 +2446,6 @@ public:
*/
virtual void cleanup();
void set_thd(THD *thd_arg) { thd= thd_arg; }
- /**
- The nest level, if supported.
- @return
- -1 if nest level is undefined, otherwise a positive integer.
- */
- int get_nest_level() { return nest_level; }
#ifdef EMBEDDED_LIBRARY
virtual void begin_dataset() {}
#else
@@ -2537,14 +2540,6 @@ class select_export :public select_to_file {
CHARSET_INFO *write_cs; // output charset
public:
select_export(sql_exchange *ex) :select_to_file(ex) {}
- /**
- Creates a select_export to represent INTO OUTFILE <filename> with a
- defined level of subquery nesting.
- */
- select_export(sql_exchange *ex, uint nest_level_arg) :select_to_file(ex)
- {
- nest_level= nest_level_arg;
- }
~select_export();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items);
@@ -2554,15 +2549,6 @@ public:
class select_dump :public select_to_file {
public:
select_dump(sql_exchange *ex) :select_to_file(ex) {}
- /**
- Creates a select_export to represent INTO DUMPFILE <filename> with a
- defined level of subquery nesting.
- */
- select_dump(sql_exchange *ex, uint nest_level_arg) :
- select_to_file(ex)
- {
- nest_level= nest_level_arg;
- }
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items);
};
@@ -3033,16 +3019,6 @@ class select_dumpvar :public select_result_interceptor {
public:
List<my_var> var_list;
select_dumpvar() { var_list.empty(); row_count= 0;}
- /**
- Creates a select_dumpvar to represent INTO <variable> with a defined
- level of subquery nesting.
- */
- select_dumpvar(uint nest_level_arg)
- {
- var_list.empty();
- row_count= 0;
- nest_level= nest_level_arg;
- }
~select_dumpvar() {}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 681ab81eeaf..6315c4f3500 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1922,20 +1922,17 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
if (! (di= find_handler(thd, table_list)))
{
if (!(di= new Delayed_insert()))
- {
- thd->fatal_error();
goto end_create;
- }
pthread_mutex_lock(&LOCK_thread_count);
thread_count++;
pthread_mutex_unlock(&LOCK_thread_count);
di->thd.set_db(table_list->db, (uint) strlen(table_list->db));
- di->thd.set_query(my_strdup(table_list->table_name, MYF(MY_WME)), 0);
+ di->thd.set_query(my_strdup(table_list->table_name,
+ MYF(MY_WME | ME_FATALERROR)), 0);
if (di->thd.db == NULL || di->thd.query() == NULL)
{
/* The error is reported */
delete di;
- thd->fatal_error();
goto end_create;
}
di->table_list= *table_list; // Needed to open table
@@ -1953,8 +1950,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
pthread_mutex_unlock(&di->mutex);
di->unlock();
delete di;
- my_error(ER_CANT_CREATE_THREAD, MYF(0), error);
- thd->fatal_error();
+ my_error(ER_CANT_CREATE_THREAD, MYF(ME_FATALERROR), error);
goto end_create;
}
@@ -2308,12 +2304,6 @@ static void handle_delayed_insert_impl(THD *thd, Delayed_insert *di)
goto err;
}
- /*
- Open table requires an initialized lex in case the table is
- partitioned. The .frm file contains a partial SQL string which is
- parsed using a lex, that depends on initialized thd->lex.
- */
- lex_start(thd);
thd->lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock()
/*
Statement-based replication of INSERT DELAYED has problems with RAND()
@@ -2331,8 +2321,8 @@ static void handle_delayed_insert_impl(THD *thd, Delayed_insert *di)
}
if (!(di->table->file->ha_table_flags() & HA_CAN_INSERT_DELAYED))
{
- thd->fatal_error();
- my_error(ER_DELAYED_NOT_SUPPORTED, MYF(0), di->table_list.table_name);
+ my_error(ER_DELAYED_NOT_SUPPORTED, MYF(ME_FATALERROR),
+ di->table_list.table_name);
goto err;
}
if (di->table->triggers)
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 74f4cc0ec0d..e1bf05fff23 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -458,7 +458,7 @@ struct ilink
struct ilink **prev,*next;
static void *operator new(size_t size) throw ()
{
- return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE));
+ return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE | ME_FATALERROR));
}
static void operator delete(void* ptr_arg, size_t size)
{
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 2f65ba20b77..68b00cad891 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1369,54 +1369,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->stmt_da->disable_status(); // Don't send anything back
error=TRUE; // End server
break;
-
-#ifdef REMOVED
- case COM_CREATE_DB: // QQ: To be removed
- {
- LEX_STRING db, alias;
- HA_CREATE_INFO create_info;
-
- status_var_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB]);
- if (thd->make_lex_string(&db, packet, packet_length, FALSE) ||
- thd->make_lex_string(&alias, db.str, db.length, FALSE) ||
- check_db_name(&db))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL");
- break;
- }
- if (check_access(thd, CREATE_ACL, db.str , 0, 1, 0,
- is_schema_db(db.str)))
- break;
- general_log_print(thd, command, "%.*s", db.length, db.str);
- bzero(&create_info, sizeof(create_info));
- mysql_create_db(thd, (lower_case_table_names == 2 ? alias.str : db.str),
- &create_info, 0);
- break;
- }
- case COM_DROP_DB: // QQ: To be removed
- {
- status_var_increment(thd->status_var.com_stat[SQLCOM_DROP_DB]);
- LEX_STRING db;
-
- if (thd->make_lex_string(&db, packet, packet_length, FALSE) ||
- check_db_name(&db))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL");
- break;
- }
- if (check_access(thd, DROP_ACL, db.str, 0, 1, 0, is_schema_db(db.str)))
- break;
- if (thd->locked_tables || thd->active_transaction())
- {
- my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
- ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
- break;
- }
- general_log_write(thd, command, "%.*s", db.length, db.str);
- mysql_rm_db(thd, db.str, 0, 0);
- break;
- }
-#endif
#ifndef EMBEDDED_LIBRARY
case COM_BINLOG_DUMP:
{
@@ -2073,7 +2025,6 @@ mysql_execute_command(THD *thd)
A better approach would be to reset this for any commands
that is not a SHOW command or a select that only access local
variables, but for now this is probably good enough.
- Don't reset warnings when executing a stored routine.
*/
if ((sql_command_flags[lex->sql_command] & CF_DIAGNOSTIC_STMT) != 0)
thd->warning_info->set_read_only(TRUE);
@@ -2276,7 +2227,7 @@ mysql_execute_command(THD *thd)
privileges_requested,
all_tables, FALSE, UINT_MAX, FALSE);
else
- res= check_access(thd, privileges_requested, any_db, 0, 0, 0, UINT_MAX);
+ res= check_access(thd, privileges_requested, any_db, 0, 0, 0, 0);
if (res)
break;
@@ -5831,7 +5782,6 @@ bool check_stack_overrun(THD *thd, long margin,
my_snprintf(ebuff, sizeof(ebuff), ER(ER_STACK_OVERRUN_NEED_MORE),
stack_used, my_thread_stack_size, margin);
my_message(ER_STACK_OVERRUN_NEED_MORE, ebuff, MYF(ME_FATALERROR));
- thd->fatal_error();
return 1;
}
#ifndef DBUG_OFF
@@ -6495,13 +6445,17 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
DBUG_RETURN(0); /* purecov: inspected */
if (table->db.str)
{
+ ptr->is_fqtn= TRUE;
ptr->db= table->db.str;
ptr->db_length= table->db.length;
}
else if (lex->copy_db_to(&ptr->db, &ptr->db_length))
DBUG_RETURN(0);
+ else
+ ptr->is_fqtn= FALSE;
ptr->alias= alias_str;
+ ptr->is_alias= alias ? TRUE : FALSE;
if (lower_case_table_names && table->table.length)
table->table.length= my_casedn_str(files_charset_info, table->table.str);
ptr->table_name=table->table.str;
@@ -7051,7 +7005,6 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
{
thd->thread_stack= (char*) &tmp_thd;
thd->store_globals();
- lex_start(thd);
}
if (thd)
@@ -7548,6 +7501,63 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
}
+/*
+ Given a table in the source list, find a correspondent table in the
+ table references list.
+
+ @param lex Pointer to LEX representing multi-delete.
+ @param src Source table to match.
+ @param ref Table references list.
+
+ @remark The source table list (tables listed before the FROM clause
+ or tables listed in the FROM clause before the USING clause) may
+ contain table names or aliases that must match unambiguously one,
+ and only one, table in the target table list (table references list,
+ after FROM/USING clause).
+
+ @return Matching table, NULL otherwise.
+*/
+
+static TABLE_LIST *multi_delete_table_match(LEX *lex, TABLE_LIST *tbl,
+ TABLE_LIST *tables)
+{
+ TABLE_LIST *match= NULL;
+ DBUG_ENTER("multi_delete_table_match");
+
+ for (TABLE_LIST *elem= tables; elem; elem= elem->next_local)
+ {
+ int cmp;
+
+ if (tbl->is_fqtn && elem->is_alias)
+ continue; /* no match */
+ if (tbl->is_fqtn && elem->is_fqtn)
+ cmp= my_strcasecmp(table_alias_charset, tbl->table_name, elem->table_name) ||
+ strcmp(tbl->db, elem->db);
+ else if (elem->is_alias)
+ cmp= my_strcasecmp(table_alias_charset, tbl->alias, elem->alias);
+ else
+ cmp= my_strcasecmp(table_alias_charset, tbl->table_name, elem->table_name) ||
+ strcmp(tbl->db, elem->db);
+
+ if (cmp)
+ continue;
+
+ if (match)
+ {
+ my_error(ER_NONUNIQ_TABLE, MYF(0), elem->alias);
+ DBUG_RETURN(NULL);
+ }
+
+ match= elem;
+ }
+
+ if (!match)
+ my_error(ER_UNKNOWN_TABLE, MYF(0), tbl->table_name, "MULTI DELETE");
+
+ DBUG_RETURN(match);
+}
+
+
/**
Link tables in auxilary table list of multi-delete with corresponding
elements in main table list, and set proper locks for them.
@@ -7573,20 +7583,9 @@ bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
{
lex->table_count++;
/* All tables in aux_tables must be found in FROM PART */
- TABLE_LIST *walk;
- for (walk= tables; walk; walk= walk->next_local)
- {
- if (!my_strcasecmp(table_alias_charset,
- target_tbl->alias, walk->alias) &&
- !strcmp(walk->db, target_tbl->db))
- break;
- }
+ TABLE_LIST *walk= multi_delete_table_match(lex, target_tbl, tables);
if (!walk)
- {
- my_error(ER_UNKNOWN_TABLE, MYF(0),
- target_tbl->table_name, "MULTI DELETE");
DBUG_RETURN(TRUE);
- }
if (!walk->derived)
{
target_tbl->table_name= walk->table_name;
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 9cd3ac78a77..c0eb3e67c84 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -932,6 +932,85 @@ int check_signed_flag(partition_info *part_info)
return error;
}
+/**
+ Initialize lex object for use in fix_fields and parsing.
+
+ SYNOPSIS
+ init_lex_with_single_table()
+ @param thd The thread object
+ @param table The table object
+ @return Operation status
+ @retval TRUE An error occurred, memory allocation error
+ @retval FALSE Ok
+
+ DESCRIPTION
+ This function is used to initialize a lex object on the
+ stack for use by fix_fields and for parsing. In order to
+ work properly it also needs to initialize the
+ Name_resolution_context object of the lexer.
+ Finally it needs to set a couple of variables to ensure
+ proper functioning of fix_fields.
+*/
+
+static int
+init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex)
+{
+ TABLE_LIST *table_list;
+ Table_ident *table_ident;
+ SELECT_LEX *select_lex= &lex->select_lex;
+ Name_resolution_context *context= &select_lex->context;
+ /*
+ We will call the parser to create a part_info struct based on the
+ partition string stored in the frm file.
+ We will use a local lex object for this purpose. However we also
+ need to set the Name_resolution_object for this lex object. We
+ do this by using add_table_to_list where we add the table that
+ we're working with to the Name_resolution_context.
+ */
+ thd->lex= lex;
+ lex_start(thd);
+ context->init();
+ if ((!(table_ident= new Table_ident(thd,
+ table->s->table_name,
+ table->s->db, TRUE))) ||
+ (!(table_list= select_lex->add_table_to_list(thd,
+ table_ident,
+ NULL,
+ 0))))
+ return TRUE;
+ context->resolve_in_table_list_only(table_list);
+ lex->use_only_table_context= TRUE;
+ select_lex->cur_pos_in_select_list= UNDEF_POS;
+ table->map= 1; //To ensure correct calculation of const item
+ table->get_fields_in_item_tree= TRUE;
+ table_list->table= table;
+ return FALSE;
+}
+
+/**
+ End use of local lex with single table
+
+ SYNOPSIS
+ end_lex_with_single_table()
+ @param thd The thread object
+ @param table The table object
+ @param old_lex The real lex object connected to THD
+
+ DESCRIPTION
+ This function restores the real lex object after calling
+ init_lex_with_single_table and also restores some table
+ variables temporarily set.
+*/
+
+static void
+end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex)
+{
+ LEX *lex= thd->lex;
+ table->map= 0;
+ table->get_fields_in_item_tree= FALSE;
+ lex_end(lex);
+ thd->lex= old_lex;
+}
/*
The function uses a new feature in fix_fields where the flag
@@ -972,55 +1051,18 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
bool is_sub_part)
{
partition_info *part_info= table->part_info;
- uint dir_length, home_dir_length;
bool result= TRUE;
- TABLE_LIST tables;
- TABLE_LIST *save_table_list, *save_first_table, *save_last_table;
int error;
- Name_resolution_context *context;
const char *save_where;
- char* db_name;
- char db_name_string[FN_REFLEN];
- bool save_use_only_table_context;
+ LEX *old_lex= thd->lex;
+ LEX lex;
DBUG_ENTER("fix_fields_part_func");
- /*
- Set-up the TABLE_LIST object to be a list with a single table
- Set the object to zero to create NULL pointers and set alias
- and real name to table name and get database name from file name.
- TODO: Consider generalizing or refactoring Lex::add_table_to_list() so
- it can be used in all places where we create TABLE_LIST objects.
- Also consider creating appropriate constructors for TABLE_LIST.
- */
-
- bzero((void*)&tables, sizeof(TABLE_LIST));
- tables.alias= tables.table_name= (char*) table->s->table_name.str;
- tables.table= table;
- tables.next_local= 0;
- tables.next_name_resolution_table= 0;
- /*
- Cache the table in Item_fields. All the tables can be cached except
- the trigger pseudo table.
- */
- tables.cacheable_table= TRUE;
- context= thd->lex->current_context();
- tables.select_lex= context->select_lex;
- strmov(db_name_string, table->s->normalized_path.str);
- dir_length= dirname_length(db_name_string);
- db_name_string[dir_length - 1]= 0;
- home_dir_length= dirname_length(db_name_string);
- db_name= &db_name_string[home_dir_length];
- tables.db= db_name;
+ if (init_lex_with_single_table(thd, table, &lex))
+ goto end;
- table->map= 1; //To ensure correct calculation of const item
- table->get_fields_in_item_tree= TRUE;
- save_table_list= context->table_list;
- save_first_table= context->first_name_resolution_table;
- save_last_table= context->last_name_resolution_table;
- context->table_list= &tables;
- context->first_name_resolution_table= &tables;
- context->last_name_resolution_table= NULL;
- func_expr->walk(&Item::change_context_processor, 0, (uchar*) context);
+ func_expr->walk(&Item::change_context_processor, 0,
+ (uchar*) &lex.select_lex.context);
save_where= thd->where;
thd->where= "partition function";
/*
@@ -1035,30 +1077,18 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
that does this during val_int must be disallowed as partition
function.
SEE Bug #21658
- */
- /*
+
This is a tricky call to prepare for since it can have a large number
of interesting side effects, both desirable and undesirable.
*/
-
- save_use_only_table_context= thd->lex->use_only_table_context;
- thd->lex->use_only_table_context= TRUE;
- thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
-
error= func_expr->fix_fields(thd, (Item**)&func_expr);
- thd->lex->use_only_table_context= save_use_only_table_context;
-
- context->table_list= save_table_list;
- context->first_name_resolution_table= save_first_table;
- context->last_name_resolution_table= save_last_table;
if (unlikely(error))
{
DBUG_PRINT("info", ("Field in partition function not part of table"));
clear_field_flag(table);
goto end;
}
- thd->where= save_where;
if (unlikely(func_expr->const_item()))
{
my_error(ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0));
@@ -1069,8 +1099,11 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
goto end;
result= set_up_field_array(table, is_sub_part);
end:
- table->get_fields_in_item_tree= FALSE;
- table->map= 0; //Restore old value
+ end_lex_with_single_table(thd, table, old_lex);
+#if !defined(DBUG_OFF)
+ func_expr->walk(&Item::change_context_processor, 0,
+ (uchar*) 0);
+#endif
DBUG_RETURN(result);
}
@@ -2407,8 +2440,7 @@ char *generate_partition_syntax(partition_info *part_info,
default:
DBUG_ASSERT(0);
/* We really shouldn't get here, no use in continuing from here */
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- current_thd->fatal_error();
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
DBUG_RETURN(NULL);
}
if (part_info->part_expr)
@@ -4109,26 +4141,13 @@ bool mysql_unpack_partition(THD *thd,
LEX lex;
DBUG_ENTER("mysql_unpack_partition");
- thd->lex= &lex;
thd->variables.character_set_client= system_charset_info;
Parser_state parser_state(thd, part_buf, part_info_len);
- lex_start(thd);
- *work_part_info_used= false;
- /*
- We need to use the current SELECT_LEX since I need to keep the
- Name_resolution_context object which is referenced from the
- Item_field objects.
- This is not a nice solution since if the parser uses current_select
- for anything else it will corrupt the current LEX object.
- Also, we need to make sure there even is a select -- if the statement
- was a "USE ...", current_select will be NULL, but we may still end up
- here if we try to log to a partitioned table. This is currently
- unsupported, but should still fail rather than crash!
- */
- if (!(thd->lex->current_select= old_lex->current_select))
+ if (init_lex_with_single_table(thd, table, &lex))
goto end;
+
/*
All Items created is put into a free list on the THD object. This list
is used to free all Item objects after completing a query. We don't
@@ -4138,6 +4157,7 @@ bool mysql_unpack_partition(THD *thd,
Thus we move away the current list temporarily and start a new list that
we then save in the partition info structure.
*/
+ *work_part_info_used= FALSE;
lex.part_info= new partition_info();/* Indicates MYSQLparse from this place */
if (!lex.part_info)
{
@@ -4251,8 +4271,7 @@ bool mysql_unpack_partition(THD *thd,
result= FALSE;
end:
- lex_end(thd->lex);
- thd->lex= old_lex;
+ end_lex_with_single_table(thd, table, old_lex);
thd->variables.character_set_client= old_character_set_client;
DBUG_RETURN(result);
}
@@ -5484,10 +5503,7 @@ static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
&lpt->deleted, lpt->pack_frm_data,
lpt->pack_frm_len)))
{
- if (error != ER_OUTOFMEMORY)
- file->print_error(error, MYF(0));
- else
- lpt->thd->fatal_error();
+ file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATALERROR));
DBUG_RETURN(TRUE);
}
DBUG_RETURN(FALSE);
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 936c9ae8866..d15c97de912 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -1359,7 +1359,6 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv)
}
new_thd->thread_stack= (char*) &tables;
new_thd->store_globals();
- lex_start(new_thd);
new_thd->db= my_strdup("mysql", MYF(0));
new_thd->db_length= 5;
bzero((uchar*)&tables, sizeof(tables));
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 13197d44ce2..52e66ca8b50 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -9760,7 +9760,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item_sum *item_sum=(Item_sum*) item;
result= item_sum->create_tmp_field(group, table, convert_blob_length);
if (!result)
- thd->fatal_error();
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
return result;
}
case Item::FIELD_ITEM:
@@ -10904,8 +10904,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
We don't want this error to be converted to a warning, e.g. in case of
INSERT IGNORE ... SELECT.
*/
- thd->fatal_error();
- table->file->print_error(error,MYF(0));
+ table->file->print_error(error, MYF(ME_FATALERROR));
DBUG_RETURN(1);
}
@@ -15111,8 +15110,7 @@ calc_group_buffer(JOIN *join,ORDER *group)
default:
/* This case should never be choosen */
DBUG_ASSERT(0);
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- join->thd->fatal_error();
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
}
}
parts++;
diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc
index e8fa3d984a7..b711a273ae8 100644
--- a/sql/sql_servers.cc
+++ b/sql/sql_servers.cc
@@ -128,7 +128,7 @@ bool servers_init(bool dont_read_servers_table)
}
/* Initialize the mem root for data */
- init_alloc_root(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
+ init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
if (dont_read_servers_table)
goto end;
@@ -140,7 +140,6 @@ bool servers_init(bool dont_read_servers_table)
DBUG_RETURN(TRUE);
thd->thread_stack= (char*) &thd;
thd->store_globals();
- lex_start(thd);
/*
It is safe to call servers_reload() since servers_* arrays and hashes which
will be freed there are global static objects and thus are initialized
@@ -180,7 +179,7 @@ static bool servers_load(THD *thd, TABLE_LIST *tables)
my_hash_reset(&servers_cache);
free_root(&mem, MYF(0));
- init_alloc_root(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
+ init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
init_read_record(&read_record_info,thd,table=tables[0].table,NULL,1,0,
FALSE);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index b9f5015f8f0..3af0df73079 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1705,6 +1705,32 @@ public:
template class I_List<thread_info>;
#endif
+static const char *thread_state_info(THD *tmp)
+{
+ if (tmp->locked)
+ return "Locked";
+#ifndef EMBEDDED_LIBRARY
+ if (tmp->net.reading_or_writing)
+ {
+ if (tmp->net.reading_or_writing == 2)
+ return "Writing to net";
+ else if (tmp->command == COM_SLEEP)
+ return "";
+ else
+ return "Reading from net";
+ }
+ else
+#endif
+ {
+ if (tmp->proc_info)
+ return tmp->proc_info;
+ else if (tmp->mysys_var && tmp->mysys_var->current_cond)
+ return "Waiting on cond";
+ else
+ return NULL;
+ }
+}
+
void mysqld_list_processes(THD *thd,const char *user, bool verbose)
{
Item *field;
@@ -1766,20 +1792,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
if ((mysys_var= tmp->mysys_var))
pthread_mutex_lock(&mysys_var->mutex);
thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0);
-#ifndef EMBEDDED_LIBRARY
- thd_info->state_info= (char*) (tmp->locked ? "Locked" :
- tmp->net.reading_or_writing ?
- (tmp->net.reading_or_writing == 2 ?
- "Writing to net" :
- thd_info->command == COM_SLEEP ? "" :
- "Reading from net") :
- tmp->proc_info ? tmp->proc_info :
- tmp->mysys_var &&
- tmp->mysys_var->current_cond ?
- "Waiting on cond" : NullS);
-#else
- thd_info->state_info= (char*)"Writing to net";
-#endif
+ thd_info->state_info= thread_state_info(tmp);
if (mysys_var)
pthread_mutex_unlock(&mysys_var->mutex);
@@ -1891,21 +1904,7 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
table->field[5]->store((longlong)(tmp->start_time ?
now - tmp->start_time : 0), FALSE);
/* STATE */
-#ifndef EMBEDDED_LIBRARY
- val= (char*) (tmp->locked ? "Locked" :
- tmp->net.reading_or_writing ?
- (tmp->net.reading_or_writing == 2 ?
- "Writing to net" :
- tmp->command == COM_SLEEP ? "" :
- "Reading from net") :
- tmp->proc_info ? tmp->proc_info :
- tmp->mysys_var &&
- tmp->mysys_var->current_cond ?
- "Waiting on cond" : NullS);
-#else
- val= (char *) (tmp->proc_info ? tmp->proc_info : NullS);
-#endif
- if (val)
+ if ((val= thread_state_info(tmp)))
{
table->field[6]->store(val, strlen(val), cs);
table->field[6]->set_notnull();
@@ -5071,8 +5070,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
break;
default:
DBUG_ASSERT(0);
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- current_thd->fatal_error();
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
DBUG_RETURN(1);
}
table->field[7]->set_notnull();
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 593450cacd5..a0ea75a0b0a 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -23,6 +23,7 @@
#include <my_sys.h>
#include <m_string.h>
#include <m_ctype.h>
+#include <mysql_com.h>
#ifdef HAVE_FCONVERT
#include <floatingpoint.h>
#endif
@@ -499,22 +500,6 @@ bool String::append(const char *s,uint32 arg_length, CHARSET_INFO *cs)
return FALSE;
}
-
-#ifdef TO_BE_REMOVED
-bool String::append(FILE* file, uint32 arg_length, myf my_flags)
-{
- if (realloc(str_length+arg_length))
- return TRUE;
- if (my_fread(file, (uchar*) Ptr + str_length, arg_length, my_flags))
- {
- shrink(str_length);
- return TRUE;
- }
- str_length+=arg_length;
- return FALSE;
-}
-#endif
-
bool String::append(IO_CACHE* file, uint32 arg_length)
{
if (realloc(str_length+arg_length))
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 75dc1163eec..38f843e7e8f 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -22,10 +22,6 @@
#pragma interface /* gcc class implementation */
#endif
-#ifndef NOT_FIXED_DEC
-#define NOT_FIXED_DEC 31
-#endif
-
class String;
int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index aa2ed498de1..434d17d8e58 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -1660,7 +1660,7 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, char *db, char *name)
DBUG_ENTER("drop_all_triggers");
bzero(&table, sizeof(table));
- init_alloc_root(&table.mem_root, 8192, 0);
+ init_sql_alloc(&table.mem_root, 8192, 0);
if (Table_triggers_list::check_n_load(thd, db, name, &table, 1))
{
@@ -1871,7 +1871,7 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db,
DBUG_ENTER("change_table_name");
bzero(&table, sizeof(table));
- init_alloc_root(&table.mem_root, 8192, 0);
+ init_sql_alloc(&table.mem_root, 8192, 0);
/*
This method interfaces the mysql server code protected by
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index bc491fe3a9e..3a7309a0ea4 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -135,7 +135,6 @@ void udf_init()
initialized = 1;
new_thd->thread_stack= (char*) &new_thd;
new_thd->store_globals();
- lex_start(new_thd);
new_thd->set_db(db, sizeof(db)-1);
bzero((uchar*) &tables,sizeof(tables));
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 21d0243a403..798d68d6a00 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -662,11 +662,13 @@ int mysql_update(THD *thd,
If (ignore && error is ignorable) we don't have to
do anything; otherwise...
*/
+ myf flags= 0;
+
if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
- thd->fatal_error(); /* Other handler errors are fatal */
+ flags|= ME_FATALERROR; /* Other handler errors are fatal */
prepare_record_for_error_message(error, table);
- table->file->print_error(error,MYF(0));
+ table->file->print_error(error,MYF(flags));
error= 1;
break;
}
@@ -763,9 +765,8 @@ int mysql_update(THD *thd,
*/
{
/* purecov: begin inspected */
- thd->fatal_error();
prepare_record_for_error_message(loc_error, table);
- table->file->print_error(loc_error,MYF(0));
+ table->file->print_error(loc_error,MYF(ME_FATALERROR));
error= 1;
/* purecov: end */
}
@@ -1742,11 +1743,13 @@ bool multi_update::send_data(List<Item> &not_used_values)
If (ignore && error == is ignorable) we don't have to
do anything; otherwise...
*/
+ myf flags= 0;
+
if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
- thd->fatal_error(); /* Other handler errors are fatal */
+ flags|= ME_FATALERROR; /* Other handler errors are fatal */
prepare_record_for_error_message(error, table);
- table->file->print_error(error,MYF(0));
+ table->file->print_error(error,MYF(flags));
DBUG_RETURN(1);
}
}
@@ -2030,9 +2033,8 @@ int multi_update::do_updates()
err:
{
- thd->fatal_error();
prepare_record_for_error_message(local_error, table);
- table->file->print_error(local_error,MYF(0));
+ table->file->print_error(local_error,MYF(ME_FATALERROR));
}
err2:
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 337dc2c7359..7b264796b30 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -466,6 +466,90 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
DBUG_RETURN(result);
}
+/**
+ @brief Creates a new SELECT_LEX for a UNION branch.
+
+ Sets up and initializes a SELECT_LEX structure for a query once the parser
+ discovers a UNION token. The current SELECT_LEX is pushed on the stack and
+ the new SELECT_LEX becomes the current one.
+
+ @param lex The parser state.
+
+ @param is_union_distinct True if the union preceding the new select statement
+ uses UNION DISTINCT.
+
+ @param is_top_level This should be @c TRUE if the newly created SELECT_LEX
+ is a non-nested statement.
+
+ @return <code>false</code> if successful, <code>true</code> if an error was
+ reported. In the latter case parsing should stop.
+ */
+bool add_select_to_union_list(LEX *lex, bool is_union_distinct,
+ bool is_top_level)
+{
+ /*
+ Only the last SELECT can have INTO. Since the grammar won't allow INTO in
+ a nested SELECT, we make this check only when creating a top-level SELECT.
+ */
+ if (is_top_level && lex->result)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
+ return TRUE;
+ }
+ if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
+ {
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ return TRUE;
+ }
+ /* This counter shouldn't be incremented for UNION parts */
+ lex->nest_level--;
+ if (mysql_new_select(lex, 0))
+ return TRUE;
+ mysql_init_select(lex);
+ lex->current_select->linkage=UNION_TYPE;
+ if (is_union_distinct) /* UNION DISTINCT - remember position */
+ lex->current_select->master_unit()->union_distinct=
+ lex->current_select;
+ return FALSE;
+}
+
+/**
+ @brief Initializes a SELECT_LEX for a query within parentheses (aka
+ braces).
+
+ @return false if successful, true if an error was reported. In the latter
+ case parsing should stop.
+ */
+bool setup_select_in_parentheses(LEX *lex)
+{
+ SELECT_LEX * sel= lex->current_select;
+ if (sel->set_braces(1))
+ {
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ return TRUE;
+ }
+ if (sel->linkage == UNION_TYPE &&
+ !sel->master_unit()->first_select()->braces &&
+ sel->master_unit()->first_select()->linkage ==
+ UNION_TYPE)
+ {
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ return TRUE;
+ }
+ if (sel->linkage == UNION_TYPE &&
+ sel->olap != UNSPECIFIED_OLAP_TYPE &&
+ sel->master_unit()->fake_select_lex)
+ {
+ my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY");
+ return TRUE;
+ }
+ /* select in braces, can't contain global parameters */
+ if (sel->master_unit()->fake_select_lex)
+ sel->master_unit()->global_parameters=
+ sel->master_unit()->fake_select_lex;
+ return FALSE;
+}
+
%}
%union {
int num;
@@ -519,10 +603,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%pure_parser /* We have threads */
/*
- Currently there are 168 shift/reduce conflicts.
+ Currently there are 174 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
-%expect 168
+%expect 174
/*
Comments for TOKENS.
@@ -1192,7 +1276,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <item>
literal text_literal insert_ident order_ident
- simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
+ simple_ident expr opt_expr opt_else sum_expr in_sum_expr
variable variable_aux bool_pri
predicate bit_expr
table_wild simple_expr udf_expr
@@ -1235,6 +1319,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
join_table_list join_table
table_factor table_ref esc_table_ref
select_derived derived_table_list
+ select_derived_union
%type <date_time_type> date_time_type;
%type <interval> interval
@@ -1270,8 +1355,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <variable> internal_variable_name
-%type <select_lex> subselect take_first_select
- get_select_lex
+%type <select_lex> subselect
+ get_select_lex query_specification
+ query_expression_body
%type <boolfunc2creator> comp_op
@@ -1352,7 +1438,7 @@ END_OF_INPUT
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM
- THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM
+ THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM DELETE_SYM
%%
/*
@@ -6807,37 +6893,22 @@ select_init:
select_paren:
SELECT_SYM select_part2
{
- LEX *lex= Lex;
- SELECT_LEX * sel= lex->current_select;
- if (sel->set_braces(1))
- {
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ if (setup_select_in_parentheses(Lex))
MYSQL_YYABORT;
- }
- if (sel->linkage == UNION_TYPE &&
- !sel->master_unit()->first_select()->braces &&
- sel->master_unit()->first_select()->linkage ==
- UNION_TYPE)
- {
- my_parse_error(ER(ER_SYNTAX_ERROR));
- MYSQL_YYABORT;
- }
- if (sel->linkage == UNION_TYPE &&
- sel->olap != UNSPECIFIED_OLAP_TYPE &&
- sel->master_unit()->fake_select_lex)
- {
- my_error(ER_WRONG_USAGE, MYF(0),
- "CUBE/ROLLUP", "ORDER BY");
- MYSQL_YYABORT;
- }
- /* select in braces, can't contain global parameters */
- if (sel->master_unit()->fake_select_lex)
- sel->master_unit()->global_parameters=
- sel->master_unit()->fake_select_lex;
}
| '(' select_paren ')'
;
+/* The equivalent of select_paren for nested queries. */
+select_paren_derived:
+ SELECT_SYM select_part2_derived
+ {
+ if (setup_select_in_parentheses(Lex))
+ MYSQL_YYABORT;
+ }
+ | '(' select_paren_derived ')'
+ ;
+
select_init2:
select_part2
{
@@ -6998,7 +7069,14 @@ select_item_list:
;
select_item:
- remember_name select_item2 remember_end select_alias
+ remember_name table_wild remember_end
+ {
+ THD *thd= YYTHD;
+
+ if (add_item_to_list(thd, $2))
+ MYSQL_YYABORT;
+ }
+ | remember_name expr remember_end select_alias
{
THD *thd= YYTHD;
DBUG_ASSERT($1 < $3);
@@ -7035,11 +7113,6 @@ remember_end:
}
;
-select_item2:
- table_wild { $$=$1; /* table.* */ }
- | expr { $$=$1; }
- ;
-
select_alias:
/* empty */ { $$=null_lex_str;}
| AS ident { $$=$2; }
@@ -8676,6 +8749,7 @@ when_list:
}
;
+/* Equivalent to <table reference> in the SQL:2003 standard. */
/* Warning - may return NULL in case of incomplete SELECT */
table_ref:
table_factor { $$=$1; }
@@ -8703,6 +8777,7 @@ esc_table_ref:
| '{' ident table_ref '}' { $$=$3; }
;
+/* Equivalent to <table reference list> in the SQL:2003 standard. */
/* Warning - may return NULL in case of incomplete SELECT */
derived_table_list:
esc_table_ref { $$=$1; }
@@ -8856,6 +8931,13 @@ normal_join:
| CROSS JOIN_SYM {}
;
+/*
+ This is a flattening of the rules <table factor> and <table primary>
+ in the SQL:2003 standard, since we don't have <sample clause>
+
+ I.e.
+ <table factor> ::= <table primary> [ <sample clause> ]
+*/
/* Warning - may return NULL in case of incomplete SELECT */
table_factor:
{
@@ -8893,12 +8975,29 @@ table_factor:
/* incomplete derived tables return NULL, we must be
nested in select_derived rule to be here. */
}
- | '(' get_select_lex select_derived union_opt ')' opt_table_alias
+ /*
+ Represents a flattening of the following rules from the SQL:2003
+ standard. This sub-rule corresponds to the sub-rule
+ <table primary> ::= ... | <derived table> [ AS ] <correlation name>
+
+ The following rules have been flattened into query_expression_body
+ (since we have no <with clause>).
+
+ <derived table> ::= <table subquery>
+ <table subquery> ::= <subquery>
+ <subquery> ::= <left paren> <query expression> <right paren>
+ <query expression> ::= [ <with clause> ] <query expression body>
+
+ For the time being we use the non-standard rule
+ select_derived_union which is a compromise between the standard
+ and our parser. Possibly this rule could be replaced by our
+ query_expression_body.
+ */
+ | '(' get_select_lex select_derived_union ')' opt_table_alias
{
/* Use $2 instead of Lex->current_select as derived table will
alter value of Lex->current_select. */
-
- if (!($3 || $6) && $2->embedding &&
+ if (!($3 || $5) && $2->embedding &&
!$2->embedding->nested_join->join_list.elements)
{
/* we have a derived table ($3 == NULL) but no alias,
@@ -8920,7 +9019,7 @@ table_factor:
if (ti == NULL)
MYSQL_YYABORT;
if (!($$= sel->add_table_to_list(lex->thd,
- ti, $6, 0,
+ new Table_ident(unit), $5, 0,
TL_READ)))
MYSQL_YYABORT;
@@ -8928,7 +9027,8 @@ table_factor:
lex->pop_context();
lex->nest_level--;
}
- else if ($4 || $6)
+ else if ($3->select_lex &&
+ $3->select_lex->master_unit()->is_union() || $5)
{
/* simple nested joins cannot have aliases or unions */
my_parse_error(ER(ER_SYNTAX_ERROR));
@@ -8943,6 +9043,62 @@ table_factor:
}
;
+select_derived_union:
+ select_derived opt_order_clause opt_limit_clause
+ | select_derived_union
+ UNION_SYM
+ union_option
+ {
+ if (add_select_to_union_list(Lex, (bool)$3, FALSE))
+ MYSQL_YYABORT;
+ }
+ query_specification
+ {
+ /*
+ Remove from the name resolution context stack the context of the
+ last select in the union.
+ */
+ Lex->pop_context();
+ }
+ opt_order_clause opt_limit_clause
+ ;
+
+/* The equivalent of select_init2 for nested queries. */
+select_init2_derived:
+ select_part2_derived
+ {
+ LEX *lex= Lex;
+ SELECT_LEX * sel= lex->current_select;
+ if (lex->current_select->set_braces(0))
+ {
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ MYSQL_YYABORT;
+ }
+ if (sel->linkage == UNION_TYPE &&
+ sel->master_unit()->first_select()->braces)
+ {
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ MYSQL_YYABORT;
+ }
+ }
+ ;
+
+/* The equivalent of select_part2 for nested queries. */
+select_part2_derived:
+ {
+ LEX *lex= Lex;
+ SELECT_LEX *sel= lex->current_select;
+ if (sel->linkage != UNION_TYPE)
+ mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LIST;
+ }
+ select_options select_item_list
+ {
+ Select->parsing_place= NO_MATTER;
+ }
+ opt_select_from select_lock_type
+ ;
+
/* handle contents of parentheses in join expression */
select_derived:
get_select_lex
@@ -9557,8 +9713,7 @@ procedure_item:
select_var_list_init:
{
LEX *lex=Lex;
- if (!lex->describe &&
- (!(lex->result= new select_dumpvar(lex->nest_level))))
+ if (!lex->describe && (!(lex->result= new select_dumpvar())))
MYSQL_YYABORT;
}
select_var_list
@@ -9639,7 +9794,7 @@ into_destination:
LEX *lex= Lex;
lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
if (!(lex->exchange= new sql_exchange($2.str, 0)) ||
- !(lex->result= new select_export(lex->exchange, lex->nest_level)))
+ !(lex->result= new select_export(lex->exchange)))
MYSQL_YYABORT;
}
opt_load_data_charset
@@ -9653,7 +9808,7 @@ into_destination:
lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
if (!(lex->exchange= new sql_exchange($2.str,1)))
MYSQL_YYABORT;
- if (!(lex->result= new select_dump(lex->exchange, lex->nest_level)))
+ if (!(lex->result= new select_dump(lex->exchange)))
MYSQL_YYABORT;
}
}
@@ -10114,7 +10269,7 @@ delete:
lex->ignore= 0;
lex->select_lex.init_order();
}
- opt_delete_options single_multi {}
+ opt_delete_options single_multi
;
single_multi:
@@ -10129,45 +10284,45 @@ single_multi:
| table_wild_list
{ mysql_init_multi_delete(Lex); }
FROM join_table_list where_clause
- {
+ {
if (multi_delete_set_locks_and_link_aux_tables(Lex))
MYSQL_YYABORT;
}
| FROM table_alias_ref_list
{ mysql_init_multi_delete(Lex); }
USING join_table_list where_clause
- {
+ {
if (multi_delete_set_locks_and_link_aux_tables(Lex))
MYSQL_YYABORT;
}
;
table_wild_list:
- table_wild_one {}
- | table_wild_list ',' table_wild_one {}
+ table_wild_one
+ | table_wild_list ',' table_wild_one
;
table_wild_one:
- ident opt_wild opt_table_alias
+ ident opt_wild
{
Table_ident *ti= new Table_ident($1);
if (ti == NULL)
MYSQL_YYABORT;
if (!Select->add_table_to_list(YYTHD,
ti,
- $3,
+ NULL,
TL_OPTION_UPDATING | TL_OPTION_ALIAS,
Lex->lock_option))
MYSQL_YYABORT;
}
- | ident '.' ident opt_wild opt_table_alias
+ | ident '.' ident opt_wild
{
Table_ident *ti= new Table_ident(YYTHD, $1, $3, 0);
if (ti == NULL)
MYSQL_YYABORT;
if (!Select->add_table_to_list(YYTHD,
ti,
- $5,
+ NULL,
TL_OPTION_UPDATING | TL_OPTION_ALIAS,
Lex->lock_option))
MYSQL_YYABORT;
@@ -13272,33 +13427,8 @@ union_clause:
union_list:
UNION_SYM union_option
{
- LEX *lex=Lex;
- if (lex->result &&
- (lex->result->get_nest_level() == -1 ||
- lex->result->get_nest_level() == lex->nest_level))
- {
- /*
- Only the last SELECT can have INTO unless the INTO and UNION
- are at different nest levels. In version 5.1 and above, INTO
- will onle be allowed at top level.
- */
- my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
- MYSQL_YYABORT;
- }
- if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
- {
- my_parse_error(ER(ER_SYNTAX_ERROR));
+ if (add_select_to_union_list(Lex, (bool)$2, TRUE))
MYSQL_YYABORT;
- }
- /* This counter shouldn't be incremented for UNION parts */
- Lex->nest_level--;
- if (mysql_new_select(lex, 0))
- MYSQL_YYABORT;
- mysql_init_select(lex);
- lex->current_select->linkage=UNION_TYPE;
- if ($2) /* UNION DISTINCT - remember position */
- lex->current_select->master_unit()->union_distinct=
- lex->current_select;
}
select_init
{
@@ -13351,22 +13481,39 @@ union_option:
| ALL { $$=0; }
;
-take_first_select: /* empty */
- {
- $$= Lex->current_select->master_unit()->first_select();
- };
+query_specification:
+ SELECT_SYM select_init2_derived
+ {
+ $$= Lex->current_select->master_unit()->first_select();
+ }
+ | '(' select_paren_derived ')'
+ {
+ $$= Lex->current_select->master_unit()->first_select();
+ }
+ ;
+query_expression_body:
+ query_specification
+ | query_expression_body
+ UNION_SYM union_option
+ {
+ if (add_select_to_union_list(Lex, (bool)$3, FALSE))
+ MYSQL_YYABORT;
+ }
+ query_specification
+ {
+ Lex->pop_context();
+ $$= $1;
+ }
+ ;
+
+/* Corresponds to <query expression> in the SQL:2003 standard. */
subselect:
- SELECT_SYM subselect_start select_init2 take_first_select
- subselect_end
- {
- $$= $4;
- }
- | '(' subselect_start select_paren take_first_select
- subselect_end ')'
- {
- $$= $4;
- };
+ subselect_start query_expression_body subselect_end
+ {
+ $$= $2;
+ }
+ ;
subselect_start:
{
diff --git a/sql/table.cc b/sql/table.cc
index 22b4b2f9b5e..39a7e163c37 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1649,9 +1649,6 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str,
share->table_name.str, (long) outparam));
- /* Parsing of partitioning information from .frm needs thd->lex set up. */
- DBUG_ASSERT(thd->lex->is_lex_started);
-
error= 1;
bzero((char*) outparam, sizeof(*outparam));
outparam->in_use= thd;
diff --git a/sql/table.h b/sql/table.h
index 49a97958807..76bebd3fdaa 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1332,6 +1332,12 @@ struct TABLE_LIST
*/
bool create;
bool internal_tmp_table;
+ /** TRUE if an alias for this table was specified in the SQL. */
+ bool is_alias;
+ /** TRUE if the table is referred to in the statement using a fully
+ qualified name (<db_name>.<table_name>).
+ */
+ bool is_fqtn;
/* View creation context. */
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 650678c721b..8740a8ec906 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1578,7 +1578,6 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
DBUG_RETURN(1);
thd->thread_stack= (char*) &thd;
thd->store_globals();
- lex_start(thd);
/* Init all memory structures that require explicit destruction */
if (my_hash_init(&tz_names, &my_charset_latin1, 20,
@@ -1594,7 +1593,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
my_hash_free(&tz_names);
goto end;
}
- init_alloc_root(&tz_storage, 32 * 1024, 0);
+ init_sql_alloc(&tz_storage, 32 * 1024, 0);
VOID(pthread_mutex_init(&tz_LOCK, MY_MUTEX_INIT_FAST));
tz_inited= 1;