summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <monty@mishka.mysql.fi>2003-10-03 00:42:47 +0300
committerunknown <monty@mishka.mysql.fi>2003-10-03 00:42:47 +0300
commit0adf47e67ac25d47490c9566231518c3ef8cbefc (patch)
treedf007a7a062ed4d83fa64a359a92d1f141e826d1 /sql
parent7a58bfee6195cdb2804a75ccd90af81c87f696e4 (diff)
parent2985e91acd78841fac42b298cea19c7332895eb9 (diff)
downloadmariadb-git-0adf47e67ac25d47490c9566231518c3ef8cbefc.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-4.0
into mishka.mysql.fi:/home/my/mysql-4.0
Diffstat (limited to 'sql')
-rw-r--r--sql/item_func.cc234
-rw-r--r--sql/item_func.h40
-rw-r--r--sql/log.cc6
-rw-r--r--sql/mysqld.cc12
-rw-r--r--sql/sql_class.h5
5 files changed, 157 insertions, 140 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 4e1cc3865ba..fd6d17d0cf2 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1835,8 +1835,8 @@ bool Item_func_set_user_var::fix_fields(THD *thd,TABLE_LIST *tables)
if (Item_func::fix_fields(thd,tables) ||
!(entry= get_variable(&thd->user_vars, name, 1)))
return 1;
- entry->type= cached_result_type;
- entry->update_query_id=thd->query_id;
+ entry->update_query_id= thd->query_id;
+ cached_result_type= args[0]->result_type();
return 0;
}
@@ -1847,10 +1847,10 @@ Item_func_set_user_var::fix_length_and_dec()
maybe_null=args[0]->maybe_null;
max_length=args[0]->max_length;
decimals=args[0]->decimals;
- cached_result_type=args[0]->result_type();
}
-void Item_func_set_user_var::update_hash(void *ptr, uint length,
+
+bool Item_func_set_user_var::update_hash(const void *ptr, uint length,
Item_result type)
{
if ((null_value=args[0]->null_value))
@@ -1863,6 +1863,8 @@ void Item_func_set_user_var::update_hash(void *ptr, uint length,
}
else
{
+ if (type == STRING_RESULT)
+ length++; // Store strings with end \0
if (length <= extra_size)
{
/* Save value in value struct */
@@ -1887,73 +1889,151 @@ void Item_func_set_user_var::update_hash(void *ptr, uint length,
goto err;
}
}
+ if (type == STRING_RESULT)
+ {
+ length--; // Fix length change above
+ entry->value[length]= 0; // Store end \0
+ }
memcpy(entry->value,ptr,length);
entry->length= length;
entry->type=type;
}
- return;
+ return 0;
err:
current_thd->fatal_error=1; // Probably end of memory
null_value=1;
- return;
+ return 1; // Error
}
-bool
-Item_func_set_user_var::update()
+
+/* Get the value of a variable as a double */
+
+double user_var_entry::val(my_bool *null_value)
{
- DBUG_ENTER("Item_func_set_user_var::update");
- switch (cached_result_type) {
- case REAL_RESULT: (void)native_val(); break;
- case INT_RESULT: (void)native_val_int(); break;
- case STRING_RESULT: (void)native_val_str(); break;
+ if ((*null_value= (value == 0)))
+ return 0.0;
+
+ switch (type) {
+ case REAL_RESULT:
+ return *(double*) value;
+ case INT_RESULT:
+ return (double) *(longlong*) value;
+ case STRING_RESULT:
+ return atof(value); // This is null terminated
}
- DBUG_RETURN(current_thd->fatal_error);
+ return 0.0; // Impossible
}
-double
-Item_func_set_user_var::val()
+/* Get the value of a variable as an integer */
+
+longlong user_var_entry::val_int(my_bool *null_value)
{
- DBUG_ENTER("Item_func_set_user_var::val");
- switch (cached_result_type) {
- case REAL_RESULT: return native_val(); break;
- case INT_RESULT: return native_val_int(); break;
+ if ((*null_value= (value == 0)))
+ return LL(0);
+
+ switch (type) {
+ case REAL_RESULT:
+ return (longlong) *(double*) value;
+ case INT_RESULT:
+ return *(longlong*) value;
case STRING_RESULT:
- {
- String *res= native_val_str();
- return !res ? 0 : atof(res->c_ptr());
+ return strtoull(value,NULL,10); // String is null terminated
}
+ return LL(0); // Impossible
+}
+
+
+/* Get the value of a variable as a string */
+
+String *user_var_entry::val_str(my_bool *null_value, String *str,
+ uint decimals)
+{
+ if ((*null_value= (value == 0)))
+ return (String*) 0;
+
+ switch (type) {
+ case REAL_RESULT:
+ str->set(*(double*) value, decimals);
+ break;
+ case INT_RESULT:
+ str->set(*(longlong*) value);
+ break;
+ case STRING_RESULT:
+ if (str->copy(value, length))
+ str= 0; // EOM error
}
- DBUG_RETURN(args[0]->val());
+ return(str);
}
-longlong
-Item_func_set_user_var::val_int()
+
+/*
+ This functions is invoked on SET @variable or @variable:= expression.
+
+ SYNOPSIS
+ Item_func_set_user_var::update()
+
+ NOTES
+ We have to store the expression as such in the variable, independent of
+ the value method used by the user
+
+ RETURN
+ 0 Ok
+ 1 EOM Error
+
+*/
+
+
+bool
+Item_func_set_user_var::update()
{
- DBUG_ENTER("Item_func_set_user_var::val_int");
+ bool res;
+ DBUG_ENTER("Item_func_set_user_var::update");
+ LINT_INIT(res);
+
switch (cached_result_type) {
- case REAL_RESULT: return (longlong)native_val(); break;
- case INT_RESULT: return native_val_int(); break;
- case STRING_RESULT:
+ case REAL_RESULT:
{
- String *res= native_val_str();
- return !res ? 0 : strtoull(res->c_ptr(),NULL,10);
+ double value=args[0]->val();
+ res= update_hash((void*) &value,sizeof(value), REAL_RESULT);
+ break;
}
+ case INT_RESULT:
+ {
+ longlong value=args[0]->val_int();
+ res= update_hash((void*) &value,sizeof(longlong), INT_RESULT);
+ break;
}
- DBUG_RETURN(args[0]->val_int());
+ case STRING_RESULT:
+ String *tmp;
+ tmp=args[0]->val_str(&value);
+ if (!tmp) // Null value
+ res= update_hash((void*) 0,0,STRING_RESULT);
+ else
+ res= update_hash((void*) tmp->ptr(),tmp->length(),STRING_RESULT);
+ break;
+ }
+ DBUG_RETURN(res);
}
-String *
-Item_func_set_user_var::val_str(String *str)
+
+double Item_func_set_user_var::val()
{
- DBUG_ENTER("Item_func_set_user_var::val_str");
- switch (cached_result_type) {
- case REAL_RESULT: str->set(native_val(),decimals); break;
- case INT_RESULT: str->set(native_val_int(),decimals); break;
- case STRING_RESULT: str= native_val_str(str); break;
- }
- DBUG_RETURN(str);
+ update(); // Store expression
+ return entry->val(&null_value);
+}
+
+longlong Item_func_set_user_var::val_int()
+{
+ update(); // Store expression
+ return entry->val_int(&null_value);
+}
+
+String *Item_func_set_user_var::val_str(String *str)
+{
+ update(); // Store expression
+ return entry->val_str(&null_value, str, decimals);
}
@@ -1967,75 +2047,30 @@ void Item_func_set_user_var::print(String *str)
}
-user_var_entry *Item_func_get_user_var::get_entry()
-{
- if (!var_entry || ! var_entry->value)
- {
- null_value=1;
- return 0;
- }
- null_value=0;
- return var_entry;
-}
-
String *
Item_func_get_user_var::val_str(String *str)
{
DBUG_ENTER("Item_func_get_user_var::val_str");
- user_var_entry *entry=get_entry();
- if (!entry)
- return NULL;
- switch (entry->type) {
- case REAL_RESULT:
- str->set(*(double*) entry->value,decimals);
- break;
- case INT_RESULT:
- str->set(*(longlong*) entry->value);
- break;
- case STRING_RESULT:
- if (str->copy(entry->value, entry->length-1))
- {
- null_value=1;
- return NULL;
- }
- break;
- }
- DBUG_RETURN(str);
+ if (!var_entry)
+ return (String*) 0; // No such variable
+ DBUG_RETURN(var_entry->val_str(&null_value, str, decimals));
}
double Item_func_get_user_var::val()
{
- user_var_entry *entry=get_entry();
- if (!entry)
- return 0.0;
- switch (entry->type) {
- case REAL_RESULT:
- return *(double*) entry->value;
- case INT_RESULT:
- return (double) *(longlong*) entry->value;
- case STRING_RESULT:
- return atof(entry->value); // This is null terminated
- }
- return 0.0; // Impossible
+ if (!var_entry)
+ return 0.0; // No such variable
+ return (var_entry->val(&null_value));
}
longlong Item_func_get_user_var::val_int()
{
- user_var_entry *entry=get_entry();
- if (!entry)
- return LL(0);
- switch (entry->type) {
- case REAL_RESULT:
- return (longlong) *(double*) entry->value;
- case INT_RESULT:
- return *(longlong*) entry->value;
- case STRING_RESULT:
- return strtoull(entry->value,NULL,10); // String is null terminated
- }
- return LL(0); // Impossible
+ if (!var_entry)
+ return LL(0); // No such variable
+ return (var_entry->val_int(&null_value));
}
@@ -2045,12 +2080,15 @@ void Item_func_get_user_var::fix_length_and_dec()
maybe_null=1;
decimals=NOT_FIXED_DEC;
max_length=MAX_BLOB_WIDTH;
- var_entry= get_variable(&thd->user_vars, name, 0);
+ if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
+ null_value= 1;
}
bool Item_func_get_user_var::const_item() const
-{ return var_entry && current_thd->query_id != var_entry->update_query_id; }
+{
+ return var_entry && current_thd->query_id != var_entry->update_query_id;
+}
enum Item_result Item_func_get_user_var::result_type() const
diff --git a/sql/item_func.h b/sql/item_func.h
index ffc587c3cf3..09aba9694dd 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -888,45 +888,16 @@ class Item_func_set_user_var :public Item_func
enum Item_result cached_result_type;
LEX_STRING name;
user_var_entry *entry;
-
- double native_val()
- {
- double value=args[0]->val();
- update_hash((void*) &value,sizeof(value), REAL_RESULT);
- return value;
- }
-
- longlong native_val_int()
- {
- longlong value=args[0]->val_int();
- update_hash((void*) &value,sizeof(longlong),INT_RESULT);
- return value;
- }
-
- String *native_val_str(String *str)
- {
- char buffer[MAX_FIELD_WIDTH];
- String *res=args[0]->val_str(str);
- if (!res) // Null value
- update_hash((void*) 0,0,STRING_RESULT);
- else
- update_hash(res->c_ptr(),res->length()+1,STRING_RESULT);
- return res;
- }
-
- String *native_val_str()
- {
- char buffer[MAX_FIELD_WIDTH];
- String tmp(buffer,sizeof(buffer));
- return native_val_str(&tmp);
- }
+ char buffer[MAX_FIELD_WIDTH];
+ String value;
public:
- Item_func_set_user_var(LEX_STRING a,Item *b): Item_func(b), name(a) {}
+ Item_func_set_user_var(LEX_STRING a,Item *b):
+ Item_func(b), name(a), value(buffer,sizeof(buffer)) {}
double val();
longlong val_int();
String *val_str(String *str);
- void update_hash(void *ptr, uint length, enum Item_result type);
+ bool update_hash(const void *ptr, uint length, enum Item_result type);
bool update();
enum Item_result result_type () const { return cached_result_type; }
bool fix_fields(THD *thd,struct st_table_list *tables);
@@ -945,7 +916,6 @@ class Item_func_get_user_var :public Item_func
public:
Item_func_get_user_var(LEX_STRING a):
Item_func(), name(a) {}
- user_var_entry *get_entry();
double val();
longlong val_int();
String *val_str(String* str);
diff --git a/sql/log.cc b/sql/log.cc
index 6307ac0c11e..33ca82aa14f 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1315,9 +1315,9 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback)
/*
Now this Query_log_event has artificial log_pos 0. It must be adjusted
to reflect the real position in the log. Not doing it would confuse the
- slave: it would prevent this one from knowing where he is in the master's
- binlog, which would result in wrong positions being shown to the user,
- MASTER_POS_WAIT undue waiting etc.
+ slave: it would prevent this one from knowing where he is in the
+ master's binlog, which would result in wrong positions being shown to
+ the user, MASTER_POS_WAIT undue waiting etc.
*/
qinfo.set_log_pos(this);
if (qinfo.write(&log_file))
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index bcf115feccc..1bb51ea8e91 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -55,7 +55,9 @@
char pstack_file_name[80];
#endif /* __linux__ */
-#if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ)
+/* We have HAVE_purify below as this speeds up the shutdown of MySQL */
+
+#if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ) || defined(HAVE_purify) && defined(__linux__)
#define HAVE_CLOSE_SERVER_SOCK 1
#endif
@@ -534,12 +536,14 @@ static void close_connections(void)
struct timespec abstime;
int error;
LINT_INIT(error);
+ DBUG_PRINT("info",("Waiting for select_thread"));
+
#ifndef DONT_USE_THR_ALARM
if (pthread_kill(select_thread,THR_CLIENT_ALARM))
break; // allready dead
#endif
set_timespec(abstime, 2);
- for (uint tmp=0 ; tmp < 10 ; tmp++)
+ for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
{
error=pthread_cond_timedwait(&COND_thread_count,&LOCK_thread_count,
&abstime);
@@ -700,8 +704,8 @@ static void close_server_sock()
VOID(shutdown(tmp_sock,2));
#if defined(__NETWARE__)
/*
- The following code is disabled for normal systems as it causes MySQL
- AIX 4.3 during shutdown (not tested, but likely)
+ The following code is disabled for normal systems as it may cause MySQL
+ to hang on AIX 4.3 during shutdown
*/
DBUG_PRINT("info",("calling closesocket on unix/IP socket"));
VOID(closesocket(tmp_sock));
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 8aa3d48bc35..2ed9cb7b877 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -783,8 +783,13 @@ class user_var_entry
char *value;
ulong length, update_query_id;
Item_result type;
+
+ double val(my_bool *null_value);
+ longlong val_int(my_bool *null_value);
+ String *val_str(my_bool *null_value, String *str, uint decimals);
};
+
/* Class for unique (removing of duplicates) */
class Unique :public Sql_alloc