diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-01-15 19:07:46 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-01-15 19:07:46 +0100 |
commit | aca8e7ed6b176f28e8a34ebddc989574d93f305c (patch) | |
tree | c0d20e5b3e9518f48d789e2220eea46d9010966d /sql | |
parent | 750b9147fced7202b541be946e044eb739b20a03 (diff) | |
parent | 4f67a14700c0266c58b05be0dbd8fc10f88464a6 (diff) | |
download | mariadb-git-aca8e7ed6b176f28e8a34ebddc989574d93f305c.tar.gz |
5.3 merge
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_ndbcluster_binlog.cc | 1 | ||||
-rw-r--r-- | sql/item.cc | 14 | ||||
-rw-r--r-- | sql/item.h | 32 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 24 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 28 | ||||
-rw-r--r-- | sql/item_func.cc | 30 | ||||
-rw-r--r-- | sql/item_func.h | 63 | ||||
-rw-r--r-- | sql/item_geofunc.cc | 4 | ||||
-rw-r--r-- | sql/item_geofunc.h | 30 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 13 | ||||
-rw-r--r-- | sql/item_strfunc.h | 29 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 21 | ||||
-rw-r--r-- | sql/item_timefunc.h | 42 | ||||
-rw-r--r-- | sql/item_xmlfunc.cc | 1 | ||||
-rw-r--r-- | sql/item_xmlfunc.h | 8 | ||||
-rw-r--r-- | sql/log.cc | 8 | ||||
-rw-r--r-- | sql/log_event.cc | 86 | ||||
-rw-r--r-- | sql/log_event.h | 6 | ||||
-rw-r--r-- | sql/mysqld.cc | 2 | ||||
-rw-r--r-- | sql/sp_head.cc | 50 | ||||
-rw-r--r-- | sql/sql_acl.cc | 124 | ||||
-rw-r--r-- | sql/sql_connect.cc | 13 | ||||
-rw-r--r-- | sql/sql_db.cc | 5 | ||||
-rw-r--r-- | sql/sql_lex.cc | 2 | ||||
-rw-r--r-- | sql/sql_list.h | 11 | ||||
-rw-r--r-- | sql/sql_priv.h | 35 | ||||
-rw-r--r-- | sql/sql_profile.cc | 29 | ||||
-rw-r--r-- | sql/sql_profile.h | 6 | ||||
-rw-r--r-- | sql/sql_select.cc | 31 | ||||
-rw-r--r-- | sql/sql_time.cc | 4 | ||||
-rw-r--r-- | sql/table.cc | 36 |
31 files changed, 512 insertions, 276 deletions
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 59b9d6eab6b..856781db28a 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2006, 2011, Oracle and/or its affiliates. + Copyright (c) 2012, 2013, Monty Proram Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/item.cc b/sql/item.cc index 8be339541e1..e6462d1c070 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -8851,9 +8851,10 @@ int Item_cache_temporal::save_in_field(Field *field, bool no_conversions) } -void Item_cache_temporal::store_packed(longlong val_arg) +void Item_cache_temporal::store_packed(longlong val_arg, Item *example) { /* An explicit values is given, save it. */ + store(example); value_cached= true; value= val_arg; null_value= false; @@ -9599,11 +9600,18 @@ table_map Item_ref::used_tables() const void Item_ref::update_used_tables() -{ +{ if (!get_depended_from()) - (*ref)->update_used_tables(); + (*ref)->update_used_tables(); + maybe_null= (*ref)->maybe_null; } +void Item_direct_view_ref::update_used_tables() +{ + Item_ref::update_used_tables(); + if (view->table && view->table->maybe_null) + maybe_null= TRUE; +} table_map Item_direct_view_ref::used_tables() const { diff --git a/sql/item.h b/sql/item.h index 0d38c5eb5f8..baff64cac24 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1440,18 +1440,6 @@ public: max_length= char_to_byte_length_safe(max_char_length_arg, collation.collation->mbmaxlen); } - void fix_char_length_ulonglong(ulonglong max_char_length_arg) - { - ulonglong max_result_length= max_char_length_arg * - collation.collation->mbmaxlen; - if (max_result_length >= MAX_BLOB_WIDTH) - { - max_length= MAX_BLOB_WIDTH; - maybe_null= 1; - } - else - max_length= (uint32) max_result_length; - } /* Return TRUE if the item points to a column of an outer-joined table. */ @@ -2063,9 +2051,14 @@ public: bitmap_fast_test_and_set(tab->read_set, field->field_index); if (field->vcol_info) tab->mark_virtual_col(field); - } + } + } + void update_used_tables() + { + update_table_bitmaps(); + if (field && field->table) + maybe_null= field->maybe_null(); } - void update_used_tables() { update_table_bitmaps(); } Item *get_tmp_table_item(THD *thd); bool collect_item_field_processor(uchar * arg); bool add_field_to_set_processor(uchar * arg); @@ -3116,7 +3109,11 @@ public: enum Item_result result_type () const { return orig_item->result_type(); } enum_field_types field_type() const { return orig_item->field_type(); } table_map used_tables() const { return orig_item->used_tables(); } - void update_used_tables() { orig_item->update_used_tables(); } + void update_used_tables() + { + orig_item->update_used_tables(); + maybe_null= orig_item->maybe_null; + } bool const_item() const { return orig_item->const_item(); } table_map not_null_tables() const { return orig_item->not_null_tables(); } bool walk(Item_processor processor, bool walk_subquery, uchar *arg) @@ -3208,6 +3205,7 @@ public: Item *replace_equal_field(uchar *arg); table_map used_tables() const; table_map not_null_tables() const; + void update_used_tables(); bool walk(Item_processor processor, bool walk_subquery, uchar *arg) { return (*ref)->walk(processor, walk_subquery, arg) || @@ -4033,7 +4031,7 @@ public: bool cache_value(); bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); int save_in_field(Field *field, bool no_conversions); - void store_packed(longlong val_arg); + void store_packed(longlong val_arg, Item *example); /* Having a clone_item method tells optimizer that this object is a constant and need not be optimized further. @@ -4042,7 +4040,7 @@ public: Item *clone_item() { Item_cache_temporal *item= new Item_cache_temporal(cached_field_type); - item->store_packed(value); + item->store_packed(value, example); return item; } }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d950c0c1443..3e64e3969e4 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. - Copyright (c) 2009, 2012 Monty Program Ab + Copyright (c) 2009, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -914,7 +914,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, if (save_arena) thd->set_query_arena(save_arena); - cache->store_packed(value); + cache->store_packed(value, item); *cache_arg= cache; *item_arg= cache_arg; } @@ -1353,7 +1353,7 @@ int Arg_comparator::compare_e_row() void Item_func_truth::fix_length_and_dec() { - maybe_null= 0; + set_persist_maybe_null(0); null_value= 0; decimals= 0; max_length= 1; @@ -1865,7 +1865,8 @@ longlong Item_func_eq::val_int() void Item_func_equal::fix_length_and_dec() { Item_bool_func2::fix_length_and_dec(); - maybe_null=null_value=0; + set_persist_maybe_null(0); + null_value= 0; } longlong Item_func_equal::val_int() @@ -2004,7 +2005,7 @@ void Item_func_interval::fix_length_and_dec() } } } - maybe_null= 0; + set_persist_maybe_null(0); max_length= 2; used_tables_cache|= row->used_tables(); not_null_tables_cache= row->not_null_tables(); @@ -2685,7 +2686,7 @@ void Item_func_nullif::fix_length_and_dec() { Item_bool_func2::fix_length_and_dec(); - maybe_null=1; + set_persist_maybe_null(1); if (args[0]) // Only false if EOM { max_length=args[0]->max_length; @@ -4546,6 +4547,8 @@ void Item_cond::update_used_tables() item->update_used_tables(); used_tables_cache|= item->used_tables(); const_item_cache&= item->const_item(); + if (!persistent_maybe_null && item->maybe_null) + maybe_null= 1; } } @@ -4720,10 +4723,9 @@ longlong Item_is_not_null_test::val_int() */ void Item_is_not_null_test::update_used_tables() { + args[0]->update_used_tables(); if (!args[0]->maybe_null) used_tables_cache= 0; /* is always true */ - else - args[0]->update_used_tables(); } @@ -5004,7 +5006,7 @@ Item_func_regex::fix_fields(THD *thd, Item **ref) int comp_res= regcomp(TRUE); if (comp_res == -1) { // Will always return NULL - maybe_null=1; + set_persist_maybe_null(1); fixed= 1; return FALSE; } @@ -5014,7 +5016,7 @@ Item_func_regex::fix_fields(THD *thd, Item **ref) maybe_null= args[0]->maybe_null; } else - maybe_null=1; + set_persist_maybe_null(1); fixed= 1; return FALSE; } @@ -5828,6 +5830,8 @@ void Item_equal::update_used_tables() used_tables_cache|= item->used_tables(); /* see commentary at Item_equal::update_const() */ const_item_cache&= item->const_item() && !item->is_outer_field(); + if (!persistent_maybe_null && item->maybe_null) + maybe_null= 1; } } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 34d1a0bd0ae..e9b77152d12 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -767,6 +767,11 @@ public: my_decimal *decimal_op(my_decimal *); enum_field_types field_type() const; void fix_length_and_dec(); + void update_used_tables() + { + Item_func_coalesce::update_used_tables(); + maybe_null= args[1]->maybe_null; + } const char *func_name() const { return "ifnull"; } Field *tmp_table_field(TABLE *table); uint decimal_precision() const; @@ -789,6 +794,11 @@ public: enum_field_types field_type() const { return cached_field_type; } bool fix_fields(THD *, Item **); void fix_length_and_dec(); + void update_used_tables() + { + Item_func::update_used_tables(); + maybe_null= args[1]->maybe_null || args[2]->maybe_null; + } uint decimal_precision() const; const char *func_name() const { return "if"; } bool eval_not_null_tables(uchar *opt_arg); @@ -1254,6 +1264,12 @@ public: my_decimal *val_decimal(my_decimal *); bool fix_fields(THD *thd, Item **ref); void fix_length_and_dec(); + void update_used_tables() + { + Item_func::update_used_tables(); + if (else_expr_num == -1 || args[else_expr_num]->maybe_null) + maybe_null= 1; + } uint decimal_precision() const; table_map not_null_tables() const { return 0; } enum Item_result result_type () const { return cached_result_type; } @@ -1375,13 +1391,14 @@ public: enum Functype functype() const { return ISNULL_FUNC; } void fix_length_and_dec() { - decimals=0; max_length=1; maybe_null=0; + decimals=0; max_length=1; set_persist_maybe_null(0); update_used_tables(); } const char *func_name() const { return "isnull"; } /* Optimize case of not_null_column IS NULL */ virtual void update_used_tables() { + args[0]->update_used_tables(); if (!args[0]->maybe_null) { used_tables_cache= 0; /* is always false */ @@ -1389,7 +1406,6 @@ public: } else { - args[0]->update_used_tables(); used_tables_cache= args[0]->used_tables(); const_item_cache= args[0]->const_item(); } @@ -1437,7 +1453,7 @@ public: enum Functype functype() const { return ISNOTNULL_FUNC; } void fix_length_and_dec() { - decimals=0; max_length=1; maybe_null=0; + decimals=0; max_length=1; set_persist_maybe_null(0); } const char *func_name() const { return "isnotnull"; } optimize_type select_optimize() const { return OPTIMIZE_NULL; } @@ -1505,6 +1521,12 @@ public: void cleanup(); longlong val_int(); bool fix_fields(THD *thd, Item **ref); + void update_used_tables() + { + Item_bool_func::update_used_tables(); + if (regex_is_const) + maybe_null= 1; + } const char *func_name() const { return "regexp"; } virtual inline void print(String *str, enum_query_type query_type) diff --git a/sql/item_func.cc b/sql/item_func.cc index 441eb37d701..7053b8fec65 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2008-2011 Monty Program Ab + Copyright (c) 2009, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -111,7 +111,7 @@ void Item_func::set_arguments(List<Item> &list) } Item_func::Item_func(List<Item> &list) - :allowed_arg_cols(1) + :allowed_arg_cols(1), persistent_maybe_null(0) { set_arguments(list); } @@ -119,6 +119,7 @@ Item_func::Item_func(List<Item> &list) Item_func::Item_func(THD *thd, Item_func *item) :Item_result_field(thd, item), allowed_arg_cols(item->allowed_arg_cols), + persistent_maybe_null(0), arg_count(item->arg_count), used_tables_cache(item->used_tables_cache), not_null_tables_cache(item->not_null_tables_cache), @@ -446,6 +447,8 @@ void Item_func::update_used_tables() args[i]->update_used_tables(); used_tables_cache|=args[i]->used_tables(); const_item_cache&=args[i]->const_item(); + if (!persistent_maybe_null && args[i]->maybe_null) + maybe_null= 1; } } @@ -1712,7 +1715,7 @@ void Item_func_div::fix_length_and_dec() case IMPOSSIBLE_RESULT: DBUG_ASSERT(0); } - maybe_null= 1; // devision by zero + set_persist_maybe_null(1); // devision by zero DBUG_VOID_RETURN; } @@ -1796,7 +1799,7 @@ void Item_func_int_div::fix_length_and_dec() max_length=args[0]->max_length - (argtype == DECIMAL_RESULT || argtype == INT_RESULT ? args[0]->decimals : 0); - maybe_null=1; + set_persist_maybe_null(1); unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag; } @@ -1883,7 +1886,7 @@ void Item_func_mod::result_precision() void Item_func_mod::fix_length_and_dec() { Item_num_op::fix_length_and_dec(); - maybe_null= 1; + set_persist_maybe_null(1); unsigned_flag= args[0]->unsigned_flag; } @@ -3078,7 +3081,7 @@ longlong Item_func_field::val_int() void Item_func_field::fix_length_and_dec() { - maybe_null=0; max_length=3; + set_persist_maybe_null(0); max_length=3; cmp_type= args[0]->result_type(); for (uint i=1; i < arg_count ; i++) cmp_type= item_cmp_type(cmp_type, args[i]->result_type()); @@ -4163,7 +4166,8 @@ longlong Item_func_last_insert_id::val_int() thd->first_successful_insert_id_in_prev_stmt= value; return value; } - return thd->read_first_successful_insert_id_in_prev_stmt(); + return + static_cast<longlong>(thd->read_first_successful_insert_id_in_prev_stmt()); } @@ -5282,7 +5286,7 @@ void Item_func_get_user_var::fix_length_and_dec() { THD *thd=current_thd; int error; - maybe_null=1; + set_persist_maybe_null(1); decimals=NOT_FIXED_DEC; max_length=MAX_BLOB_WIDTH; @@ -5481,7 +5485,7 @@ void Item_func_get_system_var::update_null_value() void Item_func_get_system_var::fix_length_and_dec() { char *cptr; - maybe_null= TRUE; + set_persist_maybe_null(1); max_length= 0; if (var->check_type(var_type)) @@ -6048,7 +6052,7 @@ bool Item_func_match::fix_fields(THD *thd, Item **ref) status_var_increment(thd->status_var.feature_fulltext); - maybe_null=1; + set_persist_maybe_null(1); join_key=0; /* @@ -6382,7 +6386,7 @@ longlong Item_func_row_count::val_int() Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name) :Item_func(), context(context_arg), m_name(name), m_sp(NULL), sp_result_field(NULL) { - maybe_null= 1; + set_persist_maybe_null(1); m_name->init_qname(current_thd); dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE)); dummy_table->s= (TABLE_SHARE*) (dummy_table+1); @@ -6393,7 +6397,7 @@ Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name, List<Item> &list) :Item_func(list), context(context_arg), m_name(name), m_sp(NULL),sp_result_field(NULL) { - maybe_null= 1; + set_persist_maybe_null(1); m_name->init_qname(current_thd); dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE)); dummy_table->s= (TABLE_SHARE*) (dummy_table+1); @@ -6534,7 +6538,7 @@ void Item_func_sp::fix_length_and_dec() decimals= sp_result_field->decimals(); max_length= sp_result_field->field_length; collation.set(sp_result_field->charset()); - maybe_null= 1; + set_persist_maybe_null(1); unsigned_flag= test(sp_result_field->flags & UNSIGNED_FLAG); DBUG_VOID_RETURN; diff --git a/sql/item_func.h b/sql/item_func.h index f1b97151cbe..88491be44a2 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1,7 +1,7 @@ #ifndef ITEM_FUNC_INCLUDED #define ITEM_FUNC_INCLUDED /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2009-2011 Monty Program Ab + Copyright (c) 2009, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -39,6 +39,8 @@ protected: 0 means get this number from first argument */ uint allowed_arg_cols; + /* maybe_null can't be changed by parameters or used table state */ + bool persistent_maybe_null; public: uint arg_count; table_map used_tables_cache, not_null_tables_cache; @@ -64,13 +66,13 @@ public: enum Type type() const { return FUNC_ITEM; } virtual enum Functype functype() const { return UNKNOWN_FUNC; } Item_func(void): - allowed_arg_cols(1), arg_count(0) + allowed_arg_cols(1), persistent_maybe_null(0), arg_count(0) { with_sum_func= 0; with_field= 0; } Item_func(Item *a): - allowed_arg_cols(1), arg_count(1) + allowed_arg_cols(1), persistent_maybe_null(0), arg_count(1) { args= tmp_arg; args[0]= a; @@ -78,7 +80,7 @@ public: with_field= a->with_field; } Item_func(Item *a,Item *b): - allowed_arg_cols(1), arg_count(2) + allowed_arg_cols(1), persistent_maybe_null(0), arg_count(2) { args= tmp_arg; args[0]= a; args[1]= b; @@ -86,7 +88,7 @@ public: with_field= a->with_field || b->with_field; } Item_func(Item *a,Item *b,Item *c): - allowed_arg_cols(1) + allowed_arg_cols(1), persistent_maybe_null(0) { arg_count= 0; if ((args= (Item**) sql_alloc(sizeof(Item*)*3))) @@ -98,7 +100,7 @@ public: } } Item_func(Item *a,Item *b,Item *c,Item *d): - allowed_arg_cols(1) + allowed_arg_cols(1), persistent_maybe_null(0) { arg_count= 0; if ((args= (Item**) sql_alloc(sizeof(Item*)*4))) @@ -112,7 +114,7 @@ public: } } Item_func(Item *a,Item *b,Item *c,Item *d,Item* e): - allowed_arg_cols(1) + allowed_arg_cols(1), persistent_maybe_null(0) { arg_count= 5; if ((args= (Item**) sql_alloc(sizeof(Item*)*5))) @@ -170,6 +172,18 @@ public: my_decimal *val_decimal(my_decimal *); + void fix_char_length_ulonglong(ulonglong max_char_length_arg) + { + ulonglong max_result_length= max_char_length_arg * + collation.collation->mbmaxlen; + if (max_result_length >= MAX_BLOB_WIDTH) + { + max_length= MAX_BLOB_WIDTH; + set_persist_maybe_null(1); + } + else + max_length= (uint32) max_result_length; + } bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems, uint flags, int item_sep) { @@ -371,6 +385,11 @@ public: info.bool_function= &Item::restore_to_before_no_rows_in_result; walk(&Item::call_bool_func_processor, FALSE, (uchar*) &info); } + inline void set_persist_maybe_null(bool mb_null) + { + maybe_null= mb_null; + persistent_maybe_null= 1; + } }; @@ -584,7 +603,7 @@ public: } double val_real(); enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } - void fix_length_and_dec() { maybe_null= 1; } + void fix_length_and_dec() { set_persist_maybe_null(1); } const char *func_name() const { return "double_typecast"; } virtual void print(String *str, enum_query_type query_type); }; @@ -725,7 +744,7 @@ class Item_dec_func :public Item_real_func void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); - maybe_null=1; + set_persist_maybe_null(1); } }; @@ -1057,7 +1076,7 @@ public: Item_func_coercibility(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "coercibility"; } - void fix_length_and_dec() { max_length=10; maybe_null= 0; } + void fix_length_and_dec() { max_length=10; set_persist_maybe_null(0); } table_map not_null_tables() const { return 0; } }; @@ -1199,6 +1218,7 @@ public: const char *func_name() const { return "last_insert_id"; } void fix_length_and_dec() { + unsigned_flag= TRUE; if (arg_count) max_length= args[0]->max_length; unsigned_flag=1; @@ -1219,7 +1239,7 @@ public: {} longlong val_int(); const char *func_name() const { return "benchmark"; } - void fix_length_and_dec() { max_length=1; maybe_null=0; } + void fix_length_and_dec() { max_length=1; set_persist_maybe_null(0); } virtual void print(String *str, enum_query_type query_type); bool check_vcol_func_processor(uchar *int_arg) { @@ -1472,7 +1492,7 @@ public: double val_real() { DBUG_ASSERT(fixed == 1); null_value= 1; return 0.0; } longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; } enum Item_result result_type () const { return STRING_RESULT; } - void fix_length_and_dec() { maybe_null=1; max_length=0; } + void fix_length_and_dec() { set_persist_maybe_null(1); max_length=0; } }; #endif /* HAVE_DLOPEN */ @@ -1493,7 +1513,7 @@ class Item_func_get_lock :public Item_int_func Item_func_get_lock(Item *a,Item *b) :Item_int_func(a,b) {} longlong val_int(); const char *func_name() const { return "get_lock"; } - void fix_length_and_dec() { max_length=1; maybe_null=1;} + void fix_length_and_dec() { max_length=1; set_persist_maybe_null(1);} bool check_vcol_func_processor(uchar *int_arg) { return trace_unsupported_by_check_vcol_func_processor(func_name()); @@ -1507,7 +1527,7 @@ public: Item_func_release_lock(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "release_lock"; } - void fix_length_and_dec() { max_length=1; maybe_null=1;} + void fix_length_and_dec() { max_length=1; set_persist_maybe_null(1);} bool check_vcol_func_processor(uchar *int_arg) { return trace_unsupported_by_check_vcol_func_processor(func_name()); @@ -1524,7 +1544,7 @@ public: Item_master_pos_wait(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {} longlong val_int(); const char *func_name() const { return "master_pos_wait"; } - void fix_length_and_dec() { max_length=21; maybe_null=1;} + void fix_length_and_dec() { max_length=21; set_persist_maybe_null(1);} bool check_vcol_func_processor(uchar *int_arg) { return trace_unsupported_by_check_vcol_func_processor(func_name()); @@ -1741,7 +1761,8 @@ public: Item_func_inet_aton(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "inet_aton"; } - void fix_length_and_dec() { decimals= 0; max_length= 21; maybe_null= 1; unsigned_flag= 1;} + void fix_length_and_dec() + { decimals= 0; max_length= 21; set_persist_maybe_null(1); unsigned_flag= 1; } }; @@ -1810,7 +1831,8 @@ public: Item_func_is_free_lock(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "is_free_lock"; } - void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;} + void fix_length_and_dec() + { decimals= 0; max_length= 1; set_persist_maybe_null(1); } bool check_vcol_func_processor(uchar *int_arg) { return trace_unsupported_by_check_vcol_func_processor(func_name()); @@ -1824,7 +1846,8 @@ public: Item_func_is_used_lock(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "is_used_lock"; } - void fix_length_and_dec() { decimals=0; max_length=10; maybe_null=1;} + void fix_length_and_dec() + { decimals= 0; max_length= 10; set_persist_maybe_null(1);} bool check_vcol_func_processor(uchar *int_arg) { return trace_unsupported_by_check_vcol_func_processor(func_name()); @@ -1847,7 +1870,7 @@ public: Item_func_row_count() :Item_int_func() {} longlong val_int(); const char *func_name() const { return "row_count"; } - void fix_length_and_dec() { decimals= 0; maybe_null=0; } + void fix_length_and_dec() { decimals= 0; set_persist_maybe_null(0); } bool check_vcol_func_processor(uchar *int_arg) { @@ -1987,7 +2010,7 @@ public: Item_func_found_rows() :Item_int_func() {} longlong val_int(); const char *func_name() const { return "found_rows"; } - void fix_length_and_dec() { decimals= 0; maybe_null=0; } + void fix_length_and_dec() { decimals= 0; set_persist_maybe_null(0); } bool check_vcol_func_processor(uchar *int_arg) { return trace_unsupported_by_check_vcol_func_processor(func_name()); diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index bc89a6c14b3..e3e80bdf59f 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -53,7 +53,7 @@ void Item_geometry_func::fix_length_and_dec() collation.set(&my_charset_bin); decimals=0; max_length= (uint32) 4294967295U; - maybe_null= 1; + set_persist_maybe_null(1); } @@ -147,7 +147,7 @@ void Item_func_as_wkt::fix_length_and_dec() { collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); max_length=MAX_BLOB_WIDTH; - maybe_null= 1; + set_persist_maybe_null(1); } diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 3638d9f62e8..ee61f921adb 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -89,7 +89,7 @@ public: { // "GeometryCollection" is the longest fix_length_and_charset(20, default_charset()); - maybe_null= 1; + set_persist_maybe_null(1); }; }; @@ -224,7 +224,7 @@ public: { Item_func::print(str, query_type); } - void fix_length_and_dec() { maybe_null= 1; } + void fix_length_and_dec() { set_persist_maybe_null(1); } bool is_null() { (void) val_int(); return null_value; } }; @@ -251,7 +251,7 @@ public: Item_func::print(str, query_type); } - void fix_length_and_dec() { maybe_null= 1; } + void fix_length_and_dec() { set_persist_maybe_null(1); } bool is_null() { (void) val_int(); return null_value; } }; @@ -342,7 +342,7 @@ public: longlong val_int(); optimize_type select_optimize() const { return OPTIMIZE_NONE; } const char *func_name() const { return "st_isempty"; } - void fix_length_and_dec() { maybe_null= 1; } + void fix_length_and_dec() { set_persist_maybe_null(1); } }; class Item_func_issimple: public Item_bool_func @@ -356,7 +356,7 @@ public: longlong val_int(); optimize_type select_optimize() const { return OPTIMIZE_NONE; } const char *func_name() const { return "st_issimple"; } - void fix_length_and_dec() { maybe_null= 1; } + void fix_length_and_dec() { set_persist_maybe_null(1); } }; class Item_func_isclosed: public Item_bool_func @@ -366,7 +366,7 @@ public: longlong val_int(); optimize_type select_optimize() const { return OPTIMIZE_NONE; } const char *func_name() const { return "st_isclosed"; } - void fix_length_and_dec() { maybe_null= 1; } + void fix_length_and_dec() { set_persist_maybe_null(1); } }; class Item_func_dimension: public Item_int_func @@ -376,7 +376,7 @@ public: Item_func_dimension(Item *a): Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "st_dimension"; } - void fix_length_and_dec() { max_length= 10; maybe_null= 1; } + void fix_length_and_dec() { max_length= 10; set_persist_maybe_null(1); } }; class Item_func_x: public Item_real_func @@ -389,7 +389,7 @@ public: void fix_length_and_dec() { Item_real_func::fix_length_and_dec(); - maybe_null= 1; + set_persist_maybe_null(1); } }; @@ -404,7 +404,7 @@ public: void fix_length_and_dec() { Item_real_func::fix_length_and_dec(); - maybe_null= 1; + set_persist_maybe_null(1); } }; @@ -416,7 +416,7 @@ public: Item_func_numgeometries(Item *a): Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "st_numgeometries"; } - void fix_length_and_dec() { max_length= 10; maybe_null= 1; } + void fix_length_and_dec() { max_length= 10; set_persist_maybe_null(1); } }; @@ -427,7 +427,7 @@ public: Item_func_numinteriorring(Item *a): Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "st_numinteriorrings"; } - void fix_length_and_dec() { max_length= 10; maybe_null= 1; } + void fix_length_and_dec() { max_length= 10; set_persist_maybe_null(1); } }; @@ -438,7 +438,7 @@ public: Item_func_numpoints(Item *a): Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "st_numpoints"; } - void fix_length_and_dec() { max_length= 10; maybe_null= 1; } + void fix_length_and_dec() { max_length= 10; set_persist_maybe_null(1); } }; @@ -452,7 +452,7 @@ public: void fix_length_and_dec() { Item_real_func::fix_length_and_dec(); - maybe_null= 1; + set_persist_maybe_null(1); } }; @@ -467,7 +467,7 @@ public: void fix_length_and_dec() { Item_real_func::fix_length_and_dec(); - maybe_null= 1; + set_persist_maybe_null(1); } }; @@ -479,7 +479,7 @@ public: Item_func_srid(Item *a): Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "srid"; } - void fix_length_and_dec() { max_length= 10; maybe_null= 1; } + void fix_length_and_dec() { max_length= 10; set_persist_maybe_null(1); } }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index cce99ec2991..28009e7154e 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1,5 +1,6 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2009, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -466,7 +467,7 @@ String *Item_func_aes_decrypt::val_str(String *str) void Item_func_aes_decrypt::fix_length_and_dec() { max_length=args[0]->max_length; - maybe_null= 1; + set_persist_maybe_null(1); } @@ -2410,7 +2411,7 @@ void Item_func_elt::fix_length_and_dec() set_if_bigger(decimals,args[i]->decimals); } fix_char_length(char_length); - maybe_null=1; // NULL if wrong first arg + set_persist_maybe_null(1); // NULL if wrong first arg } @@ -2658,7 +2659,7 @@ void Item_func_repeat::fix_length_and_dec() else { max_length= MAX_BLOB_WIDTH; - maybe_null= 1; + set_persist_maybe_null(1); } } @@ -2735,7 +2736,7 @@ void Item_func_rpad::fix_length_and_dec() else { max_length= MAX_BLOB_WIDTH; - maybe_null= 1; + set_persist_maybe_null(1); } } @@ -2839,7 +2840,7 @@ void Item_func_lpad::fix_length_and_dec() else { max_length= MAX_BLOB_WIDTH; - maybe_null= 1; + set_persist_maybe_null(1); } } @@ -3798,7 +3799,7 @@ bool Item_func_dyncol_create::fix_fields(THD *thd, Item **ref) void Item_func_dyncol_create::fix_length_and_dec() { - maybe_null= TRUE; + set_persist_maybe_null(1); collation.set(&my_charset_bin); decimals= 0; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 9ed2627a518..786f66e3aab 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -3,6 +3,7 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2009, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -354,7 +355,7 @@ public: String *val_str(String *); void fix_length_and_dec() { - maybe_null=1; + set_persist_maybe_null(1); /* 9 = MAX ((8- (arg_len % 8)) + 1) */ max_length = args[0]->max_length + 9; } @@ -370,7 +371,7 @@ public: String *val_str(String *); void fix_length_and_dec() { - maybe_null=1; + set_persist_maybe_null(1); /* 9 = MAX ((8- (arg_len % 8)) + 1) */ max_length= args[0]->max_length; if (max_length >= 9U) @@ -398,7 +399,7 @@ public: constructor_helper(); } String *val_str(String *); - void fix_length_and_dec() { maybe_null=1; max_length = 13; } + void fix_length_and_dec() { set_persist_maybe_null(1); max_length = 13; } const char *func_name() const { return "encrypt"; } bool check_vcol_func_processor(uchar *int_arg) { @@ -468,7 +469,7 @@ public: void fix_length_and_dec() { max_length= MAX_FIELD_NAME * system_charset_info->mbmaxlen; - maybe_null=1; + set_persist_maybe_null(1); } const char *func_name() const { return "database"; } const char *fully_qualified_func_name() const { return "database()"; } @@ -649,7 +650,7 @@ public: { collation.set(default_charset()); max_length=64; - maybe_null= 1; + set_persist_maybe_null(1); } }; @@ -676,7 +677,7 @@ public: Item_func_unhex(Item *a) :Item_str_func(a) { /* there can be bad hex strings */ - maybe_null= 1; + set_persist_maybe_null(1); } const char *func_name() const { return "unhex"; } String *val_str(String *); @@ -762,7 +763,7 @@ public: void fix_length_and_dec() { collation.set(&my_charset_bin, DERIVATION_COERCIBLE); - maybe_null=1; + set_persist_maybe_null(1); max_length=MAX_BLOB_WIDTH; } bool check_vcol_func_processor(uchar *int_arg) @@ -795,7 +796,7 @@ public: { decimals= 0; fix_length_and_charset(3 * 8 + 7, default_charset()); - maybe_null= 1; + set_persist_maybe_null(1); } }; @@ -910,7 +911,7 @@ public: { collation.set(system_charset_info); max_length= 64 * collation.collation->mbmaxlen; // should be enough - maybe_null= 0; + set_persist_maybe_null(0); }; table_map not_null_tables() const { return 0; } }; @@ -925,7 +926,7 @@ public: { collation.set(system_charset_info); max_length= 64 * collation.collation->mbmaxlen; // should be enough - maybe_null= 0; + set_persist_maybe_null(0); }; table_map not_null_tables() const { return 0; } }; @@ -971,7 +972,8 @@ class Item_func_uncompress: public Item_str_func String buffer; public: Item_func_uncompress(Item *a): Item_str_func(a){} - void fix_length_and_dec(){ maybe_null= 1; max_length= MAX_BLOB_WIDTH; } + void fix_length_and_dec() + { set_persist_maybe_null(1); max_length= MAX_BLOB_WIDTH; } const char *func_name() const{return "uncompress";} String *val_str(String *) ZLIB_DEPENDED_FUNCTION }; @@ -1040,7 +1042,7 @@ public: max_length= MAX_DYNAMIC_COLUMN_LENGTH; } void fix_length_and_dec() - { maybe_null= 1; } + { set_persist_maybe_null(1); } /* Mark that collation can change between calls */ bool dynamic_result() { return 1; } @@ -1059,7 +1061,8 @@ class Item_func_dyncol_list: public Item_str_func { public: Item_func_dyncol_list(Item *str) :Item_str_func(str) {}; - void fix_length_and_dec() { maybe_null= 1; max_length= MAX_BLOB_WIDTH; }; + void fix_length_and_dec() + { set_persist_maybe_null(1); max_length= MAX_BLOB_WIDTH; }; const char *func_name() const{ return "column_list"; } String *val_str(String *); }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 117276e488b..02a7b8511af 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. - Copyright (c) 2009, 2011, Monty Program Ab + Copyright (c) 2009, 2013, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -945,7 +945,7 @@ void Item_func_monthname::fix_length_and_dec() collation.set(cs, DERIVATION_COERCIBLE, repertoire); decimals=0; max_length= locale->max_month_name_length * collation.collation->mbmaxlen; - maybe_null=1; + set_persist_maybe_null(1); } @@ -1095,7 +1095,7 @@ void Item_func_dayname::fix_length_and_dec() collation.set(cs, DERIVATION_COERCIBLE, repertoire); decimals=0; max_length= locale->max_day_name_length * collation.collation->mbmaxlen; - maybe_null=1; + set_persist_maybe_null(1); } @@ -1446,7 +1446,7 @@ void Item_temporal_func::fix_length_and_dec() { MAX_DATETIME_WIDTH, MAX_DATETIME_WIDTH, MAX_DATE_WIDTH, MAX_DATETIME_WIDTH, MIN_TIME_WIDTH }; - maybe_null= true; + set_persist_maybe_null(1); max_length= max_time_type_width[mysql_type_to_time_type(field_type())+2]; if (decimals) { @@ -1501,13 +1501,10 @@ bool Item_func_from_days::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) bzero(ltime, sizeof(MYSQL_TIME)); if (get_date_from_daynr((long) value, <ime->year, <ime->month, <ime->day)) - return (null_value= 1); - - if ((fuzzy_date & TIME_NO_ZERO_DATE) && ltime->year == 0) - return (null_value= 1); + return 0; ltime->time_type= MYSQL_TIMESTAMP_DATE; - return (null_value= 0); + return 0; } @@ -1519,7 +1516,7 @@ void Item_func_curdate::fix_length_and_dec() ltime.hour= ltime.minute= ltime.second= 0; ltime.time_type= MYSQL_TIMESTAMP_DATE; Item_datefunc::fix_length_and_dec(); - maybe_null= false; + set_persist_maybe_null(0); } /** @@ -1758,7 +1755,7 @@ void Item_func_date_format::fix_length_and_dec() collation.collation->mbmaxlen; set_if_smaller(max_length,MAX_BLOB_WIDTH); } - maybe_null=1; // If wrong date + set_persist_maybe_null(1); // If wrong date } @@ -2102,7 +2099,7 @@ void Item_extract::print(String *str, enum_query_type query_type) void Item_extract::fix_length_and_dec() { - maybe_null=1; // If wrong date + set_persist_maybe_null(1); // If wrong date switch (int_type) { case INTERVAL_YEAR: max_length=4; date_value=1; break; case INTERVAL_YEAR_MONTH: max_length=6; date_value=1; break; diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 3af08a8168e..3e3cd698efc 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -82,7 +82,7 @@ public: { decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; - maybe_null=1; + set_persist_maybe_null(1); } enum_monotonicity_info get_monotonicity_info() const; longlong val_int_endpoint(bool left_endp, bool *incl_endp); @@ -105,7 +105,7 @@ public: { decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; - maybe_null=1; + set_persist_maybe_null(1); } enum_monotonicity_info get_monotonicity_info() const; longlong val_int_endpoint(bool left_endp, bool *incl_endp); @@ -138,7 +138,7 @@ public: { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; - maybe_null=1; + set_persist_maybe_null(1); } bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool check_vcol_func_processor(uchar *int_arg) { return FALSE;} @@ -170,7 +170,7 @@ public: { decimals= 0; fix_char_length(2); - maybe_null= 1; + set_persist_maybe_null(1); } bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool check_vcol_func_processor(uchar *int_arg) { return FALSE;} @@ -208,7 +208,7 @@ public: { decimals= 0; fix_char_length(3); - maybe_null= 1; + set_persist_maybe_null(1); } bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool check_vcol_func_processor(uchar *int_arg) { return FALSE;} @@ -229,7 +229,7 @@ public: { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; - maybe_null=1; + set_persist_maybe_null(1); } bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool check_vcol_func_processor(uchar *int_arg) { return FALSE;} @@ -250,7 +250,7 @@ public: { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; - maybe_null=1; + set_persist_maybe_null(1); } bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool check_vcol_func_processor(uchar *int_arg) { return FALSE;} @@ -271,7 +271,7 @@ public: { decimals=0; max_length=1*MY_CHARSET_BIN_MB_MAXLEN; - maybe_null=1; + set_persist_maybe_null(1); } bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool check_vcol_func_processor(uchar *int_arg) { return FALSE;} @@ -292,7 +292,7 @@ public: { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; - maybe_null=1; + set_persist_maybe_null(1); } bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool check_vcol_func_processor(uchar *int_arg) { return FALSE;} @@ -313,7 +313,7 @@ public: { decimals=0; max_length=2*MY_CHARSET_BIN_MB_MAXLEN; - maybe_null=1; + set_persist_maybe_null(1); } }; @@ -327,7 +327,7 @@ public: { decimals=0; max_length=6*MY_CHARSET_BIN_MB_MAXLEN; - maybe_null=1; + set_persist_maybe_null(1); } bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool check_vcol_func_processor(uchar *int_arg) { return FALSE;} @@ -350,7 +350,7 @@ public: { decimals=0; max_length=4*MY_CHARSET_BIN_MB_MAXLEN; - maybe_null=1; + set_persist_maybe_null(1); } bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool check_vcol_func_processor(uchar *int_arg) { return FALSE;} @@ -384,7 +384,7 @@ public: { decimals= 0; fix_char_length(1); - maybe_null= 1; + set_persist_maybe_null(1); } bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool check_vcol_func_processor(uchar *int_arg) { return FALSE;} @@ -419,7 +419,7 @@ public: decimals= args[0]->decimals; set_if_smaller(decimals, TIME_SECOND_PART_DIGITS); max_length=17 + (decimals ? decimals + 1 : 0); - maybe_null= 1; + set_persist_maybe_null(1); } void find_num_type() { hybrid_type= decimals ? DECIMAL_RESULT : INT_RESULT; } double real_op() { DBUG_ASSERT(0); return 0; } @@ -466,7 +466,7 @@ public: const char *func_name() const { return "time_to_sec"; } void fix_num_length_and_dec() { - maybe_null= true; + set_persist_maybe_null(1); Item_func_seconds_hybrid::fix_num_length_and_dec(); } bool check_partition_func_processor(uchar *int_arg) {return FALSE;} @@ -537,7 +537,7 @@ public: { store_now_in_TIME(<ime); Item_timefunc::fix_length_and_dec(); - maybe_null= false; + set_persist_maybe_null(0); } bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); /* @@ -619,7 +619,7 @@ public: { store_now_in_TIME(<ime); Item_temporal_func::fix_length_and_dec(); - maybe_null= false; + set_persist_maybe_null(0); } bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); virtual void store_now_in_TIME(MYSQL_TIME *now_time)=0; @@ -664,7 +664,7 @@ public: void update_used_tables() { Item_func_now::update_used_tables(); - maybe_null= false; + set_persist_maybe_null(0); used_tables_cache|= RAND_TABLE_BIT; } }; @@ -959,7 +959,7 @@ public: void fix_length_and_dec() { decimals=0; - maybe_null=1; + set_persist_maybe_null(1); } bool check_partition_func_processor(uchar *int_arg) {return FALSE;} bool check_vcol_func_processor(uchar *int_arg) { return FALSE;} @@ -981,7 +981,7 @@ public: void fix_length_and_dec() { decimals=0; - maybe_null=1; + set_persist_maybe_null(1); } virtual void print(String *str, enum_query_type query_type); }; @@ -1003,7 +1003,7 @@ public: const char *func_name() const { return "get_format"; } void fix_length_and_dec() { - maybe_null= 1; + set_persist_maybe_null(1); decimals=0; fix_length_and_charset(17, default_charset()); } diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index ae0a74c5ba6..5a824e48b7b 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -2604,6 +2604,7 @@ void Item_xml_str_func::fix_length_and_dec() status_var_increment(current_thd->status_var.feature_xml); nodeset_func= 0; + set_persist_maybe_null(1); if (agg_arg_charsets_for_comparison(collation, args, arg_count)) return; diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h index 800cf6ed760..3356b4ac902 100644 --- a/sql/item_xmlfunc.h +++ b/sql/item_xmlfunc.h @@ -34,14 +34,10 @@ protected: public: Item_xml_str_func(Item *a, Item *b): Item_str_func(a,b) - { - maybe_null= TRUE; - } + {} Item_xml_str_func(Item *a, Item *b, Item *c): Item_str_func(a,b,c) - { - maybe_null= TRUE; - } + {} void fix_length_and_dec(); String *parse_xml(String *raw_xml, String *parsed_xml_buf); bool check_vcol_func_processor(uchar *int_arg) diff --git a/sql/log.cc b/sql/log.cc index b7218615f58..abda8c52d88 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2010, 2013 Monty Program Ab + Copyright (c) 2009, 2013, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -5024,12 +5024,18 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd, /* Write pending event to the cache. */ + DBUG_EXECUTE_IF("simulate_disk_full_at_flush_pending", + {DBUG_SET("+d,simulate_file_write_error");}); if (pending->write(file)) { set_write_error(thd, is_transactional); if (check_write_error(thd) && cache_data && stmt_has_updated_non_trans_table(thd)) cache_data->set_incident(); + delete pending; + cache_data->set_pending(NULL); + DBUG_EXECUTE_IF("simulate_disk_full_at_flush_pending", + {DBUG_SET("-d,simulate_file_write_error");}); DBUG_RETURN(1); } diff --git a/sql/log_event.cc b/sql/log_event.cc index a46da2304b2..d5cfa9367c5 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. - Copyright (c) 2010, 2012, Monty Program Ab + Copyright (c) 2009, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,7 +46,7 @@ #include "rpl_record.h" #include "transaction.h" #include <my_dir.h> -#include "sql_show.h" +#include "sql_show.h" // append_identifier #endif /* MYSQL_CLIENT */ @@ -92,6 +92,23 @@ TYPELIB binlog_checksum_typelib= */ #define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1) +/* + Explicit instantiation to unsigned int of template available_buffer + function. +*/ +template unsigned int available_buffer<unsigned int>(const char*, + const char*, + unsigned int); + +/* + Explicit instantiation to unsigned int of template valid_buffer_range + function. +*/ +template bool valid_buffer_range<unsigned int>(unsigned int, + const char*, + const char*, + unsigned int); + /* replication event checksum is introduced in the following "checksum-home" version. The checksum-aware servers extract FD's version to decide whether the FD event @@ -1572,7 +1589,7 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, ev = new Rand_log_event(buf, description_event); break; case USER_VAR_EVENT: - ev = new User_var_log_event(buf, description_event); + ev = new User_var_log_event(buf, event_len, description_event); break; case FORMAT_DESCRIPTION_EVENT: ev = new Format_description_log_event(buf, event_len, description_event); @@ -2297,7 +2314,7 @@ void Rows_log_event::print_verbose(IO_CACHE *file, for (const uchar *value= m_rows_buf; value < m_rows_end; ) { size_t length; - my_b_printf(file, "### %s %s.%s\n", + my_b_printf(file, "### %s %`s.%`s\n", sql_command, map->get_db_name(), map->get_table_name()); /* Print the first image */ @@ -2463,7 +2480,7 @@ void Query_log_event::pack_info(THD *thd, Protocol *protocol) { buf.append(STRING_WITH_LEN("use ")); append_identifier(thd, &buf, db, db_len); - buf.append("; "); + buf.append(STRING_WITH_LEN("; ")); } if (query && q_len) buf.append(query, q_len); @@ -3333,17 +3350,11 @@ void Query_log_event::print_query_header(IO_CACHE* file, } else if (db) { - /* Room for expand ` to `` + initial/final ` + \0 */ - char buf[FN_REFLEN*2+3]; - different_db= memcmp(print_event_info->db, db, db_len + 1); if (different_db) memcpy(print_event_info->db, db, db_len + 1); if (db[0] && different_db) - { - my_snprintf(buf, sizeof(buf), "%`s", db); - my_b_printf(file, "use %s%s\n", buf, print_event_info->delimiter); - } + my_b_printf(file, "use %`s%s\n", db, print_event_info->delimiter); } end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10); @@ -5175,7 +5186,7 @@ void Load_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info, } if (db && db[0] && different_db) - my_b_printf(&cache, "%suse %s%s\n", + my_b_printf(&cache, "%suse %`s%s\n", commented ? "# " : "", db, print_event_info->delimiter); @@ -5227,7 +5238,7 @@ void Load_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info, { if (i) my_b_printf(&cache, ","); - my_b_printf(&cache, "%s", field); + my_b_printf(&cache, "%`s", field); field += field_lens[i] + 1; } @@ -6287,19 +6298,35 @@ void User_var_log_event::pack_info(THD *thd, Protocol* protocol) User_var_log_event:: -User_var_log_event(const char* buf, +User_var_log_event(const char* buf, uint event_len, const Format_description_log_event* description_event) :Log_event(buf, description_event) #ifndef MYSQL_CLIENT , deferred(false) #endif { + bool error= false; + const char* buf_start= buf; /* The Post-Header is empty. The Variable Data part begins immediately. */ const char *start= buf; buf+= description_event->common_header_len + description_event->post_header_len[USER_VAR_EVENT-1]; name_len= uint4korr(buf); name= (char *) buf + UV_NAME_LEN_SIZE; + + /* + We don't know yet is_null value, so we must assume that name_len + may have the bigger value possible, is_null= True and there is no + payload for val. + */ + if (0 == name_len || + !valid_buffer_range<uint>(name_len, buf_start, name, + event_len - UV_VAL_IS_NULL)) + { + error= true; + goto err; + } + buf+= UV_NAME_LEN_SIZE + name_len; is_null= (bool) *buf; flags= User_var_log_event::UNDEF_F; // defaults to UNDEF_F @@ -6312,6 +6339,14 @@ User_var_log_event(const char* buf, } else { + if (!valid_buffer_range<uint>(UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE, + buf_start, buf, event_len)) + { + error= true; + goto err; + } + type= (Item_result) buf[UV_VAL_IS_NULL]; charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE); val_len= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + @@ -6319,6 +6354,12 @@ User_var_log_event(const char* buf, val= (char *) (buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE); + if (!valid_buffer_range<uint>(val_len, buf_start, val, event_len)) + { + error= true; + goto err; + } + /** We need to check if this is from an old server that did not pack information for flags. @@ -6353,6 +6394,10 @@ User_var_log_event(const char* buf, val_len); } } + +err: + if (error) + name= 0; } @@ -6498,8 +6543,9 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) char *hex_str; CHARSET_INFO *cs; - if (!(hex_str= (char *)my_alloca(2*val_len+1+2))) // 2 hex digits / byte - break; // no error, as we are 'void' + hex_str= (char *)my_malloc(2*val_len+1+2,MYF(MY_WME)); // 2 hex digits / byte + if (!hex_str) + return; str_to_hex(hex_str, val, val_len); /* For proper behaviour when mysqlbinlog|mysql, we need to explicitely @@ -6517,7 +6563,7 @@ void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) my_b_printf(&cache, ":=_%s %s COLLATE `%s`%s\n", cs->csname, hex_str, cs->name, print_event_info->delimiter); - my_afree(hex_str); + my_free(hex_str); } break; case ROW_RESULT: @@ -7756,9 +7802,9 @@ void Execute_load_query_log_event::pack_info(THD *thd, Protocol *protocol) buf.real_alloc(9 + db_len + q_len + 10 + 21); if (db && db_len) { - if (buf.append("use ") || + if (buf.append(STRING_WITH_LEN("use ")) || append_identifier(thd, &buf, db, db_len) || - buf.append("; ")) + buf.append(STRING_WITH_LEN("; "))) return; } if (query && q_len && buf.append(query, q_len)) diff --git a/sql/log_event.h b/sql/log_event.h index bf45dd0cc93..2c2e1dcd8b9 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -2693,7 +2693,7 @@ public: void print(FILE* file, PRINT_EVENT_INFO* print_event_info); #endif - User_var_log_event(const char* buf, + User_var_log_event(const char* buf, uint event_len, const Format_description_log_event *description_event); ~User_var_log_event() {} Log_event_type get_type_code() { return USER_VAR_EVENT;} @@ -2705,9 +2705,9 @@ public: and which case the applier adjusts execution path. */ bool is_deferred() { return deferred; } - void set_deferred() { deferred= val; } + void set_deferred() { deferred= true; } #endif - bool is_valid() const { return 1; } + bool is_valid() const { return name != 0; } private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 37e54a6638c..14737cd69bb 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5354,7 +5354,7 @@ void create_thread_to_handle_connection(THD *thd) if (cached_thread_count > wake_thread) { /* Get thread from cache */ - thread_cache.append(thd); + thread_cache.push_back(thd); wake_thread++; mysql_cond_signal(&COND_thread_cache); } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 0d92a68a2d4..22bce1dad4f 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -4020,8 +4020,6 @@ typedef struct st_sp_table Multi-set key: db_name\0table_name\0alias\0 - for normal tables db_name\0table_name\0 - for temporary tables - Note that in both cases we don't take last '\0' into account when - we count length of key. */ LEX_STRING qname; uint db_length, table_name_length; @@ -4078,19 +4076,26 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) for (; table ; table= table->next_global) if (!table->derived && !table->schema_table) { - char tname[(SAFE_NAME_LEN + 1) * 3]; // db\0table\0alias\0 - uint tlen, alen; - - tlen= table->db_length; - memcpy(tname, table->db, tlen); - tname[tlen++]= '\0'; - memcpy(tname+tlen, table->table_name, table->table_name_length); - tlen+= table->table_name_length; - tname[tlen++]= '\0'; - alen= strlen(table->alias); - memcpy(tname+tlen, table->alias, alen); - tlen+= alen; - tname[tlen]= '\0'; + /* + Structure of key for the multi-set is "db\0table\0alias\0". + Since "alias" part can have arbitrary length we use String + object to construct the key. By default String will use + buffer allocated on stack with NAME_LEN bytes reserved for + alias, since in most cases it is going to be smaller than + NAME_LEN bytes. + */ + char tname_buff[(SAFE_NAME_LEN + 1) * 3]; + String tname(tname_buff, sizeof(tname_buff), &my_charset_bin); + uint temp_table_key_length; + + tname.length(0); + tname.append(table->db, table->db_length); + tname.append('\0'); + tname.append(table->table_name, table->table_name_length); + tname.append('\0'); + temp_table_key_length= tname.length(); + tname.append(table->alias); + tname.append('\0'); /* Upgrade the lock type because this table list will be used @@ -4105,9 +4110,10 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) (and therefore should not be prelocked). Otherwise we will erroneously treat table with same name but with different alias as non-temporary. */ - if ((tab= (SP_TABLE*) my_hash_search(&m_sptabs, (uchar *)tname, tlen)) || - ((tab= (SP_TABLE*) my_hash_search(&m_sptabs, (uchar *)tname, - tlen - alen - 1)) && + if ((tab= (SP_TABLE *)my_hash_search(&m_sptabs, (uchar *)tname.ptr(), + tname.length())) || + ((tab= (SP_TABLE *)my_hash_search(&m_sptabs, (uchar *)tname.ptr(), + temp_table_key_length)) && tab->temp)) { if (tab->lock_type < table->lock_type) @@ -4126,11 +4132,11 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) lex_for_tmp_check->create_info.options & HA_LEX_CREATE_TMP_TABLE) { tab->temp= TRUE; - tab->qname.length= tlen - alen - 1; + tab->qname.length= temp_table_key_length; } else - tab->qname.length= tlen; - tab->qname.str= (char*) thd->memdup(tname, tab->qname.length + 1); + tab->qname.length= tname.length(); + tab->qname.str= (char*) thd->memdup(tname.ptr(), tab->qname.length); if (!tab->qname.str) return FALSE; tab->table_name_length= table->table_name_length; @@ -4199,7 +4205,7 @@ sp_head::add_used_tables_to_table_list(THD *thd, if (!(tab_buff= (char *)thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST)) * stab->lock_count)) || !(key_buff= (char*)thd->memdup(stab->qname.str, - stab->qname.length + 1))) + stab->qname.length))) DBUG_RETURN(FALSE); for (uint j= 0; j < stab->lock_count; j++) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index b8e7d891e05..9921969929d 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2009-2011, Monty Program Ab + Copyright (c) 2009, 2013, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -560,7 +560,18 @@ static bool update_user_table(THD *thd, TABLE *table, const char *host, static my_bool acl_load(THD *thd, TABLE_LIST *tables); static my_bool grant_load(THD *thd, TABLE_LIST *tables); static inline void get_grantor(THD *thd, char* grantor); - +/* + Enumeration of various ACL's and Hashes used in handle_grant_struct() +*/ +enum enum_acl_lists +{ + USER_ACL= 0, + DB_ACL, + COLUMN_PRIVILEGES_HASH, + PROC_PRIVILEGES_HASH, + FUNC_PRIVILEGES_HASH, + ACL_PROXY_USERS +}; /* Convert scrambled password to binary form, according to scramble type, Binary form is stored in user.salt. @@ -767,7 +778,12 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) convert db to lower case and give a warning if the db wasn't already in lower case */ - (void) strmov(tmp_name, host.db); + char *end = strnmov(tmp_name, host.db, sizeof(tmp_name)); + if (end >= tmp_name + sizeof(tmp_name)) + { + sql_print_warning(ER(ER_WRONG_DB_NAME), host.db); + continue; + } my_casedn_str(files_charset_info, host.db); if (strcmp(host.db, tmp_name) != 0) sql_print_warning("'host' entry '%s|%s' had database in mixed " @@ -1038,7 +1054,12 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) convert db to lower case and give a warning if the db wasn't already in lower case */ - (void)strmov(tmp_name, db.db); + char *end = strnmov(tmp_name, db.db, sizeof(tmp_name)); + if (end >= tmp_name + sizeof(tmp_name)) + { + sql_print_warning(ER(ER_WRONG_DB_NAME), db.db); + continue; + } my_casedn_str(files_charset_info, db.db); if (strcmp(db.db, tmp_name) != 0) { @@ -3007,15 +3028,23 @@ static GRANT_NAME *name_hash_search(HASH *name_hash, const char *user, const char *tname, bool exact, bool name_tolower) { - char helping [SAFE_NAME_LEN*2+USERNAME_LENGTH+3], *name_ptr; + char helping[SAFE_NAME_LEN*2+USERNAME_LENGTH+3]; + char *hend = helping + sizeof(helping); uint len; GRANT_NAME *grant_name,*found=0; HASH_SEARCH_STATE state; - name_ptr= strmov(strmov(helping, user) + 1, db) + 1; - len = (uint) (strmov(name_ptr, tname) - helping) + 1; + char *db_ptr= strmov(helping, user) + 1; + char *tname_ptr= strnmov(db_ptr, db, hend - db_ptr) + 1; + if (tname_ptr > hend) + return 0; // invalid name = not found + char *end= strnmov(tname_ptr, tname, hend - tname_ptr) + 1; + if (end > hend) + return 0; // invalid name = not found + + len = (uint) (end - helping); if (name_tolower) - my_casedn_str(files_charset_info, name_ptr); + my_casedn_str(files_charset_info, tname_ptr); for (grant_name= (GRANT_NAME*) my_hash_first(name_hash, (uchar*) helping, len, &state); grant_name ; @@ -4016,7 +4045,12 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, if (lower_case_table_names && db) { - strmov(tmp_db,db); + char *end= strnmov(tmp_db,db, sizeof(tmp_db)); + if (end >= tmp_db + sizeof(tmp_db)) + { + my_error(ER_WRONG_DB_NAME ,MYF(0), db); + DBUG_RETURN(TRUE); + } my_casedn_str(files_charset_info, tmp_db); db=tmp_db; } @@ -6058,20 +6092,20 @@ static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop, Delete from grant structure if drop is true. Update in grant structure if drop is false and user_to is not NULL. Search in grant structure if drop is false and user_to is NULL. - Structures are numbered as follows: - 0 acl_users - 1 acl_dbs - 2 column_priv_hash - 3 proc_priv_hash - 4 func_priv_hash - 5 acl_proxy_users + Structures are enumerated as follows: + 0 ACL_USER + 1 ACL_DB + 2 COLUMN_PRIVILEGES_HASH + 3 PROC_PRIVILEGES_HASH + 4 FUNC_PRIVILEGES_HASH + 5 ACL_PROXY_USERS @retval > 0 At least one element matched. @retval 0 OK, but no element matched. - @retval -1 Wrong arguments to function. + @retval -1 Wrong arguments to function or Out of Memory */ -static int handle_grant_struct(uint struct_no, bool drop, +static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, LEX_USER *user_from, LEX_USER *user_to) { int result= 0; @@ -6095,21 +6129,21 @@ static int handle_grant_struct(uint struct_no, bool drop, /* Get the number of elements in the in-memory structure. */ switch (struct_no) { - case 0: + case USER_ACL: elements= acl_users.elements; break; - case 1: + case DB_ACL: elements= acl_dbs.elements; break; - case 2: + case COLUMN_PRIVILEGES_HASH: grant_name_hash= &column_priv_hash; elements= grant_name_hash->records; break; - case 3: + case PROC_PRIVILEGES_HASH: grant_name_hash= &proc_priv_hash; elements= grant_name_hash->records; break; - case 4: + case FUNC_PRIVILEGES_HASH: grant_name_hash= &func_priv_hash; elements= grant_name_hash->records; break; @@ -6131,21 +6165,21 @@ static int handle_grant_struct(uint struct_no, bool drop, Get a pointer to the element. */ switch (struct_no) { - case 0: + case USER_ACL: acl_user= dynamic_element(&acl_users, idx, ACL_USER*); user= acl_user->user; host= acl_user->host.hostname; break; - case 1: + case DB_ACL: acl_db= dynamic_element(&acl_dbs, idx, ACL_DB*); user= acl_db->user; host= acl_db->host.hostname; break; - case 2: - case 3: - case 4: + case COLUMN_PRIVILEGES_HASH: + case PROC_PRIVILEGES_HASH: + case FUNC_PRIVILEGES_HASH: grant_name= (GRANT_NAME*) my_hash_element(grant_name_hash, idx); user= grant_name->user; host= grant_name->host.hostname; @@ -6177,17 +6211,17 @@ static int handle_grant_struct(uint struct_no, bool drop, if ( drop ) { switch ( struct_no ) { - case 0: + case USER_ACL: delete_dynamic_element(&acl_users, idx); break; - case 1: + case DB_ACL: delete_dynamic_element(&acl_dbs, idx); break; - case 2: - case 3: - case 4: + case COLUMN_PRIVILEGES_HASH: + case PROC_PRIVILEGES_HASH: + case FUNC_PRIVILEGES_HASH: my_hash_delete(grant_name_hash, (uchar*) grant_name); break; @@ -6215,19 +6249,19 @@ static int handle_grant_struct(uint struct_no, bool drop, else if ( user_to ) { switch ( struct_no ) { - case 0: + case USER_ACL: acl_user->user= strdup_root(&mem, user_to->user.str); acl_user->host.hostname= strdup_root(&mem, user_to->host.str); break; - case 1: + case DB_ACL: acl_db->user= strdup_root(&mem, user_to->user.str); acl_db->host.hostname= strdup_root(&mem, user_to->host.str); break; - case 2: - case 3: - case 4: + case COLUMN_PRIVILEGES_HASH: + case PROC_PRIVILEGES_HASH: + case FUNC_PRIVILEGES_HASH: { /* Save old hash key and its length to be able properly update @@ -6324,7 +6358,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, else { /* Handle user array. */ - if ((handle_grant_struct(0, drop, user_from, user_to)) || found) + if ((handle_grant_struct(USER_ACL, drop, user_from, user_to)) || found) { result= 1; /* At least one record/element found. */ /* If search is requested, we do not need to search further. */ @@ -6342,7 +6376,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, else { /* Handle db array. */ - if (((handle_grant_struct(1, drop, user_from, user_to) && ! result) || + if (((handle_grant_struct(DB_ACL, drop, user_from, user_to) && ! result) || found) && ! result) { result= 1; /* At least one record/element found. */ @@ -6361,7 +6395,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, else { /* Handle procs array. */ - if (((handle_grant_struct(3, drop, user_from, user_to) && ! result) || + if (((handle_grant_struct(PROC_PRIVILEGES_HASH, drop, user_from, user_to) && ! result) || found) && ! result) { result= 1; /* At least one record/element found. */ @@ -6370,7 +6404,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, goto end; } /* Handle funcs array. */ - if (((handle_grant_struct(4, drop, user_from, user_to) && ! result) || + if (((handle_grant_struct(FUNC_PRIVILEGES_HASH, drop, user_from, user_to) && ! result) || found) && ! result) { result= 1; /* At least one record/element found. */ @@ -6405,7 +6439,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, else { /* Handle columns hash. */ - if (((handle_grant_struct(2, drop, user_from, user_to) && ! result) || + if (((handle_grant_struct(COLUMN_PRIVILEGES_HASH, drop, user_from, user_to) && ! result) || found) && ! result) result= 1; /* At least one record/element found. */ } @@ -6414,7 +6448,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, /* Handle proxies_priv table. */ if (tables[5].table) { - if ((found= handle_grant_table(tables, 5, drop, user_from, user_to)) < 0) + if ((found= handle_grant_table(tables, ACL_PROXY_USERS, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch the in-memory array. */ result= -1; @@ -6422,7 +6456,7 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, else { /* Handle proxies_priv array. */ - if ((handle_grant_struct(5, drop, user_from, user_to) && !result) || + if ((handle_grant_struct(ACL_PROXY_USERS, drop, user_from, user_to) && !result) || found) result= 1; /* At least one record/element found. */ } diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 81a85f10a16..9f6185280cd 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -905,6 +905,19 @@ static int check_connection(THD *thd) my_error(ER_BAD_HOST_ERROR, MYF(0)); return 1; } + /* BEGIN : DEBUG */ + DBUG_EXECUTE_IF("addr_fake_ipv4", + { + struct sockaddr *sa= (sockaddr *) &net->vio->remote; + sa->sa_family= AF_INET; + struct in_addr *ip4= &((struct sockaddr_in *)sa)->sin_addr; + /* See RFC 5737, 192.0.2.0/23 is reserved */ + const char* fake= "192.0.2.4"; + ip4->s_addr= inet_addr(fake); + strcpy(ip, fake); + };); + /* END : DEBUG */ + if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME)))) return 1; /* The error is set by my_strdup(). */ thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 99e5f3a035c..cbe59503058 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1,5 +1,6 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2009, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -754,7 +755,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) { ulong deleted_tables= 0; bool error= true; - char path[FN_REFLEN+16]; + char path[FN_REFLEN + 16]; MY_DIR *dirp; uint length; bool found_other_files= false; @@ -916,7 +917,7 @@ update_binlog: if (!(query= (char*) thd->alloc(MAX_DROP_TABLE_Q_LEN))) goto exit; /* not much else we can do */ - query_pos= query_data_start= strmov(query,"drop table "); + query_pos= query_data_start= strmov(query,"DROP TABLE "); query_end= query + MAX_DROP_TABLE_Q_LEN; db_len= strlen(db); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 13622cb420a..b3ee0636bd7 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2009, 2013, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1864,6 +1865,7 @@ void st_select_lex::init_query() ref_pointer_array= 0; select_n_where_fields= 0; select_n_having_items= 0; + n_child_sum_items= 0; subquery_in_having= explicit_limit= 0; is_item_list_lookup= 0; first_execution= 1; diff --git a/sql/sql_list.h b/sql/sql_list.h index 2b2d9e59771..b4e0ab84aab 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -1,7 +1,6 @@ #ifndef INCLUDES_MYSQL_SQL_LIST_H #define INCLUDES_MYSQL_SQL_LIST_H -/* - Copyright (c) 2000, 2010, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -169,6 +168,14 @@ protected: public: uint elements; + bool operator==(const base_list &rhs) const + { + return + elements == rhs.elements && + first == rhs.first && + last == rhs.last; + } + inline void empty() { elements=0; first= &end_of_list; last=&first;} inline base_list() { empty(); } /** diff --git a/sql/sql_priv.h b/sql/sql_priv.h index ea89a67f210..6e778c09bd8 100644 --- a/sql/sql_priv.h +++ b/sql/sql_priv.h @@ -153,6 +153,41 @@ #define OPTION_ALLOW_BATCH (ULL(1) << 36) // THD, intern (slave) #define OPTION_SKIP_REPLICATION (ULL(1) << 37) // THD, user +/* + Check how many bytes are available on buffer. + + @param buf_start Pointer to buffer start. + @param buf_current Pointer to the current position on buffer. + @param buf_len Buffer length. + + @return Number of bytes available on event buffer. +*/ +template <class T> T available_buffer(const char* buf_start, + const char* buf_current, + T buf_len) +{ + return buf_len - (buf_current - buf_start); +} + +/* + Check if jump value is within buffer limits. + + @param jump Number of positions we want to advance. + @param buf_start Pointer to buffer start + @param buf_current Pointer to the current position on buffer. + @param buf_len Buffer length. + + @return True If jump value is within buffer limits. + False Otherwise. +*/ +template <class T> bool valid_buffer_range(T jump, + const char* buf_start, + const char* buf_current, + T buf_len) +{ + return (jump <= available_buffer(buf_start, buf_current, buf_len)); +} + /* The rest of the file is included in the server only */ #ifndef MYSQL_CLIENT diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index 2d00a19870b..feb7810fa28 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -46,6 +46,7 @@ #define TIME_I_S_DECIMAL_SIZE (TIME_FLOAT_DIGITS*100)+(TIME_FLOAT_DIGITS-3) #define MAX_QUERY_LENGTH 300 +#define MAX_QUERY_HISTORY 101 /** Connects Information_Schema and Profiling. @@ -264,9 +265,12 @@ void PROF_MEASUREMENT::collect() QUERY_PROFILE::QUERY_PROFILE(PROFILING *profiling_arg, const char *status_arg) :profiling(profiling_arg), profiling_query_id(0), query_source(NULL) { - profile_start= new PROF_MEASUREMENT(this, status_arg); - entries.push_back(profile_start); - profile_end= profile_start; + m_seq_counter= 1; + PROF_MEASUREMENT *prof= new PROF_MEASUREMENT(this, status_arg); + prof->m_seq= m_seq_counter++; + m_start_time_usecs= prof->time_usecs; + m_end_time_usecs= m_start_time_usecs; + entries.push_back(prof); } QUERY_PROFILE::~QUERY_PROFILE() @@ -305,9 +309,14 @@ void QUERY_PROFILE::new_status(const char *status_arg, else prof= new PROF_MEASUREMENT(this, status_arg); - profile_end= prof; + prof->m_seq= m_seq_counter++; + m_end_time_usecs= prof->time_usecs; entries.push_back(prof); + /* Maintain the query history size. */ + while (entries.elements > MAX_QUERY_HISTORY) + delete entries.pop(); + DBUG_VOID_RETURN; } @@ -467,8 +476,7 @@ bool PROFILING::show_profiles() String elapsed; - PROF_MEASUREMENT *ps= prof->profile_start; - PROF_MEASUREMENT *pe= prof->profile_end; + double query_time_usecs= prof->m_end_time_usecs - prof->m_start_time_usecs; if (++idx <= unit->offset_limit_cnt) continue; @@ -477,7 +485,7 @@ bool PROFILING::show_profiles() protocol->prepare_for_resend(); protocol->store((uint32)(prof->profiling_query_id)); - protocol->store((double)(pe->time_usecs - ps->time_usecs)/(1000.0*1000), + protocol->store((double)(query_time_usecs/(1000.0*1000)), (uint32) TIME_FLOAT_DIGITS-1, &elapsed); if (prof->query_source != NULL) protocol->store(prof->query_source, strlen(prof->query_source), @@ -537,17 +545,18 @@ int PROFILING::fill_statistics_info(THD *thd_arg, TABLE_LIST *tables, Item *cond us also include a numbering of each state per query. The query_id and the "seq" together are unique. */ - ulonglong seq; + ulong seq; void *entry_iterator; PROF_MEASUREMENT *entry, *previous= NULL; /* ...and for each query, go through all its state-change steps. */ - for (seq= 0, entry_iterator= query->entries.new_iterator(); + for (entry_iterator= query->entries.new_iterator(); entry_iterator != NULL; entry_iterator= query->entries.iterator_next(entry_iterator), - seq++, previous=entry, row_number++) + previous=entry, row_number++) { entry= query->entries.iterator_value(entry_iterator); + seq= entry->m_seq; /* Skip the first. We count spans of fence, not fence-posts. */ if (previous == NULL) continue; diff --git a/sql/sql_profile.h b/sql/sql_profile.h index 7705f6ca476..f8970bb162a 100644 --- a/sql/sql_profile.h +++ b/sql/sql_profile.h @@ -186,6 +186,7 @@ private: char *file; unsigned int line; + ulong m_seq; double time_usecs; char *allocated_status_memory; @@ -217,8 +218,9 @@ private: query_id_t profiling_query_id; /* Session-specific id. */ char *query_source; - PROF_MEASUREMENT *profile_start; - PROF_MEASUREMENT *profile_end; + double m_start_time_usecs; + double m_end_time_usecs; + ulong m_seq_counter; Queue<PROF_MEASUREMENT> entries; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 79cef2c3538..5995abc74f1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2012 Oracle and/or its affiliates. - Copyright (c) 2009, 2012, Monty Program Ab + Copyright (c) 2009, 2013 Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2004,6 +2004,8 @@ bool JOIN::setup_subquery_caches() */ void JOIN::restore_tmp() { + DBUG_PRINT("info", ("restore_tmp this %p tmp_join %p", this, tmp_join)); + DBUG_ASSERT(tmp_join != this); memcpy(tmp_join, this, (size_t) sizeof(JOIN)); } @@ -7609,8 +7611,9 @@ get_best_combination(JOIN *join) if ( !(keyuse= join->best_positions[tablenr].key)) { j->type=JT_ALL; - if (tablenr != join->const_tables) - join->full_join=1; + if (join->best_positions[tablenr].use_join_buffer && + tablenr != join->const_tables) + join->full_join= 1; } /*if (join->best_positions[tablenr].sj_strategy == SJ_OPT_LOOSE_SCAN) @@ -8591,7 +8594,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) We will use join cache here : prevent sorting of the first table only and sort at the end. */ - if (i != join->const_tables && join->table_count > join->const_tables + 1) + if (i != join->const_tables && + join->table_count > join->const_tables + 1 && + join->best_positions[i].use_join_buffer) join->full_join= 1; } @@ -10640,21 +10645,19 @@ void JOIN::cleanup(bool full) } } } - /* - We are not using tables anymore - Unlock all tables. We may be in an INSERT .... SELECT statement. - */ if (full) { - if (tmp_join) - tmp_table_param.copy_field= 0; - group_fields.delete_elements(); /* - Ensure that the above delete_elements() would not be called + Ensure that the following delete_elements() would not be called twice for the same list. */ - if (tmp_join && tmp_join != this) - tmp_join->group_fields= group_fields; + if (tmp_join && tmp_join != this && + tmp_join->group_fields == this->group_fields) + tmp_join->group_fields.empty(); + + // Run Cached_item DTORs! + group_fields.delete_elements(); + /* We can't call delete_elements() on copy_funcs as this will cause problems in free_elements() as some of the elements are then deleted. diff --git a/sql/sql_time.cc b/sql/sql_time.cc index 5c0471fdfaa..57dbd979933 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. - Copyright (c) 2009-2011 Monty Program Ab + Copyright (c) 2009, 2013 Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -154,7 +154,7 @@ bool get_date_from_daynr(long daynr,uint *ret_year,uint *ret_month, uchar *month_pos; DBUG_ENTER("get_date_from_daynr"); - if (daynr < 365 || daynr > MAX_DAY_NUMBER) + if (daynr < 366 || daynr > MAX_DAY_NUMBER) DBUG_RETURN(1); year= (uint) (daynr*100 / 36525L); diff --git a/sql/table.cc b/sql/table.cc index cc3ab6f8c36..a36a6d19484 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4966,19 +4966,33 @@ TABLE *TABLE_LIST::get_real_join_table() DBUG_ASSERT(tbl->derived == NULL || tbl->derived->first_select()->next_select() == NULL); - if (tbl->table) - table= tbl->table; - tbl= (tbl->view != NULL ? - tbl->view->select_lex.get_table_list() : - tbl->derived->first_select()->get_table_list()); - - /* find left table in outer join on this level */ - while(tbl->outer_join & JOIN_TYPE_RIGHT) { - DBUG_ASSERT(tbl->next_local); - tbl= tbl->next_local; + List_iterator_fast<TABLE_LIST> ti; + { + List_iterator_fast<TABLE_LIST> + ti(tbl->view != NULL ? + tbl->view->select_lex.top_join_list : + tbl->derived->first_select()->top_join_list); + for (;;) + { + tbl= NULL; + /* + Find left table in outer join on this level + (the list is reverted). + */ + for (TABLE_LIST *t= ti++; t; t= ti++) + tbl= t; + /* + It is impossible that the list is empty + so tbl can't be NULL after above loop. + */ + if (!tbl->nested_join) + break; + /* go deeper if we've found nested join */ + ti= tbl->nested_join->join_list; + } + } } - } return tbl->table; |