summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <cmiller@zippy.cornsilk.net>2006-11-02 17:51:59 -0500
committerunknown <cmiller@zippy.cornsilk.net>2006-11-02 17:51:59 -0500
commit75ed6f1a3ba3e908d7feaf5f1fd658ff7e4309f3 (patch)
treedc9dc6a9c5046129bcdf2523c94969503fb1a0cc /sql
parent74a15e2f8e73ec23c69d667e7c36b03822ba3fb4 (diff)
parent6afaa993e4142527a0f6cc8b9d853e976105a716 (diff)
downloadmariadb-git-75ed6f1a3ba3e908d7feaf5f1fd658ff7e4309f3.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-5.1
into zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-maint BitKeeper/deleted/.del-CMakeLists.txt~1: Auto merged BitKeeper/deleted/.del-make_win_bin_dist: Auto merged configure.in: Auto merged include/my_global.h: Auto merged include/mysql.h: Auto merged libmysqld/lib_sql.cc: Auto merged mysql-test/include/mix1.inc: Auto merged mysql-test/r/ctype_utf8.result: Auto merged mysql-test/r/innodb_mysql.result: Auto merged mysql-test/r/log_tables.result: Auto merged mysql-test/r/trigger.result: Auto merged mysql-test/r/view.result: Auto merged mysql-test/t/ctype_utf8.test: Auto merged mysql-test/t/im_daemon_life_cycle.imtest: Auto merged mysql-test/t/sp-error.test: Auto merged mysql-test/t/sp.test: Auto merged mysql-test/t/trigger.test: Auto merged mysql-test/t/view.test: Auto merged netware/BUILD/mwenv: Auto merged scripts/make_binary_distribution.sh: Auto merged sql/Makefile.am: Auto merged sql/handler.cc: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/log.cc: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/set_var.cc: Auto merged sql/sp.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_delete.cc: Auto merged sql/sql_insert.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_prepare.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_show.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_trigger.cc: Auto merged sql/sql_union.cc: Auto merged sql/sql_update.cc: Auto merged sql/sql_view.cc: Auto merged sql/sql_yacc.yy: Auto merged sql/table.cc: Auto merged storage/innobase/handler/ha_innodb.cc: Auto merged tests/mysql_client_test.c: Auto merged include/my_time.h: manual merge. mysql-test/mysql-test-run.pl: manual merge. mysql-test/r/ps.result: manual merge. mysql-test/t/disabled.def: manual merge. mysql-test/t/ps.test: manual merge.
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am7
-rw-r--r--sql/field.cc35
-rw-r--r--sql/item_strfunc.cc1
-rw-r--r--sql/item_timefunc.cc236
-rw-r--r--sql/lex.h6
-rw-r--r--sql/mysqld.cc10
-rw-r--r--sql/opt_range.cc11
-rw-r--r--sql/opt_range.h2
-rw-r--r--sql/set_var.cc3
-rw-r--r--sql/sp.cc23
-rw-r--r--sql/sql_acl.cc67
-rw-r--r--sql/sql_class.cc8
-rw-r--r--sql/sql_class.h9
-rw-r--r--sql/sql_db.cc5
-rw-r--r--sql/sql_parse.cc134
-rw-r--r--sql/sql_prepare.cc33
-rw-r--r--sql/sql_select.cc4
-rw-r--r--sql/sql_show.cc6
-rw-r--r--sql/sql_table.cc13
-rw-r--r--sql/sql_trigger.cc13
-rw-r--r--sql/sql_union.cc15
-rw-r--r--sql/sql_view.cc64
-rw-r--r--sql/sql_view.h2
-rw-r--r--sql/sql_yacc.yy7
-rw-r--r--sql/stacktrace.c2
-rw-r--r--sql/table.cc2
-rw-r--r--sql/time.cc19
27 files changed, 516 insertions, 221 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 97e00471a6e..19038adfe18 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -30,12 +30,13 @@ libexec_PROGRAMS = mysqld
noinst_PROGRAMS = gen_lex_hash
bin_PROGRAMS = mysql_tzinfo_to_sql
gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@
-LDADD = $(top_builddir)/vio/libvio.a \
+SUPPORTING_LIBS = $(top_builddir)/vio/libvio.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/regex/libregex.a \
- $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
-mysqld_DEPENDENCIES= @mysql_plugin_libs@ $(LDADD)
+ $(top_builddir)/strings/libmystrings.a
+mysqld_DEPENDENCIES= @mysql_plugin_libs@ $(SUPPORTING_LIBS)
+LDADD = $(SUPPORTING_LIBS) @ZLIB_LIBS@
mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \
@pstack_libs@ \
@mysql_plugin_libs@ \
diff --git a/sql/field.cc b/sql/field.cc
index 09e919d872a..122a44305f2 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4875,9 +4875,10 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
{
TIME ltime;
long tmp;
- int error;
+ int error= 0;
+ int warning;
- if (str_to_time(from, len, &ltime, &error))
+ if (str_to_time(from, len, &ltime, &warning))
{
tmp=0L;
error= 2;
@@ -4886,29 +4887,27 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
}
else
{
- if (error)
+ if (warning & MYSQL_TIME_WARN_TRUNCATED)
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED,
from, len, MYSQL_TIMESTAMP_TIME, 1);
-
- if (ltime.month)
- ltime.day=0;
- tmp=(ltime.day*24L+ltime.hour)*10000L+(ltime.minute*100+ltime.second);
- if (tmp > 8385959)
+ if (warning & MYSQL_TIME_WARN_OUT_OF_RANGE)
{
- tmp=8385959;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
from, len, MYSQL_TIMESTAMP_TIME, !error);
error= 1;
}
+ if (ltime.month)
+ ltime.day=0;
+ tmp=(ltime.day*24L+ltime.hour)*10000L+(ltime.minute*100+ltime.second);
if (error > 1)
error= 2;
}
if (ltime.neg)
tmp= -tmp;
- error |= Field_time::store((longlong) tmp, FALSE);
+ int3store(ptr,tmp);
return error;
}
@@ -4928,16 +4927,16 @@ int Field_time::store(double nr)
ASSERT_COLUMN_MARKED_FOR_WRITE;
long tmp;
int error= 0;
- if (nr > 8385959.0)
+ if (nr > (double)TIME_MAX_VALUE)
{
- tmp=8385959L;
+ tmp= TIME_MAX_VALUE;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE, nr, MYSQL_TIMESTAMP_TIME);
error= 1;
}
- else if (nr < -8385959.0)
+ else if (nr < (double)-TIME_MAX_VALUE)
{
- tmp= -8385959L;
+ tmp= -TIME_MAX_VALUE;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE, nr, MYSQL_TIMESTAMP_TIME);
error= 1;
@@ -4966,17 +4965,17 @@ int Field_time::store(longlong nr, bool unsigned_val)
ASSERT_COLUMN_MARKED_FOR_WRITE;
long tmp;
int error= 0;
- if (nr < (longlong) -8385959L && !unsigned_val)
+ if (nr < (longlong) -TIME_MAX_VALUE && !unsigned_val)
{
- tmp= -8385959L;
+ tmp= -TIME_MAX_VALUE;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE, nr,
MYSQL_TIMESTAMP_TIME, 1);
error= 1;
}
- else if (nr > (longlong) 8385959 || nr < 0 && unsigned_val)
+ else if (nr > (longlong) TIME_MAX_VALUE || nr < 0 && unsigned_val)
{
- tmp=8385959L;
+ tmp= TIME_MAX_VALUE;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE, nr,
MYSQL_TIMESTAMP_TIME, 1);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 7a82dd753b3..bf837f6720b 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2965,6 +2965,7 @@ String *Item_func_compress::val_str(String *str)
null_value= 1;
return 0;
}
+ null_value= 0;
if (res->is_empty()) return res;
/*
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index d32adde5e64..f378e5037dc 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -96,6 +96,125 @@ static bool make_datetime(date_time_format_types format, TIME *ltime,
/*
+ Wrapper over make_datetime() with validation of the input TIME value
+
+ NOTE
+ see make_datetime() for more information
+
+ RETURN
+ 1 if there was an error during converion
+ 0 otherwise
+*/
+
+static bool make_datetime_with_warn(date_time_format_types format, TIME *ltime,
+ String *str)
+{
+ int warning= 0;
+ bool rc;
+
+ if (make_datetime(format, ltime, str))
+ return 1;
+ if (check_time_range(ltime, &warning))
+ return 1;
+ if (!warning)
+ return 0;
+
+ make_truncated_value_warning(current_thd, str->ptr(), str->length(),
+ MYSQL_TIMESTAMP_TIME, NullS);
+ return make_datetime(format, ltime, str);
+}
+
+
+/*
+ Wrapper over make_time() with validation of the input TIME value
+
+ NOTE
+ see make_time() for more info
+
+ RETURN
+ 1 if there was an error during conversion
+ 0 otherwise
+*/
+
+static bool make_time_with_warn(const DATE_TIME_FORMAT *format,
+ TIME *l_time, String *str)
+{
+ int warning= 0;
+ make_time(format, l_time, str);
+ if (check_time_range(l_time, &warning))
+ return 1;
+ if (warning)
+ {
+ make_truncated_value_warning(current_thd, str->ptr(), str->length(),
+ MYSQL_TIMESTAMP_TIME, NullS);
+ make_time(format, l_time, str);
+ }
+
+ return 0;
+}
+
+
+/*
+ Convert seconds to TIME value with overflow checking
+
+ SYNOPSIS:
+ sec_to_time()
+ seconds number of seconds
+ unsigned_flag 1, if 'seconds' is unsigned, 0, otherwise
+ ltime output TIME value
+
+ DESCRIPTION
+ If the 'seconds' argument is inside TIME data range, convert it to a
+ corresponding value.
+ Otherwise, truncate the resulting value to the nearest endpoint, and
+ produce a warning message.
+
+ RETURN
+ 1 if the value was truncated during conversion
+ 0 otherwise
+*/
+
+static bool sec_to_time(longlong seconds, bool unsigned_flag, TIME *ltime)
+{
+ uint sec;
+
+ bzero((char *)ltime, sizeof(*ltime));
+
+ if (seconds < 0)
+ {
+ if (unsigned_flag)
+ goto overflow;
+ ltime->neg= 1;
+ if (seconds < -3020399)
+ goto overflow;
+ seconds= -seconds;
+ }
+ else if (seconds > 3020399)
+ goto overflow;
+
+ sec= (uint) ((ulonglong) seconds % 3600);
+ ltime->hour= (uint) (seconds/3600);
+ ltime->minute= sec/60;
+ ltime->second= sec % 60;
+
+ return 0;
+
+overflow:
+ ltime->hour= TIME_MAX_HOUR;
+ ltime->minute= TIME_MAX_MINUTE;
+ ltime->second= TIME_MAX_SECOND;
+
+ char buf[22];
+ int len= (int)(longlong10_to_str(seconds, buf, unsigned_flag ? 10 : -10)
+ - buf);
+ make_truncated_value_warning(current_thd, buf, len, MYSQL_TIMESTAMP_TIME,
+ NullS);
+
+ return 1;
+}
+
+
+/*
Date formats corresponding to compound %r and %T conversion specifiers
Note: We should init at least first element of "positions" array
@@ -1546,8 +1665,6 @@ int Item_func_sysdate_local::save_in_field(Field *to, bool no_conversions)
String *Item_func_sec_to_time::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- longlong seconds=(longlong) args[0]->val_int();
- uint sec;
TIME ltime;
if ((null_value=args[0]->null_value) || str->alloc(19))
@@ -1556,19 +1673,8 @@ String *Item_func_sec_to_time::val_str(String *str)
return (String*) 0;
}
- ltime.neg= 0;
- if (seconds < 0)
- {
- seconds= -seconds;
- ltime.neg= 1;
- }
-
- sec= (uint) ((ulonglong) seconds % 3600);
- ltime.day= 0;
- ltime.hour= (uint) (seconds/3600);
- ltime.minute= sec/60;
- ltime.second= sec % 60;
-
+ sec_to_time(args[0]->val_int(), args[0]->unsigned_flag, &ltime);
+
make_time((DATE_TIME_FORMAT *) 0, &ltime, str);
return str;
}
@@ -1577,16 +1683,15 @@ String *Item_func_sec_to_time::val_str(String *str)
longlong Item_func_sec_to_time::val_int()
{
DBUG_ASSERT(fixed == 1);
- longlong seconds=args[0]->val_int();
- longlong sign=1;
+ TIME ltime;
+
if ((null_value=args[0]->null_value))
return 0;
- if (seconds < 0)
- {
- seconds= -seconds;
- sign= -1;
- }
- return sign*((seconds / 3600)*10000+((seconds/60) % 60)*100+ (seconds % 60));
+
+ sec_to_time(args[0]->val_int(), args[0]->unsigned_flag, &ltime);
+
+ return (ltime.neg ? -1 : 1) *
+ ((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
}
@@ -2030,11 +2135,15 @@ bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const
(date_sub_interval == other->date_sub_interval));
}
+/*
+ 'interval_names' reflects the order of the enumeration interval_type.
+ See item_timefunc.h
+ */
static const char *interval_names[]=
{
- "year", "quarter", "month", "day", "hour",
- "minute", "week", "second", "microsecond",
+ "year", "quarter", "month", "week", "day",
+ "hour", "minute", "second", "microsecond",
"year_month", "day_hour", "day_minute",
"day_second", "hour_minute", "hour_second",
"minute_second", "day_microsecond",
@@ -2571,7 +2680,9 @@ String *Item_func_add_time::val_str(String *str)
}
if (l_time1.neg != l_time2.neg)
l_sign= -l_sign;
-
+
+ bzero((char *)&l_time3, sizeof(l_time3));
+
l_time3.neg= calc_time_diff(&l_time1, &l_time2, -l_sign,
&seconds, &microseconds);
@@ -2600,9 +2711,9 @@ String *Item_func_add_time::val_str(String *str)
}
l_time3.hour+= days*24;
- if (!make_datetime(l_time1.second_part || l_time2.second_part ?
- TIME_MICROSECOND : TIME_ONLY,
- &l_time3, str))
+ if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY,
+ &l_time3, str))
return str;
null_date:
@@ -2657,6 +2768,8 @@ String *Item_func_timediff::val_str(String *str)
if (l_time1.neg != l_time2.neg)
l_sign= -l_sign;
+ bzero((char *)&l_time3, sizeof(l_time3));
+
l_time3.neg= calc_time_diff(&l_time1, &l_time2, l_sign,
&seconds, &microseconds);
@@ -2670,9 +2783,9 @@ String *Item_func_timediff::val_str(String *str)
calc_time_from_sec(&l_time3, (long) seconds, microseconds);
- if (!make_datetime(l_time1.second_part || l_time2.second_part ?
- TIME_MICROSECOND : TIME_ONLY,
- &l_time3, str))
+ if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY,
+ &l_time3, str))
return str;
null_date:
@@ -2690,29 +2803,58 @@ String *Item_func_maketime::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
TIME ltime;
+ bool overflow= 0;
- long hour= (long) args[0]->val_int();
- long minute= (long) args[1]->val_int();
- long second= (long) args[2]->val_int();
+ longlong hour= args[0]->val_int();
+ longlong minute= args[1]->val_int();
+ longlong second= args[2]->val_int();
if ((null_value=(args[0]->null_value ||
- args[1]->null_value ||
- args[2]->null_value ||
- minute > 59 || minute < 0 ||
- second > 59 || second < 0 ||
- str->alloc(19))))
+ args[1]->null_value ||
+ args[2]->null_value ||
+ minute < 0 || minute > 59 ||
+ second < 0 || second > 59 ||
+ str->alloc(19))))
return 0;
+ bzero((char *)&ltime, sizeof(ltime));
ltime.neg= 0;
+
+ /* Check for integer overflows */
if (hour < 0)
{
- ltime.neg= 1;
- hour= -hour;
+ if (args[0]->unsigned_flag)
+ overflow= 1;
+ else
+ ltime.neg= 1;
+ }
+ if (-hour > UINT_MAX || hour > UINT_MAX)
+ overflow= 1;
+
+ if (!overflow)
+ {
+ ltime.hour= (uint) ((hour < 0 ? -hour : hour));
+ ltime.minute= (uint) minute;
+ ltime.second= (uint) second;
+ }
+ else
+ {
+ ltime.hour= TIME_MAX_HOUR;
+ ltime.minute= TIME_MAX_MINUTE;
+ ltime.second= TIME_MAX_SECOND;
+ char buf[28];
+ char *ptr= longlong10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10);
+ int len = (int)(ptr - buf) +
+ my_sprintf(ptr, (ptr, ":%02u:%02u", (uint)minute, (uint)second));
+ make_truncated_value_warning(current_thd, buf, len, MYSQL_TIMESTAMP_TIME,
+ NullS);
+ }
+
+ if (make_time_with_warn((DATE_TIME_FORMAT *) 0, &ltime, str))
+ {
+ null_value= 1;
+ return 0;
}
- ltime.hour= (ulong) hour;
- ltime.minute= (ulong) minute;
- ltime.second= (ulong) second;
- make_time((DATE_TIME_FORMAT *) 0, &ltime, str);
return str;
}
@@ -3056,7 +3198,7 @@ bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date)
goto null_date;
null_value= 0;
- bzero((char*) ltime, sizeof(ltime));
+ bzero((char*) ltime, sizeof(*ltime));
date_time_format.format.str= (char*) format->ptr();
date_time_format.format.length= format->length();
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
diff --git a/sql/lex.h b/sql/lex.h
index f19c9413e0e..711becc123f 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -45,6 +45,10 @@ SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"};
Symbols are broken into separated arrays to allow field names with
same name as functions.
These are kept sorted for human lookup (the symbols are hashed).
+
+ NOTE! The symbol tables should be the same regardless of what features
+ are compiled into the server. Don't add ifdef'ed symbols to the
+ lists
*/
static SYMBOL symbols[] = {
@@ -383,11 +387,9 @@ static SYMBOL symbols[] = {
{ "PACK_KEYS", SYM(PACK_KEYS_SYM)},
{ "PARSER", SYM(PARSER_SYM)},
{ "PARTIAL", SYM(PARTIAL)},
-#ifdef WITH_PARTITION_STORAGE_ENGINE
{ "PARTITION", SYM(PARTITION_SYM)},
{ "PARTITIONING", SYM(PARTITIONING_SYM)},
{ "PARTITIONS", SYM(PARTITIONS_SYM)},
-#endif
{ "PASSWORD", SYM(PASSWORD)},
{ "PHASE", SYM(PHASE_SYM)},
{ "PLUGIN", SYM(PLUGIN_SYM)},
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index a1b8b908b7e..a6b063a47d4 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -6592,6 +6592,10 @@ static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff)
#endif /* HAVE_OPENSSL */
+/*
+ Variables shown by SHOW STATUS in alphabetical order
+*/
+
SHOW_VAR status_vars[]= {
{"Aborted_clients", (char*) &aborted_threads, SHOW_LONG},
{"Aborted_connects", (char*) &aborted_connects, SHOW_LONG},
@@ -8099,16 +8103,20 @@ void refresh_status(THD *thd)
{
pthread_mutex_lock(&LOCK_status);
- /* We must update the global status before cleaning up the thread */
+ /* Add thread's status variabes to global status */
add_to_status(&global_status_var, &thd->status_var);
+
+ /* Reset thread's status variables */
bzero((char*) &thd->status_var, sizeof(thd->status_var));
+ /* Reset some global variables */
for (SHOW_VAR *ptr= status_vars; ptr->name; ptr++)
{
/* Note that SHOW_LONG_NOFLUSH variables are not reset */
if (ptr->type == SHOW_LONG)
*(ulong*) ptr->value= 0;
}
+
/* Reset the counters of all key caches (default and named). */
process_key_caches(reset_key_cache_counters);
pthread_mutex_unlock(&LOCK_status);
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 5878771c096..79b3e023a5f 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2101,6 +2101,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
key_parts->null_bit= key_part_info->null_bit;
key_parts->image_type =
(key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW;
+ key_parts->flag= key_part_info->key_part_flag;
}
param.real_keynr[param.keys++]=idx;
}
@@ -3236,6 +3237,11 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar)
key_part->field= (*field);
key_part->image_type = Field::itRAW;
+ /*
+ We set keypart flag to 0 here as the only HA_PART_KEY_SEG is checked
+ in the RangeAnalysisModule.
+ */
+ key_part->flag= 0;
/* We don't set key_parts->null_bit as it will not be used */
ppar->is_part_keypart[part]= !in_subpart_fields;
@@ -5655,7 +5661,9 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
}
break;
case Item_func::GT_FUNC:
- if (field_is_equal_to_item(field,value))
+ /* Don't use open ranges for partial key_segments */
+ if (field_is_equal_to_item(field,value) &&
+ !(key_part->flag & HA_PART_KEY_SEG))
tree->min_flag=NEAR_MIN;
/* fall through */
case Item_func::GE_FUNC:
@@ -7644,6 +7652,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
key_part->length= key_info->key_part[part].length;
key_part->store_length= key_info->key_part[part].store_length;
key_part->null_bit= key_info->key_part[part].null_bit;
+ key_part->flag= key_info->key_part[part].key_part_flag;
}
if (insert_dynamic(&quick->ranges,(gptr)&range))
goto err;
diff --git a/sql/opt_range.h b/sql/opt_range.h
index a88c79e8bab..170766c7c10 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -27,6 +27,8 @@
typedef struct st_key_part {
uint16 key,part, store_length, length;
uint8 null_bit;
+ /* Keypart flags (0 if partition pruning is used) */
+ uint8 flag;
Field *field;
Field::imagetype image_type;
} KEY_PART;
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 4369c288cd5..40e74be2cf0 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -743,7 +743,7 @@ static int show_slave_skip_errors(THD *thd, SHOW_VAR *var, char *buff)
#endif /* HAVE_REPLICATION */
/*
- Variables shown by SHOW variables in alphabetical order
+ Variables shown by SHOW VARIABLES in alphabetical order
*/
SHOW_VAR init_vars[]= {
@@ -3141,6 +3141,7 @@ static byte *get_warning_count(THD *thd)
{
thd->sys_var_tmp.long_value=
(thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
+ thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
return (byte*) &thd->sys_var_tmp.long_value;
}
diff --git a/sql/sp.cc b/sql/sp.cc
index 20e07afa92a..45a177d3e7a 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -653,6 +653,17 @@ db_drop_routine(THD *thd, int type, sp_name *name)
if (table->file->ha_delete_row(table->record[0]))
ret= SP_DELETE_ROW_FAILED;
}
+
+ if (ret == SP_OK)
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+ }
+
close_thread_tables(thd);
DBUG_RETURN(ret);
}
@@ -687,6 +698,17 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
if ((table->file->ha_update_row(table->record[1],table->record[0])))
ret= SP_WRITE_ROW_FAILED;
}
+
+ if (ret == SP_OK)
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+ }
+
close_thread_tables(thd);
DBUG_RETURN(ret);
}
@@ -765,6 +787,7 @@ print_field_values(THD *thd, TABLE *table,
return SP_INTERNAL_ERROR;
}
}
+
return SP_OK;
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index c55fc744cd0..aa13c2f08f4 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3140,9 +3140,22 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
grant_option=TRUE;
thd->mem_root= old_root;
pthread_mutex_unlock(&acl_cache->lock);
+
+ if (!result) /* success */
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+ }
+
rw_unlock(&LOCK_grant);
- if (!result)
+
+ if (!result) /* success */
send_ok(thd);
+
/* Tables are automatically closed */
DBUG_RETURN(result);
}
@@ -3294,9 +3307,21 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
grant_option=TRUE;
thd->mem_root= old_root;
pthread_mutex_unlock(&acl_cache->lock);
+ if (!result && !no_error)
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+ }
+
rw_unlock(&LOCK_grant);
+
if (!result && !no_error)
send_ok(thd);
+
/* Tables are automatically closed */
DBUG_RETURN(result);
}
@@ -3394,11 +3419,23 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
}
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (!result)
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (!result)
send_ok(thd);
+
DBUG_RETURN(result);
}
@@ -5398,6 +5435,13 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list)
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (mysql_bin_log.is_open())
+ {
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (result)
@@ -5454,6 +5498,13 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
rebuild_check_host();
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (mysql_bin_log.is_open())
+ {
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (result)
@@ -5523,6 +5574,13 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
rebuild_check_host();
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (mysql_bin_log.is_open())
+ {
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (result)
@@ -5697,6 +5755,13 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (mysql_bin_log.is_open())
+ {
+ thd->binlog_query(THD::MYSQL_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 5da8d27a887..776ba4dabea 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -241,6 +241,7 @@ THD::THD()
// Must be reset to handle error with THD's created for init of mysqld
lex->current_select= 0;
start_time=(time_t) 0;
+ time_after_lock=(time_t) 0;
current_linfo = 0;
slave_thread = 0;
variables.pseudo_thread_id= 0;
@@ -512,14 +513,13 @@ THD::~THD()
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
{
- ulong *end= (ulong*) ((byte*) to_var + offsetof(STATUS_VAR,
- last_system_status_var) +
+ ulong *end= (ulong*) ((byte*) to_var +
+ offsetof(STATUS_VAR, last_system_status_var) +
sizeof(ulong));
ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
while (to != end)
*(to++)+= *(from++);
- /* it doesn't make sense to add last_query_cost values */
}
/*
@@ -858,7 +858,6 @@ int THD::send_explain_fields(select_result *result)
field_list.push_back(new Item_empty_string("select_type", 19, cs));
field_list.push_back(item= new Item_empty_string("table", NAME_LEN, cs));
item->maybe_null= 1;
-#ifdef WITH_PARTITION_STORAGE_ENGINE
if (lex->describe & DESCRIBE_PARTITIONS)
{
/* Maximum length of string that make_used_partitions_str() can produce */
@@ -867,7 +866,6 @@ int THD::send_explain_fields(select_result *result)
field_list.push_back(item);
item->maybe_null= 1;
}
-#endif
field_list.push_back(item= new Item_empty_string("type", 10, cs));
item->maybe_null= 1;
field_list.push_back(item=new Item_empty_string("possible_keys",
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 95283ec2fc8..9fec77bdbf7 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -337,12 +337,17 @@ typedef struct system_status_var
ulong com_stmt_reset;
ulong com_stmt_close;
+ /*
+ Status variables which it does not make sense to add to
+ global status variable counter
+ */
double last_query_cost;
} STATUS_VAR;
/*
- This is used for 'show status'. It must be updated to the last ulong
- variable in system_status_var
+ This is used for 'SHOW STATUS'. It must be updated to the last ulong
+ variable in system_status_var which is makes sens to add to the global
+ counter
*/
#define last_system_status_var com_stmt_close
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 3960236e828..37096fd897e 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -705,6 +705,7 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
qinfo.db = db;
qinfo.db_len = strlen(db);
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
mysql_bin_log.write(&qinfo);
}
send_ok(thd, result);
@@ -783,6 +784,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
qinfo.db_len = strlen(db);
thd->clear_error();
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
mysql_bin_log.write(&qinfo);
}
send_ok(thd, result);
@@ -905,6 +907,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
qinfo.db_len = strlen(db);
thd->clear_error();
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
mysql_bin_log.write(&qinfo);
}
thd->server_status|= SERVER_STATUS_DB_DROPPED;
@@ -931,6 +934,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
tbl_name_len= strlen(tbl->table_name) + 3;
if (query_pos + tbl_name_len + 1 >= query_end)
{
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
write_to_binlog(thd, query, query_pos -1 - query, db, db_len);
query_pos= query_data_start;
}
@@ -943,6 +947,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
if (query_pos != query_data_start)
{
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
write_to_binlog(thd, query, query_pos -1 - query, db, db_len);
}
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 21c7f6074f9..72e1fb4a415 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1214,7 +1214,14 @@ pthread_handler_t handle_one_connection(void *arg)
{
execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
if (thd->query_error)
+ {
thd->killed= THD::KILL_CONNECTION;
+ sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
+ thd->thread_id,(thd->db ? thd->db : "unconnected"),
+ sctx->user ? sctx->user : "unauthenticated",
+ sctx->host_or_ip, "init_connect command failed");
+ sql_print_warning("%s", net->last_error);
+ }
thd->proc_info=0;
thd->set_time();
thd->init_for_queries();
@@ -3231,6 +3238,7 @@ end_with_restore_list:
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
+ /* Presumably, REPAIR and binlog writing doesn't require synchronization */
if (mysql_bin_log.is_open())
{
thd->clear_error(); // No binlog error generated
@@ -3263,6 +3271,7 @@ end_with_restore_list:
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
+ /* Presumably, ANALYZE and binlog writing doesn't require synchronization */
if (mysql_bin_log.is_open())
{
thd->clear_error(); // No binlog error generated
@@ -3287,6 +3296,7 @@ end_with_restore_list:
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
+ /* Presumably, OPTIMIZE and binlog writing doesn't require synchronization */
if (mysql_bin_log.is_open())
{
thd->clear_error(); // No binlog error generated
@@ -3590,6 +3600,7 @@ end_with_restore_list:
/* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
thd->options|= OPTION_KEEP_LOG;
}
+ /* DDL and binlog write order protected by LOCK_open */
res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
lex->drop_temporary);
}
@@ -3989,13 +4000,9 @@ end_with_restore_list:
break;
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog */
if (!(res= mysql_create_user(thd, lex->users_list)))
- {
- if (mysql_bin_log.is_open())
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
send_ok(thd);
- }
break;
}
case SQLCOM_DROP_USER:
@@ -4005,15 +4012,9 @@ end_with_restore_list:
break;
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog */
if (!(res= mysql_drop_user(thd, lex->users_list)))
- {
- if (mysql_bin_log.is_open())
- {
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
send_ok(thd);
- }
break;
}
case SQLCOM_RENAME_USER:
@@ -4023,15 +4024,9 @@ end_with_restore_list:
break;
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog */
if (!(res= mysql_rename_user(thd, lex->users_list)))
- {
- if (mysql_bin_log.is_open())
- {
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
send_ok(thd);
- }
break;
}
case SQLCOM_REVOKE_ALL:
@@ -4039,15 +4034,9 @@ end_with_restore_list:
if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) &&
check_global_access(thd,CREATE_USER_ACL))
break;
+ /* Conditionally writes to binlog */
if (!(res = mysql_revoke_all(thd, lex->users_list)))
- {
- if (mysql_bin_log.is_open())
- {
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
send_ok(thd);
- }
break;
}
case SQLCOM_REVOKE:
@@ -4106,6 +4095,7 @@ end_with_restore_list:
check_grant_routine(thd, grants | GRANT_ACL, all_tables,
lex->type == TYPE_ENUM_PROCEDURE, 0))
goto error;
+ /* Conditionally writes to binlog */
res= mysql_routine_grant(thd, all_tables,
lex->type == TYPE_ENUM_PROCEDURE,
lex->users_list, grants,
@@ -4118,16 +4108,11 @@ end_with_restore_list:
GRANT_ACL),
all_tables, 0, UINT_MAX, 0))
goto error;
+ /* Conditionally writes to binlog */
res= mysql_table_grant(thd, all_tables, lex->users_list,
lex->columns, lex->grant,
lex->sql_command == SQLCOM_REVOKE);
}
- if (!res && mysql_bin_log.is_open())
- {
- thd->clear_error();
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
}
else
{
@@ -4138,16 +4123,11 @@ end_with_restore_list:
goto error;
}
else
+ /* Conditionally writes to binlog */
res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
lex->sql_command == SQLCOM_REVOKE);
if (!res)
{
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
if (lex->sql_command == SQLCOM_GRANT)
{
List_iterator <LEX_USER> str_list(lex->users_list);
@@ -4185,6 +4165,7 @@ end_with_restore_list:
We WANT to write and we CAN write.
! we write after unlocking the table.
*/
+ /* Presumably, RESET and binlog writing doesn't require synchronization */
if (!lex->no_write_to_binlog && write_to_binlog)
{
if (mysql_bin_log.is_open())
@@ -4701,20 +4682,16 @@ end_with_restore_list:
already puts on CREATE FUNCTION.
*/
if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
+ /* Conditionally writes to binlog */
result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics);
else
+ /* Conditionally writes to binlog */
result= sp_update_function(thd, lex->spname, &lex->sp_chistics);
}
}
switch (result)
{
case SP_OK:
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
send_ok(thd);
break;
case SP_KEY_NOT_FOUND:
@@ -4759,9 +4736,11 @@ end_with_restore_list:
}
#endif
if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
- result= sp_drop_procedure(thd, lex->spname);
+ /* Conditionally writes to binlog */
+ result= sp_drop_procedure(thd, lex->spname); /* Conditionally writes to binlog */
else
- result= sp_drop_function(thd, lex->spname);
+ /* Conditionally writes to binlog */
+ result= sp_drop_function(thd, lex->spname); /* Conditionally writes to binlog */
}
else
{
@@ -4774,6 +4753,8 @@ end_with_restore_list:
{
if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0))
goto error;
+
+ /* Does NOT write to binlog */
if (!(res = mysql_drop_function(thd, &lex->spname->m_name)))
{
send_ok(thd);
@@ -4794,12 +4775,6 @@ end_with_restore_list:
switch (result)
{
case SP_OK:
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- thd->binlog_query(THD::MYSQL_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
send_ok(thd);
break;
case SP_KEY_NOT_FOUND:
@@ -4898,49 +4873,7 @@ end_with_restore_list:
if (end_active_trans(thd))
goto error;
- if (!(res= mysql_create_view(thd, thd->lex->create_view_mode)) &&
- mysql_bin_log.is_open())
- {
- String buff;
- const LEX_STRING command[3]=
- {{ C_STRING_WITH_LEN("CREATE ") },
- { C_STRING_WITH_LEN("ALTER ") },
- { C_STRING_WITH_LEN("CREATE OR REPLACE ") }};
- thd->clear_error();
-
- buff.append(command[thd->lex->create_view_mode].str,
- command[thd->lex->create_view_mode].length);
- view_store_options(thd, first_table, &buff);
- buff.append(STRING_WITH_LEN("VIEW "));
- /* Test if user supplied a db (ie: we did not use thd->db) */
- if (first_table->db && first_table->db[0] &&
- (thd->db == NULL || strcmp(first_table->db, thd->db)))
- {
- append_identifier(thd, &buff, first_table->db,
- first_table->db_length);
- buff.append('.');
- }
- append_identifier(thd, &buff, first_table->table_name,
- first_table->table_name_length);
- if (lex->view_list.elements)
- {
- List_iterator_fast<LEX_STRING> names(lex->view_list);
- LEX_STRING *name;
- int i;
-
- for (i= 0; name= names++; i++)
- {
- buff.append(i ? ", " : "(");
- append_identifier(thd, &buff, name->str, name->length);
- }
- buff.append(')');
- }
- buff.append(STRING_WITH_LEN(" AS "));
- buff.append(first_table->source.str, first_table->source.length);
-
- thd->binlog_query(THD::STMT_QUERY_TYPE,
- buff.ptr(), buff.length(), FALSE, FALSE);
- }
+ res= mysql_create_view(thd, first_table, thd->lex->create_view_mode);
break;
}
case SQLCOM_DROP_VIEW:
@@ -4948,13 +4881,8 @@ end_with_restore_list:
if (check_table_access(thd, DROP_ACL, all_tables, 0) ||
end_active_trans(thd))
goto error;
- if (!(res= mysql_drop_view(thd, first_table, thd->lex->drop_mode)) &&
- mysql_bin_log.is_open())
- {
- thd->clear_error();
- thd->binlog_query(THD::STMT_QUERY_TYPE,
- thd->query, thd->query_length, FALSE, FALSE);
- }
+ /* Conditionally writes to binlog. */
+ res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
break;
}
case SQLCOM_CREATE_TRIGGER:
@@ -4962,6 +4890,7 @@ end_with_restore_list:
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog. */
res= mysql_create_or_drop_trigger(thd, all_tables, 1);
/* We don't care about trigger body after this point */
@@ -4974,6 +4903,7 @@ end_with_restore_list:
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog. */
res= mysql_create_or_drop_trigger(thd, all_tables, 0);
break;
}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 314d4ed5631..013c3a17fd6 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2287,6 +2287,14 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
#endif
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
+
+ /*
+ If the free_list is not empty, we'll wrongly free some externally
+ allocated items when cleaning up after validation of the prepared
+ statement.
+ */
+ DBUG_ASSERT(thd->free_list == NULL);
+
error= stmt->execute(&expanded_query,
test(flags & (ulong) CURSOR_TYPE_READ_ONLY));
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -2349,6 +2357,13 @@ void mysql_sql_stmt_execute(THD *thd)
DBUG_PRINT("info",("stmt: %p", stmt));
+ /*
+ If the free_list is not empty, we'll wrongly free some externally
+ allocated items when cleaning up after validation of the prepared
+ statement.
+ */
+ DBUG_ASSERT(thd->free_list == NULL);
+
if (stmt->set_params_from_vars(stmt, lex->prepared_stmt_params,
&expanded_query))
goto set_params_data_err;
@@ -2839,12 +2854,12 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
external changes when cleaning up after validation.
*/
DBUG_ASSERT(thd->change_list.is_empty());
- /*
- If the free_list is not empty, we'll wrongly free some externally
- allocated items when cleaning up after validation of the prepared
- statement.
+
+ /*
+ The only case where we should have items in the thd->free_list is
+ after stmt->set_params_from_vars(), which may in some cases create
+ Item_null objects.
*/
- DBUG_ASSERT(thd->free_list == NULL);
if (error == 0)
error= check_prepared_statement(this, name.str != 0);
@@ -2943,7 +2958,13 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
allocated items when cleaning up after execution of this statement.
*/
DBUG_ASSERT(thd->change_list.is_empty());
- DBUG_ASSERT(thd->free_list == NULL);
+
+ /*
+ The only case where we should have items in the thd->free_list is
+ after stmt->set_params_from_vars(), which may in some cases create
+ Item_null objects.
+ */
+
thd->set_n_backup_statement(this, &stmt_backup);
if (expanded_query->length() &&
alloc_query(thd, (char*) expanded_query->ptr(),
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e5cbe0180ad..2065d418fd4 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2207,7 +2207,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
continue;
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
- bool no_partitions_used= table->no_partitions_used;
+ const bool no_partitions_used= table->no_partitions_used;
#else
const bool no_partitions_used= FALSE;
#endif
@@ -11791,7 +11791,7 @@ part_of_refkey(TABLE *table,Field *field)
for (uint part=0 ; part < ref_parts ; part++,key_part++)
if (field->eq(key_part->field) &&
- !(key_part->key_part_flag & HA_PART_KEY_SEG))
+ !(key_part->key_part_flag & (HA_PART_KEY_SEG | HA_NULL_PART)))
return table->reginfo.join_tab->ref.items[part];
}
return (Item*) 0;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 07d1fb80183..f6e39fb7913 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1664,7 +1664,9 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
"%s:%u", tmp_sctx->host_or_ip, tmp->peer_port);
}
else
- thd_info->host= thd->strdup(tmp_sctx->host_or_ip);
+ thd_info->host= thd->strdup(tmp_sctx->host_or_ip[0] ?
+ tmp_sctx->host_or_ip :
+ tmp_sctx->host ? tmp_sctx->host : "");
if ((thd_info->db=tmp->db)) // Safe test
thd_info->db=thd->strdup(thd_info->db);
thd_info->command=(int) tmp->command;
@@ -5247,7 +5249,7 @@ ST_FIELD_INFO columns_fields_info[]=
{"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
{"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Field"},
{"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
- {"COLUMN_DEFAULT", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Default"},
+ {"COLUMN_DEFAULT", MAX_FIELD_VARCHARLENGTH, MYSQL_TYPE_STRING, 0, 1, "Default"},
{"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"},
{"DATA_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
{"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 6a868f07ce9..511d9fa6677 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5288,6 +5288,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
+ /* Conditionally writes to binlog. */
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
alter_info->tablespace_op));
strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db,
@@ -5443,10 +5444,10 @@ view_err:
!table->s->tmp_table) // no need to touch frm
{
error=0;
+ VOID(pthread_mutex_lock(&LOCK_open));
if (new_name != table_name || new_db != db)
{
thd->proc_info="rename";
- VOID(pthread_mutex_lock(&LOCK_open));
/* Then do a 'simple' rename of the table */
error=0;
if (!access(new_name_buff,F_OK))
@@ -5469,7 +5470,6 @@ view_err:
error= -1;
}
}
- VOID(pthread_mutex_unlock(&LOCK_open));
}
if (!error)
@@ -5478,16 +5478,12 @@ view_err:
case LEAVE_AS_IS:
break;
case ENABLE:
- VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- VOID(pthread_mutex_unlock(&LOCK_open));
error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
/* COND_refresh will be signaled in close_thread_tables() */
break;
case DISABLE:
- VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- VOID(pthread_mutex_unlock(&LOCK_open));
error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
/* COND_refresh will be signaled in close_thread_tables() */
break;
@@ -5512,6 +5508,7 @@ view_err:
table->file->print_error(error, MYF(0));
error= -1;
}
+ VOID(pthread_mutex_unlock(&LOCK_open));
table_list->table=0; // For query cache
query_cache_invalidate3(thd, table_list, 0);
DBUG_RETURN(error);
@@ -6512,7 +6509,7 @@ end_temporary:
thd->some_tables_deleted=0;
DBUG_RETURN(FALSE);
- err1:
+err1:
if (new_table)
{
/* close_temporary_table() frees the new_table pointer. */
@@ -6521,7 +6518,7 @@ end_temporary:
else
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
- err:
+err:
DBUG_RETURN(TRUE);
}
/* mysql_alter_table */
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index ca95b39f215..fb56b7ae3b0 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -276,8 +276,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
table->triggers->drop_trigger(thd, tables, &stmt_query));
end:
- VOID(pthread_mutex_unlock(&LOCK_open));
- start_waiting_global_read_lock(thd);
if (!result)
{
@@ -286,13 +284,16 @@ end:
thd->clear_error();
/* Such a statement can always go directly to binlog, no trans cache. */
- Query_log_event qinfo(thd, stmt_query.ptr(), stmt_query.length(), 0,
- FALSE);
- mysql_bin_log.write(&qinfo);
+ thd->binlog_query(THD::STMT_QUERY_TYPE,
+ stmt_query.ptr(), stmt_query.length(), FALSE, FALSE);
}
+ }
+
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ start_waiting_global_read_lock(thd);
+ if (!result)
send_ok(thd);
- }
DBUG_RETURN(result);
}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index cfaf21fa957..722a99eb2d1 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -694,7 +694,17 @@ bool st_select_lex_unit::change_result(select_subselect *result,
List<Item> *st_select_lex_unit::get_unit_column_types()
{
- bool is_union= test(first_select()->next_select());
+ SELECT_LEX *sl= first_select();
+ bool is_union= test(sl->next_select());
+ bool is_procedure= test(sl->join->procedure);
+
+ if (is_procedure)
+ {
+ /* Types for "SELECT * FROM t1 procedure analyse()"
+ are generated during execute */
+ return &sl->join->procedure_fields_list;
+ }
+
if (is_union)
{
@@ -702,7 +712,8 @@ List<Item> *st_select_lex_unit::get_unit_column_types()
/* Types are generated during prepare */
return &types;
}
- return &first_select()->item_list;
+
+ return &sl->item_list;
}
bool st_select_lex::cleanup()
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 718b776400c..9598cbb9465 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -212,6 +212,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
SYNOPSIS
mysql_create_view()
thd - thread handler
+ views - views to create
mode - VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
RETURN VALUE
@@ -219,7 +220,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
TRUE Error
*/
-bool mysql_create_view(THD *thd,
+bool mysql_create_view(THD *thd, TABLE_LIST *views,
enum_view_create_mode mode)
{
LEX *lex= thd->lex;
@@ -532,6 +533,49 @@ bool mysql_create_view(THD *thd,
}
VOID(pthread_mutex_lock(&LOCK_open));
res= mysql_register_view(thd, view, mode);
+
+ if (mysql_bin_log.is_open())
+ {
+ String buff;
+ const LEX_STRING command[3]=
+ {{ C_STRING_WITH_LEN("CREATE ") },
+ { C_STRING_WITH_LEN("ALTER ") },
+ { C_STRING_WITH_LEN("CREATE OR REPLACE ") }};
+
+ buff.append(command[thd->lex->create_view_mode].str,
+ command[thd->lex->create_view_mode].length);
+ view_store_options(thd, views, &buff);
+ buff.append(STRING_WITH_LEN("VIEW "));
+ /* Test if user supplied a db (ie: we did not use thd->db) */
+ if (views->db && views->db[0] &&
+ (thd->db == NULL || strcmp(views->db, thd->db)))
+ {
+ append_identifier(thd, &buff, views->db,
+ views->db_length);
+ buff.append('.');
+ }
+ append_identifier(thd, &buff, views->table_name,
+ views->table_name_length);
+ if (lex->view_list.elements)
+ {
+ List_iterator_fast<LEX_STRING> names(lex->view_list);
+ LEX_STRING *name;
+ int i;
+
+ for (i= 0; name= names++; i++)
+ {
+ buff.append(i ? ", " : "(");
+ append_identifier(thd, &buff, name->str, name->length);
+ }
+ buff.append(')');
+ }
+ buff.append(STRING_WITH_LEN(" AS "));
+ buff.append(views->source.str, views->source.length);
+
+ thd->binlog_query(THD::STMT_QUERY_TYPE,
+ buff.ptr(), buff.length(), FALSE, FALSE);
+ }
+
VOID(pthread_mutex_unlock(&LOCK_open));
if (view->revision != 1)
query_cache_invalidate3(thd, view, 0);
@@ -1302,13 +1346,13 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
enum legacy_db_type not_used;
DBUG_ENTER("mysql_drop_view");
+ VOID(pthread_mutex_lock(&LOCK_open));
for (view= views; view; view= view->next_local)
{
TABLE_SHARE *share;
frm_type_enum type= FRMTYPE_ERROR;
build_table_filename(path, sizeof(path),
view->db, view->table_name, reg_ext, 0);
- VOID(pthread_mutex_lock(&LOCK_open));
if (access(path, F_OK) ||
FRMTYPE_VIEW != (type= mysql_frm_type(thd, path, &not_used)))
@@ -1320,7 +1364,6 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
name);
- VOID(pthread_mutex_unlock(&LOCK_open));
continue;
}
if (type == FRMTYPE_TABLE)
@@ -1337,7 +1380,6 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
non_existant_views.append(',');
non_existant_views.append(String(view->table_name,system_charset_info));
}
- VOID(pthread_mutex_unlock(&LOCK_open));
continue;
}
if (my_delete(path, MYF(MY_WME)))
@@ -1358,24 +1400,36 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
}
query_cache_invalidate3(thd, view, 0);
sp_cache_invalidate();
- VOID(pthread_mutex_unlock(&LOCK_open));
}
+
if (error)
{
+ VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(TRUE);
}
if (wrong_object_name)
{
+ VOID(pthread_mutex_unlock(&LOCK_open));
my_error(ER_WRONG_OBJECT, MYF(0), wrong_object_db, wrong_object_name,
"VIEW");
DBUG_RETURN(TRUE);
}
if (non_existant_views.length())
{
+ VOID(pthread_mutex_unlock(&LOCK_open));
my_error(ER_BAD_TABLE_ERROR, MYF(0), non_existant_views.c_ptr());
DBUG_RETURN(TRUE);
}
+
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ thd->binlog_query(THD::STMT_QUERY_TYPE,
+ thd->query, thd->query_length, FALSE, FALSE);
+ }
+
send_ok(thd);
+ VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(FALSE);
}
diff --git a/sql/sql_view.h b/sql/sql_view.h
index 7e54d57cfdf..fc480167216 100644
--- a/sql/sql_view.h
+++ b/sql/sql_view.h
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-bool mysql_create_view(THD *thd,
+bool mysql_create_view(THD *thd, TABLE_LIST *view,
enum_view_create_mode mode);
bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 7b3141b751f..adada9252f9 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -3231,6 +3231,7 @@ opt_partitioning:
partitioning:
PARTITION_SYM
{
+#ifdef WITH_PARTITION_STORAGE_ENGINE
LEX *lex= Lex;
lex->part_info= new partition_info();
if (!lex->part_info)
@@ -3242,6 +3243,12 @@ partitioning:
{
lex->alter_info.flags|= ALTER_PARTITION;
}
+#else
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ "partitioning", "--with-partition");
+ YYABORT;
+#endif
+
}
partition
;
diff --git a/sql/stacktrace.c b/sql/stacktrace.c
index a2fe2ab88f1..77e7707592d 100644
--- a/sql/stacktrace.c
+++ b/sql/stacktrace.c
@@ -186,7 +186,7 @@ terribly wrong...\n");
#if defined(__alpha__) && defined(__GNUC__)
uchar** new_fp = find_prev_fp(pc, fp);
- if (frame_count == SIGRETURN_FRAME_COUNT - 1)
+ if (frame_count == sigreturn_frame_count - 1)
{
new_fp += 90;
}
diff --git a/sql/table.cc b/sql/table.cc
index 92d1103893a..df09b322ff8 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1181,7 +1181,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
as we need to test for NULL = NULL.
*/
if (field->real_maybe_null())
- key_part->key_part_flag|= HA_PART_KEY_SEG;
+ key_part->key_part_flag|= HA_NULL_PART;
}
keyinfo->usable_key_parts= usable_parts; // Filesort
diff --git a/sql/time.cc b/sql/time.cc
index 0461f7723c6..25a1995dd01 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -25,14 +25,25 @@
#ifndef TESTTIME
+/*
+ Name description of interval names used in statements.
+
+ 'interval_type_to_name' is ordered and sorted on interval size and
+ interval complexity.
+ Order of elements in 'interval_type_to_name' should correspond to
+ the order of elements in 'interval_type' enum
+
+ See also interval_type, interval_names
+*/
+
LEX_STRING interval_type_to_name[INTERVAL_LAST] = {
{ C_STRING_WITH_LEN("YEAR")},
{ C_STRING_WITH_LEN("QUARTER")},
{ C_STRING_WITH_LEN("MONTH")},
+ { C_STRING_WITH_LEN("WEEK")},
{ C_STRING_WITH_LEN("DAY")},
{ C_STRING_WITH_LEN("HOUR")},
{ C_STRING_WITH_LEN("MINUTE")},
- { C_STRING_WITH_LEN("WEEK")},
{ C_STRING_WITH_LEN("SECOND")},
{ C_STRING_WITH_LEN("MICROSECOND")},
{ C_STRING_WITH_LEN("YEAR_MONTH")},
@@ -278,9 +289,9 @@ my_time_t TIME_to_timestamp(THD *thd, const TIME *t, my_bool *in_dst_time_gap)
bool
str_to_time_with_warn(const char *str, uint length, TIME *l_time)
{
- int was_cut;
- bool ret_val= str_to_time(str, length, l_time, &was_cut);
- if (was_cut)
+ int warning;
+ bool ret_val= str_to_time(str, length, l_time, &warning);
+ if (ret_val || warning)
make_truncated_value_warning(current_thd, str, length,
MYSQL_TIMESTAMP_TIME, NullS);
return ret_val;