diff options
author | unknown <anozdrin/alik@station.> | 2007-12-14 16:30:22 +0300 |
---|---|---|
committer | unknown <anozdrin/alik@station.> | 2007-12-14 16:30:22 +0300 |
commit | 541ac204014fb7a051156fb369fadcf77342788c (patch) | |
tree | 362dc5c4acd0fff3e86d1b9d4b96ef068d73b341 /sql | |
parent | a6eec72e7bcf1ef04dd4569e51fa8845cb192fc1 (diff) | |
parent | 35742460f4f252f6d08217997ea2f103b57a5201 (diff) | |
download | mariadb-git-541ac204014fb7a051156fb369fadcf77342788c.tar.gz |
Merge station.:/mnt/raid/alik/MySQL/devel/5.1
into station.:/mnt/raid/alik/MySQL/devel/5.1-rt
client/mysqltest.c:
Auto merged
include/mysql_com.h:
Auto merged
libmysqld/emb_qcache.cc:
Auto merged
libmysqld/emb_qcache.h:
Auto merged
libmysqld/lib_sql.cc:
Auto merged
mysql-test/lib/mtr_report.pl:
Auto merged
sql/ha_partition.cc:
Auto merged
sql/item_func.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/mysqld.cc:
Auto merged
sql/opt_range.cc:
Auto merged
sql/set_var.cc:
Auto merged
sql/set_var.h:
Auto merged
sql/slave.cc:
Auto merged
sql/sql_class.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_db.cc:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_partition.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_table.cc:
Auto merged
sql/table.cc:
Auto merged
storage/myisam/ha_myisam.cc:
Auto merged
sql/protocol.cc:
SCCS merged
Diffstat (limited to 'sql')
-rw-r--r-- | sql/events.cc | 4 | ||||
-rw-r--r-- | sql/field.cc | 3 | ||||
-rw-r--r-- | sql/field.h | 1 | ||||
-rw-r--r-- | sql/ha_partition.cc | 21 | ||||
-rw-r--r-- | sql/item.cc | 16 | ||||
-rw-r--r-- | sql/item.h | 21 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 63 | ||||
-rw-r--r-- | sql/item_func.cc | 16 | ||||
-rw-r--r-- | sql/item_func.h | 50 | ||||
-rw-r--r-- | sql/item_geofunc.cc | 2 | ||||
-rw-r--r-- | sql/item_subselect.cc | 4 | ||||
-rw-r--r-- | sql/key.cc | 13 | ||||
-rw-r--r-- | sql/mysql_priv.h | 38 | ||||
-rw-r--r-- | sql/mysqld.cc | 87 | ||||
-rw-r--r-- | sql/opt_range.cc | 38 | ||||
-rw-r--r-- | sql/protocol.cc | 10 | ||||
-rw-r--r-- | sql/set_var.cc | 98 | ||||
-rw-r--r-- | sql/set_var.h | 1 | ||||
-rw-r--r-- | sql/slave.cc | 21 | ||||
-rw-r--r-- | sql/sql_class.cc | 17 | ||||
-rw-r--r-- | sql/sql_class.h | 4 | ||||
-rw-r--r-- | sql/sql_db.cc | 1 | ||||
-rw-r--r-- | sql/sql_insert.cc | 18 | ||||
-rw-r--r-- | sql/sql_parse.cc | 28 | ||||
-rw-r--r-- | sql/sql_partition.cc | 14 | ||||
-rw-r--r-- | sql/sql_plugin.cc | 56 | ||||
-rw-r--r-- | sql/sql_select.cc | 39 | ||||
-rw-r--r-- | sql/sql_select.h | 11 | ||||
-rw-r--r-- | sql/sql_string.cc | 5 | ||||
-rw-r--r-- | sql/sql_table.cc | 129 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 47 | ||||
-rw-r--r-- | sql/table.cc | 12 | ||||
-rw-r--r-- | sql/table.h | 1 | ||||
-rw-r--r-- | sql/udf_example.c | 10 |
34 files changed, 627 insertions, 272 deletions
diff --git a/sql/events.cc b/sql/events.cc index 73b8f2cda84..87385082a82 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -825,8 +825,8 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS) { DBUG_ASSERT(thd->lex->select_lex.db); - if (check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, - is_schema_db(thd->lex->select_lex.db))) + if (!is_schema_db(thd->lex->select_lex.db) && // There is no events in I_S + check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, 0)) DBUG_RETURN(1); db= thd->lex->select_lex.db; } diff --git a/sql/field.cc b/sql/field.cc index 942c0538abb..93588992fed 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5701,6 +5701,9 @@ void Field_date::sql_type(String &res) const 1 Value was cut during conversion 2 Wrong date string 3 Datetime value that was cut (warning level NOTE) + This is used by opt_range.cc:get_mm_leaf(). Note that there is a + nearly-identical class Field_date doesn't ever return 3 from its + store function. */ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs) diff --git a/sql/field.h b/sql/field.h index 4b09f50a59a..9f76deb18bc 100644 --- a/sql/field.h +++ b/sql/field.h @@ -25,6 +25,7 @@ #define NOT_FIXED_DEC 31 #define DATETIME_DEC 6 +const uint32 max_field_size= (uint32) 4294967295U; class Send_field; class Protocol; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 5d712b5c64e..3f1634a6ad1 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1606,7 +1606,11 @@ error: void ha_partition::update_create_info(HA_CREATE_INFO *create_info) { - m_file[0]->update_create_info(create_info); + info(HA_STATUS_AUTO); + + if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) + create_info->auto_increment_value= stats.auto_increment_value; + create_info->data_file_name= create_info->index_file_name = NULL; return; } @@ -3422,14 +3426,17 @@ int ha_partition::index_init(uint inx, bool sorted) */ if (m_lock_type == F_WRLCK) bitmap_union(table->read_set, &m_part_info->full_part_field_set); - else if (sorted && m_table_flags & HA_PARTIAL_COLUMN_READ) + else if (sorted) { /* - An ordered scan is requested and necessary fields aren't in read_set. - This may happen e.g. with SELECT COUNT(*) FROM t1. We must ensure - that all fields of current key are included into read_set, as - partitioning requires them for sorting - (see ha_partition::handle_ordered_index_scan). + An ordered scan is requested. We must make sure all fields of the + used index are in the read set, as partitioning requires them for + sorting (see ha_partition::handle_ordered_index_scan). + + The SQL layer may request an ordered index scan without having index + fields in the read set when + - it needs to do an ordered scan over an index prefix. + - it evaluates ORDER BY with SELECT COUNT(*) FROM t1. TODO: handle COUNT(*) queries via unordered scan. */ diff --git a/sql/item.cc b/sql/item.cc index 364b27d9972..4d579597d21 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1262,14 +1262,14 @@ bool Item_name_const::fix_fields(THD *thd, Item **ref) s.length(0); if (value_item->fix_fields(thd, &value_item) || - name_item->fix_fields(thd, &name_item)) - return TRUE; - if (!(value_item->const_item() && name_item->const_item())) + name_item->fix_fields(thd, &name_item) || + !value_item->const_item() || + !name_item->const_item() || + !(item_name= name_item->val_str(&s))) // Can't have a NULL name + { + my_error(ER_RESERVED_SYNTAX, MYF(0), "NAME_CONST"); return TRUE; - - if (!(item_name= name_item->val_str(&s))) - return TRUE; /* Can't have a NULL name */ - + } set_name(item_name->ptr(), (uint) item_name->length(), system_charset_info); max_length= value_item->max_length; decimals= value_item->decimals; @@ -3693,7 +3693,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) } /* Search in SELECT and GROUP lists of the outer select. */ - if (outer_context->resolve_in_select_list) + if (place != IN_WHERE && place != IN_ON) { if (!(ref= resolve_ref_in_select_and_group(thd, this, select))) return -1; /* Some error occurred (e.g. ambiguous names). */ diff --git a/sql/item.h b/sql/item.h index 2219153616b..b98389bc8d4 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2622,16 +2622,23 @@ class Item_cache: public Item protected: Item *example; table_map used_table_map; + /* + Field that this object will get value from. This is set/used by + index-based subquery engines to detect and remove the equality injected + by IN->EXISTS transformation. + For all other uses of Item_cache, cached_field doesn't matter. + */ + Field *cached_field; enum enum_field_types cached_field_type; public: Item_cache(): - example(0), used_table_map(0), cached_field_type(MYSQL_TYPE_STRING) + example(0), used_table_map(0), cached_field(0), cached_field_type(MYSQL_TYPE_STRING) { fixed= 1; null_value= 1; } Item_cache(enum_field_types field_type_arg): - example(0), used_table_map(0), cached_field_type(field_type_arg) + example(0), used_table_map(0), cached_field(0), cached_field_type(field_type_arg) { fixed= 1; null_value= 1; @@ -2647,6 +2654,8 @@ public: decimals= item->decimals; collation.set(item->collation); unsigned_flag= item->unsigned_flag; + if (item->type() == FIELD_ITEM) + cached_field= ((Item_field *)item)->field; return 0; }; virtual void store(Item *)= 0; @@ -2658,6 +2667,14 @@ public: // to prevent drop fixed flag (no need parent cleanup call) void cleanup() {} void print(String *str); + bool eq_def(Field *field) + { + return cached_field ? cached_field->eq_def (field) : FALSE; + } + bool eq(const Item *item, bool binary_cmp) const + { + return this == item; + } }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 3c738fe9ff1..1d1e28593d4 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -24,7 +24,8 @@ #include <m_ctype.h> #include "sql_select.h" -static bool convert_constant_item(THD *thd, Field *field, Item **item); +static bool convert_constant_item(THD *thd, Item_field *field_item, + Item **item); static Item_result item_store_type(Item_result a, Item *item, my_bool unsigned_flag) @@ -351,7 +352,7 @@ longlong Item_func_nop_all::val_int() SYNOPSIS convert_constant_item() thd thread handle - field item will be converted using the type of this field + field_item item will be converted using the type of this field item [in/out] reference to the item to convert DESCRIPTION @@ -374,8 +375,10 @@ longlong Item_func_nop_all::val_int() 1 Item was replaced with an integer version of the item */ -static bool convert_constant_item(THD *thd, Field *field, Item **item) +static bool convert_constant_item(THD *thd, Item_field *field_item, + Item **item) { + Field *field= field_item->field; int result= 0; if (!(*item)->with_subselect && (*item)->const_item()) @@ -385,9 +388,11 @@ static bool convert_constant_item(THD *thd, Field *field, Item **item) enum_check_fields orig_count_cuted_fields= thd->count_cuted_fields; my_bitmap_map *old_write_map; my_bitmap_map *old_read_map; + ulonglong orig_field_val; /* original field value if valid */ LINT_INIT(old_write_map); LINT_INIT(old_read_map); + LINT_INIT(orig_field_val); if (table) { @@ -398,7 +403,14 @@ static bool convert_constant_item(THD *thd, Field *field, Item **item) thd->variables.sql_mode= (orig_sql_mode & ~MODE_NO_ZERO_DATE) | MODE_INVALID_DATES; thd->count_cuted_fields= CHECK_FIELD_IGNORE; - if (!(*item)->save_in_field(field, 1) && !((*item)->null_value)) + + /* + Store the value of the field if it references an outer field because + the call to save_in_field below overrides that value. + */ + if (field_item->depended_from) + orig_field_val= field->val_int(); + if (!(*item)->is_null() && !(*item)->save_in_field(field, 1)) { Item *tmp= new Item_int_with_ref(field->val_int(), *item, test(field->flags & UNSIGNED_FLAG)); @@ -406,6 +418,13 @@ static bool convert_constant_item(THD *thd, Field *field, Item **item) thd->change_item_tree(item, tmp); result= 1; // Item was replaced } + /* Restore the original field value. */ + if (field_item->depended_from) + { + result= field->store(orig_field_val, TRUE); + /* orig_field_val must be a valid value that can be restored back. */ + DBUG_ASSERT(!result); + } thd->variables.sql_mode= orig_sql_mode; thd->count_cuted_fields= orig_count_cuted_fields; if (table) @@ -462,15 +481,14 @@ void Item_bool_func2::fix_length_and_dec() thd= current_thd; if (!thd->is_context_analysis_only()) { - Item *arg_real_item= args[0]->real_item(); - if (arg_real_item->type() == FIELD_ITEM) + if (args[0]->real_item()->type() == FIELD_ITEM) { - Field *field=((Item_field*) arg_real_item)->field; - if (field->can_be_compared_as_longlong() && - !(arg_real_item->is_datetime() && + Item_field *field_item= (Item_field*) (args[0]->real_item()); + if (field_item->field->can_be_compared_as_longlong() && + !(field_item->is_datetime() && args[1]->result_type() == STRING_RESULT)) { - if (convert_constant_item(thd, field,&args[1])) + if (convert_constant_item(thd, field_item, &args[1])) { cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, INT_RESULT); // Works for all types. @@ -479,15 +497,14 @@ void Item_bool_func2::fix_length_and_dec() } } } - arg_real_item= args[1]->real_item(); - if (arg_real_item->type() == FIELD_ITEM) + if (args[1]->real_item()->type() == FIELD_ITEM) { - Field *field=((Item_field*) arg_real_item)->field; - if (field->can_be_compared_as_longlong() && - !(arg_real_item->is_datetime() && + Item_field *field_item= (Item_field*) (args[1]->real_item()); + if (field_item->field->can_be_compared_as_longlong() && + !(field_item->is_datetime() && args[0]->result_type() == STRING_RESULT)) { - if (convert_constant_item(thd, field,&args[0])) + if (convert_constant_item(thd, field_item, &args[0])) { cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, INT_RESULT); // Works for all types. @@ -1959,16 +1976,16 @@ void Item_func_between::fix_length_and_dec() thd->lex->sql_command != SQLCOM_CREATE_VIEW && thd->lex->sql_command != SQLCOM_SHOW_CREATE) { - Field *field=((Item_field*) (args[0]->real_item()))->field; - if (field->can_be_compared_as_longlong()) + Item_field *field_item= (Item_field*) (args[0]->real_item()); + if (field_item->field->can_be_compared_as_longlong()) { /* The following can't be recoded with || as convert_constant_item changes the argument */ - if (convert_constant_item(thd, field,&args[1])) + if (convert_constant_item(thd, field_item, &args[1])) cmp_type=INT_RESULT; // Works for all types. - if (convert_constant_item(thd, field,&args[2])) + if (convert_constant_item(thd, field_item, &args[2])) cmp_type=INT_RESULT; // Works for all types. } } @@ -3603,13 +3620,13 @@ void Item_func_in::fix_length_and_dec() thd->lex->sql_command != SQLCOM_SHOW_CREATE && cmp_type != INT_RESULT) { - Field *field= ((Item_field*) (args[0]->real_item()))->field; - if (field->can_be_compared_as_longlong()) + Item_field *field_item= (Item_field*) (args[0]->real_item()); + if (field_item->field->can_be_compared_as_longlong()) { bool all_converted= TRUE; for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++) { - if (!convert_constant_item (thd, field, &arg[0])) + if (!convert_constant_item (thd, field_item, &arg[0])) all_converted= FALSE; } if (all_converted) diff --git a/sql/item_func.cc b/sql/item_func.cc index d219987e46b..bdd600c3fc9 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2960,6 +2960,12 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, func->max_length=min(initid.max_length,MAX_BLOB_WIDTH); func->maybe_null=initid.maybe_null; const_item_cache=initid.const_item; + /* + Keep used_tables_cache in sync with const_item_cache. + See the comment in Item_udf_func::update_used tables. + */ + if (!const_item_cache && !used_tables_cache) + used_tables_cache= RAND_TABLE_BIT; func->decimals=min(initid.decimals,NOT_FIXED_DEC); } initialized=1; @@ -3840,10 +3846,12 @@ Item_func_set_user_var::fix_length_and_dec() bool Item_func_set_user_var::register_field_in_read_map(uchar *arg) { - TABLE *table= (TABLE *) arg; - if (result_field && - (!table || result_field->table == table)) - bitmap_set_bit(result_field->table->read_set, result_field->field_index); + if (result_field) + { + TABLE *table= (TABLE *) arg; + if (result_field->table == table || !table) + bitmap_set_bit(result_field->table->read_set, result_field->field_index); + } return 0; } diff --git a/sql/item_func.h b/sql/item_func.h index 629d0dbfdbc..e09b584de95 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1022,6 +1022,56 @@ public: fixed= 1; return res; } + void update_used_tables() + { + /* + TODO: Make a member in UDF_INIT and return if a UDF is deterministic or + not. + Currently UDF_INIT has a member (const_item) that is an in/out + parameter to the init() call. + The code in udf_handler::fix_fields also duplicates the arguments + handling code in Item_func::fix_fields(). + + The lack of information if a UDF is deterministic makes writing + a correct update_used_tables() for UDFs impossible. + One solution to this would be : + - Add a is_deterministic member of UDF_INIT + - (optionally) deprecate the const_item member of UDF_INIT + - Take away the duplicate code from udf_handler::fix_fields() and + make Item_udf_func call Item_func::fix_fields() to process its + arguments as for any other function. + - Store the deterministic flag returned by <udf>_init into the + udf_handler. + - Don't implement Item_udf_func::fix_fields, implement + Item_udf_func::fix_length_and_dec() instead (similar to non-UDF + functions). + - Override Item_func::update_used_tables to call + Item_func::update_used_tables() and add a RAND_TABLE_BIT to the + result of Item_func::update_used_tables() if the UDF is + non-deterministic. + - (optionally) rename RAND_TABLE_BIT to NONDETERMINISTIC_BIT to + better describe its usage. + + The above would require a change of the UDF API. + Until that change is done here's how the current code works: + We call Item_func::update_used_tables() only when we know that + the function depends on real non-const tables and is deterministic. + This can be done only because we know that the optimizer will + call update_used_tables() only when there's possibly a new const + table. So update_used_tables() can only make a Item_func more + constant than it is currently. + That's why we don't need to do anything if a function is guaranteed + to return non-constant (it's non-deterministic) or is already a + const. + */ + if ((used_tables_cache & ~PSEUDO_TABLE_BITS) && + !(used_tables_cache & RAND_TABLE_BIT)) + { + Item_func::update_used_tables(); + if (!const_item_cache && !used_tables_cache) + used_tables_cache= RAND_TABLE_BIT; + } + } void cleanup(); Item_result result_type () const { return udf.result_type(); } table_map not_null_tables() const { return 0; } diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 332e88c950d..2da5965c94d 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -37,7 +37,7 @@ void Item_geometry_func::fix_length_and_dec() { collation.set(&my_charset_bin); decimals=0; - max_length=MAX_BLOB_WIDTH; + max_length= max_field_size; maybe_null= 1; } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 423f067e54d..e2003f820b6 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1843,7 +1843,9 @@ int subselect_single_select_engine::exec() DBUG_RETURN(1); } } - if (select_lex->uncacheable && executed) + if (select_lex->uncacheable && + select_lex->uncacheable != UNCACHEABLE_EXPLAIN + && executed) { if (join->reinit()) { diff --git a/sql/key.cc b/sql/key.cc index e8354ed2635..6ddfe10848f 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -127,19 +127,6 @@ void key_copy(uchar *to_key, uchar *from_record, KEY *key_info, key_part->null_bit); key_length--; } - if (key_part->type == HA_KEYTYPE_BIT) - { - Field_bit *field= (Field_bit *) (key_part->field); - if (field->bit_len) - { - uchar bits= get_rec_bits(from_record + - key_part->null_offset + - (key_part->null_bit == 128), - field->bit_ofs, field->bit_len); - *to_key++= bits; - key_length--; - } - } if (key_part->key_part_flag & HA_BLOB_PART || key_part->key_part_flag & HA_VAR_LENGTH_PART) { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 46e08191480..f61267711b0 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -266,7 +266,7 @@ protected: #define QUERY_ALLOC_PREALLOC_SIZE 8192 #define TRANS_ALLOC_BLOCK_SIZE 4096 #define TRANS_ALLOC_PREALLOC_SIZE 4096 -#define RANGE_ALLOC_BLOCK_SIZE 2048 +#define RANGE_ALLOC_BLOCK_SIZE 4096 #define ACL_ALLOC_BLOCK_SIZE 1024 #define UDF_ALLOC_BLOCK_SIZE 1024 #define TABLE_ALLOC_BLOCK_SIZE 1024 @@ -680,6 +680,8 @@ void free_items(Item *item); void cleanup_items(Item *item); class THD; void close_thread_tables(THD *thd); + +#ifndef NO_EMBEDDED_ACCESS_CHECKS bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables); bool check_single_table_access(THD *thd, ulong privilege, TABLE_LIST *tables, bool no_errors); @@ -687,6 +689,24 @@ bool check_routine_access(THD *thd,ulong want_access,char *db,char *name, bool is_proc, bool no_errors); bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table); bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc); +#else +inline bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables) +{ return false; } +inline bool check_single_table_access(THD *thd, ulong privilege, + TABLE_LIST *tables, bool no_errors) +{ return false; } +inline bool check_routine_access(THD *thd,ulong want_access,char *db, + char *name, bool is_proc, bool no_errors) +{ return false; } +inline bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table) +{ return false; } +inline bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list) +{ return false; } +inline bool check_some_routine_access(THD *thd, const char *db, + const char *name, bool is_proc) +{ return false; } +#endif /*NO_EMBEDDED_ACCESS_CHECKS*/ + bool multi_update_precheck(THD *thd, TABLE_LIST *tables); bool multi_delete_precheck(THD *thd, TABLE_LIST *tables); bool mysql_multi_update_prepare(THD *thd); @@ -991,11 +1011,27 @@ void kill_mysql(void); void close_connection(THD *thd, uint errcode, bool lock); bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, bool *write_to_binlog); +#ifndef NO_EMBEDDED_ACCESS_CHECKS bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv, bool no_grant, bool no_errors, bool schema_db); bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables, bool no_errors); bool check_global_access(THD *thd, ulong want_access); +#else +inline bool check_access(THD *thd, ulong access, const char *db, + ulong *save_priv, bool no_grant, bool no_errors, + bool schema_db) +{ + if (save_priv) + *save_priv= GLOBAL_ACLS; + return false; +} +inline bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables, + bool no_errors) +{ return false; } +inline bool check_global_access(THD *thd, ulong want_access) +{ return false; } +#endif /*NO_EMBEDDED_ACCESS_CHECKS*/ /* Support routine for SQL parser on partitioning syntax diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5a1a1a24a3e..319b89cb6e8 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -174,7 +174,7 @@ typedef fp_except fp_except_t; this on freebsd */ -inline void reset_floating_point_exceptions() +inline void set_proper_floating_point_mode() { /* Don't fall for overflow, underflow,divide-by-zero or loss of precision */ #if defined(__i386__) @@ -185,8 +185,22 @@ inline void reset_floating_point_exceptions() FP_X_IMP)); #endif } +#elif defined(__sgi) +/* for IRIX to use set_fpc_csr() */ +#include <sys/fpu.h> + +inline void set_proper_floating_point_mode() +{ + /* Enable denormalized DOUBLE values support for IRIX */ + { + union fpc_csr n; + n.fc_word = get_fpc_csr(); + n.fc_struct.flush = 0; + set_fpc_csr(n.fc_word); + } +} #else -#define reset_floating_point_exceptions() +#define set_proper_floating_point_mode() #endif /* __FreeBSD__ && HAVE_IEEEFP_H */ } /* cplusplus */ @@ -1164,6 +1178,8 @@ void clean_up(bool print_message) if (cleanup_done++) return; /* purecov: inspected */ + release_ddl_log(); + /* make sure that handlers finish up what they have that is dependent on the binlog @@ -3258,7 +3274,7 @@ static int init_server_components() query_cache_init(); query_cache_resize(query_cache_size); randominit(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2); - reset_floating_point_exceptions(); + set_proper_floating_point_mode(); init_thr_lock(); #ifdef HAVE_REPLICATION init_slave_list(); @@ -4011,7 +4027,6 @@ we force server id to 2, but this MySQL server will not act as a slave."); pthread_cond_wait(&COND_thread_count,&LOCK_thread_count); (void) pthread_mutex_unlock(&LOCK_thread_count); - release_ddl_log(); #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY) if (Service.IsNT() && start_mode) Service.Stop(); @@ -5241,7 +5256,7 @@ struct my_option my_long_options[] = {"concurrent-insert", OPT_CONCURRENT_INSERT, "Use concurrent insert with MyISAM. Disable with --concurrent-insert=0", (uchar**) &myisam_concurrent_insert, (uchar**) &myisam_concurrent_insert, - 0, GET_LONG, OPT_ARG, 1, 0, 2, 0, 0, 0}, + 0, GET_ULONG, OPT_ARG, 1, 0, 2, 0, 0, 0}, {"console", OPT_CONSOLE, "Write error output on screen; Don't remove the console window on windows.", (uchar**) &opt_console, (uchar**) &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -5445,7 +5460,8 @@ Disable with --skip-large-pages.", #ifdef HAVE_MMAP {"log-tc-size", OPT_LOG_TC_SIZE, "Size of transaction coordinator log.", (uchar**) &opt_tc_log_size, (uchar**) &opt_tc_log_size, 0, GET_ULONG, - REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ~0L, 0, TC_LOG_PAGE_SIZE, 0}, + REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ULONG_MAX, 0, + TC_LOG_PAGE_SIZE, 0}, #endif {"log-update", OPT_UPDATE_LOG, "The update log is deprecated since version 5.0, is replaced by the binary \ @@ -5906,8 +5922,8 @@ log and this option does nothing anymore.", NO_ARG, 0, 0, 0, 0, 0, 0}, {"warnings", 'W', "Deprecated; use --log-warnings instead.", (uchar**) &global_system_variables.log_warnings, - (uchar**) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, ~0L, - 0, 0, 0}, + (uchar**) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, + 1, 0, ULONG_MAX, 0, 0, 0}, { "back_log", OPT_BACK_LOG, "The number of outstanding connection requests MySQL can have. This comes into play when the main MySQL thread gets very many connection requests in a very short time.", (uchar**) &back_log, (uchar**) &back_log, 0, GET_ULONG, @@ -5915,12 +5931,12 @@ log and this option does nothing anymore.", {"binlog_cache_size", OPT_BINLOG_CACHE_SIZE, "The size of the cache to hold the SQL statements for the binary log during a transaction. If you often use big, multi-statement transactions you can increase this to get more performance.", (uchar**) &binlog_cache_size, (uchar**) &binlog_cache_size, 0, GET_ULONG, - REQUIRED_ARG, 32*1024L, IO_SIZE, ~0L, 0, IO_SIZE, 0}, + REQUIRED_ARG, 32*1024L, IO_SIZE, ULONG_MAX, 0, IO_SIZE, 0}, {"bulk_insert_buffer_size", OPT_BULK_INSERT_BUFFER_SIZE, "Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread!", (uchar**) &global_system_variables.bulk_insert_buff_size, (uchar**) &max_system_variables.bulk_insert_buff_size, - 0, GET_ULONG, REQUIRED_ARG, 8192*1024, 0, ~0L, 0, 1, 0}, + 0, GET_ULONG, REQUIRED_ARG, 8192*1024, 0, ULONG_MAX, 0, 1, 0}, {"connect_timeout", OPT_CONNECT_TIMEOUT, "The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake'.", (uchar**) &connect_timeout, (uchar**) &connect_timeout, @@ -5943,7 +5959,7 @@ log and this option does nothing anymore.", {"delayed_insert_limit", OPT_DELAYED_INSERT_LIMIT, "After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing.", (uchar**) &delayed_insert_limit, (uchar**) &delayed_insert_limit, 0, GET_ULONG, - REQUIRED_ARG, DELAYED_LIMIT, 1, ~0L, 0, 1, 0}, + REQUIRED_ARG, DELAYED_LIMIT, 1, ULONG_MAX, 0, 1, 0}, {"delayed_insert_timeout", OPT_DELAYED_INSERT_TIMEOUT, "How long a INSERT DELAYED thread should wait for INSERT statements before terminating.", (uchar**) &delayed_insert_timeout, (uchar**) &delayed_insert_timeout, 0, @@ -5951,7 +5967,7 @@ log and this option does nothing anymore.", { "delayed_queue_size", OPT_DELAYED_QUEUE_SIZE, "What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again.", (uchar**) &delayed_queue_size, (uchar**) &delayed_queue_size, 0, GET_ULONG, - REQUIRED_ARG, DELAYED_QUEUE_SIZE, 1, ~0L, 0, 1, 0}, + REQUIRED_ARG, DELAYED_QUEUE_SIZE, 1, ULONG_MAX, 0, 1, 0}, {"div_precision_increment", OPT_DIV_PRECINCREMENT, "Precision of the result of '/' operator will be increased on that value.", (uchar**) &global_system_variables.div_precincrement, @@ -5991,7 +6007,7 @@ log and this option does nothing anymore.", "The maximum length of the result of function group_concat.", (uchar**) &global_system_variables.group_concat_max_len, (uchar**) &max_system_variables.group_concat_max_len, 0, GET_ULONG, - REQUIRED_ARG, 1024, 4, (long) ~0, 0, 1, 0}, + REQUIRED_ARG, 1024, 4, ULONG_MAX, 0, 1, 0}, {"interactive_timeout", OPT_INTERACTIVE_TIMEOUT, "The number of seconds the server waits for activity on an interactive connection before closing it.", (uchar**) &global_system_variables.net_interactive_timeout, @@ -6001,8 +6017,8 @@ log and this option does nothing anymore.", "The size of the buffer that is used for full joins.", (uchar**) &global_system_variables.join_buff_size, (uchar**) &max_system_variables.join_buff_size, 0, GET_ULONG, - REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, - IO_SIZE, 0}, + REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ULONG_MAX, + MALLOC_OVERHEAD, IO_SIZE, 0}, {"keep_files_on_create", OPT_KEEP_FILES_ON_CREATE, "Don't overwrite stale .MYD and .MYI even if no directory is specified.", (uchar**) &global_system_variables.keep_files_on_create, @@ -6020,7 +6036,7 @@ log and this option does nothing anymore.", (uchar**) &dflt_key_cache_var.param_age_threshold, (uchar**) 0, 0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, - 300, 100, ~0L, 0, 100, 0}, + 300, 100, ULONG_MAX, 0, 100, 0}, {"key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE, "The default size of key cache blocks", (uchar**) &dflt_key_cache_var.param_block_size, @@ -6056,7 +6072,7 @@ log and this option does nothing anymore.", {"max_binlog_cache_size", OPT_MAX_BINLOG_CACHE_SIZE, "Can be used to restrict the total size used to cache a multi-transaction query.", (uchar**) &max_binlog_cache_size, (uchar**) &max_binlog_cache_size, 0, - GET_ULONG, REQUIRED_ARG, ~0L, IO_SIZE, ~0L, 0, IO_SIZE, 0}, + GET_ULONG, REQUIRED_ARG, ULONG_MAX, IO_SIZE, ULONG_MAX, 0, IO_SIZE, 0}, {"max_binlog_size", OPT_MAX_BINLOG_SIZE, "Binary log will be rotated automatically when the size exceeds this \ value. Will also apply to relay logs if max_relay_log_size is 0. \ @@ -6066,7 +6082,7 @@ The minimum value for this variable is 4096.", {"max_connect_errors", OPT_MAX_CONNECT_ERRORS, "If there is more than this number of interrupted connections from a host this host will be blocked from further connections.", (uchar**) &max_connect_errors, (uchar**) &max_connect_errors, 0, GET_ULONG, - REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ~0L, 0, 1, 0}, + REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ULONG_MAX, 0, 1, 0}, // Default max_connections of 151 is larger than Apache's default max // children, to avoid "too many connections" error in a common setup {"max_connections", OPT_MAX_CONNECTIONS, @@ -6111,7 +6127,7 @@ The minimum value for this variable is 4096.", "Limit assumed max number of seeks when looking up rows based on a key", (uchar**) &global_system_variables.max_seeks_for_key, (uchar**) &max_system_variables.max_seeks_for_key, 0, GET_ULONG, - REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0 }, + REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0 }, {"max_sort_length", OPT_MAX_SORT_LENGTH, "The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored).", (uchar**) &global_system_variables.max_sort_length, @@ -6126,25 +6142,25 @@ The minimum value for this variable is 4096.", "Maximum number of temporary tables a client can keep open at a time.", (uchar**) &global_system_variables.max_tmp_tables, (uchar**) &max_system_variables.max_tmp_tables, 0, GET_ULONG, - REQUIRED_ARG, 32, 1, ~0L, 0, 1, 0}, + REQUIRED_ARG, 32, 1, ULONG_MAX, 0, 1, 0}, {"max_user_connections", OPT_MAX_USER_CONNECTIONS, "The maximum number of active connections for a single user (0 = no limit).", (uchar**) &max_user_connections, (uchar**) &max_user_connections, 0, GET_UINT, - REQUIRED_ARG, 0, 1, ~0, 0, 1, 0}, + REQUIRED_ARG, 0, 1, UINT_MAX, 0, 1, 0}, {"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT, "After this many write locks, allow some read locks to run in between.", (uchar**) &max_write_lock_count, (uchar**) &max_write_lock_count, 0, GET_ULONG, - REQUIRED_ARG, ~0L, 1, ~0L, 0, 1, 0}, + REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0}, {"min_examined_row_limit", OPT_MIN_EXAMINED_ROW_LIMIT, "Don't log queries which examine less than min_examined_row_limit rows to file.", (uchar**) &global_system_variables.min_examined_row_limit, (uchar**) &max_system_variables.min_examined_row_limit, 0, GET_ULONG, - REQUIRED_ARG, 0, 0, ~0L, 0, 1L, 0}, + REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1L, 0}, {"multi_range_count", OPT_MULTI_RANGE_COUNT, "Number of key ranges to request at once.", (uchar**) &global_system_variables.multi_range_count, (uchar**) &max_system_variables.multi_range_count, 0, - GET_ULONG, REQUIRED_ARG, 256, 1, ~0L, 0, 1, 0}, + GET_ULONG, REQUIRED_ARG, 256, 1, ULONG_MAX, 0, 1, 0}, {"myisam_block_size", OPT_MYISAM_BLOCK_SIZE, "Block size to be used for MyISAM index pages.", (uchar**) &opt_myisam_block_size, @@ -6172,7 +6188,7 @@ The minimum value for this variable is 4096.", "Number of threads to use when repairing MyISAM tables. The value of 1 disables parallel repair.", (uchar**) &global_system_variables.myisam_repair_threads, (uchar**) &max_system_variables.myisam_repair_threads, 0, - GET_ULONG, REQUIRED_ARG, 1, 1, ~0L, 0, 1, 0}, + GET_ULONG, REQUIRED_ARG, 1, 1, ULONG_MAX, 0, 1, 0}, {"myisam_sort_buffer_size", OPT_MYISAM_SORT_BUFFER_SIZE, "The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.", (uchar**) &global_system_variables.myisam_sort_buff_size, @@ -6203,7 +6219,7 @@ The minimum value for this variable is 4096.", "If a read on a communication port is interrupted, retry this many times before giving up.", (uchar**) &global_system_variables.net_retry_count, (uchar**) &max_system_variables.net_retry_count,0, - GET_ULONG, REQUIRED_ARG, MYSQLD_NET_RETRY_COUNT, 1, ~0L, 0, 1, 0}, + GET_ULONG, REQUIRED_ARG, MYSQLD_NET_RETRY_COUNT, 1, ULONG_MAX, 0, 1, 0}, {"net_write_timeout", OPT_NET_WRITE_TIMEOUT, "Number of seconds to wait for a block to be written to a connection before aborting the write.", (uchar**) &global_system_variables.net_write_timeout, @@ -6245,17 +6261,17 @@ The minimum value for this variable is 4096.", "Allocation block size for query parsing and execution", (uchar**) &global_system_variables.query_alloc_block_size, (uchar**) &max_system_variables.query_alloc_block_size, 0, GET_ULONG, - REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0}, + REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0}, #ifdef HAVE_QUERY_CACHE {"query_cache_limit", OPT_QUERY_CACHE_LIMIT, "Don't cache results that are bigger than this.", (uchar**) &query_cache_limit, (uchar**) &query_cache_limit, 0, GET_ULONG, - REQUIRED_ARG, 1024*1024L, 0, (longlong) ULONG_MAX, 0, 1, 0}, + REQUIRED_ARG, 1024*1024L, 0, ULONG_MAX, 0, 1, 0}, {"query_cache_min_res_unit", OPT_QUERY_CACHE_MIN_RES_UNIT, "minimal size of unit in wich space for results is allocated (last unit will be trimed after writing all result data.", (uchar**) &query_cache_min_res_unit, (uchar**) &query_cache_min_res_unit, 0, GET_ULONG, REQUIRED_ARG, QUERY_CACHE_MIN_RESULT_DATA_SIZE, - 0, (longlong) ULONG_MAX, 0, 1, 0}, + 0, ULONG_MAX, 0, 1, 0}, #endif /*HAVE_QUERY_CACHE*/ {"query_cache_size", OPT_QUERY_CACHE_SIZE, "The memory allocated to store results from old queries.", @@ -6278,12 +6294,13 @@ The minimum value for this variable is 4096.", (uchar**) &global_system_variables.query_prealloc_size, (uchar**) &max_system_variables.query_prealloc_size, 0, GET_ULONG, REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, QUERY_ALLOC_PREALLOC_SIZE, - ~0L, 0, 1024, 0}, + ULONG_MAX, 0, 1024, 0}, {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE, "Allocation block size for storing ranges during optimization", (uchar**) &global_system_variables.range_alloc_block_size, (uchar**) &max_system_variables.range_alloc_block_size, 0, GET_ULONG, - REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, 4096, ~0L, 0, 1024, 0}, + REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, RANGE_ALLOC_BLOCK_SIZE, ULONG_MAX, + 0, 1024, 0}, {"read_buffer_size", OPT_RECORD_BUFFER, "Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.", (uchar**) &global_system_variables.read_buff_size, @@ -6347,7 +6364,7 @@ The minimum value for this variable is 4096.", "Synchronously flush binary log to disk after every #th event. " "Use 0 (default) to disable synchronous flushing.", (uchar**) &sync_binlog_period, (uchar**) &sync_binlog_period, 0, GET_ULONG, - REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0}, + REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1, 0}, {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default.", (uchar**) &opt_sync_frm, (uchar**) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, @@ -6385,7 +6402,7 @@ The minimum value for this variable is 4096.", {"thread_stack", OPT_THREAD_STACK, "The stack size for each thread.", (uchar**) &thread_stack, (uchar**) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK, - 1024L*128L, ~0L, 0, 1024, 0}, + 1024L*128L, ULONG_MAX, 0, 1024, 0}, { "time_format", OPT_TIME_FORMAT, "The TIME format (for future).", (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME], @@ -6401,12 +6418,12 @@ The minimum value for this variable is 4096.", "Allocation block size for various transaction-related structures", (uchar**) &global_system_variables.trans_alloc_block_size, (uchar**) &max_system_variables.trans_alloc_block_size, 0, GET_ULONG, - REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0}, + REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0}, {"transaction_prealloc_size", OPT_TRANS_PREALLOC_SIZE, "Persistent buffer for various transaction-related structures", (uchar**) &global_system_variables.trans_prealloc_size, (uchar**) &max_system_variables.trans_prealloc_size, 0, GET_ULONG, - REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0}, + REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ULONG_MAX, 0, 1024, 0}, {"thread_handling", OPT_THREAD_HANDLING, "Define threads usage for handling queries: " "one-thread-per-connection or no-threads", 0, 0, diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ae311100168..b8bdb604eea 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -276,6 +276,9 @@ public: Field *field; uchar *min_value,*max_value; // Pointer to range + /* + eq_tree() requires that left == right == 0 if the type is MAYBE_KEY. + */ SEL_ARG *left,*right; /* R-B tree children */ SEL_ARG *next,*prev; /* Links for bi-directional interval list */ SEL_ARG *parent; /* R-B tree parent */ @@ -291,7 +294,7 @@ public: SEL_ARG(Field *field, uint8 part, uchar *min_value, uchar *max_value, uint8 min_flag, uint8 max_flag, uint8 maybe_flag); SEL_ARG(enum Type type_arg) - :min_flag(0),elements(1),use_count(1),left(0),next_key_part(0), + :min_flag(0),elements(1),use_count(1),left(0),right(0),next_key_part(0), color(BLACK), type(type_arg) {} inline bool is_same(SEL_ARG *arg) @@ -2161,12 +2164,18 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, keys_to_use.intersect(head->keys_in_use_for_query); if (!keys_to_use.is_clear_all()) { +#ifndef EMBEDDED_LIBRARY // Avoid compiler warning + uchar buff[STACK_BUFF_ALLOC]; +#endif MEM_ROOT alloc; SEL_TREE *tree= NULL; KEY_PART *key_parts; KEY *key_info; PARAM param; + if (check_stack_overrun(thd, 2*STACK_MIN_SIZE, buff)) + DBUG_RETURN(0); // Fatal error flag is set + /* set up parameter that is passed to all functions */ param.thd= thd; param.baseflag= head->file->ha_table_flags(); @@ -5726,6 +5735,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, { tree= new (alloc) SEL_ARG(field, 0, 0); tree->type= SEL_ARG::IMPOSSIBLE; + goto end; } else { @@ -5734,8 +5744,32 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, for the cases like int_field > 999999999999999999999999 as well. */ tree= 0; + if (err == 3 && field->type() == FIELD_TYPE_DATE && + (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC || + type == Item_func::LT_FUNC || type == Item_func::LE_FUNC) ) + { + /* + We were saving DATETIME into a DATE column, the conversion went ok + but a non-zero time part was cut off. + + In MySQL's SQL dialect, DATE and DATETIME are compared as datetime + values. Index over a DATE column uses DATE comparison. Changing + from one comparison to the other is possible: + + datetime(date_col)< '2007-12-10 12:34:55' -> date_col<='2007-12-10' + datetime(date_col)<='2007-12-10 12:34:55' -> date_col<='2007-12-10' + + datetime(date_col)> '2007-12-10 12:34:55' -> date_col>='2007-12-10' + datetime(date_col)>='2007-12-10 12:34:55' -> date_col>='2007-12-10' + + but we'll need to convert '>' to '>=' and '<' to '<='. This will + be done together with other types at the end of this function + (grep for field_is_equal_to_item) + */ + } + else + goto end; } - goto end; } if (err < 0) { diff --git a/sql/protocol.cc b/sql/protocol.cc index c1fc1ce8643..420912b0b63 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -88,12 +88,13 @@ void net_send_error(THD *thd, uint sql_errno, const char *err) */ thd->main_da.can_overwrite_status= TRUE; + /* Abort multi-result sets */ + thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; + net_send_error_packet(thd, sql_errno, err); thd->main_da.can_overwrite_status= FALSE; - /* Abort multi-result sets */ - thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; DBUG_VOID_RETURN; } @@ -272,7 +273,10 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err) { NET *net= &thd->net; uint length; - uchar buff[MYSQL_ERRMSG_SIZE+2], *pos; + /* + buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + MYSQL_ERRMSG_SIZE:512 + */ + uchar buff[2+1+SQLSTATE_LENGTH+MYSQL_ERRMSG_SIZE], *pos; DBUG_ENTER("send_error_packet"); diff --git a/sql/set_var.cc b/sql/set_var.cc index fd0254277eb..a01a0b49dbc 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -120,6 +120,10 @@ static int check_max_delayed_threads(THD *thd, set_var *var); static void fix_thd_mem_root(THD *thd, enum_var_type type); static void fix_trans_mem_root(THD *thd, enum_var_type type); static void fix_server_id(THD *thd, enum_var_type type); +static ulonglong fix_unsigned(THD *thd, ulonglong num, + const struct my_option *option_limits); +static bool get_unsigned(THD *thd, set_var *var); +static void throw_bounds_warning(THD *thd, const char *name, ulonglong num); static KEY_CACHE *create_key_cache(const char *name, uint length); void fix_sql_mode_var(THD *thd, enum_var_type type); static uchar *get_error_count(THD *thd); @@ -1102,6 +1106,39 @@ static void fix_server_id(THD *thd, enum_var_type type) } +static void throw_bounds_warning(THD *thd, const char *name, ulonglong num) +{ + char buf[22]; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), name, + ullstr(num, buf)); +} + +static ulonglong fix_unsigned(THD *thd, ulonglong num, + const struct my_option *option_limits) +{ + bool fixed= FALSE; + ulonglong out= getopt_ull_limit_value(num, option_limits, &fixed); + + if (fixed) + throw_bounds_warning(thd, option_limits->name, num); + return out; +} + +static bool get_unsigned(THD *thd, set_var *var) +{ + if (var->value->unsigned_flag) + var->save_result.ulonglong_value= (ulonglong) var->value->val_int(); + else + { + longlong v= var->value->val_int(); + var->save_result.ulonglong_value= (ulonglong) ((v < 0) ? 0 : v); + } + return 0; +} + + sys_var_long_ptr:: sys_var_long_ptr(sys_var_chain *chain, const char *name_arg, ulong *value_ptr_arg, sys_after_update_func after_update_arg) @@ -1112,9 +1149,7 @@ sys_var_long_ptr(sys_var_chain *chain, const char *name_arg, ulong *value_ptr_ar bool sys_var_long_ptr_global::check(THD *thd, set_var *var) { - longlong v= var->value->val_int(); - var->save_result.ulonglong_value= v < 0 ? 0 : v; - return 0; + return get_unsigned(thd, var); } bool sys_var_long_ptr_global::update(THD *thd, set_var *var) @@ -1122,9 +1157,20 @@ bool sys_var_long_ptr_global::update(THD *thd, set_var *var) ulonglong tmp= var->save_result.ulonglong_value; pthread_mutex_lock(guard); if (option_limits) - *value= (ulong) getopt_ull_limit_value(tmp, option_limits); + *value= (ulong) fix_unsigned(thd, tmp, option_limits); else + { +#if SIZEOF_LONG < SIZEOF_LONG_LONG + /* Avoid overflows on 32 bit systems */ + if (tmp > ULONG_MAX) + { + tmp= ULONG_MAX; + throw_bounds_warning(thd, name, var->save_result.ulonglong_value); + } +#endif *value= (ulong) tmp; + } + pthread_mutex_unlock(guard); return 0; } @@ -1143,7 +1189,7 @@ bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var) ulonglong tmp= var->save_result.ulonglong_value; pthread_mutex_lock(&LOCK_global_system_variables); if (option_limits) - *value= (ulonglong) getopt_ull_limit_value(tmp, option_limits); + *value= (ulonglong) fix_unsigned(thd, tmp, option_limits); else *value= (ulonglong) tmp; pthread_mutex_unlock(&LOCK_global_system_variables); @@ -1193,45 +1239,36 @@ uchar *sys_var_enum_const::value_ptr(THD *thd, enum_var_type type, bool sys_var_thd_ulong::check(THD *thd, set_var *var) { - return (sys_var_thd::check(thd, var) || + return (get_unsigned(thd, var) || (check_func && (*check_func)(thd, var))); } bool sys_var_thd_ulong::update(THD *thd, set_var *var) { ulonglong tmp= var->save_result.ulonglong_value; - char buf[22]; - bool truncated= false; /* Don't use bigger value than given with --maximum-variable-name=.. */ if ((ulong) tmp > max_system_variables.*offset) { - truncated= true; - llstr(tmp, buf); + throw_bounds_warning(thd, name, tmp); tmp= max_system_variables.*offset; } -#if SIZEOF_LONG == 4 - /* Avoid overflows on 32 bit systems */ - if (tmp > (ulonglong) ~(ulong) 0) + if (option_limits) + tmp= (ulong) fix_unsigned(thd, tmp, option_limits); +#if SIZEOF_LONG < SIZEOF_LONG_LONG + else if (tmp > ULONG_MAX) { - truncated= true; - llstr(tmp, buf); - tmp= ((ulonglong) ~(ulong) 0); + tmp= ULONG_MAX; + throw_bounds_warning(thd, name, var->save_result.ulonglong_value); } #endif - if (truncated) - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_TRUNCATED_WRONG_VALUE, - ER(ER_TRUNCATED_WRONG_VALUE), name, - buf); - if (option_limits) - tmp= (ulong) getopt_ull_limit_value(tmp, option_limits); if (var->type == OPT_GLOBAL) global_system_variables.*offset= (ulong) tmp; else thd->variables.*offset= (ulong) tmp; + return 0; } @@ -1266,7 +1303,7 @@ bool sys_var_thd_ha_rows::update(THD *thd, set_var *var) tmp= max_system_variables.*offset; if (option_limits) - tmp= (ha_rows) getopt_ull_limit_value(tmp, option_limits); + tmp= (ha_rows) fix_unsigned(thd, tmp, option_limits); if (var->type == OPT_GLOBAL) { /* Lock is needed to make things safe on 32 bit systems */ @@ -1302,6 +1339,11 @@ uchar *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type, return (uchar*) &(thd->variables.*offset); } +bool sys_var_thd_ulonglong::check(THD *thd, set_var *var) +{ + return get_unsigned(thd, var); +} + bool sys_var_thd_ulonglong::update(THD *thd, set_var *var) { ulonglong tmp= var->save_result.ulonglong_value; @@ -1310,7 +1352,7 @@ bool sys_var_thd_ulonglong::update(THD *thd, set_var *var) tmp= max_system_variables.*offset; if (option_limits) - tmp= getopt_ull_limit_value(tmp, option_limits); + tmp= fix_unsigned(thd, tmp, option_limits); if (var->type == OPT_GLOBAL) { /* Lock is needed to make things safe on 32 bit systems */ @@ -1517,7 +1559,7 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) pthread_mutex_lock(&LOCK_global_system_variables); value= *(ha_rows*) value_ptr(thd, var_type, base); pthread_mutex_unlock(&LOCK_global_system_variables); - return new Item_int((longlong) value); + return new Item_int((ulonglong) value); } case SHOW_MY_BOOL: { @@ -2035,7 +2077,7 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) } key_cache->param_buff_size= - (ulonglong) getopt_ull_limit_value(tmp, option_limits); + (ulonglong) fix_unsigned(thd, tmp, option_limits); /* If key cache didn't existed initialize it, else resize it */ key_cache->in_init= 1; @@ -2083,7 +2125,7 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var) goto end; *((ulong*) (((char*) key_cache) + offset))= - (ulong) getopt_ull_limit_value(tmp, option_limits); + (ulong) fix_unsigned(thd, tmp, option_limits); /* Don't create a new key cache if it didn't exist diff --git a/sql/set_var.h b/sql/set_var.h index e8ef3c54c66..5be54200c7d 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -397,6 +397,7 @@ public: void set_default(THD *thd, enum_var_type type); SHOW_TYPE show_type() { return SHOW_LONGLONG; } uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + bool check(THD *thd, set_var *var); bool check_default(enum_var_type type) { return type == OPT_GLOBAL && !option_limits; diff --git a/sql/slave.cc b/sql/slave.cc index b1f25ee58da..7aa24319c86 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -137,6 +137,7 @@ static int terminate_slave_thread(THD *thd, pthread_cond_t* term_cond, volatile uint *slave_running, bool skip_lock); +static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info); /* Find out which replications threads are running @@ -821,7 +822,7 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi) mi->clock_diff_with_master= (long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10)); } - else + else if (!check_io_slave_killed(mi->io_thd, mi, NULL)) { mi->clock_diff_with_master= 0; /* The "most sensible" value */ sql_print_warning("\"SELECT UNIX_TIMESTAMP()\" failed on master, " @@ -1235,7 +1236,7 @@ int register_slave_on_master(MYSQL* mysql, Master_info *mi, { *suppress_warnings= TRUE; // Suppress reconnect warning } - else + else if (!check_io_slave_killed(mi->io_thd, mi, NULL)) { char buf[256]; my_snprintf(buf, sizeof(buf), "%s (Errno: %d)", mysql_error(mysql), @@ -2017,7 +2018,7 @@ static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info) { if (io_slave_killed(thd, mi)) { - if (global_system_variables.log_warnings) + if (info && global_system_variables.log_warnings) sql_print_information(info); return TRUE; } @@ -2202,11 +2203,15 @@ connected: thd->proc_info = "Registering slave on master"; if (register_slave_on_master(mysql, mi, &suppress_warnings)) { - sql_print_error("Slave I/O thread couldn't register on master"); - if (check_io_slave_killed(thd, mi, "Slave I/O thread killed while \ -registering slave on master") || - try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings, - reconnect_messages[SLAVE_RECON_ACT_REG])) + if (!check_io_slave_killed(thd, mi, "Slave I/O thread killed " + "while registering slave on master")) + { + sql_print_error("Slave I/O thread couldn't register on master"); + if (try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings, + reconnect_messages[SLAVE_RECON_ACT_REG])) + goto err; + } + else goto err; goto connected; } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 3d3f6e4a965..b4d728daa5e 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1702,16 +1702,18 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u) } } field_term_length=exchange->field_term->length(); - field_term_char= field_term_length ? (*exchange->field_term)[0] : INT_MAX; + field_term_char= field_term_length ? + (int) (uchar) (*exchange->field_term)[0] : INT_MAX; if (!exchange->line_term->length()) exchange->line_term=exchange->field_term; // Use this if it exists - field_sep_char= (exchange->enclosed->length() ? (*exchange->enclosed)[0] : - field_term_char); - escape_char= (exchange->escaped->length() ? (*exchange->escaped)[0] : -1); + field_sep_char= (exchange->enclosed->length() ? + (int) (uchar) (*exchange->enclosed)[0] : field_term_char); + escape_char= (exchange->escaped->length() ? + (int) (uchar) (*exchange->escaped)[0] : -1); is_ambiguous_field_sep= test(strchr(ESCAPE_CHARS, field_sep_char)); is_unsafe_field_sep= test(strchr(NUMERIC_CHARS, field_sep_char)); line_sep_char= (exchange->line_term->length() ? - (*exchange->line_term)[0] : INT_MAX); + (int) (uchar) (*exchange->line_term)[0] : INT_MAX); if (!field_term_length) exchange->opt_enclosed=0; if (!exchange->enclosed->length()) @@ -1868,10 +1870,11 @@ bool select_export::send_data(List<Item> &items) Don't escape field_term_char by doubling - doubling is only valid for ENCLOSED BY characters: */ - (enclosed || !is_ambiguous_field_term || *pos != field_term_char)) + (enclosed || !is_ambiguous_field_term || + (int) (uchar) *pos != field_term_char)) { char tmp_buff[2]; - tmp_buff[0]= ((int) *pos == field_sep_char && + tmp_buff[0]= ((int) (uchar) *pos == field_sep_char && is_ambiguous_field_sep) ? field_sep_char : escape_char; tmp_buff[1]= *pos ? *pos : '0'; diff --git a/sql/sql_class.h b/sql/sql_class.h index 7a5e3963a9c..8c2c2dce1de 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2302,14 +2302,13 @@ class select_insert :public select_result_interceptor { ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not COPY_INFO info; bool insert_into_view; - bool is_bulk_insert_mode; select_insert(TABLE_LIST *table_list_par, TABLE *table_par, List<Item> *fields_par, List<Item> *update_fields, List<Item> *update_values, enum_duplicates duplic, bool ignore); ~select_insert(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); - int prepare2(void); + virtual int prepare2(void); bool send_data(List<Item> &items); virtual void store_values(List<Item> &values); virtual bool can_rollback_data() { return 0; } @@ -2357,6 +2356,7 @@ public: // Needed for access from local class MY_HOOKS in prepare(), since thd is proteted. const THD *get_thd(void) { return thd; } const HA_CREATE_INFO *get_create_info() { return create_info; }; + int prepare2(void) { return 0; } }; #include <myisam.h> diff --git a/sql/sql_db.cc b/sql/sql_db.cc index d425510320e..f158b5488d0 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1119,6 +1119,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, VOID(filename_to_tablename(file->name, table_list->table_name, strlen(file->name) + 1)); table_list->alias= table_list->table_name; // If lower_case_table_names=2 + table_list->internal_tmp_table= is_prefix(file->name, tmp_file_prefix); /* Link into list */ (*tot_list_next)= table_list; tot_list_next= &table_list->next_local; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index e427a2904ba..1dd915fb9b6 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2802,8 +2802,7 @@ select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par, bool ignore_check_option_errors) :table_list(table_list_par), table(table_par), fields(fields_par), autoinc_value_of_last_inserted_row(0), - insert_into_view(table_list_par && table_list_par->view != 0), - is_bulk_insert_mode(FALSE) + insert_into_view(table_list_par && table_list_par->view != 0) { bzero((char*) &info,sizeof(info)); info.handle_duplicates= duplic; @@ -2916,14 +2915,14 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) Is table which we are changing used somewhere in other parts of query */ - if (!(lex->current_select->options & OPTION_BUFFER_RESULT) && - unique_table(thd, table_list, table_list->next_global, 0)) + if (unique_table(thd, table_list, table_list->next_global, 0)) { /* Using same table for INSERT and SELECT */ lex->current_select->options|= OPTION_BUFFER_RESULT; lex->current_select->join->select_options|= OPTION_BUFFER_RESULT; } - else if (!thd->prelocked_mode) + else if (!(lex->current_select->options & OPTION_BUFFER_RESULT) && + !thd->prelocked_mode) { /* We must not yet prepare the result table if it is the same as one of the @@ -2989,11 +2988,8 @@ int select_insert::prepare2(void) { DBUG_ENTER("select_insert::prepare2"); if (thd->lex->current_select->options & OPTION_BUFFER_RESULT && - !thd->prelocked_mode && !is_bulk_insert_mode) - { + !thd->prelocked_mode) table->file->ha_start_bulk_insert((ha_rows) 0); - is_bulk_insert_mode= TRUE; - } DBUG_RETURN(0); } @@ -3113,7 +3109,6 @@ bool select_insert::send_eof() trans_table, table->file->table_type())); error= (!thd->prelocked_mode) ? table->file->ha_end_bulk_insert():0; - is_bulk_insert_mode= FALSE; table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); @@ -3565,10 +3560,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) if (info.handle_duplicates == DUP_UPDATE) table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE); if (!thd->prelocked_mode) - { table->file->ha_start_bulk_insert((ha_rows) 0); - is_bulk_insert_mode= TRUE; - } thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c33130b40c4..b60a72e4c53 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -478,7 +478,7 @@ end: (CREATE TABLE, ALTER TABLE ... UNION=(...)). Set TL_WRITE for every child. Set 'db' for every child if not present. */ - +#ifndef NO_EMBEDDED_ACCESS_CHECKS static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list) { @@ -499,7 +499,7 @@ static bool check_merge_table_access(THD *thd, char *db, } return error; } - +#endif /* This works because items are allocated with sql_alloc() */ @@ -1952,10 +1952,6 @@ mysql_execute_command(THD *thd) switch (lex->sql_command) { case SQLCOM_SHOW_EVENTS: - if ((res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, - is_schema_db(thd->lex->select_lex.db)))) - break; - /* fall through */ case SQLCOM_SHOW_STATUS_PROC: case SQLCOM_SHOW_STATUS_FUNC: res= execute_sqlcom_select(thd, all_tables); @@ -4009,13 +4005,11 @@ create_sp_error: thd->server_status|= SERVER_MORE_RESULTS_EXISTS; } -#ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_routine_access(thd, EXECUTE_ACL, sp->m_db.str, sp->m_name.str, TRUE, FALSE)) { goto error; } -#endif select_limit= thd->variables.select_limit; thd->variables.select_limit= HA_POS_ERROR; @@ -4697,6 +4691,7 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) } +#ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check grants for commands which work only with one table. @@ -4814,7 +4809,6 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, bool dont_check_global_grants, bool no_errors, bool schema_db) { Security_context *sctx= thd->security_ctx; -#ifndef NO_EMBEDDED_ACCESS_CHECKS ulong db_access; /* GRANT command: @@ -4827,7 +4821,6 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, */ bool db_is_pattern= (test(want_access & GRANT_ACL) && dont_check_global_grants); -#endif ulong dummy; DBUG_ENTER("check_access"); DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu", @@ -4866,9 +4859,6 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, } } -#ifdef NO_EMBEDDED_ACCESS_CHECKS - DBUG_RETURN(0); -#else if ((sctx->master_access & want_access) == want_access) { /* @@ -4926,7 +4916,6 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, thd->db : "unknown"))); /* purecov: tested */ DBUG_RETURN(TRUE); /* purecov: tested */ -#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } @@ -4951,16 +4940,12 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, bool check_global_access(THD *thd, ulong want_access) { -#ifdef NO_EMBEDDED_ACCESS_CHECKS - return 0; -#else char command[128]; if ((thd->security_ctx->master_access & want_access)) return 0; get_privilege_desc(command, sizeof(command), want_access); my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command); return 1; -#endif /* NO_EMBEDDED_ACCESS_CHECKS */ } @@ -5050,9 +5035,7 @@ bool check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, bool no_errors) { -#ifndef NO_EMBEDDED_ACCESS_CHECKS TABLE_LIST *org_tables= tables; -#endif TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table(); Security_context *sctx= thd->security_ctx, *backup_ctx= thd->security_ctx; /* @@ -5139,11 +5122,7 @@ check_routine_access(THD *thd, ulong want_access,char *db, char *name, 0, no_errors, 0)) return TRUE; -#ifndef NO_EMBEDDED_ACCESS_CHECKS return check_grant_routine(thd, want_access, tables, is_proc, no_errors); -#else - return FALSE; -#endif } @@ -5213,6 +5192,7 @@ bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table) DBUG_RETURN(1); } +#endif /*NO_EMBEDDED_ACCESS_CHECKS*/ /**************************************************************************** Check stack size; Send error if there isn't enough stack to continue diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 541de387c6e..ce70e177a85 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -3991,6 +3991,7 @@ static int fast_end_partition(THD *thd, ulonglong copied, DBUG_RETURN(FALSE); } table->file->print_error(error, MYF(0)); + close_thread_tables(thd); DBUG_RETURN(TRUE); } @@ -6113,7 +6114,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, (error= table->file->repair_partitions(thd)))) { table->file->print_error(error, MYF(0)); - DBUG_RETURN(TRUE); + goto err; } } else if (fast_alter_partition & HA_PARTITION_ONE_PHASE) @@ -6160,7 +6161,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, if (mysql_write_frm(lpt, WFRM_WRITE_SHADOW | WFRM_PACK_FRM) || mysql_change_partitions(lpt)) { - DBUG_RETURN(TRUE); + goto err; } } else if (alter_info->flags == ALTER_DROP_PARTITION) @@ -6253,7 +6254,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, (release_name_lock(lpt), FALSE)) { handle_alter_part_error(lpt, not_completed, TRUE, frm_install); - DBUG_RETURN(TRUE); + goto err; } } else if ((alter_info->flags & ALTER_ADD_PARTITION) && @@ -6322,7 +6323,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, (release_name_lock(lpt), FALSE)) { handle_alter_part_error(lpt, not_completed, FALSE, frm_install); - DBUG_RETURN(TRUE); + goto err; } } else @@ -6415,7 +6416,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, (release_name_lock(lpt), FALSE)) { handle_alter_part_error(lpt, not_completed, FALSE, frm_install); - DBUG_RETURN(TRUE); + goto err; } } /* @@ -6425,6 +6426,9 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, DBUG_RETURN(fast_end_partition(thd, lpt->copied, lpt->deleted, table, table_list, FALSE, NULL, written_bin_log)); +err: + close_thread_tables(thd); + DBUG_RETURN(TRUE); } #endif diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 87595903465..2a86844c8c6 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1876,11 +1876,26 @@ err: static int check_func_int(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { + bool fixed; long long tmp; struct my_option options; value->val_int(value, &tmp); plugin_opt_set_limits(&options, var); - *(int *)save= (int) getopt_ull_limit_value(tmp, &options); + + if (var->flags & PLUGIN_VAR_UNSIGNED) + *(uint *)save= (uint) getopt_ull_limit_value((ulonglong) tmp, &options, + &fixed); + else + *(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed); + + if (fixed) + { + char buf[22]; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), var->name, + ullstr(tmp, buf)); + } return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) && (*(int *)save != (int) tmp); } @@ -1889,24 +1904,55 @@ static int check_func_int(THD *thd, struct st_mysql_sys_var *var, static int check_func_long(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { + bool fixed; long long tmp; struct my_option options; value->val_int(value, &tmp); plugin_opt_set_limits(&options, var); - *(long *)save= (long) getopt_ull_limit_value(tmp, &options); + + if (var->flags & PLUGIN_VAR_UNSIGNED) + *(ulong *)save= (ulong) getopt_ull_limit_value((ulonglong) tmp, &options, + &fixed); + else + *(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed); + + if (fixed) + { + char buf[22]; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), var->name, + ullstr(tmp, buf)); + } return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) && (*(long *)save != (long) tmp); } static int check_func_longlong(THD *thd, struct st_mysql_sys_var *var, - void *save, st_mysql_value *value) + void *save, st_mysql_value *value) { + bool fixed; long long tmp; struct my_option options; value->val_int(value, &tmp); plugin_opt_set_limits(&options, var); - *(ulonglong *)save= getopt_ull_limit_value(tmp, &options); + *(ulonglong *)save= getopt_ull_limit_value(tmp, &options, &fixed); + + if (var->flags & PLUGIN_VAR_UNSIGNED) + *(ulonglong *)save= getopt_ull_limit_value((ulonglong) tmp, &options, + &fixed); + else + *(longlong *)save= getopt_ll_limit_value(tmp, &options, &fixed); + + if (fixed) + { + char buf[22]; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), var->name, + ullstr(tmp, buf)); + } return (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) && (*(long long *)save != tmp); } @@ -2685,6 +2731,8 @@ bool sys_var_pluginvar::update(THD *thd, set_var *var) static void plugin_opt_set_limits(struct my_option *options, const struct st_mysql_sys_var *opt) { + options->sub_size= 0; + switch (opt->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_UNSIGNED | PLUGIN_VAR_THDLOCAL)) { /* global system variables */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3e759b860a8..93486aa7b65 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -223,6 +223,7 @@ static void select_describe(JOIN *join, bool need_tmp_table,bool need_order, bool distinct, const char *message=NullS); static Item *remove_additional_cond(Item* conds); static void add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab); +static bool test_if_ref(Item_field *left_item,Item *right_item); /* @@ -680,9 +681,6 @@ err: without "checking NULL", remove the predicates that were pushed down into the subquery. - We can remove the equalities that will be guaranteed to be true by the - fact that subquery engine will be using index lookup. - If the subquery compares scalar values, we can remove the condition that was wrapped into trig_cond (it will be checked when needed by the subquery engine) @@ -692,6 +690,12 @@ err: and non-NULL values, we'll do a full table scan and will rely on the equalities corresponding to non-NULL parts of left tuple to filter out non-matching records. + + TODO: We can remove the equalities that will be guaranteed to be true by the + fact that subquery engine will be using index lookup. This must be done only + for cases where there are no conversion errors of significance, e.g. 257 + that is searched in a byte. But this requires homogenization of the return + codes of all Field*::store() methods. */ void JOIN::remove_subq_pushed_predicates(Item **where) @@ -699,17 +703,13 @@ void JOIN::remove_subq_pushed_predicates(Item **where) if (conds->type() == Item::FUNC_ITEM && ((Item_func *)this->conds)->functype() == Item_func::EQ_FUNC && ((Item_func *)conds)->arguments()[0]->type() == Item::REF_ITEM && - ((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM) + ((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM && + test_if_ref ((Item_field *)((Item_func *)conds)->arguments()[1], + ((Item_func *)conds)->arguments()[0])) { *where= 0; return; } - if (conds->type() == Item::COND_ITEM && - ((class Item_func *)this->conds)->functype() == - Item_func::COND_AND_FUNC) - { - *where= remove_additional_cond(conds); - } } @@ -1258,7 +1258,7 @@ JOIN::optimize() { if (!having) { - Item *where= 0; + Item *where= conds; if (join_tab[0].type == JT_EQ_REF && join_tab[0].ref.items[0]->name == in_left_expr_name) { @@ -2365,6 +2365,11 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select, { int error; DBUG_ENTER("get_quick_record_count"); +#ifndef EMBEDDED_LIBRARY // Avoid compiler warning + uchar buff[STACK_BUFF_ALLOC]; +#endif + if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) + DBUG_RETURN(0); // Fatal error flag is set if (select) { select->head=table; @@ -3733,7 +3738,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, found_eq_constant=0; for (i=0 ; i < keyuse->elements-1 ; i++,use++) { - if (!use->used_tables) + if (!use->used_tables && use->optimize != KEY_OPTIMIZE_REF_OR_NULL) use->table->const_key_parts[use->key]|= use->keypart_map; if (use->keypart != FT_KEYPART) { @@ -10618,7 +10623,8 @@ Next_select_func setup_end_select_func(JOIN *join) /* Set up select_end */ if (table) { - if (table->group && tmp_tbl->sum_func_count) + if (table->group && tmp_tbl->sum_func_count && + !tmp_tbl->precomputed_group_by) { if (table->s->keys) { @@ -12259,8 +12265,12 @@ static bool test_if_ref(Item_field *left_item,Item *right_item) Item *ref_item=part_of_refkey(field->table,field); if (ref_item && ref_item->eq(right_item,1)) { + right_item= right_item->real_item(); if (right_item->type() == Item::FIELD_ITEM) return (field->eq_def(((Item_field *) right_item)->field)); + /* remove equalities injected by IN->EXISTS transformation */ + else if (right_item->type() == Item::CACHE_ITEM) + return ((Item_cache *)right_item)->eq_def (field); if (right_item->const_item() && !(right_item->is_null())) { /* @@ -15969,7 +15979,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, { if (tab->use_quick == 2) { - char buf[MAX_KEY/8+1]; + /* 4 bits per 1 hex digit + terminating '\0' */ + char buf[MAX_KEY / 4 + 1]; extra.append(STRING_WITH_LEN("; Range checked for each " "record (index map: 0x")); extra.append(tab->keys.print(buf)); diff --git a/sql/sql_select.h b/sql/sql_select.h index 256d57cc10a..cb59032315a 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -594,14 +594,17 @@ public: enum store_key_result copy() { enum store_key_result result; - enum_check_fields saved_count_cuted_fields= - to_field->table->in_use->count_cuted_fields; + THD *thd= to_field->table->in_use; + enum_check_fields saved_count_cuted_fields= thd->count_cuted_fields; + ulong sql_mode= thd->variables.sql_mode; + thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE); - to_field->table->in_use->count_cuted_fields= CHECK_FIELD_IGNORE; + thd->count_cuted_fields= CHECK_FIELD_IGNORE; result= copy_inner(); - to_field->table->in_use->count_cuted_fields= saved_count_cuted_fields; + thd->count_cuted_fields= saved_count_cuted_fields; + thd->variables.sql_mode= sql_mode; return result; } diff --git a/sql/sql_string.cc b/sql/sql_string.cc index a8eb7360339..2e076af45eb 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -846,7 +846,7 @@ outp: with optional left padding (for binary -> UCS2 conversion) SYNOPSIS - well_formed_copy_nhars() + well_formed_copy_nchars() to Store result here to_length Maxinum length of "to" string to_cs Character set of "to" string @@ -983,7 +983,10 @@ outp: goto outp; } else + { + from= from_prev; break; + } } *from_end_pos= from; res= to - to_start; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index cbdd7ac11c4..0bd742b898d 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -279,7 +279,7 @@ uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen) */ -typedef struct st_global_ddl_log +struct st_global_ddl_log { /* We need to adjust buffer size to be able to handle downgrades/upgrades @@ -297,10 +297,12 @@ typedef struct st_global_ddl_log uint name_len; uint io_size; bool inited; + bool do_release; bool recovery_phase; -} GLOBAL_DDL_LOG; + st_global_ddl_log() : inited(false), do_release(false) {} +}; -GLOBAL_DDL_LOG global_ddl_log; +st_global_ddl_log global_ddl_log; pthread_mutex_t LOCK_gdl; @@ -460,6 +462,7 @@ static uint read_ddl_log_header() global_ddl_log.first_used= NULL; global_ddl_log.num_entries= 0; VOID(pthread_mutex_init(&LOCK_gdl, MY_MUTEX_INIT_FAST)); + global_ddl_log.do_release= true; DBUG_RETURN(entry_no); } @@ -1150,6 +1153,9 @@ void release_ddl_log() DDL_LOG_MEMORY_ENTRY *used_list= global_ddl_log.first_used; DBUG_ENTER("release_ddl_log"); + if (!global_ddl_log.do_release) + DBUG_VOID_RETURN; + pthread_mutex_lock(&LOCK_gdl); while (used_list) { @@ -1167,6 +1173,7 @@ void release_ddl_log() global_ddl_log.inited= 0; pthread_mutex_unlock(&LOCK_gdl); VOID(pthread_mutex_destroy(&LOCK_gdl)); + global_ddl_log.do_release= false; DBUG_VOID_RETURN; } @@ -1241,6 +1248,10 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) char shadow_path[FN_REFLEN+1]; char shadow_frm_name[FN_REFLEN+1]; char frm_name[FN_REFLEN+1]; +#ifdef WITH_PARTITION_STORAGE_ENGINE + char *part_syntax_buf; + uint syntax_len; +#endif DBUG_ENTER("mysql_write_frm"); /* @@ -1264,12 +1275,8 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) #ifdef WITH_PARTITION_STORAGE_ENGINE { partition_info *part_info= lpt->table->part_info; - char *part_syntax_buf; - uint syntax_len; - if (part_info) { - TABLE_SHARE *share= lpt->table->s; if (!(part_syntax_buf= generate_partition_syntax(part_info, &syntax_len, TRUE, TRUE))) @@ -1277,16 +1284,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) DBUG_RETURN(TRUE); } part_info->part_info_string= part_syntax_buf; - share->partition_info_len= part_info->part_info_len= syntax_len; - if (share->partition_info_buffer_size < syntax_len + 1) - { - share->partition_info_buffer_size= syntax_len+1; - if (!(share->partition_info= - (char*) alloc_root(&share->mem_root, syntax_len+1))) - DBUG_RETURN(TRUE); - - } - memcpy((char*) share->partition_info, part_syntax_buf, syntax_len + 1); + part_info->part_info_len= syntax_len; } } #endif @@ -1364,7 +1362,40 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) #endif { error= 1; + goto err; + } +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (part_info) + { + TABLE_SHARE *share= lpt->table->s; + char *tmp_part_syntax_str; + if (!(part_syntax_buf= generate_partition_syntax(part_info, + &syntax_len, + TRUE, TRUE))) + { + error= 1; + goto err; + } + if (share->partition_info_buffer_size < syntax_len + 1) + { + share->partition_info_buffer_size= syntax_len+1; + if (!(tmp_part_syntax_str= (char*) strmake_root(&share->mem_root, + part_syntax_buf, + syntax_len))) + { + error= 1; + goto err; + } + share->partition_info= tmp_part_syntax_str; + } + else + memcpy((char*) share->partition_info, part_syntax_buf, syntax_len + 1); + share->partition_info_len= part_info->part_info_len= syntax_len; + part_info->part_info_string= part_syntax_buf; } +#endif + +err: VOID(pthread_mutex_unlock(&LOCK_open)); #ifdef WITH_PARTITION_STORAGE_ENGINE deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos); @@ -1630,8 +1661,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, } alias= (lower_case_table_names == 2) ? table->alias : table->table_name; /* remove .frm file and engine files */ - path_length= build_table_filename(path, sizeof(path), - db, alias, reg_ext, 0); + path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext, + table->internal_tmp_table ? + FN_IS_TMP : 0); } if (drop_temporary || (table_type == NULL && @@ -4588,6 +4620,55 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables) } + +/** + @brief Create frm file based on I_S table + + @param[in] thd thread handler + @param[in] schema_table I_S table + @param[in] dst_path path where frm should be created + @param[in] create_info Create info + + @return Operation status + @retval 0 success + @retval 1 error +*/ + + +bool mysql_create_like_schema_frm(THD* thd, TABLE_LIST* schema_table, + char *dst_path, HA_CREATE_INFO *create_info) +{ + HA_CREATE_INFO local_create_info; + Alter_info alter_info; + bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE); + uint keys= schema_table->table->s->keys; + uint db_options= 0; + DBUG_ENTER("mysql_create_like_schema_frm"); + + bzero((char*) &local_create_info, sizeof(local_create_info)); + local_create_info.db_type= schema_table->table->s->db_type(); + local_create_info.row_type= schema_table->table->s->row_type; + local_create_info.default_table_charset=default_charset_info; + alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE); + schema_table->table->use_all_columns(); + if (mysql_prepare_alter_table(thd, schema_table->table, + &local_create_info, &alter_info)) + DBUG_RETURN(1); + if (mysql_prepare_create_table(thd, &local_create_info, &alter_info, + tmp_table, &db_options, + schema_table->table->file, + &schema_table->table->s->key_info, &keys, 0)) + DBUG_RETURN(1); + local_create_info.max_rows= 0; + if (mysql_create_frm(thd, dst_path, NullS, NullS, + &local_create_info, alter_info.create_list, + keys, schema_table->table->s->key_info, + schema_table->table->file)) + DBUG_RETURN(1); + DBUG_RETURN(0); +} + + /* Create a table identical to the specified table @@ -4691,7 +4772,15 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, during the call to ha_create_table(). See bug #28614 for more info. */ VOID(pthread_mutex_lock(&LOCK_open)); - if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE))) + if (src_table->schema_table) + { + if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info)) + { + VOID(pthread_mutex_unlock(&LOCK_open)); + goto err; + } + } + else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE))) { if (my_errno == ENOENT) my_error(ER_BAD_DB_ERROR,MYF(0),db); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 80e354aef98..b4d8bb2dfb8 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1228,7 +1228,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <variable> internal_variable_name -%type <select_lex> subselect subselect_init +%type <select_lex> subselect take_first_select get_select_lex %type <boolfunc2creator> comp_op @@ -11648,37 +11648,22 @@ union_option: | ALL { $$=0; } ; -subselect: - SELECT_SYM subselect_start subselect_init subselect_end - { - $$= $3; - } - | '(' subselect_start subselect ')' - { - THD *thd= YYTHD; - /* - note that a local variable can't be used for - $3 as it's used in local variable construction - and some compilers can't guarnatee the order - in which the local variables are initialized. - */ - List_iterator<Item> it($3->item_list); - Item *item; - /* - we must fill the items list for the "derived table". - */ - while ((item= it++)) - add_item_to_list(thd, item); - } - union_clause subselect_end { $$= $3; } - ; +take_first_select: /* empty */ + { + $$= Lex->current_select->master_unit()->first_select(); + }; -subselect_init: - select_init2 - { - $$= Lex->current_select->master_unit()->first_select(); - } - ; +subselect: + SELECT_SYM subselect_start select_init2 take_first_select + subselect_end + { + $$= $4; + } + | '(' subselect_start select_paren take_first_select + subselect_end ')' + { + $$= $4; + }; subselect_start: { diff --git a/sql/table.cc b/sql/table.cc index 133b08ba703..cacb3a94582 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1793,13 +1793,18 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, outparam, is_create_table, share->default_part_db_type, &work_part_info_used); - if (!tmp) - outparam->part_info->is_auto_partitioned= share->auto_partitioned; + if (tmp) + { + thd->stmt_arena= backup_stmt_arena_ptr; + thd->restore_active_arena(&part_func_arena, &backup_arena); + goto partititon_err; + } + outparam->part_info->is_auto_partitioned= share->auto_partitioned; DBUG_PRINT("info", ("autopartitioned: %u", share->auto_partitioned)); /* we should perform the fix_partition_func in either local or caller's arena depending on work_part_info_used value */ - if (!tmp && !work_part_info_used) + if (!work_part_info_used) tmp= fix_partition_func(thd, outparam, is_create_table); thd->stmt_arena= backup_stmt_arena_ptr; thd->restore_active_arena(&part_func_arena, &backup_arena); @@ -1809,6 +1814,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, tmp= fix_partition_func(thd, outparam, is_create_table); outparam->part_info->item_free_list= part_func_arena.free_list; } +partititon_err: if (tmp) { if (is_create_table) diff --git a/sql/table.h b/sql/table.h index 7bf0f6bb792..1e80afdf421 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1097,6 +1097,7 @@ struct TABLE_LIST ... SELECT implementation). */ bool create; + bool internal_tmp_table; /* View creation context. */ diff --git a/sql/udf_example.c b/sql/udf_example.c index 6f2093cc92f..a3d149f0971 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -648,13 +648,11 @@ my_bool sequence_init(UDF_INIT *initid, UDF_ARGS *args, char *message) return 1; } bzero(initid->ptr,sizeof(longlong)); - /* - Fool MySQL to think that this function is a constant - This will ensure that MySQL only evalutes the function - when the rows are sent to the client and not before any ORDER BY - clauses + /* + sequence() is a non-deterministic function : it has different value + even if called with the same arguments. */ - initid->const_item=1; + initid->const_item=0; return 0; } |