From 95b92b4369cd85c3c04d1910e30333e862f416fa Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Nov 2005 12:27:58 +0100 Subject: [PATCH 1/6] Bug #14514 Creating table with packed key fails silently - Backport from 5.0 include/my_base.h: Rename HA_CREATE_FROM_ENGINE to HA_OPTION_CREATE_FROM_ENGINE, ie. it's a bit in the table_options variable mysql-test/r/ndb_basic.result: Add test result mysql-test/t/ndb_basic.test: Add test case for bug14514 sql/ha_ndbcluster.cc: Use new bitmask for table_options to detect if create from engine sql/handler.cc: Use new bit for create from engine --- include/my_base.h | 2 +- mysql-test/r/ndb_basic.result | 4 ++++ mysql-test/t/ndb_basic.test | 8 ++++++++ sql/ha_ndbcluster.cc | 2 +- sql/handler.cc | 2 +- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/my_base.h b/include/my_base.h index d702ec45140..271e7cd23ba 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -231,6 +231,7 @@ enum ha_base_keytype { #define HA_OPTION_CHECKSUM 32 #define HA_OPTION_DELAY_KEY_WRITE 64 #define HA_OPTION_NO_PACK_KEYS 128 /* Reserved for MySQL */ +#define HA_OPTION_CREATE_FROM_ENGINE 256 #define HA_OPTION_TEMP_COMPRESS_RECORD ((uint) 16384) /* set by isamchk */ #define HA_OPTION_READ_ONLY_DATA ((uint) 32768) /* Set by isamchk */ @@ -241,7 +242,6 @@ enum ha_base_keytype { #define HA_CREATE_TMP_TABLE 4 #define HA_CREATE_CHECKSUM 8 #define HA_CREATE_DELAY_KEY_WRITE 64 -#define HA_CREATE_FROM_ENGINE 128 /* Bits in flag to _status */ diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result index 3712fa2b5ca..42b5a39d3d8 100644 --- a/mysql-test/r/ndb_basic.result +++ b/mysql-test/r/ndb_basic.result @@ -667,3 +667,7 @@ counter datavalue 57 newval 58 newval drop table t1; +CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb; +select * from t1; +b +drop table t1; diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test index 144e466d937..c8cf5823500 100644 --- a/mysql-test/t/ndb_basic.test +++ b/mysql-test/t/ndb_basic.test @@ -606,4 +606,12 @@ select * from t1 order by counter; drop table t1; +# +# BUG#14514 Creating table with packed key fails silently +# + +CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb; +select * from t1; +drop table t1; + # End of 4.1 tests diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 608dc3eaa54..5391f0dedd0 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -3711,7 +3711,7 @@ int ha_ndbcluster::create(const char *name, const void *data, *pack_data; const char **key_names= form->keynames.type_names; char name2[FN_HEADLEN]; - bool create_from_engine= (info->table_options & HA_CREATE_FROM_ENGINE); + bool create_from_engine= (info->table_options & HA_OPTION_CREATE_FROM_ENGINE); DBUG_ENTER("create"); DBUG_PRINT("enter", ("name: %s", name)); diff --git a/sql/handler.cc b/sql/handler.cc index e6bc1496a00..e166f9885fc 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1382,7 +1382,7 @@ int ha_create_table_from_engine(THD* thd, DBUG_RETURN(3); update_create_info_from_table(&create_info, &table); - create_info.table_options|= HA_CREATE_FROM_ENGINE; + create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE; if (lower_case_table_names == 2 && !(table.file->table_flags() & HA_FILE_BASED)) From 31ea9f945d2acfa8e0dec18df8ae7094d7ca62b0 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Nov 2005 16:09:26 +0400 Subject: [PATCH 2/6] Fix for bug#14780 memory leak for mysql 4.1.14 with openssl enabled --- sql-common/client.c | 6 +++++- vio/vio.c | 2 +- vio/vio_priv.h | 1 - vio/viossl.c | 19 ------------------- 4 files changed, 6 insertions(+), 22 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index 3979b9304f7..3a598832253 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1487,11 +1487,15 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , static void mysql_ssl_free(MYSQL *mysql __attribute__((unused))) { + struct st_VioSSLConnectorFd *st= + (struct st_VioSSLConnectorFd*) mysql->connector_fd; my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); + if (st) + SSL_CTX_free(st->ssl_context); my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); mysql->options.ssl_key = 0; mysql->options.ssl_cert = 0; diff --git a/vio/vio.c b/vio/vio.c index 427c52e29d3..6174acd7024 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -83,7 +83,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type, #ifdef HAVE_OPENSSL if (type == VIO_TYPE_SSL) { - vio->viodelete =vio_ssl_delete; + vio->viodelete =vio_delete; vio->vioerrno =vio_ssl_errno; vio->read =vio_ssl_read; vio->write =vio_ssl_write; diff --git a/vio/vio_priv.h b/vio/vio_priv.h index c1c78cc6efa..eb495025ddd 100644 --- a/vio/vio_priv.h +++ b/vio/vio_priv.h @@ -28,7 +28,6 @@ void vio_ignore_timeout(Vio *vio, uint which, uint timeout); #ifdef HAVE_OPENSSL #include "my_net.h" /* needed because of struct in_addr */ -void vio_ssl_delete(Vio* vio); int vio_ssl_read(Vio *vio,gptr buf, int size); int vio_ssl_write(Vio *vio,const gptr buf,int size); void vio_ssl_timeout(Vio *vio, uint which, uint timeout); diff --git a/vio/viossl.c b/vio/viossl.c index a3a2e7190bd..62145fe5006 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -69,25 +69,6 @@ report_errors() DBUG_VOID_RETURN; } -/* - Delete a vio object - - SYNPOSIS - vio_ssl_delete() - vio Vio object. May be 0. -*/ - - -void vio_ssl_delete(Vio * vio) -{ - if (vio) - { - if (vio->type != VIO_CLOSED) - vio_close(vio); - my_free((gptr) vio,MYF(0)); - } -} - int vio_ssl_errno(Vio *vio __attribute__((unused))) { From 102c0281fa1a746d6d473fbb22237a5dac1b82ba Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 16:21:07 +0100 Subject: [PATCH 3/6] Moved check of wrong schema version earlier --- sql/ha_ndbcluster.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 6760208488f..e06559dc593 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -3285,12 +3285,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion())); } - if (m_table != (void *)tab) - { - m_table= (void *)tab; - m_table_version = tab->getObjectVersion(); - } - else if (m_table_version < tab->getObjectVersion()) + if (m_table_version < tab->getObjectVersion()) { /* The table has been altered, caller has to retry @@ -3298,6 +3293,13 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) NdbError err= ndb->getNdbError(NDB_INVALID_SCHEMA_OBJECT); DBUG_RETURN(ndb_to_mysql_error(&err)); } + if (m_table != (void *)tab) + { + m_table= (void *)tab; + m_table_version = tab->getObjectVersion(); + if (!(my_errno= build_index_list(ndb, table, ILBP_OPEN))) + DBUG_RETURN(my_errno); + } m_table_info= tab_info; } no_uncommitted_rows_init(thd); From 3190b21f95e58886e1507384bf792ed68a9f8397 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 19:16:51 +0300 Subject: [PATCH 4/6] Fix bug #14482 Wrongly applied optimization in resolve_const_item() caused crash resolve_const_item() substitutes item which will evaluate to constant with equvalent constant item, basing on the item's result type. In this case subselect was resolved as constant, and resolve_const_item() was substituting it's result's Item_caches to Item_null. Later Item_cache's function was called for Item_null object, which caused server crash. resolve_const_item() now substitutes constants for items with result_type == ROW_RESULT only for Item_rows. sql/item.cc: Fix bug #14482 Wrongly applied optimization in resolve_const_item() caused crash resolve_const_item() now applies optimization for items with result_type == ROW_RESULT only to Item_rows. mysql-test/t/select.test: Test case for bug #14482 Wrongly applied optimization in resolve_const_item() caused crash mysql-test/r/select.result: Test case for bug #14482 Wrongly applied optimization in resolve_const_item() caused crash --- mysql-test/r/select.result | 8 ++++++++ mysql-test/t/select.test | 11 +++++++++++ sql/item.cc | 15 ++++++++++++--- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 64c329ee104..b80ca2b195e 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2706,3 +2706,11 @@ select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1; count(f2) >0 1 drop table t1,t2; +create table t1 (f1 int,f2 int); +insert into t1 values(1,1); +create table t2 (f3 int, f4 int, primary key(f3,f4)); +insert into t2 values(1,1); +select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 from t2)); +f1 f2 +1 1 +drop table t1,t2; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 39c7cdfa8a9..996d5854854 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2237,4 +2237,15 @@ insert into t1 values (1,1); insert into t2 values (1,1),(1,2); select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1; drop table t1,t2; + +# +# Bug #14482 Server crash when subselecting from the same table +# +create table t1 (f1 int,f2 int); +insert into t1 values(1,1); +create table t2 (f3 int, f4 int, primary key(f3,f4)); +insert into t2 values(1,1); +select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 from t2)); +drop table t1,t2; + # End of 4.1 tests diff --git a/sql/item.cc b/sql/item.cc index 642a0ccf1b4..6ca2627dbff 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2863,7 +2863,7 @@ Item_result item_cmp_type(Item_result a,Item_result b) void resolve_const_item(THD *thd, Item **ref, Item *comp_item) { Item *item= *ref; - Item *new_item; + Item *new_item= NULL; if (item->basic_const_item()) return; // Can't be better Item_result res_type=item_cmp_type(comp_item->result_type(), @@ -2892,8 +2892,17 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) new_item= (null_value ? (Item*) new Item_null(name) : (Item*) new Item_int(name, result, length)); } - else if (res_type == ROW_RESULT) + else if (res_type == ROW_RESULT && item->type() == Item::ROW_ITEM && + comp_item->type() == Item::ROW_ITEM) { + /* + Substitute constants only in Item_rows. Don't affect other Items + with ROW_RESULT (eg Item_singlerow_subselect). + + For such Items more optimal is to detect if it is constant and replace + it with Item_row. This would optimize queries like this: + SELECT * FROM t1 WHERE (a,b) = (SELECT a,b FROM t2 LIMIT 1); + */ Item_row *item_row= (Item_row*) item; Item_row *comp_item_row= (Item_row*) comp_item; uint col; @@ -2910,7 +2919,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) while (col-- > 0) resolve_const_item(thd, item_row->addr(col), comp_item_row->el(col)); } - else + else if (res_type == REAL_RESULT) { // It must REAL_RESULT double result=item->val(); uint length=item->max_length,decimals=item->decimals; From e1af5e5dfd302b03b12e897812ecbb7befb98c3d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Nov 2005 10:41:22 +0100 Subject: [PATCH 5/6] Updated expected error --- mysql-test/r/ndb_alter_table.result | 2 +- mysql-test/t/ndb_alter_table.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ndb_alter_table.result b/mysql-test/r/ndb_alter_table.result index 62e8455ae9f..b5fceba7cee 100644 --- a/mysql-test/r/ndb_alter_table.result +++ b/mysql-test/r/ndb_alter_table.result @@ -179,7 +179,7 @@ a b c 2 two two alter table t1 drop index c; select * from t1 where b = 'two'; -ERROR HY000: Table definition has changed, please retry transaction +ERROR HY000: Can't lock file (errno: 241) select * from t1 where b = 'two'; a b c 2 two two diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test index d89b81859e7..22383a82bca 100644 --- a/mysql-test/t/ndb_alter_table.test +++ b/mysql-test/t/ndb_alter_table.test @@ -149,7 +149,7 @@ connection server1; alter table t1 drop index c; connection server2; # This should fail since index information is not automatically refreshed ---error 1105 +--error 1015 select * from t1 where b = 'two'; select * from t1 where b = 'two'; connection server1; From 2a1ae3a5e3cbc7bb076c91ba0f8b5e6242319b28 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Nov 2005 13:25:31 +0300 Subject: [PATCH 6/6] A fix and a test case for Bug#14410 "Crash in Enum or Set type in CREATE TABLE and PS/SP": make sure that 'typelib' object for ENUM values and 'Item_string' object for DEFAULT clause are created in the statement memory root. mysql-test/r/ps.result: Test results has been fixed (Bug#14410) mysql-test/t/ps.test: A test case for Bug#14410 "Crash in Enum or Set type in CREATE TABLE and PS/SP" sql/mysql_priv.h: typelib() function declaration has been changed. sql/sql_table.cc: Supply the statement memory root to use in typelib() and safe_charset_converter() functions to ensure that objects created during the first execution of CREATE TABLE statement are allocated in persistent memory of the statement. sql/table.cc: Change typelib() function to require MEM_ROOT. --- mysql-test/r/ps.result | 19 +++++++++++++++++++ mysql-test/t/ps.test | 29 +++++++++++++++++++++++++++++ sql/mysql_priv.h | 2 +- sql/sql_table.cc | 29 +++++++++++++++++++++++++---- sql/table.cc | 6 +++--- 5 files changed, 77 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index f5bf3ffa96d..d46c2d5b3d5 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -699,3 +699,22 @@ execute stmt; @@tx_isolation REPEATABLE-READ deallocate prepare stmt; +prepare stmt from "create temporary table t1 (letter enum('','a','b','c') +not null)"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +set names latin1; +prepare stmt from "create table t1 (a enum('test') default 'test') + character set utf8"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +set names default; +deallocate prepare stmt; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index c4cb0056763..82dfc643801 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -718,4 +718,33 @@ set @@tx_isolation=default; execute stmt; deallocate prepare stmt; +# +# Bug#14410 "Crash in Enum or Set type in CREATE TABLE and PS/SP" +# +# Part I. Make sure the typelib for ENUM is created in the statement memory +# root. +prepare stmt from "create temporary table t1 (letter enum('','a','b','c') +not null)"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +# Part II. Make sure that when the default value is converted to UTF-8, +# the new item is # created in the statement memory root. +set names latin1; +prepare stmt from "create table t1 (a enum('test') default 'test') + character set utf8"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +# Cleanup +set names default; +deallocate prepare stmt; + # End of 4.1 tests + diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a9057ae24f6..c128fac8d9e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1119,7 +1119,7 @@ int calc_weekday(long daynr,bool sunday_first_day_of_week); uint calc_week(TIME *l_time, uint week_behaviour, uint *year); void find_date(char *pos,uint *vek,uint flag); TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end); -TYPELIB *typelib(List &strings); +TYPELIB *typelib(MEM_ROOT *mem_root, List &strings); ulong get_form_pos(File file, uchar *head, TYPELIB *save_names); ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames, const char *newname); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0e0a05ea099..294c59af90f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -524,7 +524,14 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, */ if (!interval) { - interval= sql_field->interval= typelib(sql_field->interval_list); + /* + Create the typelib in prepared statement memory if we're + executing one. + */ + MEM_ROOT *stmt_root= thd->current_arena->mem_root; + + interval= sql_field->interval= typelib(stmt_root, + sql_field->interval_list); List_iterator it(sql_field->interval_list); String conv, *tmp; for (uint i= 0; (tmp= it++); i++) @@ -534,7 +541,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, { uint cnv_errs; conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs); - char *buf= (char*) sql_alloc(conv.length()+1); + char *buf= (char*) alloc_root(stmt_root, conv.length()+1); memcpy(buf, conv.ptr(), conv.length()); buf[conv.length()]= '\0'; interval->type_names[i]= buf; @@ -556,8 +563,22 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, */ if (sql_field->def && cs != sql_field->def->collation.collation) { - if (!(sql_field->def= - sql_field->def->safe_charset_converter(cs))) + Item_arena backup_arena; + bool need_to_change_arena= + !thd->current_arena->is_conventional_execution(); + if (need_to_change_arena) + { + /* Asser that we don't do that at every PS execute */ + DBUG_ASSERT(thd->current_arena->is_first_stmt_execute()); + thd->set_n_backup_item_arena(thd->current_arena, &backup_arena); + } + + sql_field->def= sql_field->def->safe_charset_converter(cs); + + if (need_to_change_arena) + thd->restore_backup_item_arena(thd->current_arena, &backup_arena); + + if (! sql_field->def) { /* Could not convert */ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); diff --git a/sql/table.cc b/sql/table.cc index 04d1a95cd9b..de539205ffd 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1099,15 +1099,15 @@ fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types, } /* fix_type_pointers */ -TYPELIB *typelib(List &strings) +TYPELIB *typelib(MEM_ROOT *mem_root, List &strings) { - TYPELIB *result=(TYPELIB*) sql_alloc(sizeof(TYPELIB)); + TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB)); if (!result) return 0; result->count=strings.elements; result->name=""; uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1); - if (!(result->type_names= (const char**) sql_alloc(nbytes))) + if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes))) return 0; result->type_lengths= (uint*) (result->type_names + result->count + 1); List_iterator it(strings);