summaryrefslogtreecommitdiff
path: root/sql/item_func.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item_func.cc')
-rw-r--r--sql/item_func.cc830
1 files changed, 352 insertions, 478 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc
index ed457adcff9..4df7638370a 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -769,13 +769,14 @@ void Item_num_op::find_num_type(void)
{
hybrid_type= DECIMAL_RESULT;
result_precision();
+ fix_decimals();
}
else
{
DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
- decimals= 0;
hybrid_type=INT_RESULT;
result_precision();
+ decimals= 0;
}
DBUG_PRINT("info", ("Type: %s",
(hybrid_type == REAL_RESULT ? "REAL_RESULT" :
@@ -1706,6 +1707,7 @@ void Item_func_div::fix_length_and_dec()
break;
case DECIMAL_RESULT:
result_precision();
+ fix_decimals();
break;
case STRING_RESULT:
case ROW_RESULT:
@@ -1905,6 +1907,16 @@ longlong Item_func_neg::int_op()
if (args[0]->unsigned_flag &&
(ulonglong) value > (ulonglong) LONGLONG_MAX + 1)
return raise_integer_overflow();
+
+ if (value == LONGLONG_MIN)
+ {
+ if (args[0]->unsigned_flag != unsigned_flag)
+ /* negation of LONGLONG_MIN is LONGLONG_MIN. */
+ return LONGLONG_MIN;
+ else
+ return raise_integer_overflow();
+ }
+
return check_integer_overflow(-value, !args[0]->unsigned_flag && value < 0);
}
@@ -2201,7 +2213,7 @@ longlong Item_func_shift_left::val_int()
return 0;
}
null_value=0;
- return (shift < sizeof(longlong)*8 ? (longlong) res : LL(0));
+ return (shift < sizeof(longlong)*8 ? (longlong) res : 0);
}
longlong Item_func_shift_right::val_int()
@@ -2216,7 +2228,7 @@ longlong Item_func_shift_right::val_int()
return 0;
}
null_value=0;
- return (shift < sizeof(longlong)*8 ? (longlong) res : LL(0));
+ return (shift < sizeof(longlong)*8 ? (longlong) res : 0);
}
@@ -3149,7 +3161,7 @@ void Item_func_find_in_set::fix_length_and_dec()
find->length(), 0);
enum_bit=0;
if (enum_value)
- enum_bit=LL(1) << (enum_value-1);
+ enum_bit=1LL << (enum_value-1);
}
}
}
@@ -3230,7 +3242,7 @@ longlong Item_func_find_in_set::val_int()
wc == (my_wc_t) separator)
return (longlong) ++position;
else
- return LL(0);
+ return 0;
}
}
return 0;
@@ -3736,120 +3748,6 @@ udf_handler::~udf_handler()
bool udf_handler::get_arguments() { return 0; }
#endif /* HAVE_DLOPEN */
-/*
-** User level locks
-*/
-
-mysql_mutex_t LOCK_user_locks;
-static HASH hash_user_locks;
-
-class User_level_lock
-{
- uchar *key;
- size_t key_length;
-
-public:
- int count;
- bool locked;
- mysql_cond_t cond;
- my_thread_id thread_id;
- void set_thread(THD *thd) { thread_id= thd->thread_id; }
-
- User_level_lock(const uchar *key_arg,uint length, ulong id)
- :key_length(length),count(1),locked(1), thread_id(id)
- {
- key= (uchar*) my_memdup(key_arg,length,MYF(0));
- mysql_cond_init(key_user_level_lock_cond, &cond, NULL);
- if (key)
- {
- if (my_hash_insert(&hash_user_locks,(uchar*) this))
- {
- my_free(key);
- key=0;
- }
- }
- }
- ~User_level_lock()
- {
- if (key)
- {
- my_hash_delete(&hash_user_locks,(uchar*) this);
- my_free(key);
- }
- mysql_cond_destroy(&cond);
- }
- inline bool initialized() { return key != 0; }
- friend void item_user_lock_release(User_level_lock *ull);
- friend uchar *ull_get_key(const User_level_lock *ull, size_t *length,
- my_bool not_used);
-};
-
-uchar *ull_get_key(const User_level_lock *ull, size_t *length,
- my_bool not_used __attribute__((unused)))
-{
- *length= ull->key_length;
- return ull->key;
-}
-
-#ifdef HAVE_PSI_INTERFACE
-static PSI_mutex_key key_LOCK_user_locks;
-
-static PSI_mutex_info all_user_mutexes[]=
-{
- { &key_LOCK_user_locks, "LOCK_user_locks", PSI_FLAG_GLOBAL}
-};
-
-static void init_user_lock_psi_keys(void)
-{
- const char* category= "sql";
- int count;
-
- if (PSI_server == NULL)
- return;
-
- count= array_elements(all_user_mutexes);
- PSI_server->register_mutex(category, all_user_mutexes, count);
-}
-#endif
-
-static bool item_user_lock_inited= 0;
-
-void item_user_lock_init(void)
-{
-#ifdef HAVE_PSI_INTERFACE
- init_user_lock_psi_keys();
-#endif
-
- mysql_mutex_init(key_LOCK_user_locks, &LOCK_user_locks, MY_MUTEX_INIT_SLOW);
- my_hash_init(&hash_user_locks,system_charset_info,
- 16,0,0,(my_hash_get_key) ull_get_key,NULL,0);
- item_user_lock_inited= 1;
-}
-
-void item_user_lock_free(void)
-{
- if (item_user_lock_inited)
- {
- item_user_lock_inited= 0;
- my_hash_free(&hash_user_locks);
- mysql_mutex_destroy(&LOCK_user_locks);
- }
-}
-
-void item_user_lock_release(User_level_lock *ull)
-{
- ull->locked=0;
- ull->thread_id= 0;
- if (--ull->count)
- mysql_cond_signal(&ull->cond);
- else
- delete ull;
-}
-
-/**
- Wait until we are at or past the given position in the master binlog
- on the slave.
-*/
longlong Item_master_pos_wait::val_int()
{
@@ -3951,7 +3849,7 @@ class Interruptible_wait
/** Time to wait before polling the connection status. */
-const ulonglong Interruptible_wait::m_interrupt_interval= 5 * ULL(1000000000);
+const ulonglong Interruptible_wait::m_interrupt_interval= 5 * 1000000000ULL;
/**
@@ -3996,7 +3894,136 @@ int Interruptible_wait::wait(mysql_cond_t *cond, mysql_mutex_t *mutex)
/**
- Get a user level lock. If the thread has an old lock this is first released.
+ For locks with EXPLICIT duration, MDL returns a new ticket
+ every time a lock is granted. This allows to implement recursive
+ locks without extra allocation or additional data structures, such
+ as below. However, if there are too many tickets in the same
+ MDL_context, MDL_context::find_ticket() is getting too slow,
+ since it's using a linear search.
+ This is why a separate structure is allocated for a user
+ level lock, and before requesting a new lock from MDL,
+ GET_LOCK() checks thd->ull_hash if such lock is already granted,
+ and if so, simply increments a reference counter.
+*/
+
+class User_level_lock
+{
+public:
+ MDL_ticket *lock;
+ int refs;
+};
+
+
+/** Extract a hash key from User_level_lock. */
+
+uchar *ull_get_key(const uchar *ptr, size_t *length,
+ my_bool not_used __attribute__((unused)))
+{
+ User_level_lock *ull = (User_level_lock*) ptr;
+ MDL_key *key = ull->lock->get_key();
+ *length= key->length();
+ return (uchar*) key->ptr();
+}
+
+
+/**
+ Release all user level locks for this THD.
+*/
+
+void mysql_ull_cleanup(THD *thd)
+{
+ User_level_lock *ull;
+ DBUG_ENTER("mysql_ull_cleanup");
+
+ for (uint i= 0; i < thd->ull_hash.records; i++)
+ {
+ ull = (User_level_lock*) my_hash_element(&thd->ull_hash, i);
+ thd->mdl_context.release_lock(ull->lock);
+ my_free(ull);
+ }
+
+ my_hash_free(&thd->ull_hash);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ Set explicit duration for metadata locks corresponding to
+ user level locks to protect them from being released at the end
+ of transaction.
+*/
+
+void mysql_ull_set_explicit_lock_duration(THD *thd)
+{
+ User_level_lock *ull;
+ DBUG_ENTER("mysql_ull_set_explicit_lock_duration");
+
+ for (uint i= 0; i < thd->ull_hash.records; i++)
+ {
+ ull= (User_level_lock*) my_hash_element(&thd->ull_hash, i);
+ thd->mdl_context.set_lock_duration(ull->lock, MDL_EXPLICIT);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ When MDL detects a lock wait timeout, it pushes
+ an error into the statement diagnostics area.
+ For GET_LOCK(), lock wait timeout is not an error,
+ but a special return value (0). NULL is returned in
+ case of error.
+ Capture and suppress lock wait timeout.
+*/
+
+class Lock_wait_timeout_handler: public Internal_error_handler
+{
+public:
+ Lock_wait_timeout_handler() :m_lock_wait_timeout(false) {}
+
+ bool m_lock_wait_timeout;
+
+ bool handle_condition(THD * /* thd */, uint sql_errno,
+ const char * /* sqlstate */,
+ MYSQL_ERROR::enum_warning_level /* level */,
+ const char *message,
+ MYSQL_ERROR ** /* cond_hdl */);
+};
+
+bool
+Lock_wait_timeout_handler::
+handle_condition(THD * /* thd */, uint sql_errno,
+ const char * /* sqlstate */,
+ MYSQL_ERROR::enum_warning_level /* level */,
+ const char *message,
+ MYSQL_ERROR ** /* cond_hdl */)
+{
+ if (sql_errno == ER_LOCK_WAIT_TIMEOUT)
+ {
+ m_lock_wait_timeout= true;
+ return true; /* condition handled */
+ }
+ return false;
+}
+
+
+static int ull_name_ok(String *name)
+{
+ if (!name || !name->length())
+ return 0;
+
+ if (name->length() > NAME_LEN)
+ {
+ my_error(ER_TOO_LONG_IDENT, MYF(0), name->c_ptr_safe());
+ return 0;
+ }
+ return 1;
+}
+
+
+/**
+ Get a user level lock.
@retval
1 : Got lock
@@ -4009,14 +4036,13 @@ int Interruptible_wait::wait(mysql_cond_t *cond, mysql_mutex_t *mutex)
longlong Item_func_get_lock::val_int()
{
DBUG_ASSERT(fixed == 1);
- String *res=args[0]->val_str(&value);
+ String *res= args[0]->val_str(&value);
ulonglong timeout= args[1]->val_int();
- THD *thd=current_thd;
+ THD *thd= current_thd;
User_level_lock *ull;
- int error;
- Interruptible_wait timed_cond(thd);
DBUG_ENTER("Item_func_get_lock::val_int");
+ null_value= 1;
/*
In slave thread no need to get locks, everything is serialized. Anyway
there is no way to make GET_LOCK() work on slave like it did on master
@@ -4025,103 +4051,70 @@ longlong Item_func_get_lock::val_int()
it's not guaranteed to be same as on master.
*/
if (thd->slave_thread)
+ {
+ null_value= 0;
DBUG_RETURN(1);
+ }
- mysql_mutex_lock(&LOCK_user_locks);
-
- if (!res || !res->length())
- {
- mysql_mutex_unlock(&LOCK_user_locks);
- null_value=1;
+ if (!ull_name_ok(res))
DBUG_RETURN(0);
- }
+
DBUG_PRINT("info", ("lock %.*s, thd=%ld", res->length(), res->ptr(),
(long) thd->real_id));
- null_value=0;
-
- if (thd->ull)
+ /* HASH entries are of type User_level_lock. */
+ if (! my_hash_inited(&thd->ull_hash) &&
+ my_hash_init(&thd->ull_hash, &my_charset_bin,
+ 16 /* small hash */, 0, 0, ull_get_key, NULL, 0))
{
- item_user_lock_release(thd->ull);
- thd->ull=0;
- }
-
- if (!(ull= ((User_level_lock *) my_hash_search(&hash_user_locks,
- (uchar*) res->ptr(),
- (size_t) res->length()))))
- {
- ull= new User_level_lock((uchar*) res->ptr(), (size_t) res->length(),
- thd->thread_id);
- if (!ull || !ull->initialized())
- {
- delete ull;
- mysql_mutex_unlock(&LOCK_user_locks);
- null_value=1; // Probably out of memory
- DBUG_RETURN(0);
- }
- ull->set_thread(thd);
- thd->ull=ull;
- mysql_mutex_unlock(&LOCK_user_locks);
- DBUG_PRINT("info", ("made new lock"));
- DBUG_RETURN(1); // Got new lock
+ DBUG_RETURN(0);
}
- ull->count++;
- DBUG_PRINT("info", ("ull->count=%d", ull->count));
- /*
- Structure is now initialized. Try to get the lock.
- Set up control struct to allow others to abort locks.
- */
- THD_STAGE_INFO(thd, stage_user_lock);
- thd->mysys_var->current_mutex= &LOCK_user_locks;
- thd->mysys_var->current_cond= &ull->cond;
+ MDL_request ull_request;
+ ull_request.init(MDL_key::USER_LOCK, res->c_ptr_safe(), "",
+ MDL_SHARED_NO_WRITE, MDL_EXPLICIT);
+ MDL_key *ull_key = &ull_request.key;
- timed_cond.set_timeout(timeout * ULL(1000000000));
- error= 0;
- thd_wait_begin(thd, THD_WAIT_USER_LOCK);
- while (ull->locked && !thd->killed)
+ if ((ull= (User_level_lock*)
+ my_hash_search(&thd->ull_hash, ull_key->ptr(), ull_key->length())))
{
- DBUG_PRINT("info", ("waiting on lock"));
- error= timed_cond.wait(&ull->cond, &LOCK_user_locks);
- if (error == ETIMEDOUT || error == ETIME)
- {
- DBUG_PRINT("info", ("lock wait timeout"));
- break;
- }
- error= 0;
+ /* Recursive lock */
+ ull->refs++;
+ null_value = 0;
+ DBUG_RETURN(1);
}
- thd_wait_end(thd);
- if (ull->locked)
+ Lock_wait_timeout_handler lock_wait_timeout_handler;
+ thd->push_internal_handler(&lock_wait_timeout_handler);
+ bool error= thd->mdl_context.acquire_lock(&ull_request, timeout);
+ (void) thd->pop_internal_handler();
+ if (error)
{
- if (!--ull->count)
- {
- DBUG_ASSERT(0);
- delete ull; // Should never happen
- }
- if (!error) // Killed (thd->killed != 0)
- {
- error=1;
- null_value=1; // Return NULL
- }
+ if (lock_wait_timeout_handler.m_lock_wait_timeout)
+ null_value= 0;
+ DBUG_RETURN(0);
}
- else // We got the lock
+
+ ull= (User_level_lock*) my_malloc(sizeof(User_level_lock),
+ MYF(MY_WME|MY_THREAD_SPECIFIC));
+ if (ull == NULL)
{
- ull->locked=1;
- ull->set_thread(thd);
- ull->thread_id= thd->thread_id;
- thd->ull=ull;
- error=0;
- DBUG_PRINT("info", ("got the lock"));
+ thd->mdl_context.release_lock(ull_request.ticket);
+ DBUG_RETURN(0);
}
- mysql_mutex_unlock(&LOCK_user_locks);
- mysql_mutex_lock(&thd->mysys_var->mutex);
- thd->mysys_var->current_mutex= 0;
- thd->mysys_var->current_cond= 0;
- mysql_mutex_unlock(&thd->mysys_var->mutex);
+ ull->lock= ull_request.ticket;
+ ull->refs= 1;
+
+ if (my_hash_insert(&thd->ull_hash, (uchar*) ull))
+ {
+ thd->mdl_context.release_lock(ull->lock);
+ my_free(ull);
+ DBUG_RETURN(0);
+ }
+ null_value= 0;
- DBUG_RETURN(!error ? 1 : 0);
+ DBUG_RETURN(1);
}
@@ -4136,43 +4129,86 @@ longlong Item_func_get_lock::val_int()
longlong Item_func_release_lock::val_int()
{
DBUG_ASSERT(fixed == 1);
- String *res=args[0]->val_str(&value);
- User_level_lock *ull;
- longlong result;
- THD *thd=current_thd;
+ String *res= args[0]->val_str(&value);
+ THD *thd= current_thd;
DBUG_ENTER("Item_func_release_lock::val_int");
- if (!res || !res->length())
- {
- null_value=1;
+ null_value= 1;
+
+ if (!ull_name_ok(res))
DBUG_RETURN(0);
- }
+
DBUG_PRINT("info", ("lock %.*s", res->length(), res->ptr()));
- null_value=0;
- result=0;
- mysql_mutex_lock(&LOCK_user_locks);
- if (!(ull= ((User_level_lock*) my_hash_search(&hash_user_locks,
- (const uchar*) res->ptr(),
- (size_t) res->length()))))
+ MDL_key ull_key;
+ ull_key.mdl_key_init(MDL_key::USER_LOCK, res->c_ptr_safe(), "");
+
+ User_level_lock *ull;
+
+ if (!(ull=
+ (User_level_lock*) my_hash_search(&thd->ull_hash,
+ ull_key.ptr(), ull_key.length())))
{
- null_value=1;
+ null_value= thd->mdl_context.get_lock_owner(&ull_key) == 0;
+ DBUG_RETURN(0);
}
- else
+ null_value= 0;
+ if (--ull->refs == 0)
{
- DBUG_PRINT("info", ("ull->locked=%d ull->thread=%lu thd=%lu",
- (int) ull->locked,
- (long)ull->thread_id,
- (long)thd->thread_id));
- if (ull->locked && current_thd->thread_id == ull->thread_id)
- {
- DBUG_PRINT("info", ("release lock"));
- result=1; // Release is ok
- item_user_lock_release(ull);
- thd->ull=0;
- }
+ my_hash_delete(&thd->ull_hash, (uchar*) ull);
+ thd->mdl_context.release_lock(ull->lock);
+ my_free(ull);
}
- mysql_mutex_unlock(&LOCK_user_locks);
- DBUG_RETURN(result);
+ DBUG_RETURN(1);
+}
+
+
+/**
+ Check a user level lock.
+
+ Sets null_value=TRUE on error.
+
+ @retval
+ 1 Available
+ @retval
+ 0 Already taken, or error
+*/
+
+longlong Item_func_is_free_lock::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ String *res= args[0]->val_str(&value);
+ THD *thd= current_thd;
+ null_value= 1;
+
+ if (!ull_name_ok(res))
+ return 0;
+
+ MDL_key ull_key;
+ ull_key.mdl_key_init(MDL_key::USER_LOCK, res->c_ptr_safe(), "");
+
+ null_value= 0;
+ return thd->mdl_context.get_lock_owner(&ull_key) == 0;
+}
+
+
+longlong Item_func_is_used_lock::val_int()
+{
+ DBUG_ASSERT(fixed == 1);
+ String *res= args[0]->val_str(&value);
+ THD *thd= current_thd;
+ null_value= 1;
+
+ if (!ull_name_ok(res))
+ return 0;
+
+ MDL_key ull_key;
+ ull_key.mdl_key_init(MDL_key::USER_LOCK, res->c_ptr_safe(), "");
+ ulong thread_id = thd->mdl_context.get_lock_owner(&ull_key);
+ if (thread_id == 0)
+ return 0;
+
+ null_value= 0;
+ return thread_id;
}
@@ -4273,6 +4309,54 @@ void Item_func_benchmark::print(String *str, enum_query_type query_type)
}
+mysql_mutex_t LOCK_item_func_sleep;
+
+#ifdef HAVE_PSI_INTERFACE
+static PSI_mutex_key key_LOCK_item_func_sleep;
+
+static PSI_mutex_info item_func_sleep_mutexes[]=
+{
+ { &key_LOCK_item_func_sleep, "LOCK_user_locks", PSI_FLAG_GLOBAL}
+};
+
+
+static void init_item_func_sleep_psi_keys(void)
+{
+ const char* category= "sql";
+ int count;
+
+ if (PSI_server == NULL)
+ return;
+
+ count= array_elements(item_func_sleep_mutexes);
+ PSI_server->register_mutex(category, item_func_sleep_mutexes, count);
+}
+#endif
+
+static bool item_func_sleep_inited= 0;
+
+
+void item_func_sleep_init(void)
+{
+#ifdef HAVE_PSI_INTERFACE
+ init_item_func_sleep_psi_keys();
+#endif
+
+ mysql_mutex_init(key_LOCK_item_func_sleep, &LOCK_item_func_sleep, MY_MUTEX_INIT_SLOW);
+ item_func_sleep_inited= 1;
+}
+
+
+void item_func_sleep_free(void)
+{
+ if (item_func_sleep_inited)
+ {
+ item_func_sleep_inited= 0;
+ mysql_mutex_destroy(&LOCK_item_func_sleep);
+ }
+}
+
+
/** This function is just used to create tests with time gaps. */
longlong Item_func_sleep::val_int()
@@ -4301,23 +4385,23 @@ longlong Item_func_sleep::val_int()
timed_cond.set_timeout((ulonglong) (timeout * 1000000000.0));
mysql_cond_init(key_item_func_sleep_cond, &cond, NULL);
- mysql_mutex_lock(&LOCK_user_locks);
+ mysql_mutex_lock(&LOCK_item_func_sleep);
THD_STAGE_INFO(thd, stage_user_sleep);
- thd->mysys_var->current_mutex= &LOCK_user_locks;
+ thd->mysys_var->current_mutex= &LOCK_item_func_sleep;
thd->mysys_var->current_cond= &cond;
error= 0;
thd_wait_begin(thd, THD_WAIT_SLEEP);
while (!thd->killed)
{
- error= timed_cond.wait(&cond, &LOCK_user_locks);
+ error= timed_cond.wait(&cond, &LOCK_item_func_sleep);
if (error == ETIMEDOUT || error == ETIME)
break;
error= 0;
}
thd_wait_end(thd);
- mysql_mutex_unlock(&LOCK_user_locks);
+ mysql_mutex_unlock(&LOCK_item_func_sleep);
mysql_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= 0;
thd->mysys_var->current_cond= 0;
@@ -4653,7 +4737,7 @@ double user_var_entry::val_real(bool *null_value)
longlong user_var_entry::val_int(bool *null_value) const
{
if ((*null_value= (value == 0)))
- return LL(0);
+ return 0;
switch (type) {
case REAL_RESULT:
@@ -4677,7 +4761,7 @@ longlong user_var_entry::val_int(bool *null_value) const
DBUG_ASSERT(0); // Impossible
break;
}
- return LL(0); // Impossible
+ return 0; // Impossible
}
@@ -4815,7 +4899,7 @@ void Item_func_set_user_var::save_item_result(Item *item)
{
DBUG_ENTER("Item_func_set_user_var::save_item_result");
- switch (cached_result_type) {
+ switch (args[0]->result_type()) {
case REAL_RESULT:
save_result.vreal= item->val_result();
break;
@@ -5170,7 +5254,7 @@ longlong Item_func_get_user_var::val_int()
{
DBUG_ASSERT(fixed == 1);
if (!var_entry)
- return LL(0); // No such variable
+ return 0; // No such variable
return (var_entry->val_int(&null_value));
}
@@ -5652,24 +5736,6 @@ enum_field_types Item_func_get_system_var::field_type() const
}
-/*
- Uses var, var_type, component, cache_present, used_query_id, thd,
- cached_llval, null_value, cached_null_value
-*/
-#define get_sys_var_safe(type) \
-do { \
- type value; \
- mysql_mutex_lock(&LOCK_global_system_variables); \
- value= *(type*) var->value_ptr(thd, var_type, &component); \
- mysql_mutex_unlock(&LOCK_global_system_variables); \
- cache_present |= GET_SYS_VAR_CACHE_LONG; \
- used_query_id= thd->query_id; \
- cached_llval= null_value ? 0 : (longlong) value; \
- cached_null_value= null_value; \
- return cached_llval; \
-} while (0)
-
-
longlong Item_func_get_system_var::val_int()
{
THD *thd= current_thd;
@@ -5703,51 +5769,11 @@ longlong Item_func_get_system_var::val_int()
}
}
- switch (var->show_type())
- {
- case SHOW_SINT: get_sys_var_safe (int);
- case SHOW_SLONG: get_sys_var_safe (long);
- case SHOW_SLONGLONG:get_sys_var_safe (longlong);
- case SHOW_UINT: get_sys_var_safe (uint);
- case SHOW_ULONG: get_sys_var_safe (ulong);
- case SHOW_ULONGLONG:get_sys_var_safe (ulonglong);
- case SHOW_HA_ROWS: get_sys_var_safe (ha_rows);
- case SHOW_BOOL: get_sys_var_safe (bool);
- case SHOW_MY_BOOL: get_sys_var_safe (my_bool);
- case SHOW_DOUBLE:
- {
- double dval= val_real();
-
- used_query_id= thd->query_id;
- cached_llval= (longlong) dval;
- cache_present|= GET_SYS_VAR_CACHE_LONG;
- return cached_llval;
- }
- case SHOW_CHAR:
- case SHOW_CHAR_PTR:
- case SHOW_LEX_STRING:
- {
- String *str_val= val_str(NULL);
-
- if (str_val && str_val->length())
- cached_llval= longlong_from_string_with_check (system_charset_info,
- str_val->c_ptr(),
- str_val->c_ptr() +
- str_val->length());
- else
- {
- null_value= TRUE;
- cached_llval= 0;
- }
-
- cache_present|= GET_SYS_VAR_CACHE_LONG;
- return cached_llval;
- }
-
- default:
- my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
- return 0; // keep the compiler happy
- }
+ cached_llval= var->val_int(&null_value, thd, var_type, &component);
+ cache_present |= GET_SYS_VAR_CACHE_LONG;
+ used_query_id= thd->query_id;
+ cached_null_value= null_value;
+ return cached_llval;
}
@@ -5780,61 +5806,10 @@ String* Item_func_get_system_var::val_str(String* str)
}
}
- str= &cached_strval;
- switch (var->show_type())
- {
- case SHOW_CHAR:
- case SHOW_CHAR_PTR:
- case SHOW_LEX_STRING:
- {
- mysql_mutex_lock(&LOCK_global_system_variables);
- char *cptr= var->show_type() == SHOW_CHAR ?
- (char*) var->value_ptr(thd, var_type, &component) :
- *(char**) var->value_ptr(thd, var_type, &component);
- if (cptr)
- {
- size_t len= var->show_type() == SHOW_LEX_STRING ?
- ((LEX_STRING*)(var->value_ptr(thd, var_type, &component)))->length :
- strlen(cptr);
- if (str->copy(cptr, len, collation.collation))
- {
- null_value= TRUE;
- str= NULL;
- }
- }
- else
- {
- null_value= TRUE;
- str= NULL;
- }
- mysql_mutex_unlock(&LOCK_global_system_variables);
- break;
- }
-
- case SHOW_SINT:
- case SHOW_SLONG:
- case SHOW_SLONGLONG:
- case SHOW_UINT:
- case SHOW_ULONG:
- case SHOW_ULONGLONG:
- case SHOW_HA_ROWS:
- case SHOW_BOOL:
- case SHOW_MY_BOOL:
- str->set (val_int(), collation.collation);
- break;
- case SHOW_DOUBLE:
- str->set_real (val_real(), decimals, collation.collation);
- break;
-
- default:
- my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
- str= NULL;
- break;
- }
-
+ str= var->val_str(&cached_strval, thd, var_type, &component);
cache_present|= GET_SYS_VAR_CACHE_STRING;
used_query_id= thd->query_id;
- cached_null_value= null_value;
+ cached_null_value= null_value= !str;
return str;
}
@@ -5872,58 +5847,11 @@ double Item_func_get_system_var::val_real()
}
}
- switch (var->show_type())
- {
- case SHOW_DOUBLE:
- mysql_mutex_lock(&LOCK_global_system_variables);
- cached_dval= *(double*) var->value_ptr(thd, var_type, &component);
- mysql_mutex_unlock(&LOCK_global_system_variables);
- used_query_id= thd->query_id;
- cached_null_value= null_value;
- if (null_value)
- cached_dval= 0;
- cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
- return cached_dval;
- case SHOW_CHAR:
- case SHOW_LEX_STRING:
- case SHOW_CHAR_PTR:
- {
- mysql_mutex_lock(&LOCK_global_system_variables);
- char *cptr= var->show_type() == SHOW_CHAR ?
- (char*) var->value_ptr(thd, var_type, &component) :
- *(char**) var->value_ptr(thd, var_type, &component);
- if (cptr)
- cached_dval= double_from_string_with_check (system_charset_info,
- cptr, cptr + strlen (cptr));
- else
- {
- null_value= TRUE;
- cached_dval= 0;
- }
- mysql_mutex_unlock(&LOCK_global_system_variables);
- used_query_id= thd->query_id;
- cached_null_value= null_value;
- cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
- return cached_dval;
- }
- case SHOW_SINT:
- case SHOW_SLONG:
- case SHOW_SLONGLONG:
- case SHOW_UINT:
- case SHOW_ULONG:
- case SHOW_ULONGLONG:
- case SHOW_HA_ROWS:
- case SHOW_BOOL:
- case SHOW_MY_BOOL:
- cached_dval= (double) val_int();
- cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
- used_query_id= thd->query_id;
- cached_null_value= null_value;
- return cached_dval;
- default:
- my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
- return 0;
- }
+ cached_dval= var->val_real(&null_value, thd, var_type, &component);
+ cache_present |= GET_SYS_VAR_CACHE_DOUBLE;
+ used_query_id= thd->query_id;
+ cached_null_value= null_value;
+ return cached_dval;
}
@@ -6009,15 +5937,12 @@ void Item_func_match::init_search(bool no_order)
{
DBUG_ENTER("Item_func_match::init_search");
+ if (!table->file->get_table()) // the handler isn't opened yet
+ DBUG_VOID_RETURN;
+
/* Check if init_search() has been called before */
if (ft_handler)
{
- /*
- We should reset ft_handler as it is cleaned up
- on destruction of FT_SELECT object
- (necessary in case of re-execution of subquery).
- TODO: FT_SELECT should not clean up ft_handler.
- */
if (join_key)
table->file->ft_handler= ft_handler;
DBUG_VOID_RETURN;
@@ -6026,10 +5951,10 @@ void Item_func_match::init_search(bool no_order)
if (key == NO_SUCH_KEY)
{
List<Item> fields;
- fields.push_back(new Item_string(" ",1, cmp_collation.collation));
- for (uint i=1; i < arg_count; i++)
+ fields.push_back(new Item_string(" ", 1, cmp_collation.collation));
+ for (uint i= 1; i < arg_count; i++)
fields.push_back(args[i]);
- concat_ws=new Item_func_concat_ws(fields);
+ concat_ws= new Item_func_concat_ws(fields);
/*
Above function used only to get value and do not need fix_fields for it:
Item_string - basic constant
@@ -6041,10 +5966,10 @@ void Item_func_match::init_search(bool no_order)
if (master)
{
- join_key=master->join_key=join_key|master->join_key;
+ join_key= master->join_key= join_key | master->join_key;
master->init_search(no_order);
- ft_handler=master->ft_handler;
- join_key=master->join_key;
+ ft_handler= master->ft_handler;
+ join_key= master->join_key;
DBUG_VOID_RETURN;
}
@@ -6054,7 +5979,7 @@ void Item_func_match::init_search(bool no_order)
if (!(ft_tmp=key_item()->val_str(&value)))
{
ft_tmp= &value;
- value.set("",0,cmp_collation.collation);
+ value.set("", 0, cmp_collation.collation);
}
if (ft_tmp->charset() != cmp_collation.collation)
@@ -6067,7 +5992,11 @@ void Item_func_match::init_search(bool no_order)
if (join_key && !no_order)
flags|=FT_SORTED;
- ft_handler=table->file->ft_init_ext(flags, key, ft_tmp);
+
+ if (key != NO_SUCH_KEY)
+ THD_STAGE_INFO(table->in_use, stage_fulltext_initialization);
+
+ ft_handler= table->file->ft_init_ext(flags, key, ft_tmp);
if (join_key)
table->file->ft_handler=ft_handler;
@@ -6127,7 +6056,7 @@ bool Item_func_match::fix_fields(THD *thd, Item **ref)
table=((Item_field *)item)->field->table;
if (!(table->file->ha_table_flags() & HA_CAN_FULLTEXT))
{
- my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
+ my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0), table->file->table_type());
return 1;
}
table->fulltext_searched=1;
@@ -6348,61 +6277,6 @@ Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
}
-/**
- Check a user level lock.
-
- Sets null_value=TRUE on error.
-
- @retval
- 1 Available
- @retval
- 0 Already taken, or error
-*/
-
-longlong Item_func_is_free_lock::val_int()
-{
- DBUG_ASSERT(fixed == 1);
- String *res=args[0]->val_str(&value);
- User_level_lock *ull;
-
- null_value=0;
- if (!res || !res->length())
- {
- null_value=1;
- return 0;
- }
-
- mysql_mutex_lock(&LOCK_user_locks);
- ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(),
- (size_t) res->length());
- mysql_mutex_unlock(&LOCK_user_locks);
- if (!ull || !ull->locked)
- return 1;
- return 0;
-}
-
-longlong Item_func_is_used_lock::val_int()
-{
- DBUG_ASSERT(fixed == 1);
- String *res=args[0]->val_str(&value);
- User_level_lock *ull;
-
- null_value=1;
- if (!res || !res->length())
- return 0;
-
- mysql_mutex_lock(&LOCK_user_locks);
- ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(),
- (size_t) res->length());
- mysql_mutex_unlock(&LOCK_user_locks);
- if (!ull || !ull->locked)
- return 0;
-
- null_value=0;
- return ull->thread_id;
-}
-
-
longlong Item_func_row_count::val_int()
{
DBUG_ASSERT(fixed == 1);