summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <gluh@eagle.(none)>2007-10-23 18:51:43 +0500
committerunknown <gluh@eagle.(none)>2007-10-23 18:51:43 +0500
commit8479eb1db7d1c8ccfbaa62077c54b7f5af714324 (patch)
treed36465f86e78c442a44942849b7280eab8d10bf8 /sql
parentfb9a562b1cc2b9048eff094bb7004fb3db0e7fd0 (diff)
parentc448d2ed5d2a7efd1f77b956f46d8f1e48b17350 (diff)
downloadmariadb-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')
-rw-r--r--sql/field.cc71
-rw-r--r--sql/field.h1
-rw-r--r--sql/filesort.cc5
-rw-r--r--sql/gstream.cc2
-rw-r--r--sql/ha_federated.cc11
-rw-r--r--sql/ha_heap.cc2
-rw-r--r--sql/ha_innodb.cc2
-rw-r--r--sql/ha_myisam.cc2
-rw-r--r--sql/item.cc68
-rw-r--r--sql/item.h10
-rw-r--r--sql/item_cmpfunc.cc59
-rw-r--r--sql/item_cmpfunc.h8
-rw-r--r--sql/item_func.cc7
-rw-r--r--sql/item_func.h7
-rw-r--r--sql/item_geofunc.cc18
-rw-r--r--sql/item_geofunc.h7
-rw-r--r--sql/item_strfunc.cc35
-rw-r--r--sql/item_strfunc.h3
-rw-r--r--sql/item_sum.cc9
-rw-r--r--sql/item_timefunc.cc5
-rw-r--r--sql/item_timefunc.h7
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/opt_range.cc24
-rw-r--r--sql/protocol.cc1
-rw-r--r--sql/set_var.cc5
-rw-r--r--sql/sql_acl.cc103
-rw-r--r--sql/sql_acl.h5
-rw-r--r--sql/sql_base.cc5
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_insert.cc25
-rw-r--r--sql/sql_map.cc6
-rw-r--r--sql/sql_parse.cc7
-rw-r--r--sql/sql_select.cc65
-rw-r--r--sql/sql_select.h8
-rw-r--r--sql/sql_table.cc2
-rw-r--r--sql/sql_update.cc2
-rw-r--r--sql/sql_view.cc14
-rw-r--r--sql/sql_yacc.yy23
-rw-r--r--sql/table.cc6
-rw-r--r--sql/table.h2
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(&ltime, MYSQL_TIMESTAMP_DATETIME);
- return 0;
+ return to->store_time(&ltime, 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)
&not_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.