diff options
author | unknown <cmiller@zippy.cornsilk.net> | 2006-11-02 17:51:59 -0500 |
---|---|---|
committer | unknown <cmiller@zippy.cornsilk.net> | 2006-11-02 17:51:59 -0500 |
commit | 75ed6f1a3ba3e908d7feaf5f1fd658ff7e4309f3 (patch) | |
tree | dc9dc6a9c5046129bcdf2523c94969503fb1a0cc /sql | |
parent | 74a15e2f8e73ec23c69d667e7c36b03822ba3fb4 (diff) | |
parent | 6afaa993e4142527a0f6cc8b9d853e976105a716 (diff) | |
download | mariadb-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.am | 7 | ||||
-rw-r--r-- | sql/field.cc | 35 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 1 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 236 | ||||
-rw-r--r-- | sql/lex.h | 6 | ||||
-rw-r--r-- | sql/mysqld.cc | 10 | ||||
-rw-r--r-- | sql/opt_range.cc | 11 | ||||
-rw-r--r-- | sql/opt_range.h | 2 | ||||
-rw-r--r-- | sql/set_var.cc | 3 | ||||
-rw-r--r-- | sql/sp.cc | 23 | ||||
-rw-r--r-- | sql/sql_acl.cc | 67 | ||||
-rw-r--r-- | sql/sql_class.cc | 8 | ||||
-rw-r--r-- | sql/sql_class.h | 9 | ||||
-rw-r--r-- | sql/sql_db.cc | 5 | ||||
-rw-r--r-- | sql/sql_parse.cc | 134 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 33 | ||||
-rw-r--r-- | sql/sql_select.cc | 4 | ||||
-rw-r--r-- | sql/sql_show.cc | 6 | ||||
-rw-r--r-- | sql/sql_table.cc | 13 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 13 | ||||
-rw-r--r-- | sql/sql_union.cc | 15 | ||||
-rw-r--r-- | sql/sql_view.cc | 64 | ||||
-rw-r--r-- | sql/sql_view.h | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 7 | ||||
-rw-r--r-- | sql/stacktrace.c | 2 | ||||
-rw-r--r-- | sql/table.cc | 2 | ||||
-rw-r--r-- | sql/time.cc | 19 |
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, <ime, &error)) + if (str_to_time(from, len, <ime, &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, <ime); + make_time((DATE_TIME_FORMAT *) 0, <ime, 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, <ime); + + 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, µseconds); @@ -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, µseconds); @@ -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 *)<ime, 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, <ime, str)) + { + null_value= 1; + return 0; } - ltime.hour= (ulong) hour; - ltime.minute= (ulong) minute; - ltime.second= (ulong) second; - make_time((DATE_TIME_FORMAT *) 0, <ime, 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, ¬_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; |