From 98253bd64d51d42f914c59ebabe89e3975ba9cc8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 06:15:50 -0700 Subject: func_str.result, func_str.test: Added a test case for bug #10124. sql_select.h, item_subselect.cc, sql_select.cc: Fixed bug #10124. The copy method of the store_key classes can return STORE_KEY_OK=0, STORE_KEY_FATAL=1, STORE_KEY_CONV=2 now. field.cc: Fixed bug #10124. When ussuing a warning the store methods return 2 instead of 1 now. sql/field.cc: Fixed bug #10124. When ussuing a warning the store methods return 2 instead of 1 now. sql/sql_select.cc: Fixed bug #10124. The copy method of the store_key classes can return STORE_KEY_OK=0, STORE_KEY_FATAL=1, STORE_KEY_CONV=2 now. sql/item_subselect.cc: Fixed bug #10124. The copy method of the store_key classes can return STORE_KEY_OK=0, STORE_KEY_FATAL=1, STORE_KEY_CONV=2 now. sql/sql_select.h: Fixed bug #10124. The copy method of the store_key classes can return STORE_KEY_OK=0, STORE_KEY_FATAL=1, STORE_KEY_CONV=2 now. mysql-test/t/func_str.test: Added a test case for bug #10124. mysql-test/r/func_str.result: Added a test case for bug #10124. --- mysql-test/r/func_str.result | 11 +++++++++++ mysql-test/t/func_str.test | 14 ++++++++++++++ sql/field.cc | 41 ++++++++++++++++++++++++----------------- sql/item_subselect.cc | 4 ++-- sql/sql_select.cc | 8 ++++++-- sql/sql_select.h | 25 ++++++++++++++++--------- 6 files changed, 73 insertions(+), 30 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index ea1efbc7c0a..60c77d91ca5 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -789,3 +789,14 @@ field(0,NULL,1,0) field("",NULL,"bar","") field(0.0,NULL,1.0,0.0) select field(NULL,1,2,NULL), field(NULL,1,2,0); field(NULL,1,2,NULL) field(NULL,1,2,0) 0 0 +CREATE TABLE t1 (str varchar(20) PRIMARY KEY); +CREATE TABLE t2 (num int primary key); +INSERT INTO t1 VALUES ('notnumber'); +INSERT INTO t2 VALUES (0), (1); +SELECT * FROM t1, t2 WHERE num=str; +str num +notnumber 0 +SELECT * FROM t1, t2 WHERE num=substring(str from 1 for 6); +str num +notnumber 0 +DROP TABLE t1,t2; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index a5536f7a0be..36cfac16ff3 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -527,3 +527,17 @@ DROP TABLE t1, t2; # select field(0,NULL,1,0), field("",NULL,"bar",""), field(0.0,NULL,1.0,0.0); select field(NULL,1,2,NULL), field(NULL,1,2,0); + +# +# Bug #10124: access by integer index with a string key that is not a number +# + +CREATE TABLE t1 (str varchar(20) PRIMARY KEY); +CREATE TABLE t2 (num int primary key); +INSERT INTO t1 VALUES ('notnumber'); +INSERT INTO t2 VALUES (0), (1); + +SELECT * FROM t1, t2 WHERE num=str; +SELECT * FROM t1, t2 WHERE num=substring(str from 1 for 6); + +DROP TABLE t1,t2; diff --git a/sql/field.cc b/sql/field.cc index 692f123097a..a330ffb7262 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2473,7 +2473,10 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) if (error || (from+len != end && table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))) - error= 1; + { + if (error != 1) + error= 2; + } #if SIZEOF_LONG > 4 if (unsigned_flag) { @@ -2501,10 +2504,7 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) } #endif if (error) - { set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); - error= 1; - } #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) { @@ -2770,8 +2770,11 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) (from+len != end && table->in_use->count_cuted_fields && !test_if_int(from,len,end,cs))) { - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); - error= 1; + if (error != 1) + { + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); + error= 2; + } } #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) @@ -2991,7 +2994,7 @@ int Field_float::store(const char *from,uint len,CHARSET_INFO *cs) double nr= my_strntod(cs,(char*) from,len,&end,&error); if (error || ((uint) (end-from) != len && table->in_use->count_cuted_fields)) { - error= 1; + error= 2; set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); } Field_float::store(nr); @@ -3277,7 +3280,7 @@ int Field_double::store(const char *from,uint len,CHARSET_INFO *cs) double nr= my_strntod(cs,(char*) from, len, &end, &error); if (error || ((uint) (end-from) != len && table->in_use->count_cuted_fields)) { - error= 1; + error= 2; set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); } Field_double::store(nr); @@ -3659,6 +3662,8 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs) error= 1; } } + if (error > 1) + error= 2; #ifdef WORDS_BIGENDIAN if (table->db_low_byte_first) @@ -3947,7 +3952,7 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs) if (str_to_time(from, len, <ime, &error)) { tmp=0L; - error= 1; + error= 2; set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, from, len, MYSQL_TIMESTAMP_TIME, 1); } @@ -3969,6 +3974,8 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs) from, len, MYSQL_TIMESTAMP_TIME, !error); error= 1; } + if (error > 1) + error= 2; } if (ltime.neg) @@ -4298,7 +4305,7 @@ int Field_date::store(const char *from, uint len,CHARSET_INFO *cs) if (str_to_datetime(from, len, &l_time, 1, &error) <= MYSQL_TIMESTAMP_ERROR) { tmp=0; - error= 1; + error= 2; } else tmp=(uint32) l_time.year*10000L + (uint32) (l_time.month*100+l_time.day); @@ -4489,7 +4496,7 @@ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs) if (str_to_datetime(from, len, &l_time, 1, &error) <= MYSQL_TIMESTAMP_ERROR) { tmp=0L; - error= 1; + error= 2; } else tmp= l_time.day + l_time.month*32 + l_time.year*16*32; @@ -4931,7 +4938,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) from= tmpstr.ptr(); length= tmpstr.length(); if (conv_errors) - error= 1; + error= 2; } /* @@ -4955,7 +4962,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs) from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES); if (from != end) - error= 1; + error= 2; } if (error) set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); @@ -5210,12 +5217,12 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs) from= tmpstr.ptr(); length= tmpstr.length(); if (conv_errors) - error= 1; + error= 2; } if (length > field_length) { length=field_length; - error= 1; + error= 2; } if (error) set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1); @@ -5568,7 +5575,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) from= tmpstr.ptr(); length= tmpstr.length(); if (conv_errors) - error= 1; + error= 2; } copy_length= max_data_length(); @@ -5583,7 +5590,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) copy_length, &well_formed_error); if (copy_length < length) - error= 1; + error= 2; Field_blob::store_length(copy_length); if (was_conversion || table->copy_blobs || copy_length <= MAX_FIELD_WIDTH) { // Must make a copy diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index ebc08545566..82954a664c0 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1361,7 +1361,7 @@ int subselect_uniquesubquery_engine::exec() TABLE *table= tab->table; for (store_key **copy=tab->ref.key_copy ; *copy ; copy++) { - if (tab->ref.key_err= (*copy)->copy()) + if ((tab->ref.key_err= (*copy)->copy()) & 1) { table->status= STATUS_NOT_FOUND; DBUG_RETURN(1); @@ -1414,7 +1414,7 @@ int subselect_indexsubquery_engine::exec() for (store_key **copy=tab->ref.key_copy ; *copy ; copy++) { - if (tab->ref.key_err= (*copy)->copy()) + if ((tab->ref.key_err= (*copy)->copy()) & 1) { table->status= STATUS_NOT_FOUND; DBUG_RETURN(1); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5bafe1a7df4..2f165565ce1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8223,11 +8223,15 @@ cp_buffer_from_ref(THD *thd, TABLE_REF *ref) enum enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; thd->count_cuted_fields= CHECK_FIELD_IGNORE; for (store_key **copy=ref->key_copy ; *copy ; copy++) - if ((*copy)->copy()) + { + int res; + if ((res= (*copy)->copy())) { thd->count_cuted_fields= save_count_cuted_fields; - return 1; // Something went wrong + if ((res= res & 1)) + return res; // Something went wrong } + } thd->count_cuted_fields= save_count_cuted_fields; return 0; } diff --git a/sql/sql_select.h b/sql/sql_select.h index 7e69eca4683..c7440fe4c3a 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -356,6 +356,7 @@ class store_key :public Sql_alloc char *null_ptr; char err; public: + enum store_key_result { STORE_KEY_OK, STORE_KEY_FATAL, STORE_KEY_CONV }; store_key(THD *thd, Field *field_arg, char *ptr, char *null, uint length) :null_ptr(null),err(0) { @@ -371,7 +372,7 @@ class store_key :public Sql_alloc } } virtual ~store_key() {} /* Not actually needed */ - virtual bool copy()=0; + virtual enum store_key_result copy()=0; virtual const char *name() const=0; }; @@ -392,10 +393,10 @@ class store_key_field: public store_key copy_field.set(to_field,from_field,0); } } - bool copy() + enum store_key_result copy() { copy_field.do_copy(©_field); - return err != 0; + return err != 0 ? STORE_KEY_FATAL : STORE_KEY_OK; } const char *name() const { return field_name; } }; @@ -412,9 +413,11 @@ public: null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ? &err : NullS, length), item(item_arg) {} - bool copy() + enum store_key_result copy() { - return item->save_in_field(to_field, 1) || err != 0; + int res= item->save_in_field(to_field, 1); + return (err != 0 || res > 2 ? STORE_KEY_FATAL : (store_key_result) res); + } const char *name() const { return "func"; } }; @@ -432,15 +435,19 @@ public: &err : NullS, length, item_arg), inited(0) { } - bool copy() + enum store_key_result copy() { + int res; if (!inited) { inited=1; - if (item->save_in_field(to_field, 1)) - err= 1; + if ((res= item->save_in_field(to_field, 1))) + { + if (!err) + err= res; + } } - return err != 0; + return (err > 2 ? STORE_KEY_FATAL : (store_key_result) err); } const char *name() const { return "const"; } }; -- cgit v1.2.1