diff options
author | unknown <gluh@eagle.(none)> | 2007-10-23 18:51:43 +0500 |
---|---|---|
committer | unknown <gluh@eagle.(none)> | 2007-10-23 18:51:43 +0500 |
commit | 8479eb1db7d1c8ccfbaa62077c54b7f5af714324 (patch) | |
tree | d36465f86e78c442a44942849b7280eab8d10bf8 /sql | |
parent | fb9a562b1cc2b9048eff094bb7004fb3db0e7fd0 (diff) | |
parent | c448d2ed5d2a7efd1f77b956f46d8f1e48b17350 (diff) | |
download | mariadb-git-8479eb1db7d1c8ccfbaa62077c54b7f5af714324.tar.gz |
Merge mysql.com:/home/gluh/MySQL/Merge/5.0
into mysql.com:/home/gluh/MySQL/Merge/5.0-opt
client/mysqldump.c:
Auto merged
include/config-win.h:
Auto merged
libmysql/libmysql.c:
Auto merged
myisam/sort.c:
Auto merged
mysql-test/r/func_sapdb.result:
Auto merged
mysql-test/r/variables.result:
Auto merged
mysql-test/t/variables.test:
Auto merged
sql/field.cc:
Auto merged
sql/ha_innodb.cc:
Auto merged
sql/item_func.cc:
Auto merged
sql/item_sum.cc:
Auto merged
sql/item_timefunc.h:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/set_var.cc:
Auto merged
sql/sql_acl.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
tests/mysql_client_test.c:
Auto merged
mysql-test/r/type_datetime.result:
manual merge
mysql-test/r/type_decimal.result:
manual merge
mysql-test/t/type_datetime.test:
manual merge
mysql-test/t/type_decimal.test:
manual merge
sql/item.cc:
manual merge
Diffstat (limited to 'sql')
40 files changed, 435 insertions, 210 deletions
diff --git a/sql/field.cc b/sql/field.cc index 8191d885a27..86853389c64 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1356,15 +1356,25 @@ void Field_num::add_zerofill_and_unsigned(String &res) const void Field::make_field(Send_field *field) { - if (orig_table->s->table_cache_key && *(orig_table->s->table_cache_key)) + if (orig_table && orig_table->s->table_cache_key && + *(orig_table->s->table_cache_key)) { field->org_table_name= orig_table->s->table_name; field->db_name= orig_table->s->table_cache_key; } else field->org_table_name= field->db_name= ""; - field->table_name= orig_table->alias; - field->col_name= field->org_col_name= field_name; + if (orig_table) + { + field->table_name= orig_table->alias; + field->org_col_name= field_name; + } + else + { + field->table_name= ""; + field->org_col_name= ""; + } + field->col_name= field_name; field->charsetnr= charset()->number; field->length=field_length; field->type=type(); @@ -5272,7 +5282,7 @@ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs) { tmp= l_time.day + l_time.month*32 + l_time.year*16*32; if (!error && (ret != MYSQL_TIMESTAMP_DATE) && - thd->count_cuted_fields != CHECK_FIELD_IGNORE) + (l_time.hour || l_time.minute || l_time.second || l_time.second_part)) error= 3; // Datetime was cut (note) } @@ -5319,10 +5329,16 @@ int Field_newdate::store(longlong nr, bool unsigned_val) else tmp= l_time.day + l_time.month*32 + l_time.year*16*32; + if (!error && l_time.time_type != MYSQL_TIMESTAMP_DATE && + (l_time.hour || l_time.minute || l_time.second || l_time.second_part)) + error= 3; + if (error) - set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, - error == 2 ? ER_WARN_DATA_OUT_OF_RANGE : - WARN_DATA_TRUNCATED,nr,MYSQL_TIMESTAMP_DATE, 1); + set_datetime_warning(error == 3 ? MYSQL_ERROR::WARN_LEVEL_NOTE : + MYSQL_ERROR::WARN_LEVEL_WARN, + error == 2 ? + ER_WARN_DATA_OUT_OF_RANGE : WARN_DATA_TRUNCATED, + nr,MYSQL_TIMESTAMP_DATE, 1); int3store(ptr,tmp); return error; @@ -5349,6 +5365,17 @@ int Field_newdate::store_time(MYSQL_TIME *ltime, timestamp_type time_type) set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, str.ptr(), str.length(), MYSQL_TIMESTAMP_DATE, 1); } + if (!error && ltime->time_type != MYSQL_TIMESTAMP_DATE && + (ltime->hour || ltime->minute || ltime->second || ltime->second_part)) + { + char buff[MAX_DATE_STRING_REP_LENGTH]; + String str(buff, sizeof(buff), &my_charset_latin1); + make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str); + set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, + WARN_DATA_TRUNCATED, + str.ptr(), str.length(), MYSQL_TIMESTAMP_DATE, 1); + error= 3; + } } else { @@ -7406,36 +7433,6 @@ uint Field_blob::max_packed_col_length(uint max_length) #ifdef HAVE_SPATIAL -uint Field_geom::get_key_image(char *buff, uint length, imagetype type) -{ - char *blob; - const char *dummy; - MBR mbr; - ulong blob_length= get_length(ptr); - Geometry_buffer buffer; - Geometry *gobj; - const uint image_length= SIZEOF_STORED_DOUBLE*4; - - if (blob_length < SRID_SIZE) - { - bzero(buff, image_length); - return image_length; - } - get_ptr(&blob); - gobj= Geometry::construct(&buffer, blob, blob_length); - if (!gobj || gobj->get_mbr(&mbr, &dummy)) - bzero(buff, image_length); - else - { - float8store(buff, mbr.xmin); - float8store(buff + 8, mbr.xmax); - float8store(buff + 16, mbr.ymin); - float8store(buff + 24, mbr.ymax); - } - return image_length; -} - - void Field_geom::sql_type(String &res) const { CHARSET_INFO *cs= &my_charset_latin1; diff --git a/sql/field.h b/sql/field.h index 4fcdb50f8c7..8c01931fa21 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1326,7 +1326,6 @@ public: int store(double nr); int store(longlong nr, bool unsigned_val); int store_decimal(const my_decimal *); - uint get_key_image(char *buff,uint length,imagetype type); uint size_of() const { return sizeof(*this); } int reset(void) { return !maybe_null() || Field_blob::reset(); } geometry_type get_geometry_type() { return geom_type; }; diff --git a/sql/filesort.cc b/sql/filesort.cc index db73ede99b0..08ffa2211fa 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -534,7 +534,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, file->unlock_row(); /* It does not make sense to read more keys in case of a fatal error */ if (thd->net.report_error) - DBUG_RETURN(HA_POS_ERROR); + break; } if (quick_select) { @@ -551,6 +551,9 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, file->ha_rnd_end(); } + if (thd->net.report_error) + DBUG_RETURN(HA_POS_ERROR); + DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos)); if (error != HA_ERR_END_OF_FILE) { diff --git a/sql/gstream.cc b/sql/gstream.cc index 46e12b6ef3b..0c8011549f3 100644 --- a/sql/gstream.cc +++ b/sql/gstream.cc @@ -44,7 +44,7 @@ bool Gis_read_stream::get_next_word(LEX_STRING *res) skip_space(); res->str= (char*) m_cur; /* The following will also test for \0 */ - if (!my_isvar_start(&my_charset_bin, *m_cur)) + if ((m_cur >= m_limit) || !my_isvar_start(&my_charset_bin, *m_cur)) return 1; /* diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index d8ffd6c55f8..d7f2309657b 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -2528,7 +2528,12 @@ int ha_federated::info(uint flag) status_query_string.length(0); result= mysql_store_result(mysql); - if (!result) + + /* + We're going to use fields num. 4, 12 and 13 of the resultset, + so make sure we have these fields. + */ + if (!result || (mysql_num_fields(result) < 14)) goto error; if (!mysql_num_rows(result)) @@ -2557,9 +2562,9 @@ int ha_federated::info(uint flag) data_file_length= records * mean_rec_length; if (row[12] != NULL) - update_time= (ha_rows) my_strtoll10(row[12], (char**) 0, &error); + update_time= (time_t) my_strtoll10(row[12], (char**) 0, &error); if (row[13] != NULL) - check_time= (ha_rows) my_strtoll10(row[13], (char**) 0, &error); + check_time= (time_t) my_strtoll10(row[13], (char**) 0, &error); } /* diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index bf807407df1..4b96e5b5744 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -175,7 +175,7 @@ void ha_heap::update_key_stats() else { ha_rows hash_buckets= file->s->keydef[i].hash_buckets; - uint no_records= hash_buckets ? file->s->records/hash_buckets : 2; + uint no_records= hash_buckets ? (uint) (file->s->records/hash_buckets) : 2; if (no_records < 2) no_records= 2; key->rec_per_key[key->key_parts-1]= no_records; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 86d3e930122..6b5e89848c3 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -5477,7 +5477,7 @@ ha_innobase::info( table->key_info[i].rec_per_key[j]= rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 : - rec_per_key; + (ulong) rec_per_key; } index = dict_table_get_next_index_noninline(index); diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 92fa9e405e1..ae0284fb202 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -1412,7 +1412,7 @@ void ha_myisam::start_bulk_insert(ha_rows rows) DBUG_ENTER("ha_myisam::start_bulk_insert"); THD *thd= current_thd; ulong size= min(thd->variables.read_buff_size, - table->s->avg_row_length*rows); + (ulong) (table->s->avg_row_length*rows)); DBUG_PRINT("info",("start_bulk_insert: rows %lu size %lu", (ulong) rows, size)); diff --git a/sql/item.cc b/sql/item.cc index c451fe94b29..7d1a1b20ac6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -939,9 +939,12 @@ int Item::save_in_field_no_warnings(Field *field, bool no_conversions) int res; THD *thd= field->table->in_use; enum_check_fields tmp= thd->count_cuted_fields; + ulong sql_mode= thd->variables.sql_mode; + thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE); thd->count_cuted_fields= CHECK_FIELD_IGNORE; res= save_in_field(field, no_conversions); thd->count_cuted_fields= tmp; + thd->variables.sql_mode= sql_mode; return res; } @@ -4248,6 +4251,47 @@ bool Item::is_datetime() } +String *Item::check_well_formed_result(String *str, bool send_error) +{ + /* Check whether we got a well-formed string */ + CHARSET_INFO *cs= str->charset(); + int well_formed_error; + uint wlen= cs->cset->well_formed_len(cs, + str->ptr(), str->ptr() + str->length(), + str->length(), &well_formed_error); + if (wlen < str->length()) + { + THD *thd= current_thd; + char hexbuf[7]; + enum MYSQL_ERROR::enum_warning_level level; + uint diff= str->length() - wlen; + set_if_smaller(diff, 3); + octet2hex(hexbuf, str->ptr() + wlen, diff); + if (send_error) + { + my_error(ER_INVALID_CHARACTER_STRING, MYF(0), + cs->csname, hexbuf); + return 0; + } + if ((thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))) + { + level= MYSQL_ERROR::WARN_LEVEL_ERROR; + null_value= 1; + str= 0; + } + else + { + level= MYSQL_ERROR::WARN_LEVEL_WARN; + str->length(wlen); + } + push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING, + ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf); + } + return str; +} + + /* Create a field to hold a string value from an item @@ -4366,11 +4410,8 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table) break; // Blob handled outside of case #ifdef HAVE_SPATIAL case MYSQL_TYPE_GEOMETRY: - return new Field_geom(max_length, maybe_null, name, table, - (Field::geometry_type) - ((type() == Item::TYPE_HOLDER) ? - ((Item_type_holder *)this)->get_geometry_type() : - ((Item_geometry_func *)this)->get_geometry_type())); + return new Field_geom(max_length, maybe_null, + name, table, get_geometry_type()); #endif /* HAVE_SPATIAL */ } } @@ -4772,6 +4813,19 @@ warn: } +void Item_hex_string::print(String *str) +{ + char *end= (char*) str_value.ptr() + str_value.length(), + *ptr= end - min(str_value.length(), sizeof(longlong)); + str->append("0x"); + for (; ptr != end ; ptr++) + { + str->append(_dig_vec_lower[((uchar) *ptr) >> 4]); + str->append(_dig_vec_lower[((uchar) *ptr) & 0x0F]); + } +} + + bool Item_hex_string::eq(const Item *arg, bool binary_cmp) const { if (arg->basic_const_item() && arg->type() == type()) @@ -6493,9 +6547,7 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item) prev_decimal_int_part= item->decimal_int_part(); #ifdef HAVE_SPATIAL if (item->field_type() == MYSQL_TYPE_GEOMETRY) - geometry_type= (item->type() == Item::FIELD_ITEM) ? - ((Item_field *)item)->get_geometry_type() : - (Field::geometry_type)((Item_geometry_func *)item)->get_geometry_type(); + geometry_type= item->get_geometry_type(); #endif /* HAVE_SPATIAL */ } diff --git a/sql/item.h b/sql/item.h index 3c699c0eda3..b611c59b8f1 100644 --- a/sql/item.h +++ b/sql/item.h @@ -870,6 +870,9 @@ public: */ virtual bool result_as_longlong() { return FALSE; } bool is_datetime(); + virtual Field::geometry_type get_geometry_type() const + { return Field::GEOM_GEOMETRY; }; + String *check_well_formed_result(String *str, bool send_error= 0); }; @@ -1112,6 +1115,8 @@ public: Item_name_const(Item *name_arg, Item *val): value_item(val), name_item(name_arg) { + if(!value_item->basic_const_item()) + my_error(ER_WRONG_ARGUMENTS, MYF(0), "NAME_CONST"); Item::maybe_null= TRUE; } @@ -1335,7 +1340,7 @@ public: int fix_outer_field(THD *thd, Field **field, Item **reference); virtual Item *update_value_transformer(byte *select_arg); void print(String *str); - Field::geometry_type get_geometry_type() + Field::geometry_type get_geometry_type() const { DBUG_ASSERT(field_type() == MYSQL_TYPE_GEOMETRY); return field->get_geometry_type(); @@ -1853,6 +1858,7 @@ public: enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } // to prevent drop fixed flag (no need parent cleanup call) void cleanup() {} + void print(String *str); bool eq(const Item *item, bool binary_cmp) const; virtual Item *safe_charset_converter(CHARSET_INFO *tocs); }; @@ -2637,7 +2643,7 @@ public: Field *make_field_by_type(TABLE *table); static uint32 display_length(Item *item); static enum_field_types get_real_type(Item *); - Field::geometry_type get_geometry_type() { return geometry_type; }; + Field::geometry_type get_geometry_type() const { return geometry_type; }; }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 86eb10d50b0..a9ad5ad675d 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -147,6 +147,36 @@ static int agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) } +/** + @brief Aggregates field types from the array of items. + + @param[in] items array of items to aggregate the type from + @paran[in] nitems number of items in the array + + @details This function aggregates field types from the array of items. + Found type is supposed to be used later as the result field type + of a multi-argument function. + Aggregation itself is performed by the Field::field_type_merge() + function. + + @note The term "aggregation" is used here in the sense of inferring the + result type of a function from its argument types. + + @return aggregated field type. +*/ + +enum_field_types agg_field_type(Item **items, uint nitems) +{ + uint i; + if (!nitems || items[0]->result_type() == ROW_RESULT ) + return (enum_field_types)-1; + enum_field_types res= items[0]->field_type(); + for (i= 1 ; i < nitems ; i++) + res= Field::field_type_merge(res, items[i]->field_type()); + return res; +} + + static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) { @@ -1990,10 +2020,20 @@ Item_func_ifnull::fix_length_and_dec() agg_result_type(&hybrid_type, args, 2); maybe_null=args[1]->maybe_null; decimals= max(args[0]->decimals, args[1]->decimals); - max_length= (hybrid_type == DECIMAL_RESULT || hybrid_type == INT_RESULT) ? - (max(args[0]->max_length - args[0]->decimals, - args[1]->max_length - args[1]->decimals) + decimals) : - max(args[0]->max_length, args[1]->max_length); + unsigned_flag= args[0]->unsigned_flag && args[1]->unsigned_flag; + + if (hybrid_type == DECIMAL_RESULT || hybrid_type == INT_RESULT) + { + int len0= args[0]->max_length - args[0]->decimals + - (args[0]->unsigned_flag ? 0 : 1); + + int len1= args[1]->max_length - args[1]->decimals + - (args[1]->unsigned_flag ? 0 : 1); + + max_length= max(len0, len1) + decimals + (unsigned_flag ? 0 : 1); + } + else + max_length= max(args[0]->max_length, args[1]->max_length); switch (hybrid_type) { case STRING_RESULT: @@ -2009,9 +2049,7 @@ Item_func_ifnull::fix_length_and_dec() default: DBUG_ASSERT(0); } - cached_field_type= args[0]->field_type(); - if (cached_field_type != args[1]->field_type()) - cached_field_type= Item_func::field_type(); + cached_field_type= agg_field_type(args, 2); } @@ -2159,11 +2197,13 @@ Item_func_if::fix_length_and_dec() { cached_result_type= arg2_type; collation.set(args[2]->collation.collation); + cached_field_type= args[2]->field_type(); } else if (null2) { cached_result_type= arg1_type; collation.set(args[1]->collation.collation); + cached_field_type= args[1]->field_type(); } else { @@ -2177,6 +2217,7 @@ Item_func_if::fix_length_and_dec() { collation.set(&my_charset_bin); // Number } + cached_field_type= agg_field_type(args + 1, 2); } if ((cached_result_type == DECIMAL_RESULT ) @@ -2556,7 +2597,7 @@ void Item_func_case::fix_length_and_dec() agg_arg_charsets(collation, agg, nagg, MY_COLL_ALLOW_CONV, 1)) return; - + cached_field_type= agg_field_type(agg, nagg); /* Aggregate first expression and all THEN expression types and collations when string comparison @@ -2695,6 +2736,7 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value) void Item_func_coalesce::fix_length_and_dec() { + cached_field_type= agg_field_type(args, arg_count); agg_result_type(&hybrid_type, args, arg_count); switch (hybrid_type) { case STRING_RESULT: @@ -4253,6 +4295,7 @@ Item_func_regex::fix_fields(THD *thd, Item **ref) if (args[1]->null_value) { // Will always return NULL maybe_null=1; + fixed= 1; return FALSE; } int error; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 8410c66b034..4d3df7aebf9 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -640,6 +640,7 @@ public: class Item_func_coalesce :public Item_func_numhybrid { protected: + enum_field_types cached_field_type; Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {} public: Item_func_coalesce(List<Item> &list) :Item_func_numhybrid(list) {} @@ -652,13 +653,13 @@ public: enum Item_result result_type () const { return hybrid_type; } const char *func_name() const { return "coalesce"; } table_map not_null_tables() const { return 0; } + enum_field_types field_type() const { return cached_field_type; } }; class Item_func_ifnull :public Item_func_coalesce { protected: - enum_field_types cached_field_type; bool field_type_defined; public: Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {} @@ -677,6 +678,7 @@ public: class Item_func_if :public Item_func { enum Item_result cached_result_type; + enum_field_types cached_field_type; public: Item_func_if(Item *a,Item *b,Item *c) :Item_func(a,b,c), cached_result_type(INT_RESULT) @@ -686,6 +688,7 @@ public: String *val_str(String *str); my_decimal *val_decimal(my_decimal *); enum Item_result result_type () const { return cached_result_type; } + enum_field_types field_type() const { return cached_field_type; } bool fix_fields(THD *, Item **); void fix_length_and_dec(); uint decimal_precision() const; @@ -722,6 +725,7 @@ class Item_func_case :public Item_func uint ncases; Item_result cmp_type; DTCollation cmp_collation; + enum_field_types cached_field_type; public: Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg) :Item_func(), first_expr_num(-1), else_expr_num(-1), @@ -749,6 +753,7 @@ public: uint decimal_precision() const; table_map not_null_tables() const { return 0; } enum Item_result result_type () const { return cached_result_type; } + enum_field_types field_type() const { return cached_field_type; } const char *func_name() const { return "case"; } void print(String *str); Item *find_item(String *str); @@ -1382,6 +1387,7 @@ public: bool subst_argument_checker(byte **arg) { return TRUE; } Item *compile(Item_analyzer analyzer, byte **arg_p, Item_transformer transformer, byte *arg_t); + enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } }; diff --git a/sql/item_func.cc b/sql/item_func.cc index e4d370bbdf2..22b0044242c 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1380,7 +1380,11 @@ longlong Item_func_int_div::val_int() void Item_func_int_div::fix_length_and_dec() { - max_length=args[0]->max_length - args[0]->decimals; + Item_result argtype= args[0]->result_type(); + /* use precision ony for the data type it is applicable for and valid */ + max_length=args[0]->max_length - + (argtype == DECIMAL_RESULT || argtype == INT_RESULT ? + args[0]->decimals : 0); maybe_null=1; unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag; } @@ -2243,6 +2247,7 @@ void Item_func_min_max::fix_length_and_dec() else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT)) max_length= my_decimal_precision_to_length(max_int_part+decimals, decimals, unsigned_flag); + cached_field_type= agg_field_type(args, arg_count); } diff --git a/sql/item_func.h b/sql/item_func.h index 56b5e75652c..43221a18a5b 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -435,6 +435,7 @@ public: longlong int_op(); my_decimal *decimal_op(my_decimal *); const char *func_name() const { return "-"; } + virtual bool basic_const_item() const { return args[0]->basic_const_item(); } void fix_length_and_dec(); void fix_num_length_and_dec(); uint decimal_precision() const { return args[0]->decimal_precision(); } @@ -692,7 +693,8 @@ class Item_func_min_max :public Item_func /* An item used for issuing warnings while string to DATETIME conversion. */ Item *datetime_item; THD *thd; - +protected: + enum_field_types cached_field_type; public: Item_func_min_max(List<Item> &list,int cmp_sign_arg) :Item_func(list), cmp_type(INT_RESULT), cmp_sign(cmp_sign_arg), compare_as_dates(FALSE), @@ -705,6 +707,7 @@ public: enum Item_result result_type () const { return cmp_type; } bool result_as_longlong() { return compare_as_dates; }; uint cmp_datetimes(ulonglong *value); + enum_field_types field_type() const { return cached_field_type; } }; class Item_func_min :public Item_func_min_max @@ -747,6 +750,8 @@ public: collation= args[0]->collation; max_length= args[0]->max_length; decimals=args[0]->decimals; + /* The item could be a NULL constant. */ + null_value= args[0]->null_value; } }; diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 6c012277888..966cefea9fe 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -27,7 +27,7 @@ Field *Item_geometry_func::tmp_table_field(TABLE *t_arg) { return new Field_geom(max_length, maybe_null, name, t_arg, - (Field::geometry_type) get_geometry_type()); + get_geometry_type()); } void Item_geometry_func::fix_length_and_dec() @@ -38,10 +38,6 @@ void Item_geometry_func::fix_length_and_dec() maybe_null= 1; } -int Item_geometry_func::get_geometry_type() const -{ - return (int)Field::GEOM_GEOMETRY; -} String *Item_func_geometry_from_text::val_str(String *str) { @@ -160,9 +156,9 @@ String *Item_func_geometry_type::val_str(String *str) } -int Item_func_envelope::get_geometry_type() const +Field::geometry_type Item_func_envelope::get_geometry_type() const { - return (int) Field::GEOM_POLYGON; + return Field::GEOM_POLYGON; } @@ -190,9 +186,9 @@ String *Item_func_envelope::val_str(String *str) } -int Item_func_centroid::get_geometry_type() const +Field::geometry_type Item_func_centroid::get_geometry_type() const { - return (int) Field::GEOM_POINT; + return Field::GEOM_POINT; } @@ -330,9 +326,9 @@ err: */ -int Item_func_point::get_geometry_type() const +Field::geometry_type Item_func_point::get_geometry_type() const { - return (int) Field::GEOM_POINT; + return Field::GEOM_POINT; } diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 9c7970f9e53..e99510f762f 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -33,7 +33,6 @@ public: void fix_length_and_dec(); enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; } Field *tmp_table_field(TABLE *t_arg); - virtual int get_geometry_type() const; bool is_null() { (void) val_int(); return null_value; } }; @@ -92,7 +91,7 @@ public: Item_func_centroid(Item *a): Item_geometry_func(a) {} const char *func_name() const { return "centroid"; } String *val_str(String *); - int get_geometry_type() const; + Field::geometry_type get_geometry_type() const; }; class Item_func_envelope: public Item_geometry_func @@ -101,7 +100,7 @@ public: Item_func_envelope(Item *a): Item_geometry_func(a) {} const char *func_name() const { return "envelope"; } String *val_str(String *); - int get_geometry_type() const; + Field::geometry_type get_geometry_type() const; }; class Item_func_point: public Item_geometry_func @@ -111,7 +110,7 @@ public: Item_func_point(Item *a, Item *b, Item *srid): Item_geometry_func(a, b, srid) {} const char *func_name() const { return "point"; } String *val_str(String *); - int get_geometry_type() const; + Field::geometry_type get_geometry_type() const; }; class Item_func_spatial_decomp: public Item_geometry_func diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 0c11c9eece8..4e72f117869 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -38,36 +38,6 @@ C_MODE_END String my_empty_string("",default_charset_info); -String *Item_str_func::check_well_formed_result(String *str) -{ - /* Check whether we got a well-formed string */ - CHARSET_INFO *cs= str->charset(); - int well_formed_error; - uint wlen= cs->cset->well_formed_len(cs, - str->ptr(), str->ptr() + str->length(), - str->length(), &well_formed_error); - if (wlen < str->length()) - { - THD *thd= current_thd; - char hexbuf[7]; - enum MYSQL_ERROR::enum_warning_level level; - uint diff= str->length() - wlen; - set_if_smaller(diff, 3); - octet2hex(hexbuf, str->ptr() + wlen, diff); - if (thd->variables.sql_mode & - (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)) - { - level= MYSQL_ERROR::WARN_LEVEL_ERROR; - null_value= 1; - str= 0; - } - else - level= MYSQL_ERROR::WARN_LEVEL_WARN; - push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING, - ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf); - } - return str; -} bool Item_str_func::fix_fields(THD *thd, Item **ref) @@ -2229,11 +2199,13 @@ String *Item_func_char::val_str(String *str) { DBUG_ASSERT(fixed == 1); str->length(0); + str->set_charset(collation.collation); for (uint i=0 ; i < arg_count ; i++) { int32 num=(int32) args[i]->val_int(); if (!args[i]->null_value) { + char char_num= (char) num; if (num&0xFF000000L) { str->append((char)(num>>24)); goto b2; @@ -2243,10 +2215,9 @@ String *Item_func_char::val_str(String *str) } else if (num&0xFF00L) { b1: str->append((char)(num>>8)); } - str->append((char) num); + str->append(&char_num, 1); } } - str->set_charset(collation.collation); str->realloc(str->length()); // Add end 0 (for Purify) return check_well_formed_result(str); } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 6ca0b89a22b..04d1997e879 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -35,7 +35,6 @@ public: my_decimal *val_decimal(my_decimal *); enum Item_result result_type () const { return STRING_RESULT; } void left_right_max_length(); - String *check_well_formed_result(String *str); bool fix_fields(THD *thd, Item **ref); }; @@ -535,7 +534,7 @@ public: String *val_str(String *); void fix_length_and_dec() { - max_length= arg_count * collation.collation->mbmaxlen; + max_length= arg_count * 4; } const char *func_name() const { return "char"; } }; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 48ad53fbf75..30cbe872101 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -905,7 +905,9 @@ bool Item_sum_distinct::setup(THD *thd) List<create_field> field_list; create_field field_def; /* field definition */ DBUG_ENTER("Item_sum_distinct::setup"); - DBUG_ASSERT(tree == 0); + /* It's legal to call setup() more than once when in a subquery */ + if (tree) + DBUG_RETURN(FALSE); /* Virtual table and the tree are created anew on each re-execution of @@ -913,7 +915,7 @@ bool Item_sum_distinct::setup(THD *thd) mem_root. */ if (field_list.push_back(&field_def)) - return TRUE; + DBUG_RETURN(TRUE); null_value= maybe_null= 1; quick_group= 0; @@ -925,7 +927,7 @@ bool Item_sum_distinct::setup(THD *thd) args[0]->unsigned_flag); if (! (table= create_virtual_tmp_table(thd, field_list))) - return TRUE; + DBUG_RETURN(TRUE); /* XXX: check that the case of CHAR(0) works OK */ tree_key_length= table->s->reclength - table->s->null_bytes; @@ -2443,6 +2445,7 @@ bool Item_sum_count_distinct::setup(THD *thd) /* Setup can be called twice for ROLLUP items. This is a bug. Please add DBUG_ASSERT(tree == 0) here when it's fixed. + It's legal to call setup() more than once when in a subquery */ if (tree || table || tmp_table_param) return FALSE; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index ae18e4786d7..c1fa9dce038 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1603,8 +1603,7 @@ bool Item_func_now::get_date(MYSQL_TIME *res, int Item_func_now::save_in_field(Field *to, bool no_conversions) { to->set_notnull(); - to->store_time(<ime, MYSQL_TIMESTAMP_DATETIME); - return 0; + return to->store_time(<ime, MYSQL_TIMESTAMP_DATETIME); } @@ -3310,7 +3309,7 @@ void Item_func_str_to_date::fix_length_and_dec() String format_str(format_buff, sizeof(format_buff), &my_charset_bin), *format; maybe_null= 1; decimals=0; - cached_field_type= MYSQL_TYPE_STRING; + cached_field_type= MYSQL_TYPE_DATETIME; max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; cached_timestamp_type= MYSQL_TIMESTAMP_NONE; format= args[1]->val_str(&format_str); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 94bee28bb6b..a5ecbc57e8d 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -964,7 +964,10 @@ class Item_func_maketime :public Item_str_timefunc { public: Item_func_maketime(Item *a, Item *b, Item *c) - :Item_str_timefunc(a, b ,c) {} + :Item_str_timefunc(a, b, c) + { + maybe_null= TRUE; + } String *val_str(String *str); const char *func_name() const { return "maketime"; } }; @@ -1032,7 +1035,7 @@ class Item_func_str_to_date :public Item_str_func bool const_item; public: Item_func_str_to_date(Item *a, Item *b) - :Item_str_func(a, b) + :Item_str_func(a, b), const_item(false) {} String *val_str(String *str); bool get_date(MYSQL_TIME *ltime, uint fuzzy_date); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index e50d1bd1654..e2d78303763 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1224,6 +1224,7 @@ my_bool mysql_rm_tmp_tables(void); /* item_func.cc */ extern bool check_reserved_words(LEX_STRING *name); +extern enum_field_types agg_field_type(Item **items, uint nitems); /* strfunc.cc */ ulonglong find_set(TYPELIB *lib, const char *x, uint length, CHARSET_INFO *cs, diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 04e2816d553..969777d4792 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2206,7 +2206,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records) if (param->table->file->primary_key_is_clustered()) { result= param->table->file->read_time(param->table->s->primary_key, - records, records); + (uint)records, records); } else { @@ -2414,7 +2414,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, /* Add Unique operations cost */ unique_calc_buff_size= - Unique::get_cost_calc_buff_size(non_cpk_scan_records, + Unique::get_cost_calc_buff_size((ulong)non_cpk_scan_records, param->table->file->ref_length, param->thd->variables.sortbuff_size); if (param->imerge_cost_buff_size < unique_calc_buff_size) @@ -2426,7 +2426,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, } imerge_cost += - Unique::get_use_cost(param->imerge_cost_buff, non_cpk_scan_records, + Unique::get_use_cost(param->imerge_cost_buff, (uint)non_cpk_scan_records, param->table->file->ref_length, param->thd->variables.sortbuff_size); DBUG_PRINT("info",("index_merge total cost: %g (wanted: less then %g)", @@ -2765,7 +2765,7 @@ ROR_INTERSECT_INFO* ror_intersect_init(const PARAM *param) info->is_covering= FALSE; info->index_scan_costs= 0.0; info->index_records= 0; - info->out_rows= param->table->file->records; + info->out_rows= (double) param->table->file->records; bitmap_clear_all(&info->covered_fields); return info; } @@ -6757,7 +6757,7 @@ int QUICK_RANGE_SELECT::reset() if (file->table_flags() & HA_NEED_READ_RANGE_BUFFER) { mrange_bufsiz= min(multi_range_bufsiz, - (QUICK_SELECT_I::records + 1)* head->s->reclength); + ((uint)QUICK_SELECT_I::records + 1)* head->s->reclength); while (mrange_bufsiz && ! my_multi_malloc(MYF(MY_WME), @@ -8359,7 +8359,7 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, bool have_min, bool have_max, double *read_cost, ha_rows *records) { - uint table_records; + ha_rows table_records; uint num_groups; uint num_blocks; uint keys_per_block; @@ -8376,14 +8376,14 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, keys_per_block= (table->file->block_size / 2 / (index_info->key_length + table->file->ref_length) + 1); - num_blocks= (table_records / keys_per_block) + 1; + num_blocks= (uint)(table_records / keys_per_block) + 1; /* Compute the number of keys in a group. */ keys_per_group= index_info->rec_per_key[group_key_parts - 1]; if (keys_per_group == 0) /* If there is no statistics try to guess */ /* each group contains 10% of all records */ - keys_per_group= (table_records / 10) + 1; - num_groups= (table_records / keys_per_group) + 1; + keys_per_group= (uint)(table_records / 10) + 1; + num_groups= (uint)(table_records / keys_per_group) + 1; /* Apply the selectivity of the quick select for group prefixes. */ if (range_tree && (quick_prefix_records != HA_POS_ERROR)) @@ -8427,9 +8427,9 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, *records= num_groups; DBUG_PRINT("info", - ("table rows: %u keys/block: %u keys/group: %u result rows: %lu blocks: %u", - table_records, keys_per_block, keys_per_group, (ulong) *records, - num_blocks)); + ("table rows: %lu keys/block: %u keys/group: %u result rows: %lu blocks: %u", + (ulong)table_records, keys_per_block, keys_per_group, + (ulong) *records, num_blocks)); DBUG_VOID_RETURN; } diff --git a/sql/protocol.cc b/sql/protocol.cc index ced6d78519a..2bdbe83eea1 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -824,6 +824,7 @@ bool Protocol_simple::store(const char *from, uint length, field_types[field_pos] == MYSQL_TYPE_DECIMAL || field_types[field_pos] == MYSQL_TYPE_BIT || field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL || + field_types[field_pos] == MYSQL_TYPE_NEWDATE || (field_types[field_pos] >= MYSQL_TYPE_ENUM && field_types[field_pos] <= MYSQL_TYPE_GEOMETRY)); field_pos++; diff --git a/sql/set_var.cc b/sql/set_var.cc index 2ba6662a2c5..a128529fcc7 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1040,6 +1040,9 @@ struct show_var_st init_vars[]= { {sys_readonly.name, (char*) &sys_readonly, SHOW_SYS}, {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS}, #ifdef HAVE_REPLICATION + {"relay_log" , (char*) &opt_relay_logname, SHOW_CHAR_PTR}, + {"relay_log_index", (char*) &opt_relaylog_index_name, SHOW_CHAR_PTR}, + {"relay_log_info_file", (char*) &relay_log_info_file, SHOW_CHAR_PTR}, {sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS}, {"relay_log_space_limit", (char*) &relay_log_space_limit, SHOW_LONGLONG}, #endif @@ -1764,7 +1767,7 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names) ¬_used)); if (error_len) { - strmake(buff, error, min(sizeof(buff), error_len)); + strmake(buff, error, min(sizeof(buff) - 1, error_len)); goto err; } } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 6bc6cce5e72..e62d0f40abf 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3835,50 +3835,83 @@ bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref, } -bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant, - const char* db_name, const char *table_name, - Field_iterator *fields) +/** + @brief check if a query can access a set of columns + + @param thd the current thread + @param want_access_arg the privileges requested + @param fields an iterator over the fields of a table reference. + @return Operation status + @retval 0 Success + @retval 1 Falure + @details This function walks over the columns of a table reference + The columns may originate from different tables, depending on the kind of + table reference, e.g. join. + For each table it will retrieve the grant information and will use it + to check the required access privileges for the fields requested from it. +*/ +bool check_grant_all_columns(THD *thd, ulong want_access_arg, + Field_iterator_table_ref *fields) { Security_context *sctx= thd->security_ctx; - GRANT_TABLE *grant_table; - GRANT_COLUMN *grant_column; + ulong want_access= want_access_arg; + const char *table_name= NULL; - want_access &= ~grant->privilege; - if (!want_access) - return 0; // Already checked - if (!grant_option) - goto err2; + if (grant_option) + { + const char* db_name; + GRANT_INFO *grant; + /* Initialized only to make gcc happy */ + GRANT_TABLE *grant_table= NULL; - rw_rdlock(&LOCK_grant); + rw_rdlock(&LOCK_grant); - /* reload table if someone has modified any grants */ + for (; !fields->end_of_fields(); fields->next()) + { + const char *field_name= fields->name(); - if (grant->version != grant_version) - { - grant->grant_table= - table_hash_search(sctx->host, sctx->ip, db_name, - sctx->priv_user, - table_name, 0); /* purecov: inspected */ - grant->version= grant_version; /* purecov: inspected */ - } - /* The following should always be true */ - if (!(grant_table= grant->grant_table)) - goto err; /* purecov: inspected */ + if (table_name != fields->table_name()) + { + table_name= fields->table_name(); + db_name= fields->db_name(); + grant= fields->grant(); + /* get a fresh one for each table */ + want_access= want_access_arg & ~grant->privilege; + if (want_access) + { + /* reload table if someone has modified any grants */ + if (grant->version != grant_version) + { + grant->grant_table= + table_hash_search(sctx->host, sctx->ip, db_name, + sctx->priv_user, + table_name, 0); /* purecov: inspected */ + grant->version= grant_version; /* purecov: inspected */ + } - for (; !fields->end_of_fields(); fields->next()) - { - const char *field_name= fields->name(); - grant_column= column_hash_search(grant_table, field_name, - (uint) strlen(field_name)); - if (!grant_column || (~grant_column->rights & want_access)) - goto err; - } - rw_unlock(&LOCK_grant); - return 0; + grant_table= grant->grant_table; + DBUG_ASSERT (grant_table); + } + } + + if (want_access) + { + GRANT_COLUMN *grant_column= + column_hash_search(grant_table, field_name, + (uint) strlen(field_name)); + if (!grant_column || (~grant_column->rights & want_access)) + goto err; + } + } + rw_unlock(&LOCK_grant); + return 0; err: - rw_unlock(&LOCK_grant); -err2: + rw_unlock(&LOCK_grant); + } + else + table_name= fields->table_name(); + char command[128]; get_privilege_desc(command, sizeof(command), want_access); my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), diff --git a/sql/sql_acl.h b/sql/sql_acl.h index d08f2663af5..b2007ccdf47 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -205,9 +205,8 @@ bool check_grant_column (THD *thd, GRANT_INFO *grant, const char *name, uint length, Security_context *sctx); bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref, const char *name, uint length); -bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant, - const char* db_name, const char *table_name, - Field_iterator *fields); +bool check_grant_all_columns(THD *thd, ulong want_access, + Field_iterator_table_ref *fields); bool check_grant_routine(THD *thd, ulong want_access, TABLE_LIST *procs, bool is_proc, bool no_error); bool check_grant_db(THD *thd,const char *db); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 905190cb9cd..b97ba45e18f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5424,10 +5424,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, !any_privileges) { field_iterator.set(tables); - if (check_grant_all_columns(thd, SELECT_ACL, field_iterator.grant(), - field_iterator.db_name(), - field_iterator.table_name(), - &field_iterator)) + if (check_grant_all_columns(thd, SELECT_ACL, &field_iterator)) DBUG_RETURN(TRUE); } #endif diff --git a/sql/sql_class.h b/sql/sql_class.h index 4fac86dc405..e6d65f3133a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2029,7 +2029,7 @@ class select_insert :public select_result_interceptor { ulonglong last_insert_id; 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, diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index f07af393070..770bbd1349d 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -189,11 +189,9 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, #ifndef NO_EMBEDDED_ACCESS_CHECKS if (grant_option) { - Field_iterator_table field_it; - field_it.set_table(table); - if (check_grant_all_columns(thd, INSERT_ACL, &table->grant, - table->s->db, table->s->table_name, - &field_it)) + Field_iterator_table_ref field_it; + field_it.set(table_list); + if (check_grant_all_columns(thd, INSERT_ACL, &field_it)) return -1; } #endif @@ -2647,7 +2645,8 @@ 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), last_insert_id(0), - insert_into_view(table_list_par && table_list_par->view != 0) + insert_into_view(table_list_par && table_list_par->view != 0), + is_bulk_insert_mode(FALSE) { bzero((char*) &info,sizeof(info)); info.handle_duplicates= duplic; @@ -2832,8 +2831,11 @@ int select_insert::prepare2(void) { DBUG_ENTER("select_insert::prepare2"); if (thd->lex->current_select->options & OPTION_BUFFER_RESULT && - !thd->prelocked_mode) + !thd->prelocked_mode && !is_bulk_insert_mode) + { table->file->start_bulk_insert((ha_rows) 0); + is_bulk_insert_mode= TRUE; + } DBUG_RETURN(0); } @@ -2939,6 +2941,7 @@ bool select_insert::send_eof() DBUG_ENTER("select_insert::send_eof"); error= (!thd->prelocked_mode) ? table->file->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); @@ -3129,7 +3132,10 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, create_field *cr_field; Field *field, *def_field; if (item->type() == Item::FUNC_ITEM) - field= item->tmp_table_field(&tmp_table); + if (item->result_type() != STRING_RESULT) + field= item->tmp_table_field(&tmp_table); + else + field= item->tmp_table_field_from_field_type(&tmp_table); else field= create_tmp_field(thd, &tmp_table, item, item->type(), (Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0, @@ -3271,7 +3277,10 @@ 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->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_map.cc b/sql/sql_map.cc index 03dc091b9b7..282716c6151 100644 --- a/sql/sql_map.cc +++ b/sql/sql_map.cc @@ -41,7 +41,7 @@ mapped_files::mapped_files(const my_string filename,byte *magic,uint magic_lengt struct stat stat_buf; if (!fstat(file,&stat_buf)) { - if (!(map=(byte*) my_mmap(0,(size=(ulong) stat_buf.st_size),PROT_READ, + if (!(map=(byte*) my_mmap(0,(size_t)(size=(ulong) stat_buf.st_size),PROT_READ, MAP_SHARED | MAP_NORESERVE,file, 0L))) { @@ -52,7 +52,7 @@ mapped_files::mapped_files(const my_string filename,byte *magic,uint magic_lengt if (map && memcmp(map,magic,magic_length)) { my_error(ER_WRONG_MAGIC, MYF(0), name); - VOID(my_munmap(map,size)); + VOID(my_munmap(map,(size_t)size)); map=0; } if (!map) @@ -70,7 +70,7 @@ mapped_files::~mapped_files() #ifdef HAVE_MMAP if (file >= 0) { - VOID(my_munmap(map,size)); + VOID(my_munmap(map,(size_t)size)); VOID(my_close(file,MYF(0))); file= -1; map=0; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a111208cbf9..0a8b92d28c0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6430,7 +6430,12 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, ptr->table_name); if (!schema_table || (schema_table->hidden && - lex->orig_sql_command == SQLCOM_END)) // not a 'show' command + (lex->orig_sql_command == SQLCOM_END || // not a 'show' command + /* + this check is used for show columns|keys from I_S hidden table + */ + lex->orig_sql_command == SQLCOM_SHOW_FIELDS || + lex->orig_sql_command == SQLCOM_SHOW_KEYS))) { my_error(ER_UNKNOWN_TABLE, MYF(0), ptr->table_name, INFORMATION_SCHEMA_NAME.str); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7d4421b2749..7af39071561 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5915,7 +5915,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) /* Fix for EXPLAIN */ if (sel->quick) - join->best_positions[i].records_read= sel->quick->records; + join->best_positions[i].records_read= (double)sel->quick->records; } else { @@ -14349,6 +14349,9 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array, item_field= (Item*) new Item_field(field); if (!item_field) DBUG_RETURN(TRUE); // Fatal error + + if (item->real_item()->type() != Item::FIELD_ITEM) + field->orig_table= 0; item_field->name= item->name; if (item->type() == Item::REF_ITEM) { @@ -15488,6 +15491,55 @@ static void print_join(THD *thd, String *str, List<TABLE_LIST> *tables) } +/** + @brief Print an index hint for a table + + @details Prints out the USE|FORCE|IGNORE index hints for a table. + + @param thd the current thread + @param[out] str appends the index hint here + @param hint what the hint is (as string : "USE INDEX"| + "FORCE INDEX"|"IGNORE INDEX") + @param hint_length the length of the string in 'hint' + @param indexes a list of index names for the hint +*/ + +void +TABLE_LIST::print_index_hint(THD *thd, String *str, + const char *hint, uint32 hint_length, + List<String> indexes) +{ + List_iterator_fast<String> li(indexes); + String *idx; + bool first= 1; + size_t find_length= strlen(primary_key_name); + + str->append (' '); + str->append (hint, hint_length); + str->append (STRING_WITH_LEN(" (")); + while ((idx = li++)) + { + if (first) + first= 0; + else + str->append(','); + /* + It's safe to use ptr() here because we compare the length first + and we rely that my_strcasecmp will not access more than length() + chars from the string. See test_if_string_in_list() for similar + implementation. + */ + if (find_length == idx->length() && + !my_strcasecmp (system_charset_info, primary_key_name, + idx->ptr())) + str->append(primary_key_name); + else + append_identifier (thd, str, idx->ptr(), idx->length()); + } + str->append(')'); +} + + /* Print table as it should be in join list @@ -15555,6 +15607,17 @@ void TABLE_LIST::print(THD *thd, String *str) str->append(' '); append_identifier(thd, str, alias, strlen(alias)); } + + if (use_index) + { + if (force_index) + print_index_hint(thd, str, STRING_WITH_LEN("FORCE INDEX"), *use_index); + else + print_index_hint(thd, str, STRING_WITH_LEN("USE INDEX"), *use_index); + } + if (ignore_index) + print_index_hint (thd, str, STRING_WITH_LEN("IGNORE INDEX"), *ignore_index); + } } diff --git a/sql/sql_select.h b/sql/sql_select.h index d84fbcb8c2d..4fc32e7fdb3 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -521,9 +521,13 @@ public: store_key(THD *thd, Field *field_arg, char *ptr, char *null, uint length) :null_key(0), null_ptr(null), err(0) { - if (field_arg->type() == FIELD_TYPE_BLOB) + if (field_arg->type() == FIELD_TYPE_BLOB + || field_arg->type() == FIELD_TYPE_GEOMETRY) { - /* Key segments are always packed with a 2 byte length prefix */ + /* + Key segments are always packed with a 2 byte length prefix. + See mi_rkey for details. + */ to_field=new Field_varstring(ptr, length, 2, (uchar*) null, 1, Field::NONE, field_arg->field_name, field_arg->table, field_arg->charset()); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6cbe98fe862..20b8c7a4278 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1287,7 +1287,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, } if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type == Field::GEOM_POINT) - column->length= 21; + column->length= 25; if (!column->length) { my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index c78e246f518..321d07dec76 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -362,7 +362,7 @@ int mysql_update(THD *thd, init_read_record_idx(&info, thd, table, 1, used_index); thd->proc_info="Searching rows for update"; - uint tmp_limit= limit; + ha_rows tmp_limit= limit; while (!(error=info.read_record(&info)) && !thd->killed) { diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 35a97411511..297edd0d90d 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -223,9 +223,6 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, { LEX *lex= thd->lex; bool link_to_local; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - bool definer_check_is_needed= mode != VIEW_ALTER || lex->definer; -#endif /* first table in list is target VIEW name => cut off it */ TABLE_LIST *view= lex->unlink_first_table(&link_to_local); TABLE_LIST *tables= lex->query_tables; @@ -280,7 +277,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, - same as current user - current user has SUPER_ACL */ - if (definer_check_is_needed && + if (lex->definer && (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 || my_strcasecmp(system_charset_info, lex->definer->host.str, @@ -925,6 +922,15 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, DBUG_RETURN(0); } + if (table->use_index || table->ignore_index) + { + my_error(ER_WRONG_USAGE, MYF(0), + table->ignore_index ? "IGNORE INDEX" : + (table->force_index ? "FORCE INDEX" : "USE INDEX"), + "VIEW"); + DBUG_RETURN(TRUE); + } + /* check loop via view definition */ for (TABLE_LIST *precedent= table->referencing_view; precedent; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 3fd8d339f31..368ce5673e2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3094,7 +3094,7 @@ type: spatial_type: GEOMETRY_SYM { $$= Field::GEOM_GEOMETRY; } | GEOMETRYCOLLECTION { $$= Field::GEOM_GEOMETRYCOLLECTION; } - | POINT_SYM { Lex->length= (char*)"21"; + | POINT_SYM { Lex->length= (char*)"25"; $$= Field::GEOM_POINT; } | MULTIPOINT { $$= Field::GEOM_MULTIPOINT; } @@ -7639,11 +7639,15 @@ literal: String *str= tmp ? tmp->quick_fix_field(), tmp->val_str((String*) 0) : (String*) 0; - $$= new Item_string(str ? str->ptr() : "", + $$= new Item_string(NULL, /* name will be set in select_item */ + str ? str->ptr() : "", str ? str->length() : 0, Lex->underscore_charset); - if ($$) - ((Item_string *) $$)->set_repertoire_from_value(); + if (!$$ || !$$->check_well_formed_result(&$$->str_value, TRUE)) + { + MYSQL_YYABORT; + } + ((Item_string *) $$)->set_repertoire_from_value(); } | UNDERSCORE_CHARSET BIN_NUM { @@ -7655,9 +7659,14 @@ literal: String *str= tmp ? tmp->quick_fix_field(), tmp->val_str((String*) 0) : (String*) 0; - $$= new Item_string(str ? str->ptr() : "", - str ? str->length() : 0, - Lex->charset); + $$= new Item_string(NULL, /* name will be set in select_item */ + str ? str->ptr() : "", + str ? str->length() : 0, + Lex->underscore_charset); + if (!$$ || !$$->check_well_formed_result(&$$->str_value, TRUE)) + { + MYSQL_YYABORT; + } } | DATE_SYM text_literal { $$ = $2; } | TIME_SYM text_literal { $$ = $2; } diff --git a/sql/table.cc b/sql/table.cc index a393f1a676b..7fe9aa774f3 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -732,9 +732,11 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, keyinfo->key_length+= HA_KEY_NULL_LENGTH; } if (field->type() == FIELD_TYPE_BLOB || - field->real_type() == MYSQL_TYPE_VARCHAR) + field->real_type() == MYSQL_TYPE_VARCHAR || + field->type() == FIELD_TYPE_GEOMETRY) { - if (field->type() == FIELD_TYPE_BLOB) + if (field->type() == FIELD_TYPE_BLOB || + field->type() == FIELD_TYPE_GEOMETRY) key_part->key_part_flag|= HA_BLOB_PART; else key_part->key_part_flag|= HA_VAR_LENGTH_PART; diff --git a/sql/table.h b/sql/table.h index f411ce489c4..cff4be630e4 100644 --- a/sql/table.h +++ b/sql/table.h @@ -773,6 +773,8 @@ struct TABLE_LIST private: bool prep_check_option(THD *thd, uint8 check_opt_type); bool prep_where(THD *thd, Item **conds, bool no_where_clause); + void print_index_hint(THD *thd, String *str, const char *hint, + uint32 hint_length, List<String>); /* Cleanup for re-execution in a prepared statement or a stored procedure. |