From 09944efd71a7b11de5b06e76b8019aae53d9ca36 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Jun 2005 13:31:59 +0200 Subject: [PATCH 001/216] BUG#10365 Cluster handler uses non-standard error codes - Added better error messages when trying to open a table that can't be discovered or unpacked. The most likely cause of this is that it does not have any frm data, probably since it has been created from NdbApi or is a NDB system table. - Separated functionality that was in ha_create_table_from_engine into two functions. One that checks if the table exists and another one that tries to create the table from the engine. mysql-test/r/ndb_autodiscover.result: Add tests for reading from a table that can't be discovered(SYSTAB_0) Discovery is not performed during create table anymore. mysql-test/t/ndb_autodiscover.test: Add tests for reading from a table that can't be discovered(SYSTAB_0) Discovery is not performed during create table anymore. ndb/test/ndbapi/create_tab.cpp: Set connectstring before creating Ndb object. sql/ha_ndbcluster.cc: Rename and use the function ndbcluster_table_exists_in_engine. Correct return valu from ndbcluster_discover Remove old code "ndb_discover_tables" sql/ha_ndbcluster.h: Rename function ndbcluster_table_exists to ndb ndbcluster_table_exists_in_engine sql/handler.cc: Update comment of ha_create_table_from_engine Remove parameter create_if_found from ha_create_table_from_engine, the function ha_table_exists_in_engine is now used toi check if table is found in engine. Cleanup return codes from ha_create_table_from_engine. Change name of ha_table_exists to ha_table_exists_in_engine, update comment and returne codes. sql/handler.h: Remove paramter create_if_cound from ha_create_table_from_engine Rename ha_table_exists to ha_table_exists_in_engine sql/sql_base.cc: Use the function ha_table_exists_in_engine to detect if table exists in enegine. If it exists, call function ha_create_table_from_engine to try and create it. If create of table fails, set correct error message. sql/sql_table.cc: Add comments, remove parameter create_if_found to ha_create_table_from_engine. When dropping a table, try to discover it from engine. If discover fails, use same error message as if the table didn't exists. Maybe another message should be displayed here, ex: "Table could not be dropped, unpack failed" When creating a new table, use ha_table_exists_in_engine to check if a table with the given name already exists. --- mysql-test/r/ndb_autodiscover.result | 20 +++++- mysql-test/t/ndb_autodiscover.test | 21 ++++++ ndb/test/ndbapi/create_tab.cpp | 2 +- sql/ha_ndbcluster.cc | 23 +++--- sql/ha_ndbcluster.h | 3 +- sql/handler.cc | 101 +++++++++++++-------------- sql/handler.h | 5 +- sql/sql_base.cc | 17 ++++- sql/sql_table.cc | 18 ++--- 9 files changed, 126 insertions(+), 84 deletions(-) diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result index b7afb5918a4..b278d6eb048 100644 --- a/mysql-test/r/ndb_autodiscover.result +++ b/mysql-test/r/ndb_autodiscover.result @@ -93,7 +93,7 @@ name char(20), a int, b float, c char(24) ERROR 42S01: Table 't3' already exists show status like 'handler_discover%'; Variable_name Value -Handler_discover 1 +Handler_discover 0 create table IF NOT EXISTS t3( id int not null primary key, id2 int not null, @@ -101,7 +101,7 @@ name char(20) ) engine=ndb; show status like 'handler_discover%'; Variable_name Value -Handler_discover 2 +Handler_discover 0 SHOW CREATE TABLE t3; Table Create Table t3 CREATE TABLE `t3` ( @@ -114,7 +114,7 @@ id name 1 Explorer show status like 'handler_discover%'; Variable_name Value -Handler_discover 2 +Handler_discover 1 drop table t3; flush status; create table t7( @@ -358,6 +358,20 @@ Database mysql test use test; +CREATE TABLE sys.SYSTAB_0 (a int); +ERROR 42S01: Table 'SYSTAB_0' already exists +select * from sys.SYSTAB_0; +ERROR HY000: Failed to open 'SYSTAB_0', error while unpacking from engine +CREATE TABLE IF NOT EXISTS sys.SYSTAB_0 (a int); +show warnings; +Level Code Message +select * from sys.SYSTAB_0; +ERROR HY000: Failed to open 'SYSTAB_0', error while unpacking from engine +drop table sys.SYSTAB_0; +ERROR 42S02: Unknown table 'SYSTAB_0' +drop table IF EXISTS sys.SYSTAB_0; +Warnings: +Note 1051 Unknown table 'SYSTAB_0' CREATE TABLE t9 ( a int NOT NULL PRIMARY KEY, b int diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test index bd73a36fcab..49ed8c894fe 100644 --- a/mysql-test/t/ndb_autodiscover.test +++ b/mysql-test/t/ndb_autodiscover.test @@ -453,6 +453,27 @@ drop database test2; show databases; use test; +##################################################### +# Test that it's not possible to create tables +# with same name as NDB internal tables +# This will also test that it's not possible to create +# a table with tha same name as a table that can't be +# discovered( for example a table created via NDBAPI) + +--error 1050 +CREATE TABLE sys.SYSTAB_0 (a int); +--error 1105 +select * from sys.SYSTAB_0; + +CREATE TABLE IF NOT EXISTS sys.SYSTAB_0 (a int); +show warnings; +--error 1105 +select * from sys.SYSTAB_0; + +--error 1051 +drop table sys.SYSTAB_0; +drop table IF EXISTS sys.SYSTAB_0; + ###################################################### # Note! This should always be the last step in this # file, the table t9 will be used and dropped diff --git a/ndb/test/ndbapi/create_tab.cpp b/ndb/test/ndbapi/create_tab.cpp index f3f18982ed0..283c83d30e0 100644 --- a/ndb/test/ndbapi/create_tab.cpp +++ b/ndb/test/ndbapi/create_tab.cpp @@ -77,8 +77,8 @@ int main(int argc, const char** argv){ */ // Connect to Ndb + Ndb::setConnectString(_connectstr); Ndb MyNdb( "TEST_DB" ); - MyNdb.setConnectString(_connectstr); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index eaa0473df1b..85b7ddc4892 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -4308,13 +4308,15 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name, len= tab->getFrmLength(); if (len == 0 || tab->getFrmData() == NULL) { - DBUG_PRINT("No frm data found", - ("Table is probably created via NdbApi")); - DBUG_RETURN(2); + DBUG_PRINT("error", ("No frm data found.")); + DBUG_RETURN(1); } if (unpackfrm(&data, &len, tab->getFrmData())) - DBUG_RETURN(3); + { + DBUG_PRINT("error", ("Could not unpack table")); + DBUG_RETURN(1); + } *frmlen= len; *frmblob= data; @@ -4327,13 +4329,13 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name, */ -int ndbcluster_table_exists(THD* thd, const char *db, const char *name) +int ndbcluster_table_exists_in_engine(THD* thd, const char *db, const char *name) { uint len; const void* data; const NDBTAB* tab; Ndb* ndb; - DBUG_ENTER("ndbcluster_table_exists"); + DBUG_ENTER("ndbcluster_table_exists_in_engine"); DBUG_PRINT("enter", ("db: %s, name: %s", db, name)); if (!(ndb= check_ndb_in_thd(thd))) @@ -4512,7 +4514,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path, DBUG_PRINT("info", ("%s existed on disk", name)); // The .ndb file exists on disk, but it's not in list of tables in ndb // Verify that handler agrees table is gone. - if (ndbcluster_table_exists(thd, db, file_name) == 0) + if (ndbcluster_table_exists_in_engine(thd, db, file_name) == 0) { DBUG_PRINT("info", ("NDB says %s does not exists", file_name)); it.remove(); @@ -4563,7 +4565,7 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path, while ((file_name=it2++)) { DBUG_PRINT("info", ("Table %s need discovery", name)); - if (ha_create_table_from_engine(thd, db, file_name, TRUE) == 0) + if (ha_create_table_from_engine(thd, db, file_name) == 0) files->push_back(thd->strdup(file_name)); } @@ -4639,11 +4641,8 @@ bool ndbcluster_init() pthread_mutex_init(&ndbcluster_mutex,MY_MUTEX_INIT_FAST); ndbcluster_inited= 1; -#ifdef USE_DISCOVER_ON_STARTUP - if (ndb_discover_tables() != 0) - goto ndbcluster_init_error; -#endif DBUG_RETURN(FALSE); + ndbcluster_init_error: ndbcluster_end(); DBUG_RETURN(TRUE); diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 439b4855147..5c1d121a157 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -275,7 +275,8 @@ int ndbcluster_discover(THD* thd, const char* dbname, const char* name, const void** frmblob, uint* frmlen); int ndbcluster_find_files(THD *thd,const char *db,const char *path, const char *wild, bool dir, List *files); -int ndbcluster_table_exists(THD* thd, const char *db, const char *name); +int ndbcluster_table_exists_in_engine(THD* thd, + const char *db, const char *name); int ndbcluster_drop_database(const char* path); void ndbcluster_print_error(int error, const NdbOperation *error_op); diff --git a/sql/handler.cc b/sql/handler.cc index f14564b6629..ad5cd28d932 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1336,21 +1336,18 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info, } /* - Try to discover table from engine and + Try to discover table from engine and if found, write the frm file to disk. - + RETURN VALUES: - 0 : Table existed in engine and created - on disk if so requested - 1 : Table does not exist - >1 : error + 0 : Table created ok + 1 : Table could not be created */ -int ha_create_table_from_engine(THD* thd, - const char *db, - const char *name, - bool create_if_found) +int ha_create_table_from_engine(THD* thd, + const char *db, + const char *name) { int error; const void *frmblob; @@ -1359,45 +1356,47 @@ int ha_create_table_from_engine(THD* thd, HA_CREATE_INFO create_info; TABLE table; DBUG_ENTER("ha_create_table_from_engine"); - DBUG_PRINT("enter", ("name '%s'.'%s' create_if_found: %d", - db, name, create_if_found)); + DBUG_PRINT("enter", ("name '%s'.'%s'", + db, name)); bzero((char*) &create_info,sizeof(create_info)); - if ((error= ha_discover(thd, db, name, &frmblob, &frmlen))) - DBUG_RETURN(error); - /* - Table exists in handler - frmblob and frmlen are set - */ - - if (create_if_found) + if(ha_discover(thd, db, name, &frmblob, &frmlen)) { - (void)strxnmov(path,FN_REFLEN,mysql_data_home,"/",db,"/",name,NullS); - // Save the frm file - if ((error = writefrm(path, frmblob, frmlen))) - goto err_end; - - if (openfrm(path,"",0,(uint) READ_ALL, 0, &table)) - DBUG_RETURN(1); - - update_create_info_from_table(&create_info, &table); - create_info.table_options|= HA_CREATE_FROM_ENGINE; - - if (lower_case_table_names == 2 && - !(table.file->table_flags() & HA_FILE_BASED)) - { - /* Ensure that handler gets name in lower case */ - my_casedn_str(files_charset_info, path); - } - - error=table.file->create(path,&table,&create_info); - VOID(closefrm(&table)); + // Table could not be discovered and thus not created + DBUG_RETURN(1); } -err_end: + /* + Table exists in handler and could be discovered + frmblob and frmlen are set, write the frm to disk + */ + + (void)strxnmov(path,FN_REFLEN,mysql_data_home,"/",db,"/",name,NullS); + // Save the frm file + if (writefrm(path, frmblob, frmlen)) + { + my_free((char*) frmblob, MYF(MY_ALLOW_ZERO_PTR)); + DBUG_RETURN(1); + } + + if (openfrm(path,"",0,(uint) READ_ALL, 0, &table)) + DBUG_RETURN(1); + + update_create_info_from_table(&create_info, &table); + create_info.table_options|= HA_CREATE_FROM_ENGINE; + + if (lower_case_table_names == 2 && + !(table.file->table_flags() & HA_FILE_BASED)) + { + /* Ensure that handler gets name in lower case */ + my_casedn_str(files_charset_info, path); + } + error=table.file->create(path,&table,&create_info); + VOID(closefrm(&table)); my_free((char*) frmblob, MYF(MY_ALLOW_ZERO_PTR)); - DBUG_RETURN(error); + + DBUG_RETURN(error != 0); } static int NEAR_F delete_file(const char *name,const char *ext,int extflag) @@ -1507,8 +1506,8 @@ int ha_change_key_cache(KEY_CACHE *old_key_cache, Try to discover one table from handler(s) RETURN - 0 ok. In this case *frmblob and *frmlen are set - 1 error. frmblob and frmlen may not be set + 0 ok. In this case *frmblob and *frmlen are set + >=1 error. frmblob and frmlen may not be set */ int ha_discover(THD *thd, const char *db, const char *name, @@ -1546,11 +1545,8 @@ ha_find_files(THD *thd,const char *db,const char *path, error= ndbcluster_find_files(thd, db, path, wild, dir, files); #endif DBUG_RETURN(error); - - } -#ifdef NOT_YET_USED /* Ask handler if the table exists in engine @@ -1561,20 +1557,19 @@ ha_find_files(THD *thd,const char *db,const char *path, # Error code */ -int ha_table_exists(THD* thd, const char* db, const char* name) +int ha_table_exists_in_engine(THD* thd, const char* db, const char* name) { - int error= 2; - DBUG_ENTER("ha_table_exists"); + int error= 0; + DBUG_ENTER("ha_table_exists_in_engine"); DBUG_PRINT("enter", ("db: %s, name: %s", db, name)); #ifdef HAVE_NDBCLUSTER_DB if (have_ndbcluster == SHOW_OPTION_YES) - error= ndbcluster_table_exists(thd, db, name); + error= ndbcluster_table_exists_in_engine(thd, db, name); #endif + DBUG_PRINT("exit", ("error: %d", error)); DBUG_RETURN(error); } -#endif - /* Read first row between two ranges. diff --git a/sql/handler.h b/sql/handler.h index 75e83082d10..efcdee8f56c 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -547,8 +547,7 @@ enum db_type ha_checktype(enum db_type database_type); my_bool ha_storage_engine_is_enabled(enum db_type database_type); int ha_create_table(const char *name, HA_CREATE_INFO *create_info, bool update_create_info); -int ha_create_table_from_engine(THD* thd, const char *db, const char *name, - bool create_if_found); +int ha_create_table_from_engine(THD* thd, const char *db, const char *name); int ha_delete_table(enum db_type db_type, const char *path); void ha_drop_database(char* path); int ha_init_key_cache(const char *name, KEY_CACHE *key_cache); @@ -574,6 +573,6 @@ int ha_discover(THD* thd, const char* dbname, const char* name, const void** frmblob, uint* frmlen); int ha_find_files(THD *thd,const char *db,const char *path, const char *wild, bool dir,List* files); -int ha_table_exists(THD* thd, const char* db, const char* name); +int ha_table_exists_in_engine(THD* thd, const char* db, const char* name); TYPELIB *ha_known_exts(void); int ha_start_consistent_snapshot(THD *thd); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c580842ce06..0aa2f1ce4b8 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1375,9 +1375,20 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, trying to discover the table at the same time. */ if (discover_retry_count++ != 0) - goto err; - if (ha_create_table_from_engine(thd, db, name, TRUE) != 0) - goto err; + goto err; + if (ha_table_exists_in_engine(thd, db, name) && + ha_create_table_from_engine(thd, db, name)) + { + /* Give right error message */ + thd->clear_error(); + DBUG_PRINT("error", ("Dicovery of %s/%s failed", db, name)); + my_printf_error(ER_UNKNOWN_ERROR, + "Failed to open '%-.64s', error while " + "unpacking from engine", + MYF(0), name); + + goto err; + } thd->clear_error(); // Clear error message continue; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 67aade519f5..70dd17cc8bc 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -217,15 +217,18 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, strxmov(path, mysql_data_home, "/", db, "/", alias, reg_ext, NullS); (void) unpack_filename(path,path); } - if (drop_temporary || - (access(path,F_OK) && ha_create_table_from_engine(thd,db,alias,TRUE))) + if (drop_temporary || + (access(path,F_OK) && + ha_create_table_from_engine(thd, db, alias))) { + // Table was not found on disk and table can't be created from engine if (if_exists) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), table->real_name); else - error= 1; + error= 1; + } else { @@ -1371,15 +1374,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, { bool create_if_not_exists = create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS; - if (!ha_create_table_from_engine(thd, db, table_name, - create_if_not_exists)) + if (ha_table_exists_in_engine(thd, db, table_name)) { - DBUG_PRINT("info", ("Table already existed in handler")); + DBUG_PRINT("info", ("Table with same name already existed in handler")); if (create_if_not_exists) { - create_info->table_existed= 1; // Mark that table existed - error= 0; + create_info->table_existed= 1; // Mark that table existed + error= 0; } else my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name); From 5a98e2a0d05fb9c2b626350d80ffe9161e2726c2 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Jun 2005 16:26:23 +0200 Subject: [PATCH 002/216] Bug #9558 mysqldump --no-data db t1 t2 format still dumps data - Added testcases according to spec in bug report. mysql-test/r/mysqldump.result: Update results mysql-test/t/mysqldump.test: Add tests for --no-data --- mysql-test/r/mysqldump.result | 60 +++++++++++++++++++++++++++++++++++ mysql-test/t/mysqldump.test | 15 +++++++++ 2 files changed, 75 insertions(+) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 845b0d1da45..f66647bdbf8 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1349,3 +1349,63 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +CREATE DATABASE mysqldump_test_db; +USE mysqldump_test_db; +CREATE TABLE t1 ( a INT ); +CREATE TABLE t2 ( a INT ); +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1), (2); + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS `t2`; +CREATE TABLE `t2` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS `t2`; +CREATE TABLE `t2` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +DROP TABLE t1, t2; +DROP DATABASE mysqldump_test_db; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 9f3b412b814..5a35c328314 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -543,3 +543,18 @@ CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); --exec $MYSQL_DUMP --add-drop-database --skip-comments --databases test DROP TABLE t1; + +# +# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data +# + +CREATE DATABASE mysqldump_test_db; +USE mysqldump_test_db; +CREATE TABLE t1 ( a INT ); +CREATE TABLE t2 ( a INT ); +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1), (2); +--exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db +--exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db t1 t2 +DROP TABLE t1, t2; +DROP DATABASE mysqldump_test_db; From ed483fcd21349e0ac5daf77658446ae0da37bef8 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 15 Jun 2005 16:27:41 -0700 Subject: [PATCH 003/216] Fix SHOW CREATE VIEW to handle ANSI_QUOTES mode. (Bug #6903) mysql-test/r/sql_mode.result: Update results mysql-test/r/view.result: Update results mysql-test/t/sql_mode.test: Add new regression tests sql/sql_show.cc: Fix SHOW CREATE VIEW to honor ANSI_QUOTES mode. --- mysql-test/r/sql_mode.result | 37 ++++++++++++++++++++++++++++++++++++ mysql-test/r/view.result | 4 ++-- mysql-test/t/sql_mode.test | 34 +++++++++++++++++++++++++++++++++ sql/sql_show.cc | 11 ++++++++++- 4 files changed, 83 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index c5ba4d15a50..320919198cd 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -402,4 +402,41 @@ a\b a\"b a'\b a'\"b SELECT "a\\b", "a\\\'b", "a""\\b", "a""\\\'b"; a\b a\'b a"\b a"\'b a\b a\'b a"\b a"\'b +SET @@SQL_MODE=''; +create function `foo` () returns int return 5; +show create function `foo`; +Function sql_mode Create Function +foo CREATE FUNCTION `test`.`foo`() RETURNS int(11) +return 5 +SET @@SQL_MODE='ANSI_QUOTES'; +show create function `foo`; +Function sql_mode Create Function +foo CREATE FUNCTION `test`.`foo`() RETURNS int(11) +return 5 +drop function `foo`; +create function `foo` () returns int return 5; +show create function `foo`; +Function sql_mode Create Function +foo ANSI_QUOTES CREATE FUNCTION "test"."foo"() RETURNS int(11) +return 5 +SET @@SQL_MODE=''; +show create function `foo`; +Function sql_mode Create Function +foo ANSI_QUOTES CREATE FUNCTION "test"."foo"() RETURNS int(11) +return 5 +drop function `foo`; +SET @@SQL_MODE=''; +create table t1 (a int); +create table t2 (a int); +create view v1 as select a from t1; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` from `test`.`t1` +SET @@SQL_MODE='ANSI_QUOTES'; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED VIEW "test"."v1" AS select "test"."t1"."a" AS "a" from "test"."t1" +create view v2 as select a from t2 where a in (select a from v1); +drop view v2, v1; +drop table t1, t2; SET @@SQL_MODE=@OLD_SQL_MODE; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 84be086ae37..cc93449bd1f 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -550,7 +550,7 @@ create table t1 ("a*b" int); create view v1 as select "a*b" from t1; show create view v1; View Create View -v1 CREATE VIEW "test"."v1" AS select `test`.`t1`.`a*b` AS `a*b` from `test`.`t1` +v1 CREATE VIEW "test"."v1" AS select "test"."t1"."a*b" AS "a*b" from "test"."t1" drop view v1; drop table t1; set sql_mode=default; @@ -760,7 +760,7 @@ a b 1 1 show create view v3; View Create View -v3 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v3` AS select `v1`.`col1` AS `a`,`v2`.`col1` AS `b` from `test`.`v1` join `test`.`v2` where (`v1`.`col1` = `v2`.`col1`) +v3 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v3` AS select `v1`.`col1` AS `a`,`v2`.`col1` AS `b` from (`test`.`v1` join `test`.`v2`) where (`v1`.`col1` = `v2`.`col1`) drop view v3, v2, v1; drop table t2, t1; create function `f``1` () returns int return 5; diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test index 6a0c4aecada..53e9339b73e 100644 --- a/mysql-test/t/sql_mode.test +++ b/mysql-test/t/sql_mode.test @@ -189,4 +189,38 @@ SET @@SQL_MODE=''; SELECT 'a\\b', 'a\\\"b', 'a''\\b', 'a''\\\"b'; SELECT "a\\b", "a\\\'b", "a""\\b", "a""\\\'b"; +# +# Bug #6903: ANSI_QUOTES does not come into play with SHOW CREATE FUNCTION +# or PROCEDURE because it displays the SQL_MODE used to create the routine. +# +SET @@SQL_MODE=''; +create function `foo` () returns int return 5; +show create function `foo`; +SET @@SQL_MODE='ANSI_QUOTES'; +show create function `foo`; +drop function `foo`; + +create function `foo` () returns int return 5; +show create function `foo`; +SET @@SQL_MODE=''; +show create function `foo`; +drop function `foo`; + +# +# Bug #6903: ANSI_QUOTES should have effect for SHOW CREATE VIEW (Bug #6903) +# +SET @@SQL_MODE=''; +create table t1 (a int); +create table t2 (a int); +create view v1 as select a from t1; +show create view v1; +SET @@SQL_MODE='ANSI_QUOTES'; +show create view v1; +# Test a view with a subselect, which will get shown incorrectly without +# thd->lex->view_prepare_mode set properly. +create view v2 as select a from t2 where a in (select a from v1); +drop view v2, v1; +drop table t1, t2; + + SET @@SQL_MODE=@OLD_SQL_MODE; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 68c6d1a8030..2b433981579 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -347,6 +347,9 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) DBUG_PRINT("enter",("db: %s table: %s",table_list->db, table_list->table_name)); + /* We want to preserve the tree for views. */ + thd->lex->view_prepare_mode= TRUE; + /* Only one table for now, but VIEW can involve several tables */ if (open_normal_and_derived_tables(thd, table_list)) { @@ -1061,7 +1064,13 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff) buff->append('.'); append_identifier(thd, buff, table->view_name.str, table->view_name.length); buff->append(" AS ", 4); - buff->append(table->query.str, table->query.length); + + /* + We can't just use table->query, because our SQL_MODE may trigger + a different syntax, like when ANSI_QUOTES is defined. + */ + table->view->unit.print(buff); + if (table->with_check != VIEW_CHECK_NONE) { if (table->with_check == VIEW_CHECK_LOCAL) From d18e5622ebacbb386b6cc8508dbdaae4216f4fa8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Jun 2005 15:17:47 +0200 Subject: [PATCH 004/216] BUG10365 Cluster handler uses non-standard error code - Updated after review sql/ha_ndbcluster.cc: Return -1 if table does not exists sql/handler.cc: Return -1 if table does not exists Return 0 if table exists and it could be created Return >0 if table existed but it could not be created. sql/sql_base.cc: Only need to call ha_create_table_from_engine and check if result is > 0. If that is the case, print error message --- sql/ha_ndbcluster.cc | 2 +- sql/handler.cc | 18 ++++++++++-------- sql/sql_base.cc | 3 +-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 85b7ddc4892..a7d82396eb5 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -4300,7 +4300,7 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name, { const NdbError err= dict->getNdbError(); if (err.code == 709) - DBUG_RETURN(1); + DBUG_RETURN(-1); ERR_RETURN(err); } DBUG_PRINT("info", ("Found table %s", tab->getName())); diff --git a/sql/handler.cc b/sql/handler.cc index ad5cd28d932..dacfc7d9ac5 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1340,8 +1340,9 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info, if found, write the frm file to disk. RETURN VALUES: + -1 : Table did not exists 0 : Table created ok - 1 : Table could not be created + > 0 : Error, table existed but could not be created */ @@ -1361,10 +1362,10 @@ int ha_create_table_from_engine(THD* thd, bzero((char*) &create_info,sizeof(create_info)); - if(ha_discover(thd, db, name, &frmblob, &frmlen)) + if(error= ha_discover(thd, db, name, &frmblob, &frmlen)) { // Table could not be discovered and thus not created - DBUG_RETURN(1); + DBUG_RETURN(error); } /* @@ -1377,11 +1378,11 @@ int ha_create_table_from_engine(THD* thd, if (writefrm(path, frmblob, frmlen)) { my_free((char*) frmblob, MYF(MY_ALLOW_ZERO_PTR)); - DBUG_RETURN(1); + DBUG_RETURN(2); } if (openfrm(path,"",0,(uint) READ_ALL, 0, &table)) - DBUG_RETURN(1); + DBUG_RETURN(3); update_create_info_from_table(&create_info, &table); create_info.table_options|= HA_CREATE_FROM_ENGINE; @@ -1506,14 +1507,15 @@ int ha_change_key_cache(KEY_CACHE *old_key_cache, Try to discover one table from handler(s) RETURN - 0 ok. In this case *frmblob and *frmlen are set - >=1 error. frmblob and frmlen may not be set + -1 : Table did not exists + 0 : OK. In this case *frmblob and *frmlen are set + >0 : error. frmblob and frmlen may not be set */ int ha_discover(THD *thd, const char *db, const char *name, const void **frmblob, uint *frmlen) { - int error= 1; // Table does not exist in any handler + int error= -1; // Table does not exist in any handler DBUG_ENTER("ha_discover"); DBUG_PRINT("enter", ("db: %s, name: %s", db, name)); #ifdef HAVE_NDBCLUSTER_DB diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 0aa2f1ce4b8..d6ef08b8a7c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1376,8 +1376,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, */ if (discover_retry_count++ != 0) goto err; - if (ha_table_exists_in_engine(thd, db, name) && - ha_create_table_from_engine(thd, db, name)) + if (ha_create_table_from_engine(thd, db, name) > 0) { /* Give right error message */ thd->clear_error(); From 1f86e13cbb558fa93bc5da7b731e4bf3b013dfd4 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Jun 2005 15:58:17 +0200 Subject: [PATCH 005/216] BUG#10927 mysqldump: Can't reload dump with view that consist of other view - Create a small dummy table that will take care of the problem of creating a view dependent of another view which hasn't yet been created. client/mysqldump.c: Create a dummy table for the view. ie. a table which has the same columns as the view should have. This table is dropped just before the view is created. The table is used to handle the case where a view references another view, which hasn't yet been created(during the load of the dump). mysql-test/r/mysqldump.result: Add tests for bug#10927 mysql-test/t/mysqldump.test: Add tests for bug#10927 --- client/mysqldump.c | 50 ++++++++++++++++++++++++++++++++++- mysql-test/r/mysqldump.result | 33 ++++++++++++++++++++++- mysql-test/t/mysqldump.test | 35 +++++++++++++++++++++++- 3 files changed, 115 insertions(+), 3 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 907b6233590..6b7923fcd93 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1212,7 +1212,54 @@ static uint get_table_structure(char *table, char *db) if (strcmp(field->name, "View") == 0) { if (verbose) - fprintf(stderr, "-- It's a view, skipped\n"); + fprintf(stderr, "-- It's a view, create dummy table for view\n"); + + mysql_free_result(tableRes); + + /* Create a dummy table for the view. ie. a table which has the + same columns as the view should have. This table is dropped + just before the view is created. The table is used to handle the + case where a view references another view, which hasn't yet been + created(during the load of the dump). BUG#10927 */ + + /* Create temp table by selecting from the view */ + my_snprintf(query_buff, sizeof(query_buff), + "create temporary table %s select * from %s where 1=0", + result_table, result_table); + if (mysql_query_with_error_report(sock, 0, query_buff)) + { + safe_exit(EX_MYSQLERR); + DBUG_RETURN(0); + } + + /* Get CREATE statement for the temp table */ + my_snprintf(query_buff, sizeof(query_buff), "show create table %s", + result_table); + if (mysql_query_with_error_report(sock, 0, query_buff)) + { + safe_exit(EX_MYSQLERR); + DBUG_RETURN(0); + } + tableRes= mysql_store_result(sock); + row= mysql_fetch_row(tableRes); + + if (opt_drop) + fprintf(sql_file, "DROP VIEW IF EXISTS %s;\n",opt_quoted_table); + + /* Print CREATE statement but remove TEMPORARY */ + fprintf(sql_file, "CREATE %s;\n", row[1]+17); + check_io(sql_file); + + mysql_free_result(tableRes); + + /* Drop the temp table */ + my_snprintf(buff, sizeof(buff), + "DROP TEMPORARY TABLE %s", result_table); + if (mysql_query_with_error_report(sock, 0, buff)) + { + safe_exit(EX_MYSQLERR); + DBUG_RETURN(0); + } was_views= 1; DBUG_RETURN(0); } @@ -2752,6 +2799,7 @@ static my_bool get_view_structure(char *table, char* db) } if (opt_drop) { + fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n", opt_quoted_table); fprintf(sql_file, "DROP VIEW IF EXISTS %s;\n", opt_quoted_table); check_io(sql_file); } diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index f73c9b223fd..46f13439a24 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1,6 +1,6 @@ DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa; drop database if exists mysqldump_test_db; -drop view if exists v1; +drop view if exists v1, v2, v3; CREATE TABLE t1(a int); INSERT INTO t1 VALUES (1), (2); @@ -379,6 +379,11 @@ UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; DROP TABLE IF EXISTS `v1`; DROP VIEW IF EXISTS `v1`; +CREATE TABLE `v1` ( + `a` bigint(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS `v1`; +DROP VIEW IF EXISTS `v1`; CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` from `test`.`t1`; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -1422,3 +1427,29 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +create table t1(a int, b int, c varchar(30)); +insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); +create view v3 as +select * from t1; +create view v1 as +select * from v3 where b in (1, 2, 3, 4, 5, 6, 7); +create view v2 as +select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; +drop view v1, v2, v3; +drop table t1; +show full tables; +Tables_in_test Table_type +t1 BASE TABLE +v1 VIEW +v2 VIEW +v3 VIEW +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`v3`.`a` AS `a`,`test`.`v3`.`b` AS `b`,`test`.`v3`.`c` AS `c` from `test`.`v3` where (`test`.`v3`.`b` in (1,2,3,4,5,6,7)) +select * from v1; +a b c +1 2 one +2 4 two +3 6 three +drop view v1, v2, v3; +drop table t1; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 7a39fbdf5f6..414ded28434 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -4,7 +4,7 @@ --disable_warnings DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa; drop database if exists mysqldump_test_db; -drop view if exists v1; +drop view if exists v1, v2, v3; --enable_warnings # XML output @@ -563,3 +563,36 @@ CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); --exec $MYSQL_DUMP --add-drop-database --skip-comments --databases test DROP TABLE t1; + + +# +# Bug #10927 mysqldump: Can't reload dump with view that consist of other view +# + +create table t1(a int, b int, c varchar(30)); + +insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); + +create view v3 as +select * from t1; + +create view v1 as +select * from v3 where b in (1, 2, 3, 4, 5, 6, 7); + +create view v2 as +select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; + +--exec $MYSQL_DUMP test > var/tmp/bug10927.sql +drop view v1, v2, v3; +drop table t1; +--exec $MYSQL test < var/tmp/bug10927.sql + +# Without dropping the original tables in between +--exec $MYSQL_DUMP test > var/tmp/bug10927.sql +--exec $MYSQL test < var/tmp/bug10927.sql +show full tables; +show create view v1; +select * from v1; + +drop view v1, v2, v3; +drop table t1; From 54deb826592595d831367ba9577fc391d4153a4d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jun 2005 15:08:57 +0300 Subject: [PATCH 006/216] trx0undo.c: Apply manually Jan's patch to remove 64-Windows compiler warnings that were reported by Georg Richter innobase/trx/trx0undo.c: Apply manually Jan's patch to remove 64-Windows compiler warnings that were reported by Georg Richter --- innobase/trx/trx0undo.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/innobase/trx/trx0undo.c b/innobase/trx/trx0undo.c index bb314dd35e9..a519722aac7 100644 --- a/innobase/trx/trx0undo.c +++ b/innobase/trx/trx0undo.c @@ -559,14 +559,14 @@ trx_undo_write_xid( XID* xid, /* in: X/Open XA Transaction Identification */ mtr_t* mtr) /* in: mtr */ { - mlog_write_ulint(log_hdr + TRX_UNDO_XA_FORMAT, xid->formatID, - MLOG_4BYTES, mtr); + mlog_write_ulint(log_hdr + TRX_UNDO_XA_FORMAT, + (ulint)xid->formatID, MLOG_4BYTES, mtr); - mlog_write_ulint(log_hdr + TRX_UNDO_XA_TRID_LEN, xid->gtrid_length, - MLOG_4BYTES, mtr); + mlog_write_ulint(log_hdr + TRX_UNDO_XA_TRID_LEN, + (ulint)xid->gtrid_length, MLOG_4BYTES, mtr); - mlog_write_ulint(log_hdr + TRX_UNDO_XA_BQUAL_LEN, xid->bqual_length, - MLOG_4BYTES, mtr); + mlog_write_ulint(log_hdr + TRX_UNDO_XA_BQUAL_LEN, + (ulint)xid->bqual_length, MLOG_4BYTES, mtr); mlog_write_string(log_hdr + TRX_UNDO_XA_XID, xid->data, XIDDATASIZE, mtr); @@ -581,18 +581,14 @@ trx_undo_read_xid( trx_ulogf_t* log_hdr,/* in: undo log header */ XID* xid) /* out: X/Open XA Transaction Identification */ { - ulint i; - - xid->formatID = mach_read_from_4(log_hdr + TRX_UNDO_XA_FORMAT); + xid->formatID = (long)mach_read_from_4(log_hdr + TRX_UNDO_XA_FORMAT); - xid->gtrid_length = mach_read_from_4(log_hdr + TRX_UNDO_XA_TRID_LEN); + xid->gtrid_length = + (long)mach_read_from_4(log_hdr + TRX_UNDO_XA_TRID_LEN); + xid->bqual_length = + (long)mach_read_from_4(log_hdr + TRX_UNDO_XA_BQUAL_LEN); - xid->bqual_length = mach_read_from_4(log_hdr + TRX_UNDO_XA_BQUAL_LEN); - - for (i = 0; i < XIDDATASIZE; i++) { - xid->data[i] = (char)mach_read_from_1(log_hdr + - TRX_UNDO_XA_XID + i); - } + memcpy(xid->data, log_hdr + TRX_UNDO_XA_XID, XIDDATASIZE); } /******************************************************************* From 2e0ac6d642a0fb328ad80c21c2c310166cab9452 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 17 Jun 2005 18:07:46 +0200 Subject: [PATCH 007/216] BUG#10589: des_encrypt functionality always return NULL - Push warnings if des_encrypt or des_descrypt function fails because of out of resources or wrong params. - Push warning if des_encrypt or des_decrypt function is used when server is missing support for openssl. - Add test func_encrypt_nossl that is tun when the server is missing support for openssl. mysql-test/r/func_encrypt.result: Add tests for use of des_* function with invalid parameters mysql-test/t/func_encrypt.test: Add tests for use of des_* function with invalid parameters sql/item_strfunc.cc: Push warning if invalid paremeters are used Push warning if out of resources Push warning if user tries to use des_* function when the server has been compiled without support for openssl. --- mysql-test/include/not_openssl.inc | 4 ++ mysql-test/r/func_encrypt.result | 56 ++++++++++++++++ mysql-test/r/func_encrypt_nossl.result | 93 ++++++++++++++++++++++++++ mysql-test/r/not_openssl.require | 2 + mysql-test/t/func_encrypt.test | 16 +++++ mysql-test/t/func_encrypt_nossl.test | 36 ++++++++++ sql/item_strfunc.cc | 25 ++++++- 7 files changed, 229 insertions(+), 3 deletions(-) create mode 100644 mysql-test/include/not_openssl.inc create mode 100644 mysql-test/r/func_encrypt_nossl.result create mode 100644 mysql-test/r/not_openssl.require create mode 100644 mysql-test/t/func_encrypt_nossl.test diff --git a/mysql-test/include/not_openssl.inc b/mysql-test/include/not_openssl.inc new file mode 100644 index 00000000000..afe2ed37c28 --- /dev/null +++ b/mysql-test/include/not_openssl.inc @@ -0,0 +1,4 @@ +-- require r/not_openssl.require +disable_query_log; +show variables like "have_openssl"; +enable_query_log; diff --git a/mysql-test/r/func_encrypt.result b/mysql-test/r/func_encrypt.result index d32e67fe7d5..992d01c66cd 100644 --- a/mysql-test/r/func_encrypt.result +++ b/mysql-test/r/func_encrypt.result @@ -120,6 +120,60 @@ hello select des_decrypt(des_encrypt("hello",4),'password4'); des_decrypt(des_encrypt("hello",4),'password4') hello +select des_encrypt("hello",10); +des_encrypt("hello",10) +NULL +Warnings: +Error 1108 Incorrect parameters to procedure 'des_encrypt' +select des_encrypt(NULL); +des_encrypt(NULL) +NULL +Warnings: +Error 1108 Incorrect parameters to procedure 'des_encrypt' +select des_encrypt(NULL, 10); +des_encrypt(NULL, 10) +NULL +Warnings: +Error 1108 Incorrect parameters to procedure 'des_encrypt' +select des_encrypt(NULL, NULL); +des_encrypt(NULL, NULL) +NULL +Warnings: +Error 1108 Incorrect parameters to procedure 'des_encrypt' +select des_encrypt(10, NULL); +des_encrypt(10, NULL) +NULL +Warnings: +Error 1108 Incorrect parameters to procedure 'des_encrypt' +select des_encrypt("hello", NULL); +des_encrypt("hello", NULL) +NULL +Warnings: +Error 1108 Incorrect parameters to procedure 'des_encrypt' +select des_decrypt("hello",10); +des_decrypt("hello",10) +hello +select des_decrypt(NULL); +des_decrypt(NULL) +NULL +Warnings: +Error 1108 Incorrect parameters to procedure 'des_decrypt' +select des_decrypt(NULL, 10); +des_decrypt(NULL, 10) +NULL +Warnings: +Error 1108 Incorrect parameters to procedure 'des_decrypt' +select des_decrypt(NULL, NULL); +des_decrypt(NULL, NULL) +NULL +Warnings: +Error 1108 Incorrect parameters to procedure 'des_decrypt' +select des_decrypt(10, NULL); +des_decrypt(10, NULL) +10 +select des_decrypt("hello", NULL); +des_decrypt("hello", NULL) +hello SET @a=des_decrypt(des_encrypt("hello")); flush des_key_file; select @a = des_decrypt(des_encrypt("hello")); @@ -134,6 +188,8 @@ NULL select hex(des_decrypt(des_encrypt("hello","hidden"))); hex(des_decrypt(des_encrypt("hello","hidden"))) NULL +Warnings: +Error 1108 Incorrect parameters to procedure 'des_decrypt' explain extended select des_decrypt(des_encrypt("hello",4),'password2'), des_decrypt(des_encrypt("hello","hidden")); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used diff --git a/mysql-test/r/func_encrypt_nossl.result b/mysql-test/r/func_encrypt_nossl.result new file mode 100644 index 00000000000..fea752f4a4a --- /dev/null +++ b/mysql-test/r/func_encrypt_nossl.result @@ -0,0 +1,93 @@ +select des_encrypt("test", 'akeystr'); +des_encrypt("test", 'akeystr') +NULL +Warnings: +Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select des_encrypt("test", 1); +des_encrypt("test", 1) +NULL +Warnings: +Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select des_encrypt("test", 9); +des_encrypt("test", 9) +NULL +Warnings: +Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select des_encrypt("test", 100); +des_encrypt("test", 100) +NULL +Warnings: +Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select des_encrypt("test", NULL); +des_encrypt("test", NULL) +NULL +Warnings: +Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select des_decrypt("test", 'anotherkeystr'); +des_decrypt("test", 'anotherkeystr') +NULL +Warnings: +Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select des_decrypt(1, 1); +des_decrypt(1, 1) +NULL +Warnings: +Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select des_decrypt(des_encrypt("test", 'thekey')); +des_decrypt(des_encrypt("test", 'thekey')) +NULL +Warnings: +Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select hex(des_encrypt("hello")),des_decrypt(des_encrypt("hello")); +hex(des_encrypt("hello")) des_decrypt(des_encrypt("hello")) +NULL NULL +Warnings: +Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select des_decrypt(des_encrypt("hello",4)); +des_decrypt(des_encrypt("hello",4)) +NULL +Warnings: +Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select des_decrypt(des_encrypt("hello",'test'),'test'); +des_decrypt(des_encrypt("hello",'test'),'test') +NULL +Warnings: +Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select hex(des_encrypt("hello")),hex(des_encrypt("hello",5)),hex(des_encrypt("hello",'default_password')); +hex(des_encrypt("hello")) hex(des_encrypt("hello",5)) hex(des_encrypt("hello",'default_password')) +NULL NULL NULL +Warnings: +Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select des_decrypt(des_encrypt("hello"),'default_password'); +des_decrypt(des_encrypt("hello"),'default_password') +NULL +Warnings: +Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select des_decrypt(des_encrypt("hello",4),'password4'); +des_decrypt(des_encrypt("hello",4),'password4') +NULL +Warnings: +Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +SET @a=des_decrypt(des_encrypt("hello")); +Warnings: +Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +flush des_key_file; +select @a = des_decrypt(des_encrypt("hello")); +@a = des_decrypt(des_encrypt("hello")) +NULL +select hex("hello"); +hex("hello") +68656C6C6F +select hex(des_decrypt(des_encrypt("hello",4),'password2')); +hex(des_decrypt(des_encrypt("hello",4),'password2')) +NULL +Warnings: +Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select hex(des_decrypt(des_encrypt("hello","hidden"))); +hex(des_decrypt(des_encrypt("hello","hidden"))) +NULL +Warnings: +Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working diff --git a/mysql-test/r/not_openssl.require b/mysql-test/r/not_openssl.require new file mode 100644 index 00000000000..2b5e423999c --- /dev/null +++ b/mysql-test/r/not_openssl.require @@ -0,0 +1,2 @@ +Variable_name Value +have_openssl NO diff --git a/mysql-test/t/func_encrypt.test b/mysql-test/t/func_encrypt.test index fe81a814dda..52aca7f9dcb 100644 --- a/mysql-test/t/func_encrypt.test +++ b/mysql-test/t/func_encrypt.test @@ -59,6 +59,22 @@ select hex(des_encrypt("hello")),hex(des_encrypt("hello",5)),hex(des_encrypt("he select des_decrypt(des_encrypt("hello"),'default_password'); select des_decrypt(des_encrypt("hello",4),'password4'); +# Test use of invalid parameters +select des_encrypt("hello",10); +select des_encrypt(NULL); +select des_encrypt(NULL, 10); +select des_encrypt(NULL, NULL); +select des_encrypt(10, NULL); +select des_encrypt("hello", NULL); + +select des_decrypt("hello",10); +select des_decrypt(NULL); +select des_decrypt(NULL, 10); +select des_decrypt(NULL, NULL); +select des_decrypt(10, NULL); +select des_decrypt("hello", NULL); + + # Test flush SET @a=des_decrypt(des_encrypt("hello")); flush des_key_file; diff --git a/mysql-test/t/func_encrypt_nossl.test b/mysql-test/t/func_encrypt_nossl.test new file mode 100644 index 00000000000..0e9d93f5968 --- /dev/null +++ b/mysql-test/t/func_encrypt_nossl.test @@ -0,0 +1,36 @@ +-- source include/not_openssl.inc + +# +# Test output from des_encrypt and des_decrypt when server is +# compiled without openssl suuport +# +select des_encrypt("test", 'akeystr'); +select des_encrypt("test", 1); +select des_encrypt("test", 9); +select des_encrypt("test", 100); +select des_encrypt("test", NULL); +select des_decrypt("test", 'anotherkeystr'); +select des_decrypt(1, 1); +select des_decrypt(des_encrypt("test", 'thekey')); + + +# +# Test default keys +# +select hex(des_encrypt("hello")),des_decrypt(des_encrypt("hello")); +select des_decrypt(des_encrypt("hello",4)); +select des_decrypt(des_encrypt("hello",'test'),'test'); +select hex(des_encrypt("hello")),hex(des_encrypt("hello",5)),hex(des_encrypt("hello",'default_password')); +select des_decrypt(des_encrypt("hello"),'default_password'); +select des_decrypt(des_encrypt("hello",4),'password4'); + +# Test flush +SET @a=des_decrypt(des_encrypt("hello")); +flush des_key_file; +select @a = des_decrypt(des_encrypt("hello")); + +# Test usage of wrong password +select hex("hello"); +select hex(des_decrypt(des_encrypt("hello",4),'password2')); +select hex(des_decrypt(des_encrypt("hello","hidden"))); + diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 5ca5caf6bdf..ceb925be4d2 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -373,6 +373,7 @@ String *Item_func_des_encrypt::val_str(String *str) { DBUG_ASSERT(fixed == 1); #ifdef HAVE_OPENSSL + uint code= ER_WRONG_PARAMETERS_TO_PROCEDURE; DES_cblock ivec; struct st_des_keyblock keyblock; struct st_des_keyschedule keyschedule; @@ -381,7 +382,7 @@ String *Item_func_des_encrypt::val_str(String *str) String *res= args[0]->val_str(str); if ((null_value=args[0]->null_value)) - return 0; + goto error; if ((res_length=res->length()) == 0) return &my_empty_string; @@ -429,6 +430,7 @@ String *Item_func_des_encrypt::val_str(String *str) tail= (8-(res_length) % 8); // 1..8 marking extra length res_length+=tail; + code= ER_OUT_OF_RESOURCES; if (tail && res->append(append_str, tail) || tmp_value.alloc(res_length+1)) goto error; (*res)[res_length-1]=tail; // save extra length @@ -446,6 +448,13 @@ String *Item_func_des_encrypt::val_str(String *str) return &tmp_value; error: + push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR, + code, ER(code), + "des_encrypt"); +#else + push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED), + "des_encrypt","--with-openssl"); #endif /* HAVE_OPENSSL */ null_value=1; return 0; @@ -456,6 +465,7 @@ String *Item_func_des_decrypt::val_str(String *str) { DBUG_ASSERT(fixed == 1); #ifdef HAVE_OPENSSL + uint code= ER_WRONG_PARAMETERS_TO_PROCEDURE; DES_key_schedule ks1, ks2, ks3; DES_cblock ivec; struct st_des_keyblock keyblock; @@ -464,7 +474,7 @@ String *Item_func_des_decrypt::val_str(String *str) uint length=res->length(),tail; if ((null_value=args[0]->null_value)) - return 0; + goto error; length=res->length(); if (length < 9 || (length % 8) != 1 || !((*res)[0] & 128)) return res; // Skip decryption if not encrypted @@ -495,6 +505,7 @@ String *Item_func_des_decrypt::val_str(String *str) DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2); DES_set_key_unchecked(&keyblock.key3,&keyschedule.ks3); } + code= ER_OUT_OF_RESOURCES; if (tmp_value.alloc(length-1)) goto error; @@ -508,11 +519,19 @@ String *Item_func_des_decrypt::val_str(String *str) &ivec, FALSE); /* Restore old length of key */ if ((tail=(uint) (uchar) tmp_value[length-2]) > 8) - goto error; // Wrong key + goto wrong_key; // Wrong key tmp_value.length(length-1-tail); return &tmp_value; error: + push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR, + code, ER(code), + "des_decrypt"); +wrong_key: +#else + push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED), + "des_decrypt","--with-openssl"); #endif /* HAVE_OPENSSL */ null_value=1; return 0; From 94d1d88658e5aa75d999c308ac464014f20a3d02 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 18 Jun 2005 01:55:42 +0200 Subject: [PATCH 008/216] Clean up warnings and build problems on Windows. (Bug #11045) VC++Files/sql/mysqld.dsp: Link debug server against debug yassl sql/examples/ha_archive.cc: Fix type for variables used to store number of rows Add cast when reading current position sql/examples/ha_archive.h: Fix variables used to store rows to ha_rows sql/ha_federated.cc: Remove unused variables, fix type of variable used to store query id sql/item_strfunc.cc: Remove unused variables sql/sql_acl.cc: Remove unused variables sql/sql_lex.cc: Add casts to fix type used for counting number of rows sql/sql_lex.h: Fix size of options to be ulong again sql/sql_insert.cc: Fix type of query id value sql/sql_union.cc: Cast value for number of rows to ha_rows sql/sql_yacc.yy: Remove unused variable sql/table.cc: Add casts for handling key_part lengths --- VC++Files/sql/mysqld.dsp | 2 +- sql/examples/ha_archive.cc | 10 +++++----- sql/examples/ha_archive.h | 6 +++--- sql/ha_federated.cc | 9 ++------- sql/item_strfunc.cc | 1 - sql/sql_acl.cc | 2 -- sql/sql_insert.cc | 2 +- sql/sql_lex.cc | 9 +++++---- sql/sql_lex.h | 2 +- sql/sql_union.cc | 4 +++- sql/sql_yacc.yy | 2 +- sql/table.cc | 5 +++-- 12 files changed, 25 insertions(+), 29 deletions(-) diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index 4b49f5290c7..e8f24b300cb 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -84,7 +84,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\vio.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\bdb.lib ..\lib_debug\innodb.lib ..\extra\yassl\Release\yassl.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqld-debug.exe" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\vio.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\bdb.lib ..\lib_debug\innodb.lib ..\extra\yassl\Debug\yassl.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"../client_debug/mysqld-debug.exe" /pdbtype:sept !ELSEIF "$(CFG)" == "mysqld - Win32 nt" diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc index 93cedcbf251..3bf1441852f 100644 --- a/sql/examples/ha_archive.cc +++ b/sql/examples/ha_archive.cc @@ -259,7 +259,7 @@ error: This method reads the header of a meta file and returns whether or not it was successful. *rows will contain the current number of rows in the data file upon success. */ -int ha_archive::read_meta_file(File meta_file, ulonglong *rows) +int ha_archive::read_meta_file(File meta_file, ha_rows *rows) { uchar meta_buffer[META_BUFFER_SIZE]; ulonglong check_point; @@ -273,7 +273,7 @@ int ha_archive::read_meta_file(File meta_file, ulonglong *rows) /* Parse out the meta data, we ignore version at the moment */ - *rows= uint8korr(meta_buffer + 2); + *rows= (ha_rows)uint8korr(meta_buffer + 2); check_point= uint8korr(meta_buffer + 10); DBUG_PRINT("ha_archive::read_meta_file", ("Check %d", (uint)meta_buffer[0])); @@ -296,7 +296,7 @@ int ha_archive::read_meta_file(File meta_file, ulonglong *rows) By setting dirty you say whether or not the file represents the actual state of the data file. Upon ::open() we set to dirty, and upon ::close() we set to clean. */ -int ha_archive::write_meta_file(File meta_file, ulonglong rows, bool dirty) +int ha_archive::write_meta_file(File meta_file, ha_rows rows, bool dirty) { uchar meta_buffer[META_BUFFER_SIZE]; ulonglong check_point= 0; //Reserved for the future @@ -787,7 +787,7 @@ int ha_archive::rnd_pos(byte * buf, byte *pos) DBUG_ENTER("ha_archive::rnd_pos"); statistic_increment(table->in_use->status_var.ha_read_rnd_next_count, &LOCK_status); - current_position= my_get_ptr(pos, ref_length); + current_position= (z_off_t)my_get_ptr(pos, ref_length); (void)gzseek(archive, current_position, SEEK_SET); DBUG_RETURN(get_row(archive, buf)); @@ -801,7 +801,7 @@ int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt) { int rc; byte *buf; - ulonglong rows_recorded= 0; + ha_rows rows_recorded= 0; gzFile rebuild_file; // Archive file we are working with File meta_file; // Meta file we use char data_file_name[FN_REFLEN]; diff --git a/sql/examples/ha_archive.h b/sql/examples/ha_archive.h index 2f310d8c69b..454d253abe5 100644 --- a/sql/examples/ha_archive.h +++ b/sql/examples/ha_archive.h @@ -36,7 +36,7 @@ typedef struct st_archive_share { gzFile archive_write; /* Archive file we are working with */ bool dirty; /* Flag for if a flush should occur */ bool crashed; /* Meta file is crashed */ - ulonglong rows_recorded; /* Number of rows in tables */ + ha_rows rows_recorded; /* Number of rows in tables */ } ARCHIVE_SHARE; /* @@ -88,8 +88,8 @@ public: int rnd_next(byte *buf); int rnd_pos(byte * buf, byte *pos); int get_row(gzFile file_to_read, byte *buf); - int read_meta_file(File meta_file, ulonglong *rows); - int write_meta_file(File meta_file, ulonglong rows, bool dirty); + int read_meta_file(File meta_file, ha_rows *rows); + int write_meta_file(File meta_file, ha_rows rows, bool dirty); ARCHIVE_SHARE *get_share(const char *table_name, TABLE *table); int free_share(ARCHIVE_SHARE *share); bool auto_repair() const { return 1; } // For the moment we just do this diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 89210a2f3cd..bf6674cf5cd 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -842,7 +842,7 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) query.length(0); uint table_name_length, table_base_name_length; - char *tmp_table_name, *tmp_table_base_name, *table_base_name, *select_query; + char *tmp_table_name, *table_base_name, *select_query; /* share->table_name has the file location - we want the table's name! */ table_base_name= (char*) table->s->table_name; @@ -963,7 +963,6 @@ const char **ha_federated::bas_ext() const int ha_federated::open(const char *name, int mode, uint test_if_locked) { - int rc; DBUG_ENTER("ha_federated::open"); if (!(share= get_share(name, table))) @@ -1076,7 +1075,7 @@ int ha_federated::write_row(byte *buf) { uint x= 0, num_fields= 0; Field **field; - ulong current_query_id= 1; + query_id_it current_query_id= 1; ulong tmp_query_id= 1; uint all_fields_have_same_query_id= 1; @@ -1471,8 +1470,6 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key, __attribute__ ((unused))) { char index_value[IO_SIZE]; - char key_value[IO_SIZE]; - char test_value[IO_SIZE]; String index_string(index_value, sizeof(index_value), &my_charset_bin); index_string.length(0); uint keylen; @@ -1538,7 +1535,6 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key, /* Initialized at each key walk (called multiple times unlike rnd_init()) */ int ha_federated::index_init(uint keynr) { - int error; DBUG_ENTER("ha_federated::index_init"); DBUG_PRINT("info", ("table: '%s' key: %d", table->s->table_name, keynr)); @@ -1570,7 +1566,6 @@ int ha_federated::index_next(byte *buf) int ha_federated::rnd_init(bool scan) { DBUG_ENTER("ha_federated::rnd_init"); - int num_fields, rows; /* This 'scan' flag is incredibly important for this handler to work diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 539bed58e66..88f91b3f457 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -446,7 +446,6 @@ String *Item_func_des_decrypt::val_str(String *str) { DBUG_ASSERT(fixed == 1); #ifdef HAVE_OPENSSL - DES_key_schedule ks1, ks2, ks3; DES_cblock ivec; struct st_des_keyblock keyblock; struct st_des_keyschedule keyschedule; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 04da0dd5eb5..c9f727f47d4 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2476,7 +2476,6 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, int old_row_exists= 1; int error=0; ulong store_proc_rights; - byte *key; DBUG_ENTER("replace_routine_table"); if (!initialized) @@ -3216,7 +3215,6 @@ my_bool grant_init(THD *org_thd) do { GRANT_NAME *mem_check; - longlong proc_type; HASH *hash; if (!(mem_check=new GRANT_NAME(p_table))) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 5ca75554c6f..750fe373b41 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -192,7 +192,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list, List &update_fields) { TABLE *table= insert_table_list->table; - ulong timestamp_query_id; + query_id_it timestamp_query_id; LINT_INIT(timestamp_query_id); /* diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 08f0c3badf7..43a7e06724d 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1755,12 +1755,13 @@ bool st_lex::need_correct_ident() void st_select_lex_unit::set_limit(SELECT_LEX *sl) { - ulonglong select_limit_val; + ha_rows select_limit_val; DBUG_ASSERT(! thd->current_arena->is_stmt_prepare()); - select_limit_val= sl->select_limit ? sl->select_limit->val_uint() : - HA_POS_ERROR; - offset_limit_cnt= sl->offset_limit ? sl->offset_limit->val_uint() : ULL(0); + select_limit_val= (ha_rows)(sl->select_limit ? sl->select_limit->val_uint() : + HA_POS_ERROR); + offset_limit_cnt= (ha_rows)(sl->offset_limit ? sl->offset_limit->val_uint() : + ULL(0)); select_limit_cnt= select_limit_val + offset_limit_cnt; if (select_limit_cnt < select_limit_val) select_limit_cnt= HA_POS_ERROR; // no limit diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 052873640c6..1d3289e4084 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -304,7 +304,7 @@ protected: *link_next, **link_prev; /* list of whole SELECT_LEX */ public: - ulonglong options; + ulong options; /* result of this query can't be cached, bit field, can be : UNCACHEABLE_DEPENDENT diff --git a/sql/sql_union.cc b/sql/sql_union.cc index f59d7fffe85..3d3acf40f37 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -448,7 +448,9 @@ bool st_select_lex_unit::exec() table->no_keyread=1; } res= sl->join->error; - offset_limit_cnt= sl->offset_limit ? sl->offset_limit->val_uint() : 0; + offset_limit_cnt= (ha_rows)(sl->offset_limit ? + sl->offset_limit->val_uint() : + 0); if (!res) { examined_rows+= thd->examined_row_count; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 00ef8b581f1..8918cd45406 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5641,7 +5641,7 @@ delete_limit_clause: ulong_num: NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); } - | HEX_NUM { int error; $$= (ulong) strtol($1.str, (char**) 0, 16); } + | HEX_NUM { $$= (ulong) strtol($1.str, (char**) 0, 16); } | LONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); } | ULONGLONG_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); } | DECIMAL_NUM { int error; $$= (ulong) my_strtoll10($1.str, (char**) 0, &error); } diff --git a/sql/table.cc b/sql/table.cc index f7dc0446a77..e591330ed01 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -745,8 +745,9 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, error. */ keyinfo->key_length-= (key_part->length - field->key_length()); - key_part->store_length-= (key_part->length - field->key_length()); - key_part->length= field->key_length(); + key_part->store_length-= (uint16)(key_part->length - + field->key_length()); + key_part->length= (uint16)field->key_length(); sql_print_error("Found wrong key definition in %s; Please do \"ALTER TABLE '%s' FORCE \" to fix it!", name, share->table_name); push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_CRASHED_ON_USAGE, From 2e70ec89f96c11001d0be2c5e7dbd527c01defeb Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 18 Jun 2005 02:03:49 +0200 Subject: [PATCH 009/216] Fix another .dsp trying to link debug binary against release version of yassl VC++Files/tests/mysql_client_test.dsp: Link debug version against debug yassl library --- VC++Files/tests/mysql_client_test.dsp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VC++Files/tests/mysql_client_test.dsp b/VC++Files/tests/mysql_client_test.dsp index 1d780ca5e0c..7d78be6cebd 100644 --- a/VC++Files/tests/mysql_client_test.dsp +++ b/VC++Files/tests/mysql_client_test.dsp @@ -51,8 +51,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib ..\extra\yassl\Release\yassl.lib /nologo /out:"..\mysql_client_test.exe" /incremental:yes /libpath:"..\lib_debug\" /debug /pdb:".\Debug\mysql_client_test.pdb" /pdbtype:sept /map:".\Debug\mysql_client_test.map" /subsystem:console -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib ..\extra\yassl\Release\yassl.lib /nologo /out:"..\mysql_client_test.exe" /incremental:yes /libpath:"..\lib_debug\" /debug /pdb:".\Debug\mysql_client_test.pdb" /pdbtype:sept /map:".\Debug\mysql_client_test.map" /subsystem:console +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib ..\extra\yassl\Debug\yassl.lib /nologo /out:"..\mysql_client_test.exe" /incremental:yes /libpath:"..\lib_debug\" /debug /pdb:".\Debug\mysql_client_test.pdb" /pdbtype:sept /map:".\Debug\mysql_client_test.map" /subsystem:console +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib ..\extra\yassl\Debug\yassl.lib /nologo /out:"..\mysql_client_test.exe" /incremental:yes /libpath:"..\lib_debug\" /debug /pdb:".\Debug\mysql_client_test.pdb" /pdbtype:sept /map:".\Debug\mysql_client_test.map" /subsystem:console !ELSEIF "$(CFG)" == "mysql_client_test - Win32 Release" From 93f7607de0f65317c7cc84b58d625bfc9f607643 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 18 Jun 2005 03:02:27 +0200 Subject: [PATCH 010/216] Fix information_schema test on Windows. (Bug #10844) mysql-test/mysql_test_run_new.c: Add --log-bin-trust-routine-creators mysql-test/mysql-test-run.pl: Add --log-bin-trust-routine-creators mysql-test/t/information_schema.test: Fix use of users to cope with lack of grant to %@localhost to test.* mysql-test/r/information_schema.result: Update results --- mysql-test/mysql-test-run.pl | 1 + mysql-test/mysql_test_run_new.c | 1 + mysql-test/r/information_schema.result | 3 ++- mysql-test/t/information_schema.test | 9 +++++---- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 5f321757492..db8897e54b3 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1706,6 +1706,7 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--basedir=%s", $prefix, $path_my_basedir); mtr_add_arg($args, "%s--character-sets-dir=%s", $prefix, $path_charsetsdir); mtr_add_arg($args, "%s--core", $prefix); + mtr_add_arg($args, "%s--log-bin-trust-routine-creators", $prefix); mtr_add_arg($args, "%s--default-character-set=latin1", $prefix); mtr_add_arg($args, "%s--language=%s", $prefix, $path_language); mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix); diff --git a/mysql-test/mysql_test_run_new.c b/mysql-test/mysql_test_run_new.c index b8e7f1ba2b7..b23b7ceb6a1 100644 --- a/mysql-test/mysql_test_run_new.c +++ b/mysql-test/mysql_test_run_new.c @@ -486,6 +486,7 @@ void start_master() #endif add_arg(&al, "--local-infile"); add_arg(&al, "--core"); + add_arg(&al, "--log-bin-trust-routine-creators"); add_arg(&al, "--datadir=%s", master_dir); #ifndef __WIN__ add_arg(&al, "--pid-file=%s", master_pid); diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index c6090bc663d..41c2e32e5ae 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -735,7 +735,7 @@ x_real NULL NULL x_float NULL NULL x_double_precision NULL NULL drop table t1; -create user mysqltest_4@localhost; +grant select on test.* to mysqltest_4@localhost; SELECT TABLE_NAME, COLUMN_NAME, PRIVILEGES FROM INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME='TABLE_NAME'; TABLE_NAME COLUMN_NAME PRIVILEGES @@ -748,6 +748,7 @@ COLUMN_PRIVILEGES TABLE_NAME select TABLE_CONSTRAINTS TABLE_NAME select KEY_COLUMN_USAGE TABLE_NAME select delete from mysql.user where user='mysqltest_4'; +delete from mysql.db where user='mysqltest_4'; flush privileges; SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA; table_schema count(*) diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index e03bea5899a..4b288879672 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -483,13 +483,14 @@ drop table t1; # Bug#10261 INFORMATION_SCHEMA.COLUMNS, incomplete result for non root user # -create user mysqltest_4@localhost; +grant select on test.* to mysqltest_4@localhost; connect (user4,localhost,mysqltest_4,,); connection user4; SELECT TABLE_NAME, COLUMN_NAME, PRIVILEGES FROM INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME='TABLE_NAME'; connection default; delete from mysql.user where user='mysqltest_4'; +delete from mysql.db where user='mysqltest_4'; flush privileges; # @@ -510,9 +511,9 @@ grant select on mysqltest.t2 to user2@localhost; grant select on mysqltest.* to user3@localhost; grant select on *.* to user4@localhost; -connect (con1,localhost,user1,,); -connect (con2,localhost,user2,,); -connect (con3,localhost,user3,,); +connect (con1,localhost,user1,,mysqltest); +connect (con2,localhost,user2,,mysqltest); +connect (con3,localhost,user3,,mysqltest); connect (con4,localhost,user4,,); connection con1; select * from information_schema.column_privileges; From ef920b28793302a532b87b4babfc224bb732941e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jun 2005 11:43:38 +0200 Subject: [PATCH 011/216] Fix for BUG#10151: In Item_func_case::find_item don't assume that parameter str != &(this->str_value) mysql-test/r/case.result: Testcase for BUG#10151 mysql-test/t/case.test: Testcase for BUG#10151 --- mysql-test/r/case.result | 15 +++++++++++++++ mysql-test/t/case.test | 11 +++++++++++ sql/item_cmpfunc.cc | 4 +++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index 541560afd36..fb0bc19a67e 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -154,3 +154,18 @@ t1 CREATE TABLE `t1` ( `COALESCE('a' COLLATE latin1_bin,'b')` char(1) character set latin1 collate latin1_bin NOT NULL default '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; +SELECT 'case+union+test' +UNION +SELECT CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END; +case+union+test +case+union+test +nobug +SELECT CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END; +CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END +nobug +SELECT 'case+union+test' +UNION +SELECT CASE '1' WHEN '2' THEN 'BUG' ELSE 'nobug' END; +case+union+test +case+union+test +nobug diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index 87e456baba7..ac60d7298ce 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -107,3 +107,14 @@ explain extended SELECT COALESCE('a' COLLATE latin1_bin,'b'); SHOW CREATE TABLE t1; DROP TABLE t1; + +# Test for BUG#10151 +SELECT 'case+union+test' +UNION +SELECT CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END; + +SELECT CASE LOWER('1') WHEN LOWER('2') THEN 'BUG' ELSE 'nobug' END; + +SELECT 'case+union+test' +UNION +SELECT CASE '1' WHEN '2' THEN 'BUG' ELSE 'nobug' END; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 3098e5dc77e..f24638d1a93 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1174,6 +1174,8 @@ Item *Item_func_case::find_item(String *str) String *first_expr_str,*tmp; longlong first_expr_int; double first_expr_real; + char buff[MAX_FIELD_WIDTH]; + String buff_str(buff,sizeof(buff),default_charset()); /* These will be initialized later */ LINT_INIT(first_expr_str); @@ -1186,7 +1188,7 @@ Item *Item_func_case::find_item(String *str) { case STRING_RESULT: // We can't use 'str' here as this may be overwritten - if (!(first_expr_str= args[first_expr_num]->val_str(&str_value))) + if (!(first_expr_str= args[first_expr_num]->val_str(&buff_str))) return else_expr_num != -1 ? args[else_expr_num] : 0; // Impossible break; case INT_RESULT: From d2b52d1933455342623a0759f2591fcf3874f2c9 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jun 2005 12:09:00 +0200 Subject: [PATCH 012/216] bug#10466: Datatype "timestamp" displays "YYYYMMDDHHMMSS" irrespective of display sizes. - Print warning that says display width is not supported for datatype TIMESTAMP, if user tries to create a TIMESTAMP column with display width. - Use display width for TIMESTAMP only in type_timestamp test to make sure warning is displayed correctly. mysql-test/include/ps_create.inc: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/alias.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/func_date_add.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/func_str.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/func_time.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/group_by.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/innodb.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/ps.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/ps_1general.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/ps_2myisam.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/ps_3innodb.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/ps_4heap.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/ps_5merge.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/ps_6bdb.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/ps_7ndb.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/select.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/r/type_timestamp.result: When display width is used for a TIMESTAMP column a warning is printed that the display width will be ignored. mysql-test/r/update.result: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/t/alias.test: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/t/func_date_add.test: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/t/func_str.test: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/t/func_time.test: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/t/group_by.test: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/t/innodb.test: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/t/ps.test: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/t/ps_4heap.test: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/t/ps_5merge.test: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/t/select.test: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. mysql-test/t/update.test: Reove all uses of display width in for TIMESTAMP columns, except in the type_timestamp test. sql/share/errmsg.txt: Correct swedish error message sql/sql_parse.cc: Print warning if datatype is TIMESTAMP and display width is used. --- mysql-test/include/ps_create.inc | 2 +- mysql-test/r/alias.result | 2 +- mysql-test/r/func_date_add.result | 2 +- mysql-test/r/func_str.result | 2 +- mysql-test/r/func_time.result | 2 +- mysql-test/r/group_by.result | 2 +- mysql-test/r/innodb.result | 8 ++++---- mysql-test/r/ps.result | 2 +- mysql-test/r/ps_1general.result | 2 +- mysql-test/r/ps_2myisam.result | 2 +- mysql-test/r/ps_3innodb.result | 2 +- mysql-test/r/ps_4heap.result | 2 +- mysql-test/r/ps_5merge.result | 8 ++++---- mysql-test/r/ps_6bdb.result | 2 +- mysql-test/r/ps_7ndb.result | 2 +- mysql-test/r/select.result | 2 +- mysql-test/r/type_timestamp.result | 8 ++++++++ mysql-test/r/update.result | 4 ++-- mysql-test/t/alias.test | 2 +- mysql-test/t/func_date_add.test | 2 +- mysql-test/t/func_str.test | 2 +- mysql-test/t/func_time.test | 2 +- mysql-test/t/group_by.test | 2 +- mysql-test/t/innodb.test | 8 ++++---- mysql-test/t/ps.test | 2 +- mysql-test/t/ps_4heap.test | 2 +- mysql-test/t/ps_5merge.test | 4 ++-- mysql-test/t/select.test | 2 +- mysql-test/t/update.test | 4 ++-- sql/share/errmsg.txt | 2 +- sql/sql_parse.cc | 17 +++++++++++++++++ 31 files changed, 66 insertions(+), 41 deletions(-) diff --git a/mysql-test/include/ps_create.inc b/mysql-test/include/ps_create.inc index 306ed3f1cac..b2a6fc4b920 100644 --- a/mysql-test/include/ps_create.inc +++ b/mysql-test/include/ps_create.inc @@ -33,7 +33,7 @@ eval create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), - c13 date, c14 datetime, c15 timestamp(14), c16 time, + c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, diff --git a/mysql-test/r/alias.result b/mysql-test/r/alias.result index 587c21e9129..6ad4065d392 100644 --- a/mysql-test/r/alias.result +++ b/mysql-test/r/alias.result @@ -27,7 +27,7 @@ hdl_name varchar(30) default NULL, prov_hdl_nr int(11) NOT NULL default '0', auto_wirknetz varchar(50) default NULL, auto_billing varchar(50) default NULL, -touch timestamp(14) NOT NULL, +touch timestamp NOT NULL, kategorie varchar(50) default NULL, kundentyp varchar(20) NOT NULL default '', sammel_rech_msisdn varchar(30) NOT NULL default '', diff --git a/mysql-test/r/func_date_add.result b/mysql-test/r/func_date_add.result index f4091ff4c0e..50889943b56 100644 --- a/mysql-test/r/func_date_add.result +++ b/mysql-test/r/func_date_add.result @@ -4,7 +4,7 @@ visitor_id int(10) unsigned DEFAULT '0' NOT NULL, group_id int(10) unsigned DEFAULT '0' NOT NULL, hits int(10) unsigned DEFAULT '0' NOT NULL, sessions int(10) unsigned DEFAULT '0' NOT NULL, -ts timestamp(14), +ts timestamp, PRIMARY KEY (visitor_id,group_id) )/*! engine=MyISAM */; INSERT INTO t1 VALUES (465931136,7,2,2,20000318160952); diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 1c6a4393dfc..c39652bdc1b 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -264,7 +264,7 @@ category int(10) unsigned default NULL, program int(10) unsigned default NULL, bugdesc text, created datetime default NULL, -modified timestamp(14) NOT NULL, +modified timestamp NOT NULL, bugstatus int(10) unsigned default NULL, submitter int(10) unsigned default NULL ) ENGINE=MyISAM; diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index cb51da75368..63da5589c57 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -465,7 +465,7 @@ extract(MONTH FROM "0000-00-00") extract(MONTH FROM d) extract(MONTH FROM dt) ex drop table t1; CREATE TABLE t1 ( start datetime default NULL); INSERT INTO t1 VALUES ('2002-10-21 00:00:00'),('2002-10-28 00:00:00'),('2002-11-04 00:00:00'); -CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL); +CREATE TABLE t2 ( ctime1 timestamp NOT NULL, ctime2 timestamp NOT NULL); INSERT INTO t2 VALUES (20021029165106,20021105164731); CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL); INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31"); diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 937ed401f40..02002d58f7d 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -117,7 +117,7 @@ bug_file_loc text, bug_severity enum('blocker','critical','major','normal','minor','trivial','enhancement') DEFAULT 'blocker' NOT NULL, bug_status enum('','NEW','ASSIGNED','REOPENED','RESOLVED','VERIFIED','CLOSED') DEFAULT 'NEW' NOT NULL, creation_ts datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, -delta_ts timestamp(14), +delta_ts timestamp, short_desc mediumtext, long_desc mediumtext, op_sys enum('All','Windows 3.1','Windows 95','Windows 98','Windows NT','Windows 2000','Linux','other') DEFAULT 'All' NOT NULL, diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 31480e32c16..7ff475752d3 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -973,9 +973,9 @@ number bigint(20) NOT NULL default '0', cname char(15) NOT NULL default '', carrier_id smallint(6) NOT NULL default '0', privacy tinyint(4) NOT NULL default '0', -last_mod_date timestamp(14) NOT NULL, +last_mod_date timestamp NOT NULL, last_mod_id smallint(6) NOT NULL default '0', -last_app_date timestamp(14) NOT NULL, +last_app_date timestamp NOT NULL, last_app_id smallint(6) default '-1', version smallint(6) NOT NULL default '0', assigned_scps int(11) default '0', @@ -992,9 +992,9 @@ number bigint(20) NOT NULL default '0', cname char(15) NOT NULL default '', carrier_id smallint(6) NOT NULL default '0', privacy tinyint(4) NOT NULL default '0', -last_mod_date timestamp(14) NOT NULL, +last_mod_date timestamp NOT NULL, last_mod_id smallint(6) NOT NULL default '0', -last_app_date timestamp(14) NOT NULL, +last_app_date timestamp NOT NULL, last_app_id smallint(6) default '-1', version smallint(6) NOT NULL default '0', assigned_scps int(11) default '0', diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 496d566a5ee..f07b4e2774c 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -138,7 +138,7 @@ create table t1 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), -c13 date, c14 datetime, c15 timestamp(14), c16 time, +c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 bit, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index 54c35873201..75824aa7213 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -17,7 +17,7 @@ create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), -c13 date, c14 datetime, c15 timestamp(14), c16 time, +c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 3df9b6dcb6e..92a581833b5 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -10,7 +10,7 @@ create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), -c13 date, c14 datetime, c15 timestamp(14), c16 time, +c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 851178e2aee..abd6146db7a 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -10,7 +10,7 @@ create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), -c13 date, c14 datetime, c15 timestamp(14), c16 time, +c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 60675a72bdc..62746a28f33 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -11,7 +11,7 @@ create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), -c13 date, c14 datetime, c15 timestamp(14), c16 time, +c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 varchar(100), c24 varchar(100), c25 varchar(100), c26 varchar(100), c27 varchar(100), c28 varchar(100), diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index a177290daa4..fba24eb9d0f 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -12,7 +12,7 @@ create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), -c13 date, c14 datetime, c15 timestamp(14), c16 time, +c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, @@ -32,7 +32,7 @@ create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), -c13 date, c14 datetime, c15 timestamp(14), c16 time, +c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, @@ -52,7 +52,7 @@ create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), -c13 date, c14 datetime, c15 timestamp(14), c16 time, +c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, @@ -3064,7 +3064,7 @@ create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), -c13 date, c14 datetime, c15 timestamp(14), c16 time, +c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index 92399c3b3b9..6f395dab41c 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -10,7 +10,7 @@ create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), -c13 date, c14 datetime, c15 timestamp(14), c16 time, +c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index c7dabc2016d..520852ca67a 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -10,7 +10,7 @@ create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), -c13 date, c14 datetime, c15 timestamp(14), c16 time, +c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 1c0321ac658..14ffa874795 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2073,7 +2073,7 @@ INSERT INTO t1 (pseudo) VALUES ('test1'); SELECT 1 as rnd1 from t1 where rand() > 2; rnd1 DROP TABLE t1; -CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp(14) NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM; +CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM; INSERT INTO t1 VALUES (200001,2,1,1,100,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\E$',''),(200002,2,2,1,101,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\C$',''),(200003,1,3,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,0,1,20020425060427,'c:',NULL); CREATE TABLE t2 ( hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, sampletid smallint(5) unsigned default NULL, sampletime datetime default NULL, samplevalue bigint(20) unsigned default NULL, KEY idx1 (hmid,volid,sampletid,sampletime)) ENGINE=MyISAM; INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12:00:01',35); diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result index 9b851d74a12..61ed6bbabf3 100644 --- a/mysql-test/r/type_timestamp.result +++ b/mysql-test/r/type_timestamp.result @@ -99,6 +99,14 @@ drop table t1; create table t1 (t2 timestamp(2), t4 timestamp(4), t6 timestamp(6), t8 timestamp(8), t10 timestamp(10), t12 timestamp(12), t14 timestamp(14)); +Warnings: +Warning 1287 'TIMESTAMP(2)' is deprecated; use 'TIMESTAMP' instead +Warning 1287 'TIMESTAMP(4)' is deprecated; use 'TIMESTAMP' instead +Warning 1287 'TIMESTAMP(6)' is deprecated; use 'TIMESTAMP' instead +Warning 1287 'TIMESTAMP(8)' is deprecated; use 'TIMESTAMP' instead +Warning 1287 'TIMESTAMP(10)' is deprecated; use 'TIMESTAMP' instead +Warning 1287 'TIMESTAMP(12)' is deprecated; use 'TIMESTAMP' instead +Warning 1287 'TIMESTAMP(14)' is deprecated; use 'TIMESTAMP' instead insert t1 values (0,0,0,0,0,0,0), ("1997-12-31 23:47:59", "1997-12-31 23:47:59", "1997-12-31 23:47:59", "1997-12-31 23:47:59", "1997-12-31 23:47:59", "1997-12-31 23:47:59", diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index d83952e118b..b0055346d61 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -58,7 +58,7 @@ ushows int(10) unsigned DEFAULT '0' NOT NULL, clicks int(10) unsigned DEFAULT '0' NOT NULL, iclicks int(10) unsigned DEFAULT '0' NOT NULL, uclicks int(10) unsigned DEFAULT '0' NOT NULL, -ts timestamp(14), +ts timestamp, PRIMARY KEY (place_id,ts) ); INSERT INTO t1 (place_id,shows,ishows,ushows,clicks,iclicks,uclicks,ts) @@ -75,7 +75,7 @@ client varchar(255) NOT NULL default '', replyto varchar(255) NOT NULL default '', subject varchar(100) NOT NULL default '', timestamp int(10) unsigned NOT NULL default '0', -tstamp timestamp(14) NOT NULL, +tstamp timestamp NOT NULL, status int(3) NOT NULL default '0', type varchar(15) NOT NULL default '', assignment int(10) unsigned NOT NULL default '0', diff --git a/mysql-test/t/alias.test b/mysql-test/t/alias.test index 986af339456..fd008837807 100644 --- a/mysql-test/t/alias.test +++ b/mysql-test/t/alias.test @@ -30,7 +30,7 @@ CREATE TABLE t1 ( prov_hdl_nr int(11) NOT NULL default '0', auto_wirknetz varchar(50) default NULL, auto_billing varchar(50) default NULL, - touch timestamp(14) NOT NULL, + touch timestamp NOT NULL, kategorie varchar(50) default NULL, kundentyp varchar(20) NOT NULL default '', sammel_rech_msisdn varchar(30) NOT NULL default '', diff --git a/mysql-test/t/func_date_add.test b/mysql-test/t/func_date_add.test index 93c77daf86e..29c13793b78 100644 --- a/mysql-test/t/func_date_add.test +++ b/mysql-test/t/func_date_add.test @@ -11,7 +11,7 @@ CREATE TABLE t1 ( group_id int(10) unsigned DEFAULT '0' NOT NULL, hits int(10) unsigned DEFAULT '0' NOT NULL, sessions int(10) unsigned DEFAULT '0' NOT NULL, - ts timestamp(14), + ts timestamp, PRIMARY KEY (visitor_id,group_id) )/*! engine=MyISAM */; INSERT INTO t1 VALUES (465931136,7,2,2,20000318160952); diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 728f0e2c084..cb7d5736d8e 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -128,7 +128,7 @@ CREATE TABLE t1 ( program int(10) unsigned default NULL, bugdesc text, created datetime default NULL, - modified timestamp(14) NOT NULL, + modified timestamp NOT NULL, bugstatus int(10) unsigned default NULL, submitter int(10) unsigned default NULL ) ENGINE=MyISAM; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 6ca29ccded2..66ff460fc61 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -211,7 +211,7 @@ drop table t1; CREATE TABLE t1 ( start datetime default NULL); INSERT INTO t1 VALUES ('2002-10-21 00:00:00'),('2002-10-28 00:00:00'),('2002-11-04 00:00:00'); -CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL); +CREATE TABLE t2 ( ctime1 timestamp NOT NULL, ctime2 timestamp NOT NULL); INSERT INTO t2 VALUES (20021029165106,20021105164731); CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL); INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31"); diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 21d5abcc287..0666493413b 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -134,7 +134,7 @@ CREATE TABLE t1 ( bug_severity enum('blocker','critical','major','normal','minor','trivial','enhancement') DEFAULT 'blocker' NOT NULL, bug_status enum('','NEW','ASSIGNED','REOPENED','RESOLVED','VERIFIED','CLOSED') DEFAULT 'NEW' NOT NULL, creation_ts datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, - delta_ts timestamp(14), + delta_ts timestamp, short_desc mediumtext, long_desc mediumtext, op_sys enum('All','Windows 3.1','Windows 95','Windows 98','Windows NT','Windows 2000','Linux','other') DEFAULT 'All' NOT NULL, diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 7b27d589ec3..512bc010e09 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -661,9 +661,9 @@ CREATE TABLE t1 ( cname char(15) NOT NULL default '', carrier_id smallint(6) NOT NULL default '0', privacy tinyint(4) NOT NULL default '0', - last_mod_date timestamp(14) NOT NULL, + last_mod_date timestamp NOT NULL, last_mod_id smallint(6) NOT NULL default '0', - last_app_date timestamp(14) NOT NULL, + last_app_date timestamp NOT NULL, last_app_id smallint(6) default '-1', version smallint(6) NOT NULL default '0', assigned_scps int(11) default '0', @@ -680,9 +680,9 @@ CREATE TABLE t2 ( cname char(15) NOT NULL default '', carrier_id smallint(6) NOT NULL default '0', privacy tinyint(4) NOT NULL default '0', - last_mod_date timestamp(14) NOT NULL, + last_mod_date timestamp NOT NULL, last_mod_id smallint(6) NOT NULL default '0', - last_app_date timestamp(14) NOT NULL, + last_app_date timestamp NOT NULL, last_app_id smallint(6) default '-1', version smallint(6) NOT NULL default '0', assigned_scps int(11) default '0', diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 60b77576572..d817db369d3 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -149,7 +149,7 @@ create table t1 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), - c13 date, c14 datetime, c15 timestamp(14), c16 time, + c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 bit, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, diff --git a/mysql-test/t/ps_4heap.test b/mysql-test/t/ps_4heap.test index 1c9346721ab..3ce3bea8265 100644 --- a/mysql-test/t/ps_4heap.test +++ b/mysql-test/t/ps_4heap.test @@ -31,7 +31,7 @@ eval create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), - c13 date, c14 datetime, c15 timestamp(14), c16 time, + c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 varchar(100), c24 varchar(100), c25 varchar(100), c26 varchar(100), c27 varchar(100), c28 varchar(100), diff --git a/mysql-test/t/ps_5merge.test b/mysql-test/t/ps_5merge.test index 891d1be2c57..7e94ede41d1 100644 --- a/mysql-test/t/ps_5merge.test +++ b/mysql-test/t/ps_5merge.test @@ -31,7 +31,7 @@ create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), - c13 date, c14 datetime, c15 timestamp(14), c16 time, + c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, @@ -62,7 +62,7 @@ create table t9 c1 tinyint, c2 smallint, c3 mediumint, c4 int, c5 integer, c6 bigint, c7 float, c8 double, c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4), - c13 date, c14 datetime, c15 timestamp(14), c16 time, + c13 date, c14 datetime, c15 timestamp, c16 time, c17 year, c18 tinyint, c19 bool, c20 char, c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext, c25 blob, c26 text, c27 mediumblob, c28 mediumtext, diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 372325c4cbd..5b0cb8d795b 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -1789,7 +1789,7 @@ DROP TABLE t1; # Test of bug with SUM(CASE...) # -CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp(14) NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM; +CREATE TABLE t1 (gvid int(10) unsigned default NULL, hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, mmid int(10) unsigned default NULL, hdid int(10) unsigned default NULL, fsid int(10) unsigned default NULL, ctid int(10) unsigned default NULL, dtid int(10) unsigned default NULL, cost int(10) unsigned default NULL, performance int(10) unsigned default NULL, serialnumber bigint(20) unsigned default NULL, monitored tinyint(3) unsigned default '1', removed tinyint(3) unsigned default '0', target tinyint(3) unsigned default '0', dt_modified timestamp NOT NULL, name varchar(255) binary default NULL, description varchar(255) default NULL, UNIQUE KEY hmid (hmid,volid)) ENGINE=MyISAM; INSERT INTO t1 VALUES (200001,2,1,1,100,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\E$',''),(200002,2,2,1,101,1,1,1,0,0,0,1,0,1,20020425060057,'\\\\ARKIVIO-TESTPDC\\C$',''),(200003,1,3,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,0,1,20020425060427,'c:',NULL); CREATE TABLE t2 ( hmid int(10) unsigned default NULL, volid int(10) unsigned default NULL, sampletid smallint(5) unsigned default NULL, sampletime datetime default NULL, samplevalue bigint(20) unsigned default NULL, KEY idx1 (hmid,volid,sampletid,sampletime)) ENGINE=MyISAM; INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12:00:01',35); diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index 6a90fb95760..21789a550b9 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -31,7 +31,7 @@ CREATE TABLE t1 clicks int(10) unsigned DEFAULT '0' NOT NULL, iclicks int(10) unsigned DEFAULT '0' NOT NULL, uclicks int(10) unsigned DEFAULT '0' NOT NULL, - ts timestamp(14), + ts timestamp, PRIMARY KEY (place_id,ts) ); @@ -52,7 +52,7 @@ CREATE TABLE t1 ( replyto varchar(255) NOT NULL default '', subject varchar(100) NOT NULL default '', timestamp int(10) unsigned NOT NULL default '0', - tstamp timestamp(14) NOT NULL, + tstamp timestamp NOT NULL, status int(3) NOT NULL default '0', type varchar(15) NOT NULL default '', assignment int(10) unsigned NOT NULL default '0', diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index a020cadc084..9f7d85f14fd 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5021,7 +5021,7 @@ ER_NON_UPDATABLE_TABLE por "A tabela destino %-.100s do %s no atualizvel" rus " %-.100s %s " spa "La tabla destino %-.100s del %s no es actualizable" - swe "Tabel %-.100s anvnd med '%s' r inte uppdateringsbar" + swe "Tabell %-.100s anvnd med '%s' r inte uppdateringsbar" ukr " %-.100s %s " ER_FEATURE_DISABLED eng "The '%s' feature is disabled; you need MySQL built with '%s' to have it working" diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index be7ba7d571d..dce25018b50 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5458,6 +5458,23 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, DBUG_RETURN(1); } + if (type == FIELD_TYPE_TIMESTAMP && length) + { + /* Display widths are no longer supported for TIMSTAMP as of MySQL 4.1. + In other words, for declarations such as TIMESTAMP(2), TIMESTAMP(4), + and so on, the display width is ignored. + */ + String str; + str.append("TIMESTAMP"); + str.append("("); + str.append(length); + str.append(")"); + push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_DEPRECATED_SYNTAX, + ER(ER_WARN_DEPRECATED_SYNTAX), + str.c_ptr(), "TIMESTAMP"); + } + if (!(new_field= new_create_field(thd, field_name, type, length, decimals, type_modifier, default_value, on_update_value, comment, change, interval_list, cs, uint_geom_type))) From fc0c652c07f35c9cade138191cda231005f0a780 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jun 2005 12:11:52 +0200 Subject: [PATCH 013/216] BUG#10466 Datatype "timestamp" displays "YYYYMMDDHHMMSS" irrespective of display sizes. - Use buffer for printing error message sql/sql_parse.cc: Use buffer for string --- sql/sql_parse.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index dce25018b50..8223ccb81b6 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5464,9 +5464,9 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, In other words, for declarations such as TIMESTAMP(2), TIMESTAMP(4), and so on, the display width is ignored. */ - String str; - str.append("TIMESTAMP"); - str.append("("); + char buff[32]; + String str(buff,(uint32) sizeof(buff), system_charset_info); + str.append("TIMESTAMP("); str.append(length); str.append(")"); push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN, From 9e78db81b04cbe271c01a384951ef2f3845027c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jun 2005 10:21:35 -0700 Subject: [PATCH 014/216] Fix crash when an entry was added to the mysql.tables_priv table with an empty hostname. (Bug #11330) mysql-test/r/grant.result: Update results mysql-test/t/grant.test: Add new regression test sql/sql_acl.cc: Don't call strlen() on a NULL pointer. --- mysql-test/r/grant.result | 4 ++++ mysql-test/t/grant.test | 8 ++++++++ sql/sql_acl.cc | 3 ++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index bb37480aaf8..3a793ef55e4 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -435,3 +435,7 @@ ERROR 42000: INSERT,CREATE command denied to user 'mysqltest_1'@'localhost' for revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; delete from mysql.user where user=_binary'mysqltest_1'; drop database mysqltest; +use mysql; +insert into tables_priv values ('','mysqltest_1','test_table','test_grantor','',CURRENT_TIMESTAMP,'Select','Select'); +flush privileges; +delete from tables_priv where host = '' and user = 'mysqltest_1'; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 1c8fbe0ff0d..d80ef638e79 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -392,3 +392,11 @@ revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; delete from mysql.user where user=_binary'mysqltest_1'; drop database mysqltest; +# +# Bug #11330: Entry in tables_priv with host = '' causes crash +# +connection default; +use mysql; +insert into tables_priv values ('','mysqltest_1','test_table','test_grantor','',CURRENT_TIMESTAMP,'Select','Select'); +flush privileges; +delete from tables_priv where host = '' and user = 'mysqltest_1'; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 849192154da..d191da32189 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1866,7 +1866,8 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) if (cols) { int key_len; - col_privs->field[0]->store(host.hostname,(uint) strlen(host.hostname), + col_privs->field[0]->store(host.hostname, + host.hostname ? (uint) strlen(host.hostname) : 0, &my_charset_latin1); col_privs->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); col_privs->field[2]->store(user,(uint) strlen(user), &my_charset_latin1); From c2a84d5fd2e3d86ab5dd75b13d6dac7a8a06256f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 14:19:56 +0200 Subject: [PATCH 015/216] patch client/mysqldump.c: Add description of quote_for_like Add quoting of \ to \\\\ in quote_for_like Add DBUG_* Rearranged code in dump_selected_tables so the first thing it will do is to check that the tables to dump are available Unless --force is used, program will exit if not all specified tables can be found Add files to dump to HASH table for easy iteration Simpler handling of ignore_table list. Add new error code used when table user selected to dump can not be found in db client/mysqltest.c: Make it possible to exec a command that fails by setting --error before the command to exec. Check that the error returned from executed program matches the expected error. Add DBUG_* printouts mysql-test/mysql-test-run.sh: export MYSQL_DUMP_DIR used in "--replace_result" mysql-test/r/mysqldump.result: Added test for illegal / nonexisting table and database names mysql-test/t/mysqldump.test: Added test for illegal / nonexisting table and database names --- client/mysqldump.c | 160 +++++++++++++++++++++------------- client/mysqltest.c | 35 +++++++- mysql-test/mysql-test-run.sh | 3 + mysql-test/r/mysqldump.result | 27 ++++++ mysql-test/t/mysqldump.test | 78 +++++++++++++++++ 5 files changed, 240 insertions(+), 63 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 7b18b1d92da..207235983da 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -57,6 +57,7 @@ #define EX_CONSCHECK 3 #define EX_EOM 4 #define EX_EOF 5 /* ferror for output file was got */ +#define EX_ILLEGAL_TABLE 6 /* index into 'show fields from table' */ @@ -140,14 +141,6 @@ const char *compatible_mode_names[]= TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1, "", compatible_mode_names, NULL}; -#define TABLE_RULE_HASH_SIZE 16 - -typedef struct st_table_rule_ent -{ - char* key; /* dbname.tablename */ - uint key_len; -} TABLE_RULE_ENT; - HASH ignore_table; static struct my_option my_long_options[] = @@ -538,29 +531,21 @@ static void write_footer(FILE *sql_file) } /* write_footer */ -static void free_table_ent(TABLE_RULE_ENT* e) +byte* get_table_key(const char *entry, uint *length, + my_bool not_used __attribute__((unused))) { - my_free((gptr) e, MYF(0)); -} - - -static byte* get_table_key(TABLE_RULE_ENT* e, uint* len, - my_bool not_used __attribute__((unused))) -{ - *len= e->key_len; - return (byte*)e->key; + *length= strlen(entry); + return (byte*) entry; } void init_table_rule_hash(HASH* h) { - if(hash_init(h, charset_info, TABLE_RULE_HASH_SIZE, 0, 0, - (hash_get_key) get_table_key, - (hash_free_key) free_table_ent, 0)) + if(hash_init(h, charset_info, 16, 0, 0, + (hash_get_key) get_table_key, 0, 0)) exit(EX_EOM); } - static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) @@ -633,25 +618,15 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; case (int) OPT_IGNORE_TABLE: { - uint len= (uint)strlen(argument); - TABLE_RULE_ENT* e; if (!strchr(argument, '.')) { fprintf(stderr, "Illegal use of option --ignore-table=.\n"); exit(1); } - /* len is always > 0 because we know the there exists a '.' */ - e= (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT) + len, MYF(MY_WME)); - if (!e) - exit(EX_EOM); - e->key= (char*)e + sizeof(TABLE_RULE_ENT); - e->key_len= len; - memcpy(e->key, argument, len); - if (!hash_inited(&ignore_table)) init_table_rule_hash(&ignore_table); - if(my_hash_insert(&ignore_table, (byte*)e)) + if (my_hash_insert(&ignore_table, (byte*)my_strdup(argument, MYF(0)))) exit(EX_EOM); break; } @@ -955,7 +930,28 @@ static char *quote_name(const char *name, char *buff, my_bool force) return buff; } /* quote_name */ +/* + Quote a table name so it can be used in "SHOW TABLES LIKE " + SYNOPSIS + quote_for_like + name - name of the table + buff - quoted name of the table + + DESCRIPTION + Quote \, _, ' and % characters + + Note: Because MySQL uses the C escape syntax in strings + (for example, '\n' to represent newline), you must double + any '\' that you use in your LIKE strings. For example, to + search for '\n', specify it as '\\n'. To search for '\', specify + it as '\\\\' (the backslashes are stripped once by the parser + and another time when the pattern match is done, leaving a + single backslash to be matched). + + Example: "t\1" => "t\\\\1" + +*/ static char *quote_for_like(const char *name, char *buff) { @@ -963,7 +959,13 @@ static char *quote_for_like(const char *name, char *buff) *to++= '\''; while (*name) { - if (*name == '\'' || *name == '_' || *name == '\\' || *name == '%') + if (*name == '\\') + { + *to++='\\'; + *to++='\\'; + *to++='\\'; + } + else if (*name == '\'' || *name == '_' || *name == '%') *to++= '\\'; *to++= *name++; } @@ -1114,6 +1116,7 @@ static uint getTableStructure(char *table, char* db) FILE *sql_file = md_result_file; int len; DBUG_ENTER("getTableStructure"); + DBUG_PRINT("enter", ("db: %s, table: %s", db, table)); if (!insert_pat_inited) { @@ -2165,6 +2168,7 @@ static int get_actual_table_name(const char *old_table_name, char query[50 + 2*NAME_LEN]; char show_name_buff[FN_REFLEN]; DBUG_ENTER("get_actual_table_name"); + DBUG_PRINT("enter", ("old_table_name: %s", old_table_name)); /* Check memory for quote_for_like() */ DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff)); @@ -2186,36 +2190,72 @@ static int get_actual_table_name(const char *old_table_name, row= mysql_fetch_row( tableRes ); strmake(new_table_name, row[0], buf_size-1); retval = 0; + DBUG_PRINT("info", ("new_table_name: %s", new_table_name)); } mysql_free_result(tableRes); } - return retval; + DBUG_PRINT("exit", ("retval: %d", retval)); + DBUG_RETURN(retval); } static int dump_selected_tables(char *db, char **table_names, int tables) { - uint numrows; + uint numrows, i; char table_buff[NAME_LEN*+3]; + char new_table_name[NAME_LEN]; + DYNAMIC_STRING lock_tables_query; + HASH dump_tables; + + DBUG_ENTER("dump_selected_tables"); if (init_dumping(db)) return 1; + + /* Init hash table for storing the actual name of tables to dump */ + if (hash_init(&dump_tables, charset_info, 16, 0, 0, + (hash_get_key) get_table_key, 0, 0)) + exit(EX_EOM); + + init_dynamic_string(&lock_tables_query, "LOCK TABLES ", 256, 1024); + for (; tables > 0 ; tables-- , table_names++) + { + + /* the table name passed on commandline may be wrong case */ + if (!get_actual_table_name( *table_names, + new_table_name, sizeof(new_table_name) )) + { + /* Add found table name to lock_tables_query */ + if (lock_tables) + { + dynstr_append(&lock_tables_query, + quote_name(new_table_name, table_buff, 1)); + dynstr_append(&lock_tables_query, " READ /*!32311 LOCAL */,"); + } + + /* Add found table name to dump_tables list */ + if (my_hash_insert(&dump_tables, + (byte*)my_strdup(new_table_name, MYF(0)))) + exit(EX_EOM); + + } + else + { + my_printf_error(0,"Couldn't find table: \"%s\"\n", MYF(0), + *table_names); + safe_exit(EX_ILLEGAL_TABLE); + /* We shall countinue here, if --force was given */ + } + } + if (lock_tables) { - DYNAMIC_STRING query; - int i; - - init_dynamic_string(&query, "LOCK TABLES ", 256, 1024); - for (i=0 ; i < tables ; i++) - { - dynstr_append(&query, quote_name(table_names[i], table_buff, 1)); - dynstr_append(&query, " READ /*!32311 LOCAL */,"); - } - if (mysql_real_query(sock, query.str, query.length-1)) + if (mysql_real_query(sock, lock_tables_query.str, + lock_tables_query.length-1)) DBerror(sock, "when doing LOCK TABLES"); /* We shall countinue here, if --force was given */ - dynstr_free(&query); } + dynstr_free(&lock_tables_query); if (flush_logs) { if (mysql_refresh(sock, REFRESH_LOG)) @@ -2224,20 +2264,20 @@ static int dump_selected_tables(char *db, char **table_names, int tables) } if (opt_xml) print_xml_tag1(md_result_file, "", "database name=", db, "\n"); - for (; tables > 0 ; tables-- , table_names++) - { - char new_table_name[NAME_LEN]; - /* the table name passed on commandline may be wrong case */ - if (!get_actual_table_name( *table_names, new_table_name, sizeof(new_table_name) )) - { - numrows = getTableStructure(new_table_name, db); - if (!dFlag && numrows > 0) - dumpTable(numrows, new_table_name); - } - my_free(order_by, MYF(MY_ALLOW_ZERO_PTR)); - order_by= 0; + /* Dump each selected table */ + const char *table_name; + for (i= 0 ; i < dump_tables.records ; i++) + { + table_name= hash_element(&dump_tables, i); + DBUG_PRINT("info",("Dumping table %s", table_name)); + numrows = getTableStructure(table_name, db); + if (!dFlag && numrows > 0) + dumpTable(numrows, table_name); } + hash_free(&dump_tables); + my_free(order_by, MYF(MY_ALLOW_ZERO_PTR)); + order_by= 0; if (opt_xml) { fputs("\n", md_result_file); @@ -2245,7 +2285,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) } if (lock_tables) mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"); - return 0; + DBUG_RETURN(0); } /* dump_selected_tables */ diff --git a/client/mysqltest.c b/client/mysqltest.c index e60d9ecd1c5..3c238b57a07 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -781,7 +781,7 @@ int var_set(const char *var_name, const char *var_name_end, } else v = var_reg + digit; - return eval_expr(v, var_val, (const char**)&var_val_end); + DBUG_RETURN(eval_expr(v, var_val, (const char**)&var_val_end)); } @@ -955,9 +955,38 @@ static void do_exec(struct st_query* q) replace_dynstr_append_mem(ds, buf, strlen(buf)); } error= pclose(res_file); - if (error != 0) - die("command \"%s\" failed", cmd); + { + uint status= WEXITSTATUS(error); + if(q->abort_on_error) + die("At line %u: command \"%s\" failed", start_lineno, cmd); + else + { + DBUG_PRINT("info", + ("error: %d, status: %d", error, status)); + bool ok= 0; + uint i; + for (i=0 ; (uint) i < q->expected_errors ; i++) + { + DBUG_PRINT("info", ("expected error: %d", q->expected_errno[i].code.errnum)); + if ((q->expected_errno[i].type == ERR_ERRNO) && + (q->expected_errno[i].code.errnum == status)) + ok= 1; + verbose_msg("At line %u: command \"%s\" failed with expected error: %d", + start_lineno, cmd, status); + } + if (!ok) + die("At line: %u: command \"%s\" failed with wrong error: %d", + start_lineno, cmd, status); + } + } + else if (q->expected_errno[0].type == ERR_ERRNO && + q->expected_errno[0].code.errnum != 0) + { + /* Error code we wanted was != 0, i.e. not an expected success */ + die("At line: %u: command \"%s\" succeeded - should have failed with errno %d...", + start_lineno, cmd, q->expected_errno[0].code.errnum); + } if (!disable_result_log) { diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 3f7e7d22200..6071a753c87 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -688,6 +688,9 @@ MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST --no-defaults --testcase --user=root --soc if [ "x$USE_EMBEDDED_SERVER" = "x1" ]; then MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST -A --language=$LANGUAGE -A --datadir=$SLAVE_MYDDIR -A --character-sets-dir=$CHARSETSDIR" fi +# Save path and name of mysqldump +MYSQL_DUMP_DIR="$MYSQL_DUMP" +export MYSQL_DUMP_DIR MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT" MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR $EXTRA_MYSQLBINLOG_OPT" MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose" diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index f66647bdbf8..50399c91ec9 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1409,3 +1409,30 @@ CREATE TABLE `t2` ( DROP TABLE t1, t2; DROP DATABASE mysqldump_test_db; +create database mysqldump_test_db; +use mysqldump_test_db; +create table t1(a varchar(30) primary key, b int not null); +create table t2(a varchar(30) primary key, b int not null); +create table t3(a varchar(30) primary key, b int not null); +test_sequence +------ Testing with illegal table names ------ +MYSQL_DUMP_DIR: Couldn't find table: "\d-2-1.sql" + +MYSQL_DUMP_DIR: Couldn't find table: "\t1" + +MYSQL_DUMP_DIR: Couldn't find table: "\t1" + +MYSQL_DUMP_DIR: Couldn't find table: "\\t1" + +MYSQL_DUMP_DIR: Couldn't find table: "t\1" + +MYSQL_DUMP_DIR: Couldn't find table: "t\1" + +MYSQL_DUMP_DIR: Couldn't find table: "t/1" + +test_sequence +------ Testing with illegal database names ------ +MYSQL_DUMP_DIR: Got error: 1049: Unknown database 'mysqldump_test_d' when selecting the database +MYSQL_DUMP_DIR: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when selecting the database +drop table t1, t2, t3; +drop database mysqldump_test_db; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 5a35c328314..349b1e96239 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -558,3 +558,81 @@ INSERT INTO t2 VALUES (1), (2); --exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db t1 t2 DROP TABLE t1, t2; DROP DATABASE mysqldump_test_db; + +# +# Testing with tables and databases that don't exists +# or contains illegal characters +# (Bug #9358 mysqldump crashes if tablename starts with \) +# +create database mysqldump_test_db; +use mysqldump_test_db; +create table t1(a varchar(30) primary key, b int not null); +create table t2(a varchar(30) primary key, b int not null); +create table t3(a varchar(30) primary key, b int not null); + +--disable_query_log +select '------ Testing with illegal table names ------' as test_sequence ; +--enable_query_log +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\d-2-1.sql" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\t1" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\t1" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\\\t1" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\1" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\\1" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t/1" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1" + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T%1" + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T'1" + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1" + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_" + +--disable_query_log +select '------ Testing with illegal database names ------' as test_sequence ; +--enable_query_log +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 2 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_d 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 2 +--exec $MYSQL_DUMP --compact --skip-comments "mysqld\ump_test_db" 2>&1 + +drop table t1, t2, t3; +drop database mysqldump_test_db; + + From 280b1c33e3e1ddd7b4e3b295c9e30c766da6c494 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 18:18:58 +0300 Subject: [PATCH 016/216] Cleanup during review of new code Fixed wrong allocation that could cause buffer overrun when using join cache myisam/mi_open.c: Fixed indentation mysql-test/r/lowercase_table2.result: Drop tables and databases used in the test mysql-test/t/lowercase_table2.test: Drop tables and databases used in the test mysys/my_fopen.c: Cleanup of comments and parameter names Simple optimization Removed compiler warnings sql/field.cc: Fixed wrong allocation that could cause buffer overrun sql/mysqld.cc: Removed not needed code sql/set_var.cc: Simply code sql/sql_select.cc: Use int2store/int2korr to store length of cached VARCHAR fields (Not dependent on type and faster code as we avoid one possible call) --- myisam/mi_open.c | 2 +- mysql-test/r/lowercase_table2.result | 3 +- mysql-test/t/lowercase_table2.test | 3 +- mysys/my_fopen.c | 86 ++++++++++++++++------------ sql/field.cc | 9 ++- sql/mysqld.cc | 3 - sql/set_var.cc | 2 +- sql/sql_select.cc | 18 +++--- 8 files changed, 72 insertions(+), 54 deletions(-) diff --git a/myisam/mi_open.c b/myisam/mi_open.c index e79fdb7e777..a5b303f86d4 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -78,7 +78,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) int lock_error,kfile,open_mode,save_errno,have_rtree=0; uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys, key_parts,unique_key_parts,fulltext_keys,uniques; - char name_buff[FN_REFLEN], org_name [FN_REFLEN], index_name[FN_REFLEN], + char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN], data_name[FN_REFLEN]; char *disk_cache, *disk_pos, *end_pos; MI_INFO info,*m_info,*old_info; diff --git a/mysql-test/r/lowercase_table2.result b/mysql-test/r/lowercase_table2.result index db833bcd970..f93a10dfbad 100644 --- a/mysql-test/r/lowercase_table2.result +++ b/mysql-test/r/lowercase_table2.result @@ -1,6 +1,7 @@ -DROP TABLE IF EXISTS t1,t2,t3; +DROP TABLE IF EXISTS t1,t2,t3,t2aA,t1Aa; DROP DATABASE IF EXISTS `TEST_$1`; DROP DATABASE IF EXISTS `test_$1`; +DROP DATABASE mysqltest_LC2; CREATE TABLE T1 (a int); INSERT INTO T1 VALUES (1); SHOW TABLES LIKE "T1"; diff --git a/mysql-test/t/lowercase_table2.test b/mysql-test/t/lowercase_table2.test index 51c6f6b5ac3..5e38c59386d 100644 --- a/mysql-test/t/lowercase_table2.test +++ b/mysql-test/t/lowercase_table2.test @@ -10,9 +10,10 @@ show variables like "lower_case_table_names"; enable_query_log; --disable_warnings -DROP TABLE IF EXISTS t1,t2,t3; +DROP TABLE IF EXISTS t1,t2,t3,t2aA,t1Aa; DROP DATABASE IF EXISTS `TEST_$1`; DROP DATABASE IF EXISTS `test_$1`; +DROP DATABASE mysqltest_LC2; --enable_warnings CREATE TABLE T1 (a int); diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index 002e5ca0f06..f07beec9f39 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -19,27 +19,36 @@ #include #include "mysys_err.h" -static void make_ftype(my_string to,int flag); +static void make_ftype(my_string to,int flag); - /* Open a file as stream */ +/* + Open a file as stream -FILE *my_fopen(const char *FileName, int Flags, myf MyFlags) - /* Path-name of file */ - /* Read | write .. */ - /* Special flags */ + SYNOPSIS + my_fopen() + FileName Path-name of file + Flags Read | write | append | trunc (like for open()) + MyFlags Flags for handling errors + + RETURN + 0 Error + # File handler +*/ + +FILE *my_fopen(const char *filename, int flags, myf MyFlags) { FILE *fd; char type[5]; DBUG_ENTER("my_fopen"); - DBUG_PRINT("my",("Name: '%s' Flags: %d MyFlags: %d", - FileName, Flags, MyFlags)); + DBUG_PRINT("my",("Name: '%s' flags: %d MyFlags: %d", + filename, flags, MyFlags)); /* if we are not creating, then we need to use my_access to make sure the file exists since Windows doesn't handle files like "com1.sym" very well */ #ifdef __WIN__ - if (check_if_legal_filename(FileName)) + if (check_if_legal_filename(filename)) { errno= EACCES; fd= 0; @@ -47,8 +56,8 @@ FILE *my_fopen(const char *FileName, int Flags, myf MyFlags) else #endif { - make_ftype(type,Flags); - fd = fopen(FileName, type); + make_ftype(type,flags); + fd = fopen(filename, type); } if (fd != 0) @@ -65,7 +74,7 @@ FILE *my_fopen(const char *FileName, int Flags, myf MyFlags) } pthread_mutex_lock(&THR_LOCK_open); if ((my_file_info[fileno(fd)].name = (char*) - my_strdup(FileName,MyFlags))) + my_strdup(filename,MyFlags))) { my_stream_opened++; my_file_info[fileno(fd)].type = STREAM_BY_FOPEN; @@ -81,9 +90,9 @@ FILE *my_fopen(const char *FileName, int Flags, myf MyFlags) my_errno=errno; DBUG_PRINT("error",("Got error %d on open",my_errno)); if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) - my_error((Flags & O_RDONLY) || (Flags == O_RDONLY ) ? EE_FILENOTFOUND : + my_error((flags & O_RDONLY) || (flags == O_RDONLY ) ? EE_FILENOTFOUND : EE_CANTCREATEFILE, - MYF(ME_BELL+ME_WAITTANG), FileName,my_errno); + MYF(ME_BELL+ME_WAITTANG), filename, my_errno); DBUG_RETURN((FILE*) 0); } /* my_fopen */ @@ -158,33 +167,39 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) DBUG_RETURN(fd); } /* my_fdopen */ -/* - make_ftype - Make a filehandler-open-typestring from ordinary inputflags - Note: This routine attempts to find the best possible match - between a numeric option and a string option that could be - fed to fopen. There is not a 1 to 1 mapping between the two. +/* + Make a fopen() typestring from a open() type bitmap + + SYNOPSIS + make_ftype() + to String for fopen() is stored here + flag Flag used by open() + + IMPLEMENTATION + This routine attempts to find the best possible match + between a numeric option and a string option that could be + fed to fopen. There is not a 1 to 1 mapping between the two. - r == O_RDONLY - w == O_WRONLY|O_TRUNC|O_CREAT - a == O_WRONLY|O_APPEND|O_CREAT - r+ == O_RDWR - w+ == O_RDWR|O_TRUNC|O_CREAT - a+ == O_RDWR|O_APPEND|O_CREAT + NOTE + On Unix, O_RDONLY is usually 0 + + MAPPING + r == O_RDONLY + w == O_WRONLY|O_TRUNC|O_CREAT + a == O_WRONLY|O_APPEND|O_CREAT + r+ == O_RDWR + w+ == O_RDWR|O_TRUNC|O_CREAT + a+ == O_RDWR|O_APPEND|O_CREAT */ + static void make_ftype(register my_string to, register int flag) { -#if FILE_BINARY - /* If we have binary-files */ - reg3 int org_flag=flag; -#endif - flag&= ~FILE_BINARY; /* remove binary bit */ - /* check some possible invalid combinations */ - DBUG_ASSERT(flag & (O_TRUNC|O_APPEND) != O_TRUNC|O_APPEND); + DBUG_ASSERT((flag & (O_TRUNC | O_APPEND)) != (O_TRUNC | O_APPEND)); + DBUG_ASSERT((flag & (O_WRONLY | O_RDWR)) != (O_WRONLY | O_RDWR)); - if (flag & (O_RDONLY|O_WRONLY) == O_WRONLY) + if ((flag & (O_RDONLY|O_WRONLY)) == O_WRONLY) *to++= (flag & O_APPEND) ? 'a' : 'w'; else if (flag & O_RDWR) { @@ -201,9 +216,8 @@ static void make_ftype(register my_string to, register int flag) *to++= 'r'; #if FILE_BINARY /* If we have binary-files */ - if (org_flag & FILE_BINARY) + if (flag & FILE_BINARY) *to++='b'; #endif *to='\0'; } /* make_ftype */ - diff --git a/sql/field.cc b/sql/field.cc index 692f123097a..88816151c10 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1053,6 +1053,7 @@ void Field_str::make_field(Send_field *field) uint Field::fill_cache_field(CACHE_FIELD *copy) { + uint store_length; copy->str=ptr; copy->length=pack_length(); copy->blob_field=0; @@ -1065,10 +1066,16 @@ uint Field::fill_cache_field(CACHE_FIELD *copy) } else if (!zero_pack() && (type() == FIELD_TYPE_STRING && copy->length > 4 || type() == FIELD_TYPE_VAR_STRING)) + { copy->strip=1; /* Remove end space */ + store_length= 2; + } else + { copy->strip=0; - return copy->length+(int) copy->strip; + store_length= 0; + } + return copy->length+ store_length; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ec05ea2b8ce..99c96a69ceb 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6098,9 +6098,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case (int) OPT_SLOW_QUERY_LOG: opt_slow_log=1; break; - case (int) OPT_LOG_SLOW_ADMIN_STATEMENTS: - opt_log_slow_admin_statements= 1; - break; case (int) OPT_SKIP_NEW: opt_specialflag|= SPECIAL_NO_NEW_FUNC; delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE; diff --git a/sql/set_var.cc b/sql/set_var.cc index 0f13a8a7f2d..b0fa61a12bc 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1516,7 +1516,7 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names) { if (!(res= var->value->val_str(&str))) { - strmake(buff, "NULL", 4); + strmov(buff, "NULL"); goto err; } var->save_result.ulong_value= ((ulong) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5bafe1a7df4..1031773eeed 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -28,8 +28,6 @@ #include #include -typedef uint32 cache_rec_length_type; - const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref", "MAYBE_REF","ALL","range","index","fulltext", "ref_or_null","unique_subquery","index_subquery" @@ -8074,7 +8072,7 @@ used_blob_length(CACHE_FIELD **ptr) static bool store_record_in_cache(JOIN_CACHE *cache) { - cache_rec_length_type length; + uint length; uchar *pos; CACHE_FIELD *copy,*end_field; bool last_record; @@ -8119,9 +8117,9 @@ store_record_in_cache(JOIN_CACHE *cache) end > str && end[-1] == ' ' ; end--) ; length=(uint) (end-str); - memcpy(pos+sizeof(length), str, length); - memcpy_fixed(pos, &length, sizeof(length)); - pos+= length+sizeof(length); + memcpy(pos+2, str, length); + int2store(pos, length); + pos+= length+2; } else { @@ -8155,7 +8153,7 @@ static void read_cached_record(JOIN_TAB *tab) { uchar *pos; - cache_rec_length_type length; + uint length; bool last_record; CACHE_FIELD *copy,*end_field; @@ -8184,10 +8182,10 @@ read_cached_record(JOIN_TAB *tab) { if (copy->strip) { - memcpy_fixed(&length, pos, sizeof(length)); - memcpy(copy->str, pos+sizeof(length), length); + length= uint2korr(pos); + memcpy(copy->str, pos+2, length); memset(copy->str+length, ' ', copy->length-length); - pos+= sizeof(length)+length; + pos+= 2 + length; } else { From bedb96f2aaad4abba9ceca86f2b61ed16e7aa858 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 21 Jun 2005 11:25:51 -0700 Subject: [PATCH 017/216] Restore creation of files for temporary tables in the tmpdir, which was broken by an earlier bug fix. (Bug #11440) sql/sql_table.cc: Restore code to generate temporary tables in tmpdir --- sql/sql_table.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e2e6ee23323..a7fd2a0a2bd 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1339,14 +1339,12 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, /* Check if table exists */ if (create_info->options & HA_LEX_CREATE_TMP_TABLE) { - char tmp_table_name[tmp_file_prefix_length+22+22+22+3]; - my_snprintf(tmp_table_name, sizeof(tmp_table_name), "%s%lx_%lx_%x", - tmp_file_prefix, current_pid, thd->thread_id, - thd->tmp_table++); + my_snprintf(path, sizeof(path), "%s%s%lx_%lx_%x%s", + mysql_tmpdir, tmp_file_prefix, current_pid, thd->thread_id, + thd->tmp_table++, reg_ext); if (lower_case_table_names) - my_casedn_str(files_charset_info, tmp_table_name); + my_casedn_str(files_charset_info, path); create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE; - build_table_path(path, sizeof(path), db, tmp_table_name, reg_ext); } else build_table_path(path, sizeof(path), db, alias, reg_ext); From 54d2e80ce44a3284cea48d685901af1b7849f978 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 14:12:09 +0200 Subject: [PATCH 018/216] Should not be changed --- mysql-test/r/mysqldump.result | 199 ++++++++++++++++++++-------------- mysql-test/t/mysqldump.test | 63 +++++++++-- 2 files changed, 171 insertions(+), 91 deletions(-) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 50399c91ec9..ed6aa83ec32 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1,4 +1,7 @@ -DROP TABLE IF EXISTS t1, `"t"1`; +DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa; +drop database if exists mysqldump_test_db; +drop database if exists db1; +drop view if exists v1, v2; CREATE TABLE t1(a int); INSERT INTO t1 VALUES (1), (2); @@ -18,16 +21,18 @@ INSERT INTO t1 VALUES (1), (2); DROP TABLE t1; -CREATE TABLE t1 (a decimal(240, 20)); +CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); CREATE TABLE `t1` ( - `a` decimal(240,20) default NULL + `a` decimal(64,20) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -INSERT INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('0987654321098765432109876543210987654321.00000000000000000000'); +INSERT INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('987654321098765432109876543210987654321.00000000000000000000'); DROP TABLE t1; CREATE TABLE t1 (a double); -INSERT INTO t1 VALUES (-9e999999); +INSERT INTO t1 VALUES ('-9e999999'); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 CREATE TABLE `t1` ( `a` double default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; @@ -108,7 +113,7 @@ INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES"); - + @@ -352,6 +357,41 @@ CREATE TABLE `t1` ( 2 3 drop table t1; +create table t1(a int); +create view v1 as select * from t1; + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +LOCK TABLES `t1` WRITE; +UNLOCK TABLES; +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; +DROP TABLE IF EXISTS `v1`; +DROP VIEW IF EXISTS `v1`; +CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` from `test`.`t1`; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +drop view v1; +drop table t1; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -399,7 +439,7 @@ USE `mysqldump_test_db`; drop database mysqldump_test_db; CREATE TABLE t1 (a CHAR(10)); -INSERT INTO t1 VALUES (_latin1 ''); +INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -441,7 +481,7 @@ CREATE TABLE `t1` ( /*!40000 ALTER TABLE `t1` DISABLE KEYS */; LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES (''); +INSERT INTO `t1` VALUES ('Ž™šá'); UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; @@ -462,7 +502,7 @@ CREATE TABLE `t1` ( /*!40000 ALTER TABLE `t1` DISABLE KEYS */; LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES (''); +INSERT INTO `t1` VALUES ('Ž™šá'); UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; @@ -560,9 +600,8 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; -CREATE TABLE t1 (a decimal(240, 20)); -INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), -("0987654321098765432109876543210987654321"); +CREATE TABLE t1 (a char(10)); +INSERT INTO t1 VALUES ('\''); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -574,13 +613,46 @@ INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; CREATE TABLE `t1` ( - `a` decimal(240,20) default NULL + `a` char(10) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; LOCK TABLES `t1` WRITE; -INSERT IGNORE INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('0987654321098765432109876543210987654321.00000000000000000000'); +INSERT INTO `t1` VALUES ('\''); +UNLOCK TABLES; +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +DROP TABLE t1; +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t1 VALUES (4),(5),(6); + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +LOCK TABLES `t1` WRITE; +INSERT IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6); UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; @@ -603,12 +675,14 @@ UNLOCK TABLES; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; CREATE TABLE `t1` ( - `a` decimal(240,20) default NULL + `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; -INSERT DELAYED IGNORE INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('0987654321098765432109876543210987654321.00000000000000000000'); +LOCK TABLES `t1` WRITE; +INSERT IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6); +UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -1349,12 +1423,18 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; -CREATE DATABASE mysqldump_test_db; -USE mysqldump_test_db; -CREATE TABLE t1 ( a INT ); -CREATE TABLE t2 ( a INT ); -INSERT INTO t1 VALUES (1), (2); -INSERT INTO t2 VALUES (1), (2); +create database db1; +use db1; +CREATE TABLE t2 ( +a varchar(30) default NULL, +KEY a (a(5)) +); +INSERT INTO t2 VALUES ('alfred'); +INSERT INTO t2 VALUES ('angie'); +INSERT INTO t2 VALUES ('bingo'); +INSERT INTO t2 VALUES ('waffle'); +INSERT INTO t2 VALUES ('lemon'); +create view v2 as select * from t2 where a like 'a%' with check option; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -1364,15 +1444,22 @@ INSERT INTO t2 VALUES (1), (2); /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -DROP TABLE IF EXISTS `t1`; -CREATE TABLE `t1` ( - `a` int(11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS `t2`; CREATE TABLE `t2` ( - `a` int(11) default NULL + `a` varchar(30) default NULL, + KEY `a` (`a`(5)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +/*!40000 ALTER TABLE `t2` DISABLE KEYS */; +LOCK TABLES `t2` WRITE; +INSERT INTO `t2` VALUES ('alfred'),('angie'),('bingo'),('waffle'),('lemon'); +UNLOCK TABLES; +/*!40000 ALTER TABLE `t2` ENABLE KEYS */; +DROP TABLE IF EXISTS `v2`; +DROP VIEW IF EXISTS `v2`; +CREATE ALGORITHM=UNDEFINED VIEW `db1`.`v2` AS select `db1`.`t2`.`a` AS `a` from `db1`.`t2` where (`db1`.`t2`.`a` like _latin1'a%') WITH CASCADED CHECK OPTION; + /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; @@ -1381,58 +1468,6 @@ CREATE TABLE `t2` ( /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -DROP TABLE IF EXISTS `t1`; -CREATE TABLE `t1` ( - `a` int(11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; -DROP TABLE IF EXISTS `t2`; -CREATE TABLE `t2` ( - `a` int(11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - -DROP TABLE t1, t2; -DROP DATABASE mysqldump_test_db; -create database mysqldump_test_db; -use mysqldump_test_db; -create table t1(a varchar(30) primary key, b int not null); -create table t2(a varchar(30) primary key, b int not null); -create table t3(a varchar(30) primary key, b int not null); -test_sequence ------- Testing with illegal table names ------ -MYSQL_DUMP_DIR: Couldn't find table: "\d-2-1.sql" - -MYSQL_DUMP_DIR: Couldn't find table: "\t1" - -MYSQL_DUMP_DIR: Couldn't find table: "\t1" - -MYSQL_DUMP_DIR: Couldn't find table: "\\t1" - -MYSQL_DUMP_DIR: Couldn't find table: "t\1" - -MYSQL_DUMP_DIR: Couldn't find table: "t\1" - -MYSQL_DUMP_DIR: Couldn't find table: "t/1" - -test_sequence ------- Testing with illegal database names ------ -MYSQL_DUMP_DIR: Got error: 1049: Unknown database 'mysqldump_test_d' when selecting the database -MYSQL_DUMP_DIR: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when selecting the database -drop table t1, t2, t3; -drop database mysqldump_test_db; +drop table t2; +drop view v2; +drop database db1; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 349b1e96239..86c4d9a7ebb 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -2,7 +2,10 @@ --source include/not_embedded.inc --disable_warnings -DROP TABLE IF EXISTS t1, `"t"1`; +DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa; +drop database if exists mysqldump_test_db; +drop database if exists db1; +drop view if exists v1, v2; --enable_warnings # XML output @@ -16,7 +19,7 @@ DROP TABLE t1; # Bug #2005 # -CREATE TABLE t1 (a decimal(240, 20)); +CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); --exec $MYSQL_DUMP --compact test t1 @@ -27,7 +30,7 @@ DROP TABLE t1; # CREATE TABLE t1 (a double); -INSERT INTO t1 VALUES (-9e999999); +INSERT INTO t1 VALUES ('-9e999999'); # The following replaces is here because some systems replaces the above # double with '-inf' and others with MAX_DOUBLE --replace_result (-1.79769313486232e+308) (RES) (NULL) (RES) @@ -131,6 +134,15 @@ insert into t1 values (1),(2),(3); --exec rm $MYSQL_TEST_DIR/var/tmp/t1.txt drop table t1; +# +# dump of view +# +create table t1(a int); +create view v1 as select * from t1; +--exec $MYSQL_DUMP --skip-comments test +drop view v1; +drop table t1; + # # Bug #6101: create database problem # @@ -149,7 +161,7 @@ drop database mysqldump_test_db; # if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); -INSERT INTO t1 VALUES (_latin1 ''); +INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments test t1 # # Bug#8063: make test mysqldump [ fail ] @@ -185,15 +197,24 @@ INSERT INTO `t1` VALUES (0x602010000280100005E71A); --exec $MYSQL_DUMP --skip-extended-insert --hex-blob test --skip-comments t1 DROP TABLE t1; +# +# Bug #9756 +# + +CREATE TABLE t1 (a char(10)); +INSERT INTO t1 VALUES ('\''); +--exec $MYSQL_DUMP --skip-comments test t1 +DROP TABLE t1; + # # Test for --insert-ignore # -CREATE TABLE t1 (a decimal(240, 20)); -INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), -("0987654321098765432109876543210987654321"); ---exec $MYSQL_DUMP --insert-ignore --skip-comments test t1 ---exec $MYSQL_DUMP --insert-ignore --skip-comments --delayed-insert test t1 +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t1 VALUES (4),(5),(6); +--exec $MYSQL_DUMP --skip-comments --insert-ignore test t1 +--exec $MYSQL_DUMP --skip-comments --insert-ignore --delayed-insert test t1 DROP TABLE t1; # @@ -636,3 +657,27 @@ drop table t1, t2, t3; drop database mysqldump_test_db; + + +# +# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# + +create database db1; +use db1; + +CREATE TABLE t2 ( + a varchar(30) default NULL, + KEY a (a(5)) +); + +INSERT INTO t2 VALUES ('alfred'); +INSERT INTO t2 VALUES ('angie'); +INSERT INTO t2 VALUES ('bingo'); +INSERT INTO t2 VALUES ('waffle'); +INSERT INTO t2 VALUES ('lemon'); +create view v2 as select * from t2 where a like 'a%' with check option; +--exec $MYSQL_DUMP --skip-comments db1 +drop table t2; +drop view v2; +drop database db1; From 7ff7e90fce1acf740817e89743d3b0981fee2030 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 14:16:26 +0200 Subject: [PATCH 019/216] Cset exclude: msvensson@neptunus.(none)|ChangeSet|20050622121209|37729 mysql-test/r/mysqldump.result: Exclude mysql-test/t/mysqldump.test: Exclude --- mysql-test/r/mysqldump.result | 6 +-- mysql-test/t/mysqldump.test | 95 +---------------------------------- 2 files changed, 4 insertions(+), 97 deletions(-) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index ed6aa83ec32..080bc4d1e0f 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -439,7 +439,7 @@ USE `mysqldump_test_db`; drop database mysqldump_test_db; CREATE TABLE t1 (a CHAR(10)); -INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); +INSERT INTO t1 VALUES (_latin1 ''); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -481,7 +481,7 @@ CREATE TABLE `t1` ( /*!40000 ALTER TABLE `t1` DISABLE KEYS */; LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES ('Ž™šá'); +INSERT INTO `t1` VALUES (''); UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; @@ -502,7 +502,7 @@ CREATE TABLE `t1` ( /*!40000 ALTER TABLE `t1` DISABLE KEYS */; LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES ('Ž™šá'); +INSERT INTO `t1` VALUES (''); UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 86c4d9a7ebb..f842b8f4d0b 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -161,7 +161,7 @@ drop database mysqldump_test_db; # if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); -INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); +INSERT INTO t1 VALUES (_latin1 ''); --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments test t1 # # Bug#8063: make test mysqldump [ fail ] @@ -565,99 +565,6 @@ INSERT INTO t1 VALUES (1),(2),(3); --exec $MYSQL_DUMP --add-drop-database --skip-comments --databases test DROP TABLE t1; -# -# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data -# - -CREATE DATABASE mysqldump_test_db; -USE mysqldump_test_db; -CREATE TABLE t1 ( a INT ); -CREATE TABLE t2 ( a INT ); -INSERT INTO t1 VALUES (1), (2); -INSERT INTO t2 VALUES (1), (2); ---exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db ---exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db t1 t2 -DROP TABLE t1, t2; -DROP DATABASE mysqldump_test_db; - -# -# Testing with tables and databases that don't exists -# or contains illegal characters -# (Bug #9358 mysqldump crashes if tablename starts with \) -# -create database mysqldump_test_db; -use mysqldump_test_db; -create table t1(a varchar(30) primary key, b int not null); -create table t2(a varchar(30) primary key, b int not null); -create table t3(a varchar(30) primary key, b int not null); - ---disable_query_log -select '------ Testing with illegal table names ------' as test_sequence ; ---enable_query_log ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 6 ---exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\d-2-1.sql" 2>&1 - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 6 ---exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\t1" 2>&1 - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 6 ---exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\t1" 2>&1 - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 6 ---exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\\\t1" 2>&1 - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 6 ---exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\1" 2>&1 - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 6 ---exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\\1" 2>&1 - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 6 ---exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t/1" 2>&1 - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 6 ---exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1" - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 6 ---exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T%1" - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 6 ---exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T'1" - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 6 ---exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1" - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 6 ---exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_" - ---disable_query_log -select '------ Testing with illegal database names ------' as test_sequence ; ---enable_query_log ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 2 ---exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_d 2>&1 - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR ---error 2 ---exec $MYSQL_DUMP --compact --skip-comments "mysqld\ump_test_db" 2>&1 - -drop table t1, t2, t3; -drop database mysqldump_test_db; - - - # # Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) From 4296293e03e0f3d93ce01d4882f3eba848cdc0a8 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 15:29:08 +0200 Subject: [PATCH 020/216] Merge fix client/mysqldump.c: Add missing } --- client/mysqldump.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/mysqldump.c b/client/mysqldump.c index 81c6fc1acd4..6db47e71c6a 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2407,6 +2407,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) { table_name= hash_element(&dump_tables, i); get_view_structure(table_name, db); + } } hash_free(&dump_tables); my_free(order_by, MYF(MY_ALLOW_ZERO_PTR)); From 3790b7bc29bbec29211081109ffa3a4dbc9f2908 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 15:32:05 +0200 Subject: [PATCH 021/216] Merge to 5.0 --- mysql-test/r/mysqldump.result | 87 +++++++++++++++++++++++++++++++++ mysql-test/t/mysqldump.test | 91 +++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 080bc4d1e0f..ec1c60ac0d8 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1471,3 +1471,90 @@ CREATE ALGORITHM=UNDEFINED VIEW `db1`.`v2` AS select `db1`.`t2`.`a` AS `a` from drop table t2; drop view v2; drop database db1; +CREATE DATABASE mysqldump_test_db; +USE mysqldump_test_db; +CREATE TABLE t1 ( a INT ); +CREATE TABLE t2 ( a INT ); +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1), (2); + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS `t2`; +CREATE TABLE `t2` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS `t2`; +CREATE TABLE `t2` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +DROP TABLE t1, t2; +DROP DATABASE mysqldump_test_db; +create database mysqldump_test_db; +use mysqldump_test_db; +create table t1(a varchar(30) primary key, b int not null); +create table t2(a varchar(30) primary key, b int not null); +create table t3(a varchar(30) primary key, b int not null); +test_sequence +------ Testing with illegal table names ------ +MYSQL_DUMP_DIR: Couldn't find table: "\d-2-1.sql" + +MYSQL_DUMP_DIR: Couldn't find table: "\t1" + +MYSQL_DUMP_DIR: Couldn't find table: "\t1" + +MYSQL_DUMP_DIR: Couldn't find table: "\\t1" + +MYSQL_DUMP_DIR: Couldn't find table: "t\1" + +MYSQL_DUMP_DIR: Couldn't find table: "t\1" + +MYSQL_DUMP_DIR: Couldn't find table: "t/1" + +test_sequence +------ Testing with illegal database names ------ +MYSQL_DUMP_DIR: Got error: 1049: Unknown database 'mysqldump_test_d' when selecting the database +MYSQL_DUMP_DIR: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when selecting the database +drop table t1, t2, t3; +drop database mysqldump_test_db; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index f842b8f4d0b..45815d207c7 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -588,3 +588,94 @@ create view v2 as select * from t2 where a like 'a%' with check option; drop table t2; drop view v2; drop database db1; +# +# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data +# + +CREATE DATABASE mysqldump_test_db; +USE mysqldump_test_db; +CREATE TABLE t1 ( a INT ); +CREATE TABLE t2 ( a INT ); +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1), (2); +--exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db +--exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db t1 t2 +DROP TABLE t1, t2; +DROP DATABASE mysqldump_test_db; + +# +# Testing with tables and databases that don't exists +# or contains illegal characters +# (Bug #9358 mysqldump crashes if tablename starts with \) +# +create database mysqldump_test_db; +use mysqldump_test_db; +create table t1(a varchar(30) primary key, b int not null); +create table t2(a varchar(30) primary key, b int not null); +create table t3(a varchar(30) primary key, b int not null); + +--disable_query_log +select '------ Testing with illegal table names ------' as test_sequence ; +--enable_query_log +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\d-2-1.sql" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\t1" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\t1" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\\\t1" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\1" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\\1" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t/1" 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1" + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T%1" + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T'1" + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1" + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 6 +--exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_" + +--disable_query_log +select '------ Testing with illegal database names ------' as test_sequence ; +--enable_query_log +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 2 +--exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_d 2>&1 + +--replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR +--error 2 +--exec $MYSQL_DUMP --compact --skip-comments "mysqld\ump_test_db" 2>&1 + +drop table t1, t2, t3; +drop database mysqldump_test_db; + From 4d99f7933afce0a1a39cfced2d9ed991be91284d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 15:43:49 +0200 Subject: [PATCH 022/216] Bug #9558 mysqldump --no-data db t1 t2 format still dumps data - Check the Dflag variable inside of function dump_table to see if data should be dumped or not. - Add test for --xml and --no-data as well Reapplying patch! client/mysqldump.c: Move the check of --no-data flag and "number of fields" inside of the dump_table function. mysql-test/r/mysqldump.result: Update test results add ouput for --xml and --no-data mysql-test/t/mysqldump.test: Add tests for XML and --no-data as well. --- client/mysqldump.c | 26 ++++++++++++++++++++++++-- mysql-test/r/mysqldump.result | 22 ++++++++++++++++++++++ mysql-test/t/mysqldump.test | 2 ++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 6db47e71c6a..db3a7dd980f 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1595,6 +1595,26 @@ static void dump_table(uint numFields, char *table) const char *table_type; int error= 0; + /* Check --no-data flag */ + if (dFlag) + { + if (verbose) + fprintf(stderr, + "-- Skipping dump data for table '%s', --no-data was used\n", + table); + return; + } + + /* Check that there are any fields in the table */ + if(numFields == 0) + { + if (verbose) + fprintf(stderr, + "-- Skipping dump data for table '%s', it has no fields\n", + table); + return; + } + result_table= quote_name(table,table_buff, 1); opt_quoted_table= quote_name(table, table_buff2, 0); @@ -2204,8 +2224,7 @@ static int dump_all_tables_in_db(char *database) if (include_table(hash_key, end - hash_key)) { numrows = get_table_structure(table, database); - if (!dFlag && numrows > 0) - dump_table(numrows,table); + dump_table(numrows,table); my_free(order_by, MYF(MY_ALLOW_ZERO_PTR)); order_by= 0; } @@ -2392,6 +2411,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) } if (opt_xml) print_xml_tag1(md_result_file, "", "database name=", db, "\n"); + /* Dump each selected table */ const char *table_name; for (i= 0; i < dump_tables.records; i++) @@ -2401,6 +2421,8 @@ static int dump_selected_tables(char *db, char **table_names, int tables) numrows = get_table_structure(table_name, db); dump_table(numrows, table_name); } + + /* Dump each selected view */ if (was_views) { for(i=0; i < dump_tables.records; i++) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index ec1c60ac0d8..54568d8b466 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1529,6 +1529,28 @@ CREATE TABLE `t2` ( /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + + + + + + + + + + + + + + + + + + + + + + DROP TABLE t1, t2; DROP DATABASE mysqldump_test_db; create database mysqldump_test_db; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 45815d207c7..a73f163f1ef 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -600,6 +600,8 @@ INSERT INTO t1 VALUES (1), (2); INSERT INTO t2 VALUES (1), (2); --exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db --exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db t1 t2 +--exec $MYSQL_DUMP --skip-comments --skip-create --xml --no-data mysqldump_test_db +--exec $MYSQL_DUMP --skip-comments --skip-create --xml --no-data mysqldump_test_db t1 t2 DROP TABLE t1, t2; DROP DATABASE mysqldump_test_db; From 900fe718d131434d33daf5fd01bf8250bc936bd3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 17:12:02 +0200 Subject: [PATCH 023/216] BUG#9361: Added test cases mysql-test/r/rpl_multi_update3.result: Added test cases mysql-test/t/rpl_multi_update3.test: Added test cases --- mysql-test/r/rpl_multi_update3.result | 81 ++++++++++++++++ mysql-test/t/rpl_multi_update3.test | 133 +++++++++++++++++++++++++- 2 files changed, 210 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/rpl_multi_update3.result b/mysql-test/r/rpl_multi_update3.result index 708b230b19f..1b757b1400c 100644 --- a/mysql-test/r/rpl_multi_update3.result +++ b/mysql-test/r/rpl_multi_update3.result @@ -4,6 +4,8 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; + +-------- Test for BUG#9361 -------- CREATE TABLE t1 ( a int unsigned not null auto_increment primary key, b int unsigned @@ -41,3 +43,82 @@ a b 1 6 2 6 drop table t1,t2; + +-------- Test 1 for BUG#9361 -------- +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +CREATE TABLE t1 ( +a1 char(30), +a2 int, +a3 int, +a4 char(30), +a5 char(30) +); +CREATE TABLE t2 ( +b1 int, +b2 char(30) +); +INSERT INTO t1 VALUES ('Yes', 1, NULL, 'foo', 'bar'); +INSERT INTO t2 VALUES (1, 'baz'); +UPDATE t1 a, t2 +SET a.a1 = 'No' +WHERE a.a2 = +(SELECT b1 +FROM t2 +WHERE b2 = 'baz') +AND a.a3 IS NULL +AND a.a4 = 'foo' +AND a.a5 = 'bar'; +SELECT * FROM t1; +a1 a2 a3 a4 a5 +No 1 NULL foo bar +SELECT * FROM t2; +b1 b2 +1 baz +DROP TABLE t1, t2; + +-------- Test 2 for BUG#9361 -------- +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t3; +CREATE TABLE t1 ( +i INT, +j INT, +x INT, +y INT, +z INT +); +CREATE TABLE t2 ( +i INT, +k INT, +x INT, +y INT, +z INT +); +CREATE TABLE t3 ( +j INT, +k INT, +x INT, +y INT, +z INT +); +INSERT INTO t1 VALUES ( 1, 2,13,14,15); +INSERT INTO t2 VALUES ( 1, 3,23,24,25); +INSERT INTO t3 VALUES ( 2, 3, 1,34,35), ( 2, 3, 1,34,36); +UPDATE t1 AS a +INNER JOIN t2 AS b +ON a.i = b.i +INNER JOIN t3 AS c +ON a.j = c.j AND b.k = c.k +SET a.x = b.x, +a.y = b.y, +a.z = ( +SELECT sum(z) +FROM t3 +WHERE y = 34 +) +WHERE b.x = 23; +SELECT * FROM t1; +i j x y z +1 2 23 24 71 +DROP TABLE t1, t2, t3; diff --git a/mysql-test/t/rpl_multi_update3.test b/mysql-test/t/rpl_multi_update3.test index b8c8ed79532..80b0603eb60 100644 --- a/mysql-test/t/rpl_multi_update3.test +++ b/mysql-test/t/rpl_multi_update3.test @@ -1,7 +1,13 @@ +source include/master-slave.inc; + +############################################################################## +# # Let's verify that multi-update with a subselect does not cause the slave to crash # (BUG#10442) - -source include/master-slave.inc; +# +--disable_query_log +SELECT '-------- Test for BUG#9361 --------' as ""; +--enable_query_log CREATE TABLE t1 ( a int unsigned not null auto_increment primary key, @@ -25,10 +31,129 @@ UPDATE t2, (SELECT a FROM t1) AS t SET t2.b = t.a+5 ; SELECT * FROM t1 ORDER BY a; SELECT * FROM t2 ORDER BY a; -save_master_pos; +sync_slave_with_master; connection slave; -sync_with_master; SELECT * FROM t1 ORDER BY a; SELECT * FROM t2 ORDER BY a; +connection master; drop table t1,t2; + +############################################################################## +# +# Test for BUG#9361: +# Subselects should work inside multi-updates +# +--disable_query_log +SELECT '-------- Test 1 for BUG#9361 --------' as ""; +--enable_query_log + +connection master; + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +--enable_warnings + +CREATE TABLE t1 ( + a1 char(30), + a2 int, + a3 int, + a4 char(30), + a5 char(30) +); + +CREATE TABLE t2 ( + b1 int, + b2 char(30) +); + +# Insert one row per table +INSERT INTO t1 VALUES ('Yes', 1, NULL, 'foo', 'bar'); +INSERT INTO t2 VALUES (1, 'baz'); + +# This should update the row in t1 +UPDATE t1 a, t2 + SET a.a1 = 'No' + WHERE a.a2 = + (SELECT b1 + FROM t2 + WHERE b2 = 'baz') + AND a.a3 IS NULL + AND a.a4 = 'foo' + AND a.a5 = 'bar'; + +sync_slave_with_master; +connection slave; +SELECT * FROM t1; +SELECT * FROM t2; + +connection master; +DROP TABLE t1, t2; + +############################################################################## +# +# Second test for BUG#9361 +# + +--disable_query_log +SELECT '-------- Test 2 for BUG#9361 --------' as ""; +--enable_query_log + +connection master; + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t3; +--enable_warnings + +CREATE TABLE t1 ( + i INT, + j INT, + x INT, + y INT, + z INT +); + +CREATE TABLE t2 ( + i INT, + k INT, + x INT, + y INT, + z INT +); + +CREATE TABLE t3 ( + j INT, + k INT, + x INT, + y INT, + z INT +); + +INSERT INTO t1 VALUES ( 1, 2,13,14,15); +INSERT INTO t2 VALUES ( 1, 3,23,24,25); +INSERT INTO t3 VALUES ( 2, 3, 1,34,35), ( 2, 3, 1,34,36); + +UPDATE t1 AS a +INNER JOIN t2 AS b + ON a.i = b.i +INNER JOIN t3 AS c + ON a.j = c.j AND b.k = c.k +SET a.x = b.x, + a.y = b.y, + a.z = ( + SELECT sum(z) + FROM t3 + WHERE y = 34 + ) +WHERE b.x = 23; + +sync_slave_with_master; +connection slave; + +SELECT * FROM t1; + +connection master; +DROP TABLE t1, t2, t3; From e75bdb4eccf53b741a8ac0dec2fb65fc45223447 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 20:12:21 +0200 Subject: [PATCH 024/216] Fix mysqldump for so that my_programname is set to "mysqldump". Correct test results now when error message output is predictable. client/mysqldump.c: Set mysqldump as progname instead of totally long and strange path provided by libtool. mysql-test/r/mysqldump.result: Update test results mysql-test/t/mysqldump.test: Update test result, removed --replace now ehn test output is predictable. --- client/mysqldump.c | 2 +- mysql-test/r/mysqldump.result | 18 +++++++++--------- mysql-test/t/mysqldump.test | 17 +---------------- 3 files changed, 11 insertions(+), 26 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index db3a7dd980f..ef58621cf59 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2835,7 +2835,7 @@ int main(int argc, char **argv) compatible_mode_normal_str[0]= 0; default_charset= (char *)mysql_universal_client_charset; - MY_INIT(argv[0]); + MY_INIT("mysqldump"); if (get_options(&argc, &argv)) { my_end(0); diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 54568d8b466..737c957bede 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1560,23 +1560,23 @@ create table t2(a varchar(30) primary key, b int not null); create table t3(a varchar(30) primary key, b int not null); test_sequence ------ Testing with illegal table names ------ -MYSQL_DUMP_DIR: Couldn't find table: "\d-2-1.sql" +mysqldump: Couldn't find table: "\d-2-1.sql" -MYSQL_DUMP_DIR: Couldn't find table: "\t1" +mysqldump: Couldn't find table: "\t1" -MYSQL_DUMP_DIR: Couldn't find table: "\t1" +mysqldump: Couldn't find table: "\t1" -MYSQL_DUMP_DIR: Couldn't find table: "\\t1" +mysqldump: Couldn't find table: "\\t1" -MYSQL_DUMP_DIR: Couldn't find table: "t\1" +mysqldump: Couldn't find table: "t\1" -MYSQL_DUMP_DIR: Couldn't find table: "t\1" +mysqldump: Couldn't find table: "t\1" -MYSQL_DUMP_DIR: Couldn't find table: "t/1" +mysqldump: Couldn't find table: "t/1" test_sequence ------ Testing with illegal database names ------ -MYSQL_DUMP_DIR: Got error: 1049: Unknown database 'mysqldump_test_d' when selecting the database -MYSQL_DUMP_DIR: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when selecting the database +mysqldump: Got error: 1049: Unknown database 'mysqldump_test_d' when selecting the database +mysqldump: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when selecting the database drop table t1, t2, t3; drop database mysqldump_test_db; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index a73f163f1ef..a904ffcc366 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -619,62 +619,47 @@ create table t3(a varchar(30) primary key, b int not null); --disable_query_log select '------ Testing with illegal table names ------' as test_sequence ; --enable_query_log ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\d-2-1.sql" 2>&1 - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\t1" 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\t1" 2>&1 - ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR + --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\\\t1" 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\1" 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\\1" 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t/1" 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1" ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T%1" ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T'1" ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1" ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_" --disable_query_log select '------ Testing with illegal database names ------' as test_sequence ; --enable_query_log ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 2 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_d 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 2 --exec $MYSQL_DUMP --compact --skip-comments "mysqld\ump_test_db" 2>&1 From e5d0e337f8cabe2824dd324888bca22fd628b350 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 20:22:54 +0200 Subject: [PATCH 025/216] BUG#9657 mysqldump xml ( -x ) does not format NULL fields correctly - Importing the bug fixes by patch due to merge problems. client/mysqldump.c: Import patch patch mysql-test/r/mysqldump.result: Import patch patch mysql-test/t/mysqldump.test: Import patch patch --- client/mysqldump.c | 48 +++++++++++++++++++++++++-- mysql-test/r/mysqldump.result | 62 +++++++++++++++++++++++++++++++++-- mysql-test/t/mysqldump.test | 13 ++++++++ 3 files changed, 118 insertions(+), 5 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 207235983da..f4116253f8f 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -463,7 +463,10 @@ static void write_header(FILE *sql_file, char *db_name) if (opt_xml) { fputs("\n", sql_file); - fputs("\n", sql_file); + fputs("\n", sql_file); check_io(sql_file); } else if (!opt_compact) @@ -1050,6 +1053,40 @@ static void print_xml_tag1(FILE * xml_file, const char* sbeg, } +/* + Print xml tag with for a field that is null + + SYNOPSIS + print_xml_null_tag() + xml_file - output file + sbeg - line beginning + stag_atr - tag and attribute + sval - value of attribute + send - line ending + + DESCRIPTION + Print tag with one attribute to the xml_file. Format is: + + NOTE + sval MUST be a NULL terminated string. + sval string will be qouted before output. +*/ + +static void print_xml_null_tag(FILE * xml_file, const char* sbeg, + const char* stag_atr, const char* sval, + const char* send) +{ + fputs(sbeg, xml_file); + fputs("<", xml_file); + fputs(stag_atr, xml_file); + fputs("\"", xml_file); + print_quoted_xml(xml_file, sval, strlen(sval)); + fputs("\" xsi:nil=\"true\" />", xml_file); + fputs(send, xml_file); + check_io(xml_file); +} + + /* Print xml tag with many attributes. @@ -1870,7 +1907,14 @@ static void dumpTable(uint numFields, char *table) } } else - fputs("NULL", md_result_file); + { + /* The field value is NULL */ + if (!opt_xml) + fputs("NULL", md_result_file); + else + print_xml_null_tag(md_result_file, "\t\t", "field name=", + field->name, "\n"); + } check_io(md_result_file); } } diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 50399c91ec9..e465760736f 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -2,7 +2,7 @@ DROP TABLE IF EXISTS t1, `"t"1`; CREATE TABLE t1(a int); INSERT INTO t1 VALUES (1), (2); - + @@ -103,7 +103,7 @@ DROP TABLE t1; CREATE TABLE t1(a int, b text, c varchar(3)); INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES"); - + @@ -128,7 +128,7 @@ DROP TABLE t1; CREATE TABLE t1 (`a"b"` char(2)); INSERT INTO t1 VALUES ("1\""), ("\"2"); - + @@ -1436,3 +1436,59 @@ MYSQL_DUMP_DIR: Got error: 1049: Unknown database 'mysqldump_test_d' when select MYSQL_DUMP_DIR: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when selecting the database drop table t1, t2, t3; drop database mysqldump_test_db; +create table t1 (a int(10)); +create table t2 (pk int primary key auto_increment, +a int(10), b varchar(30), c datetime, d blob, e text); +insert into t1 values (NULL), (10), (20); +insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thirty"); + + + + + + + + + 10 + + + 20 + + + + + 1 + + + + + + + + 2 + 10 + + + + + + + 3 + + twenty + + + + + + 4 + 30 + thirty + + + + + + + +drop table t1, t2; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 349b1e96239..2ee7fee2802 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -636,3 +636,16 @@ drop table t1, t2, t3; drop database mysqldump_test_db; + +# +# Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly +# + +create table t1 (a int(10)); +create table t2 (pk int primary key auto_increment, +a int(10), b varchar(30), c datetime, d blob, e text); +insert into t1 values (NULL), (10), (20); +insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thirty"); +--exec $MYSQL_DUMP --skip-comments --xml --no-create-info test +drop table t1, t2; + From 406673b0b320d66562e2778323c59034c22be225 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 20:37:14 +0200 Subject: [PATCH 026/216] Fix so that my_progname is set to "mysqldump" client/mysqldump.c: Fix progname of mysqldump mysql-test/r/mysqldump.result: Update test results mysql-test/t/mysqldump.test: Update tests, no need for results --- client/mysqldump.c | 2 +- mysql-test/r/mysqldump.result | 21 +++++++++++---------- mysql-test/t/mysqldump.test | 16 +--------------- 3 files changed, 13 insertions(+), 26 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index f4116253f8f..04f2f40068f 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2621,7 +2621,7 @@ int main(int argc, char **argv) compatible_mode_normal_str[0]= 0; default_charset= (char *)mysql_universal_client_charset; - MY_INIT(argv[0]); + MY_INIT("mysqldump"); if (get_options(&argc, &argv)) { my_end(0); diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index e465760736f..cb2e8e5528a 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1416,26 +1416,27 @@ create table t2(a varchar(30) primary key, b int not null); create table t3(a varchar(30) primary key, b int not null); test_sequence ------ Testing with illegal table names ------ -MYSQL_DUMP_DIR: Couldn't find table: "\d-2-1.sql" +mysqldump: Couldn't find table: "\d-2-1.sql" -MYSQL_DUMP_DIR: Couldn't find table: "\t1" +mysqldump: Couldn't find table: "\t1" -MYSQL_DUMP_DIR: Couldn't find table: "\t1" +mysqldump: Couldn't find table: "\t1" -MYSQL_DUMP_DIR: Couldn't find table: "\\t1" +mysqldump: Couldn't find table: "\\t1" -MYSQL_DUMP_DIR: Couldn't find table: "t\1" +mysqldump: Couldn't find table: "t\1" -MYSQL_DUMP_DIR: Couldn't find table: "t\1" +mysqldump: Couldn't find table: "t\1" -MYSQL_DUMP_DIR: Couldn't find table: "t/1" +mysqldump: Couldn't find table: "t/1" test_sequence ------ Testing with illegal database names ------ -MYSQL_DUMP_DIR: Got error: 1049: Unknown database 'mysqldump_test_d' when selecting the database -MYSQL_DUMP_DIR: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when selecting the database +mysqldump: Got error: 1049: Unknown database 'mysqldump_test_d' when selecting the database +mysqldump: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when selecting the database drop table t1, t2, t3; drop database mysqldump_test_db; +use test; create table t1 (a int(10)); create table t2 (pk int primary key auto_increment, a int(10), b varchar(30), c datetime, d blob, e text); @@ -1453,7 +1454,7 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir 20 - + diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 2ee7fee2802..7f3d3adebbc 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -573,68 +573,54 @@ create table t3(a varchar(30) primary key, b int not null); --disable_query_log select '------ Testing with illegal table names ------' as test_sequence ; --enable_query_log ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\d-2-1.sql" 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\t1" 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\t1" 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\\\t1" 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\1" 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\\1" 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t/1" 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1" ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T%1" ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T'1" ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_1" ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 6 --exec $MYSQL_DUMP --compact --skip-comments "mysqldump_test_db" "T_" --disable_query_log select '------ Testing with illegal database names ------' as test_sequence ; --enable_query_log ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 2 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_d 2>&1 ---replace_result $MYSQL_DUMP_DIR MYSQL_DUMP_DIR --error 2 --exec $MYSQL_DUMP --compact --skip-comments "mysqld\ump_test_db" 2>&1 drop table t1, t2, t3; drop database mysqldump_test_db; - +use test; # From 572d3e990ae304724477ec32bcd5fc5044196347 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 20:44:32 +0200 Subject: [PATCH 027/216] Will do cset -x on this. mysql-test/t/mysqldump.test: Once again. This change should not be here. Every time mysqldump.test has been edited in two different clones this problem appears. --- mysql-test/t/mysqldump.test | 67 ++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 7f3d3adebbc..6400afff610 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -2,7 +2,10 @@ --source include/not_embedded.inc --disable_warnings -DROP TABLE IF EXISTS t1, `"t"1`; +DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa; +drop database if exists mysqldump_test_db; +drop database if exists db1; +drop view if exists v1, v2; --enable_warnings # XML output @@ -16,7 +19,7 @@ DROP TABLE t1; # Bug #2005 # -CREATE TABLE t1 (a decimal(240, 20)); +CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); --exec $MYSQL_DUMP --compact test t1 @@ -27,7 +30,7 @@ DROP TABLE t1; # CREATE TABLE t1 (a double); -INSERT INTO t1 VALUES (-9e999999); +INSERT INTO t1 VALUES ('-9e999999'); # The following replaces is here because some systems replaces the above # double with '-inf' and others with MAX_DOUBLE --replace_result (-1.79769313486232e+308) (RES) (NULL) (RES) @@ -131,6 +134,15 @@ insert into t1 values (1),(2),(3); --exec rm $MYSQL_TEST_DIR/var/tmp/t1.txt drop table t1; +# +# dump of view +# +create table t1(a int); +create view v1 as select * from t1; +--exec $MYSQL_DUMP --skip-comments test +drop view v1; +drop table t1; + # # Bug #6101: create database problem # @@ -149,7 +161,7 @@ drop database mysqldump_test_db; # if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); -INSERT INTO t1 VALUES (_latin1 ''); +INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments test t1 # # Bug#8063: make test mysqldump [ fail ] @@ -185,15 +197,24 @@ INSERT INTO `t1` VALUES (0x602010000280100005E71A); --exec $MYSQL_DUMP --skip-extended-insert --hex-blob test --skip-comments t1 DROP TABLE t1; +# +# Bug #9756 +# + +CREATE TABLE t1 (a char(10)); +INSERT INTO t1 VALUES ('\''); +--exec $MYSQL_DUMP --skip-comments test t1 +DROP TABLE t1; + # # Test for --insert-ignore # -CREATE TABLE t1 (a decimal(240, 20)); -INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), -("0987654321098765432109876543210987654321"); ---exec $MYSQL_DUMP --insert-ignore --skip-comments test t1 ---exec $MYSQL_DUMP --insert-ignore --skip-comments --delayed-insert test t1 +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t1 VALUES (4),(5),(6); +--exec $MYSQL_DUMP --skip-comments --insert-ignore test t1 +--exec $MYSQL_DUMP --skip-comments --insert-ignore --delayed-insert test t1 DROP TABLE t1; # @@ -544,6 +565,28 @@ INSERT INTO t1 VALUES (1),(2),(3); --exec $MYSQL_DUMP --add-drop-database --skip-comments --databases test DROP TABLE t1; +# +# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# + +create database db1; +use db1; + +CREATE TABLE t2 ( + a varchar(30) default NULL, + KEY a (a(5)) +); + +INSERT INTO t2 VALUES ('alfred'); +INSERT INTO t2 VALUES ('angie'); +INSERT INTO t2 VALUES ('bingo'); +INSERT INTO t2 VALUES ('waffle'); +INSERT INTO t2 VALUES ('lemon'); +create view v2 as select * from t2 where a like 'a%' with check option; +--exec $MYSQL_DUMP --skip-comments db1 +drop table t2; +drop view v2; +drop database db1; # # Bug #9558 mysqldump --no-data db t1 t2 format still dumps data # @@ -556,6 +599,8 @@ INSERT INTO t1 VALUES (1), (2); INSERT INTO t2 VALUES (1), (2); --exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db --exec $MYSQL_DUMP --skip-comments --no-data mysqldump_test_db t1 t2 +--exec $MYSQL_DUMP --skip-comments --skip-create --xml --no-data mysqldump_test_db +--exec $MYSQL_DUMP --skip-comments --skip-create --xml --no-data mysqldump_test_db t1 t2 DROP TABLE t1, t2; DROP DATABASE mysqldump_test_db; @@ -575,13 +620,12 @@ select '------ Testing with illegal table names ------' as test_sequence ; --enable_query_log --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\d-2-1.sql" 2>&1 - --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\t1" 2>&1 --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\t1" 2>&1 - + --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\\\t1" 2>&1 @@ -620,7 +664,6 @@ select '------ Testing with illegal database names ------' as test_sequence ; drop table t1, t2, t3; drop database mysqldump_test_db; -use test; # From 051e30a45ca90a4c0ced745039b0753eeb92b1c2 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 20:45:20 +0200 Subject: [PATCH 028/216] Cset exclude: msvensson@neptunus.(none)|ChangeSet|20050622184432|37770 mysql-test/t/mysqldump.test: Exclude --- mysql-test/t/mysqldump.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 6400afff610..97711de7072 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -161,7 +161,7 @@ drop database mysqldump_test_db; # if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); -INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); +INSERT INTO t1 VALUES (_latin1 ''); --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments test t1 # # Bug#8063: make test mysqldump [ fail ] From 297bc30c4590c8047ec28130bec53cc727ba9b40 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 22 Jun 2005 20:49:58 +0200 Subject: [PATCH 029/216] Merge fixes mysql-test/r/mysqldump.result: Update test results mysql-test/t/mysqldump.test: Add "use test" removed by the cset -x --- mysql-test/r/mysqldump.result | 4 ++-- mysql-test/t/mysqldump.test | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 9075bec003b..573b2b54141 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1530,7 +1530,7 @@ CREATE TABLE `t2` ( /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - + @@ -1541,7 +1541,7 @@ CREATE TABLE `t2` ( - + diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 97711de7072..ec49eec8b46 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -664,7 +664,7 @@ select '------ Testing with illegal database names ------' as test_sequence ; drop table t1, t2, t3; drop database mysqldump_test_db; - +use test; # # Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly From e4296f586851746ad265e52c18e8e33080eb1a86 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 10:56:44 +0300 Subject: [PATCH 030/216] Fix for BUG#11185. The source of the problem is in Field_longlong::cmp. If 'this' is an unsigned number, the method casts both the current value, and the constant that we compare with to an unsigned number. As a result if the constant we compare with is a negative number, it wraps to some unsigned number, and the comparison is incorrect. When the optimizer chooses the "range" access method, this problem causes handler::read_range_next to reject the current key when the upper bound key is a negative number because handler::compare_key incorrectly considers the positive and negative keys to be equal. The current patch does not correct the source of the problem in Field_longlong::cmp because it is not easy to propagate sign information about the constant at query execution time. Instead the patch changes the range optimizer so that it never compares unsiged fields with negative constants. As an added benefit, queries that do such comparisons will execute faster because the range optimizer replaces conditions like: (a) (unsigned_int [< | <=] negative_constant) == FALSE (b) (unsigned_int [> | >=] negative_constant) == TRUE with the corresponding constants. In some cases this may even result in constant time execution. mysql-test/r/range.result: - Changed incorrect result of an old test - Added new results for BUG#11185 mysql-test/t/range.test: - Added new tests for BUG#11185 - Deleted an old comment because now the problem is fixed sql/opt_range.cc: Added a new optimization to the range optimizer where we detect that an UNSIGNED field is compared with a negative constant. Depending on the comparison operator, we know directly that the result of the comparison is either TRUE or FALSE for all input values, and we need not check each value. This optimization is also necessary so that the index range access method produces correct results when comparing unsigned fields with negative constants. --- mysql-test/r/range.result | 33 ++++++++++++++++++++++++++++++++- mysql-test/t/range.test | 22 +++++++++++++++++++--- sql/opt_range.cc | 38 +++++++++++++++++++++++++++++++++++--- 3 files changed, 86 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index afd91ce5fe9..07e96aee22b 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -556,11 +556,42 @@ count(*) 0 select count(*) from t1 where x > -16; count(*) -1 +2 select count(*) from t1 where x = 18446744073709551601; count(*) 1 drop table t1; +create table t1 (a bigint unsigned); +create index t1i on t1(a); +insert into t1 select 18446744073709551615; +insert into t1 select 18446744073709551614; +explain select * from t1 where a <> -1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index t1i t1i 9 NULL 2 Using where; Using index +select * from t1 where a <> -1; +a +18446744073709551614 +18446744073709551615 +explain select * from t1 where a > -1 or a < -1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index t1i t1i 9 NULL 2 Using where; Using index +select * from t1 where a > -1 or a < -1; +a +18446744073709551614 +18446744073709551615 +explain select * from t1 where a > -1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index t1i t1i 9 NULL 2 Using where; Using index +select * from t1 where a > -1; +a +18446744073709551614 +18446744073709551615 +explain select * from t1 where a < -1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +select * from t1 where a < -1; +a +drop table t1; set names latin1; create table t1 (a char(10), b text, key (a)) character set latin1; INSERT INTO t1 (a) VALUES diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index b51a79fba77..92b7b848a8a 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -423,14 +423,30 @@ select count(*) from t1 where x=0; select count(*) from t1 where x<0; select count(*) from t1 where x < -16; select count(*) from t1 where x = -16; -# The following query returns wrong value because the range optimizer can't -# handle search on a signed value for an unsigned parameter. This will be fixed in -# 5.0 select count(*) from t1 where x > -16; select count(*) from t1 where x = 18446744073709551601; drop table t1; +# +# Bug #11185 incorrect comparison of unsigned int to signed constant +# +create table t1 (a bigint unsigned); +create index t1i on t1(a); +insert into t1 select 18446744073709551615; +insert into t1 select 18446744073709551614; + +explain select * from t1 where a <> -1; +select * from t1 where a <> -1; +explain select * from t1 where a > -1 or a < -1; +select * from t1 where a > -1 or a < -1; +explain select * from t1 where a > -1; +select * from t1 where a > -1; +explain select * from t1 where a < -1; +select * from t1 where a < -1; + +drop table t1; + # # Bug #6045: Binary Comparison regression in MySQL 4.1 # Binary searches didn't use a case insensitive index. diff --git a/sql/opt_range.cc b/sql/opt_range.cc index bd1befb436f..75cf9e6b3f0 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -960,7 +960,9 @@ get_mm_parts(PARAM *param, COND *cond_func, Field *field, if (sel_arg->type == SEL_ARG::IMPOSSIBLE) { tree->type=SEL_TREE::IMPOSSIBLE; - DBUG_RETURN(tree); + /* If this is an NE_FUNC, we still need to check GT_FUNC. */ + if (!ne_func) + DBUG_RETURN(tree); } } else @@ -979,8 +981,9 @@ get_mm_parts(PARAM *param, COND *cond_func, Field *field, SEL_TREE *tree2= get_mm_parts(param, cond_func, field, Item_func::GT_FUNC, value, cmp_type); - if (tree2) - tree= tree_or(param,tree,tree2); + if (!tree2) + DBUG_RETURN(0) + tree= tree_or(param,tree,tree2); } DBUG_RETURN(tree); } @@ -1159,6 +1162,35 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, if (!(tree=new SEL_ARG(field,str,str2))) DBUG_RETURN(0); // out of memory + /* + Check if we are comparing an UNSIGNED integer with a negative constant. + In this case we know that: + (a) (unsigned_int [< | <=] negative_constant) == FALSE + (b) (unsigned_int [> | >=] negative_constant) == TRUE + In case (a) the condition is false for all values, and in case (b) it + is true for all values, so we can avoid unnecessary retrieval and condition + testing, and we also get correct comparison of unsinged integers with + negative integers (which otherwise fails because at query execution time + negative integers are cast to unsigned if compared with unsigned). + */ + Item_result field_result_type= field->result_type(); + Item_result value_result_type= value->result_type(); + if (field_result_type == INT_RESULT && value_result_type == INT_RESULT && + ((Field_num*)field)->unsigned_flag && !((Item_int*)value)->unsigned_flag) + { + longlong item_val= value->val_int(); + if (item_val < 0) + { + if (type == Item_func::LT_FUNC || type == Item_func::LE_FUNC) + { + tree->type= SEL_ARG::IMPOSSIBLE; + DBUG_RETURN(tree); + } + if (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC) + DBUG_RETURN(0); + } + } + switch (type) { case Item_func::LT_FUNC: if (field_is_equal_to_item(field,value)) From c4a8325da2583f783cd81d231a309b2080e34954 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 02:08:30 -0700 Subject: [PATCH 031/216] opt_range.cc: Fixed buf #11487. Added a call of QUICK_RANGE_SELECT::init to the QUICK_RANGE_SELECT::reset method. Without it the second evaluation of a subquery employing the range access failed. subselect.result, subselect.test: Added a test case for bug #11487. mysql-test/t/subselect.test: Added a test case for bug #11487. mysql-test/r/subselect.result: Added a test case for bug #11487. sql/opt_range.cc: Fixed buf #11487. Added a call of QUICK_RANGE_SELECT::init to the QUICK_RANGE_SELECT::reset method. Without it the second evaluation of a subquery employing the range access failed. --- mysql-test/r/subselect.result | 21 +++++++++++++++++++++ mysql-test/t/subselect.test | 22 ++++++++++++++++++++++ sql/opt_range.cc | 5 ++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 6703147c635..736559f8569 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2816,3 +2816,24 @@ select * from t1; EMPNUM E1 DROP TABLE t1,t2; +CREATE TABLE t1(select_id BIGINT, values_id BIGINT); +INSERT INTO t1 VALUES (1, 1); +CREATE TABLE t2 (select_id BIGINT, values_id BIGINT, +PRIMARY KEY(select_id,values_id)); +INSERT INTO t2 VALUES (0, 1), (0, 2), (0, 3), (1, 5); +SELECT values_id FROM t1 +WHERE values_id IN (SELECT values_id FROM t2 +WHERE select_id IN (1, 0)); +values_id +1 +SELECT values_id FROM t1 +WHERE values_id IN (SELECT values_id FROM t2 +WHERE select_id BETWEEN 0 AND 1); +values_id +1 +SELECT values_id FROM t1 +WHERE values_id IN (SELECT values_id FROM t2 +WHERE select_id = 0 OR select_id = 1); +values_id +1 +DROP TABLE t1, t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 2e6cea8468b..1e4930d385d 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1837,3 +1837,25 @@ WHERE t1.EMPNUM NOT IN WHERE t1.EMPNUM = t2.EMPNUM); select * from t1; DROP TABLE t1,t2; + +# +# Test for bug #11487: range access in a subquery +# + +CREATE TABLE t1(select_id BIGINT, values_id BIGINT); +INSERT INTO t1 VALUES (1, 1); +CREATE TABLE t2 (select_id BIGINT, values_id BIGINT, + PRIMARY KEY(select_id,values_id)); +INSERT INTO t2 VALUES (0, 1), (0, 2), (0, 3), (1, 5); + +SELECT values_id FROM t1 +WHERE values_id IN (SELECT values_id FROM t2 + WHERE select_id IN (1, 0)); +SELECT values_id FROM t1 +WHERE values_id IN (SELECT values_id FROM t2 + WHERE select_id BETWEEN 0 AND 1); +SELECT values_id FROM t1 +WHERE values_id IN (SELECT values_id FROM t2 + WHERE select_id = 0 OR select_id = 1); + +DROP TABLE t1, t2; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 0a8627b1fa0..200e6dfbabb 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5992,7 +5992,10 @@ int QUICK_RANGE_SELECT::reset() next=0; range= NULL; cur_range= (QUICK_RANGE**) ranges.buffer; - + + if (file->inited == handler::NONE && (error= file->ha_index_init(index))) + DBUG_RETURN(error); + /* Do not allocate the buffers twice. */ if (multi_range_length) { From 0beb0abf5a7572a461aff86eeaedbf8307bfc911 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 11:30:40 +0200 Subject: [PATCH 032/216] - fixed text file generation - the node names in the info page had changed BitKeeper/deleted/.del-generate-flag-images~f77476753fff8186: Delete: Docs/Support/generate-flag-images Docs/Makefile.am: - fixed node names for the new info file Docs/Support/generate-text-files.pl: - stop printing if the index was reached --- Docs/Makefile.am | 8 ++++---- Docs/Support/generate-flag-images | 31 ----------------------------- Docs/Support/generate-text-files.pl | 2 +- 3 files changed, 5 insertions(+), 36 deletions(-) delete mode 100755 Docs/Support/generate-flag-images diff --git a/Docs/Makefile.am b/Docs/Makefile.am index 8577fee52cb..dba3a4f819c 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -36,19 +36,19 @@ CLEAN_FILES: $(txt_files) GT = $(srcdir)/Support/generate-text-files.pl ../INSTALL-SOURCE: mysql.info $(GT) - perl -w $(GT) mysql.info "Installing" "Tutorial" > $@ + perl -w $(GT) mysql.info "installing-source" "windows-source-build" > $@ # We put the description for the binary installation here so that # people who download source wont have to see it. It is moved up to # the toplevel by the script that makes the binary tar files. INSTALL-BINARY: mysql.info $(GT) - perl -w $(GT) mysql.info "Installing binary" "Installing source" > $@ + perl -w $(GT) mysql.info "installing-binary" "installing-source" > $@ ../EXCEPTIONS-CLIENT: mysql.info $(GT) - perl -w $(GT) mysql.info "MySQL FLOSS License Exception" "Function Index" > $@ + perl -w $(GT) mysql.info "mysql-floss-license-exception" "function-index" > $@ ../support-files/MacOSX/ReadMe.txt: mysql.info $(GT) - perl -w $(GT) mysql.info "Mac OS X installation" "NetWare installation" > $@ + perl -w $(GT) mysql.info "mac-os-x-installation" "netware-installation" > $@ # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/Docs/Support/generate-flag-images b/Docs/Support/generate-flag-images deleted file mode 100755 index 21140388012..00000000000 --- a/Docs/Support/generate-flag-images +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -flags=`grep @image mirrors.texi | cut -d" " -f1 | cut -d/ -f2 | tr -d "}" | sort | uniq` - -set -x -cd Flags - -for c in $flags -do - # For PNM, to be used later - giftopnm ../Raw-Flags/$c.gif | pnmscale -xsize 30 > $c-tmp.pnm - pnmpaste $c-tmp.pnm 1 1 ../Images/flag-background.pnm > $c.pnm - rm -f $c-tmp.pnm - - # For GIF version - ppmtogif $c.pnm > $c.gif - # or cjpeg -optimize -quality 70 -outfile $c.jpg - - # For EPS version - pnmtops -noturn $c.pnm > $c.eps - - # For PDF version - ps2pdf $c.eps $c.pdf - - # For text version - echo -n "" > $c.txt - - # PNM isn't really needed - rm -f $c.pnm - -done diff --git a/Docs/Support/generate-text-files.pl b/Docs/Support/generate-text-files.pl index 6470baaa6e9..0829525f679 100755 --- a/Docs/Support/generate-text-files.pl +++ b/Docs/Support/generate-text-files.pl @@ -13,7 +13,7 @@ while () { if ($in) { - if (/Node: $tnode,/) + if (/Node: $tnode,/ || /\[index/) { $in = 0; } From 089d20959e2f5551473f843f320495a811b6191b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 16:04:10 +0500 Subject: [PATCH 033/216] WL#2286 - Compile MySQL w/YASSL support Fix for "multiple definition of __cxa_pure_virtual" link failure when compiling with icc. extra/yassl/taocrypt/include/runtime.hpp: Do not define __cxa_pure_virtual for ICC. Fixes "multiple definition of __cxa_pure_virtual" link failure on production. --- extra/yassl/taocrypt/include/runtime.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/yassl/taocrypt/include/runtime.hpp b/extra/yassl/taocrypt/include/runtime.hpp index 70768bb01d1..f506040f0d8 100644 --- a/extra/yassl/taocrypt/include/runtime.hpp +++ b/extra/yassl/taocrypt/include/runtime.hpp @@ -25,7 +25,7 @@ -#if !defined(yaSSL_NEW_HPP) && defined(__GNUC__) +#if !defined(yaSSL_NEW_HPP) && defined(__GNUC__) && !defined(__ICC) #define yaSSL_NEW_HPP From dfaf7a01845e137769b4146c8d98a1b749271bc0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 04:10:43 -0700 Subject: [PATCH 034/216] opt_range.cc: Identation correction. sql/opt_range.cc: Identation correction. --- sql/opt_range.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 1d6acb3aee1..59ec1140d15 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5994,7 +5994,7 @@ int QUICK_RANGE_SELECT::reset() cur_range= (QUICK_RANGE**) ranges.buffer; if (file->inited == handler::NONE && (error= file->ha_index_init(index))) - DBUG_RETURN(error); + DBUG_RETURN(error); /* Do not allocate the buffers twice. */ if (multi_range_length) From 98253bd64d51d42f914c59ebabe89e3975ba9cc8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 06:15:50 -0700 Subject: [PATCH 035/216] 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"; } }; From 6311217a23cd8424ad10a23ee752141257275252 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 18:13:58 +0400 Subject: [PATCH 036/216] Fix modify_defaults_file as agreed with monty (correct all occurences of an option in the section) mysys/default_modify.c: Correct all occurences of an option in the section. To avoid memory problems preallocate reserve of 1K, and realloc it later if needed (almost never). --- mysys/default_modify.c | 57 ++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/mysys/default_modify.c b/mysys/default_modify.c index 00caa7beed6..d40529817cd 100644 --- a/mysys/default_modify.c +++ b/mysys/default_modify.c @@ -20,6 +20,8 @@ #include #define BUFF_SIZE 1024 +/* should be big enough to handle at least one line */ +#define RESERVE 1024 #ifdef __WIN__ #define NEWLINE "\r\n" @@ -66,8 +68,10 @@ int modify_defaults_file(const char *file_location, const char *option, FILE *cnf_file; MY_STAT file_stat; char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer; - uint opt_len, optval_len, sect_len, nr_newlines= 0; + uint opt_len, optval_len, sect_len, nr_newlines= 0, buffer_size; my_bool in_section= FALSE, opt_applied= 0; + int reserve_occupied= 0, reserve_extended= 1, old_opt_len; + int new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN; DBUG_ENTER("modify_defaults_file"); if (!(cnf_file= my_fopen(file_location, O_RDWR | O_BINARY, MYF(0)))) @@ -80,23 +84,26 @@ int modify_defaults_file(const char *file_location, const char *option, opt_len= (uint) strlen(option); optval_len= (uint) strlen(option_value); + /* calculate the size of the buffer we need */ + buffer_size= sizeof(char) * (file_stat.st_size + + /* option name len */ + opt_len + + /* reserve for '=' char */ + 1 + + /* option value len */ + optval_len + + /* reserve space for newline */ + NEWLINE_LEN + + /* The ending zero */ + 1 + + /* reserve some additional space */ + RESERVE); + /* Reserve space to read the contents of the file and some more for the option we want to add. */ - if (!(file_buffer= (char*) my_malloc(sizeof(char) * - (file_stat.st_size + - /* option name len */ - opt_len + - /* reserve space for newline */ - NEWLINE_LEN + - /* reserve for '=' char */ - 1 + - /* option value len */ - optval_len + - /* The ending zero */ - 1), MYF(MY_WME)))) - + if (!(file_buffer= (char*) my_malloc(buffer_size, MYF(MY_WME)))) goto malloc_err; sect_len= (uint) strlen(section_name); @@ -115,13 +122,31 @@ int modify_defaults_file(const char *file_location, const char *option, } /* correct the option */ - if (!opt_applied && in_section && !strncmp(src_ptr, option, opt_len) && + if (in_section && !strncmp(src_ptr, option, opt_len) && (*(src_ptr + opt_len) == '=' || my_isspace(&my_charset_latin1, *(src_ptr + opt_len)) || *(src_ptr + opt_len) == '\0')) { + /* + we should change all options. If opt_applied is set, we are running + into reserved memory area. Hence we should check for overruns. + */ + if (opt_applied) + { + old_opt_len= strlen(linebuff); + /* could be negative */ + reserve_occupied+= new_opt_len - old_opt_len; + if (reserve_occupied > RESERVE*reserve_extended) + { + file_buffer= (char*) my_realloc(file_buffer, buffer_size + + RESERVE*reserve_extended, + MYF(MY_WME)); + reserve_extended++; + } + } + else + opt_applied= 1; dst_ptr= add_option(dst_ptr, option_value, option, remove_option); - opt_applied= 1; } else { From a5e742fedd4324d29867a15a6cabb54959108fbb Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 18:29:10 +0300 Subject: [PATCH 037/216] fixed environment restoring in case of error during SP function execution (BUG#9503) #define macro improvement mysql-test/r/sp-security.result: BUG#9503: reseting correct parameters of thread after error in SP function mysql-test/t/sp-security.test: BUG#9503: reseting correct parameters of thread after error in SP function sql/item_func.cc: fixed environment restoring in case of error during SP function execution sql/protocol.cc: added debug print sql/sql_class.h: fixed #defines to force them to be alvaise in piar, and variable name made more complex for accident repeating in other code --- mysql-test/r/sp-security.result | 17 ++++++++++++++++ mysql-test/t/sp-security.test | 36 +++++++++++++++++++++++++++++++++ sql/item_func.cc | 29 +++++++++++++------------- sql/protocol.cc | 5 +++++ sql/sql_class.h | 6 +++--- 5 files changed, 76 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index ee72fde7324..4ace6f59411 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -194,3 +194,20 @@ use test; drop database sptest; delete from mysql.user where user='usera' or user='userb' or user='userc'; delete from mysql.procs_priv where user='usera' or user='userb' or user='userc'; +drop function if exists bug_9503; +create database mysqltest// +use mysqltest// +create table t1 (s1 int)// +grant select on t1 to user1@localhost// +create function bug_9503 () returns int sql security invoker begin declare v int; +select min(s1) into v from t1; return v; end// +use mysqltest; +select bug_9503(); +ERROR 42000: execute command denied to user 'user1'@'localhost' for routine 'mysqltest.bug_9503' +grant execute on function bug_9503 to user1@localhost; +do 1; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1@localhost; +drop function bug_9503; +use test; +drop database mysqltest; diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index e1d8043ccda..72fe6c332bf 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -304,3 +304,39 @@ drop database sptest; delete from mysql.user where user='usera' or user='userb' or user='userc'; delete from mysql.procs_priv where user='usera' or user='userb' or user='userc'; +# +# BUG#9503: reseting correct parameters of thread after error in SP function +# +connect (root,localhost,root,,test); +connection root; + +--disable_warnings +drop function if exists bug_9503; +--enable_warnings +delimiter //; +create database mysqltest// +use mysqltest// +create table t1 (s1 int)// +grant select on t1 to user1@localhost// +create function bug_9503 () returns int sql security invoker begin declare v int; +select min(s1) into v from t1; return v; end// +delimiter ;// + +connect (user1,localhost,user1,,test); +connection user1; +use mysqltest; +-- error 1370 +select bug_9503(); + +connection root; +grant execute on function bug_9503 to user1@localhost; + +connection user1; +do 1; +use test; + +connection root; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1@localhost; +drop function bug_9503; +use test; +drop database mysqltest; diff --git a/sql/item_func.cc b/sql/item_func.cc index 57f68bbc2a0..de497014240 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4807,42 +4807,37 @@ Item_func_sp::execute(Item **itp) DBUG_ENTER("Item_func_sp::execute"); THD *thd= current_thd; ulong old_client_capabilites; - int res; + int res= -1; bool save_in_sub_stmt= thd->transaction.in_sub_stmt; + my_bool nsok; #ifndef NO_EMBEDDED_ACCESS_CHECKS st_sp_security_context save_ctx; #endif - if (! m_sp) + if (! m_sp && ! (m_sp= sp_find_function(thd, m_name, TRUE))) { - if (!(m_sp= sp_find_function(thd, m_name, TRUE))) - { - my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str); - DBUG_RETURN(-1); - } + my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str); + goto error; } old_client_capabilites= thd->client_capabilities; thd->client_capabilities &= ~CLIENT_MULTI_RESULTS; #ifndef EMBEDDED_LIBRARY - my_bool nsok= thd->net.no_send_ok; + nsok= thd->net.no_send_ok; thd->net.no_send_ok= TRUE; #endif + res= -1; #ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_routine_access(thd, EXECUTE_ACL, m_sp->m_db.str, m_sp->m_name.str, 0, 0)) - DBUG_RETURN(-1); + goto error_check; sp_change_security_context(thd, m_sp, &save_ctx); if (save_ctx.changed && check_routine_access(thd, EXECUTE_ACL, m_sp->m_db.str, m_sp->m_name.str, 0, 0)) - { - sp_restore_security_context(thd, m_sp, &save_ctx); - thd->client_capabilities|= old_client_capabilites & CLIENT_MULTI_RESULTS; - DBUG_RETURN(-1); - } + goto error_check; #endif /* Like for SPs, we don't binlog the substatements. If the statement which @@ -4850,6 +4845,7 @@ Item_func_sp::execute(Item **itp) it's not (e.g. SELECT myfunc()) it won't be binlogged (documented known problem). */ + tmp_disable_binlog(thd); /* don't binlog the substatements */ thd->transaction.in_sub_stmt= TRUE; @@ -4864,16 +4860,21 @@ Item_func_sp::execute(Item **itp) ER_FAILED_ROUTINE_BREAK_BINLOG, ER(ER_FAILED_ROUTINE_BREAK_BINLOG)); +error_check_ctx: #ifndef NO_EMBEDDED_ACCESS_CHECKS sp_restore_security_context(thd, m_sp, &save_ctx); #endif + thd->client_capabilities|= old_client_capabilites & CLIENT_MULTI_RESULTS; + +error_check: #ifndef EMBEDDED_LIBRARY thd->net.no_send_ok= nsok; #endif thd->client_capabilities|= old_client_capabilites & CLIENT_MULTI_RESULTS; +error: DBUG_RETURN(res); } diff --git a/sql/protocol.cc b/sql/protocol.cc index 57922cdc677..1c399a89a99 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -294,7 +294,12 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) DBUG_ENTER("send_ok"); if (net->no_send_ok || !net->vio) // hack for re-parsing queries + { + DBUG_PRINT("info", ("no send ok: %s, vio present: %s", + (net->no_send_ok ? "YES" : "NO"), + (net->vio ? "YES" : "NO"))); DBUG_VOID_RETURN; + } buff[0]=0; // No fields pos=net_store_length(buff+1,(ulonglong) affected_rows); diff --git a/sql/sql_class.h b/sql/sql_class.h index dd4b8310e51..9f263dbebf3 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1433,10 +1433,10 @@ public: }; #define tmp_disable_binlog(A) \ - ulong save_options= (A)->options; \ - (A)->options&= ~OPTION_BIN_LOG; + {ulong tmp_disable_binlog__save_options= (A)->options; \ + (A)->options&= ~OPTION_BIN_LOG -#define reenable_binlog(A) (A)->options= save_options; +#define reenable_binlog(A) (A)->options= tmp_disable_binlog__save_options;} /* Flags for the THD::system_thread (bitmap) variable */ #define SYSTEM_THREAD_DELAYED_INSERT 1 From 744f6a1a9966b83e21ae39270d07c1da6ba87fbf Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 17:38:40 +0200 Subject: [PATCH 038/216] mysql-test-run.pl: Might need a restart after test with special TZ Removed unused argument to run_mysqltest() mysql-test/mysql-test-run.pl: Might need a restart after test with special TZ Removed unused argument to run_mysqltest() --- mysql-test/mysql-test-run.pl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 4f673fe567d..1a31bbee1d5 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -303,7 +303,7 @@ sub mysqld_arguments ($$$$$); sub stop_masters_slaves (); sub stop_masters (); sub stop_slaves (); -sub run_mysqltest ($$); +sub run_mysqltest ($); sub usage ($); ###################################################################### @@ -1345,10 +1345,11 @@ sub run_testcase ($) { if ( ! $glob_use_running_server and ! $glob_use_embedded_server ) { - if ( $tinfo->{'master_restart'} or $master->[0]->{'uses_special_flags'} ) + if ( $tinfo->{'master_restart'} or + $master->[0]->{'running_master_is_special'} ) { stop_masters(); - $master->[0]->{'uses_special_flags'}= 0; # Forget about why we stopped + $master->[0]->{'running_master_is_special'}= 0; # Forget why we stopped } # ---------------------------------------------------------------------- @@ -1426,9 +1427,9 @@ sub run_testcase ($) { } } - if ( @{$tinfo->{'master_opt'}} ) + if ( $tinfo->{'master_restart'} ) { - $master->[0]->{'uses_special_flags'}= 1; + $master->[0]->{'running_master_is_special'}= 1; } } @@ -1475,7 +1476,7 @@ sub run_testcase ($) { } unlink($path_timefile); - my $res= run_mysqltest($tinfo, $tinfo->{'master_opt'}); + my $res= run_mysqltest($tinfo); if ( $res == 0 ) { @@ -1975,9 +1976,8 @@ sub stop_slaves () { } -sub run_mysqltest ($$) { +sub run_mysqltest ($) { my $tinfo= shift; - my $master_opts= shift; my $cmdline_mysqldump= "$exe_mysqldump --no-defaults -uroot " . "--socket=$master->[0]->{'path_mysock'} --password="; From 91180cb8ab4924fc9907ee16ba3479f88c309bc2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 20:22:08 +0400 Subject: [PATCH 039/216] - implement inheritance of sp_instr: public Query_arena. We need every instruction to have its own arena, because we want to track instruction's state (INITIALIZED_FOR_SP -> EXECUTED). Because of `if' statements and other conditional instructions used in stored procedures, not every instruction of a stored procedure gets executed during the first (or even subsequent) execution of the procedure. So it's better if we track the execution state of every instruction independently. All instructions of a given procedure now also share sp_head's mem_root, but keep their own free_list. This simplifies juggling with free Item lists in sp_head::execute. - free_items() moved to be a member of Query_arena. - logic of 'backup_arena' debug member of Query_arena has been changed to support multi-backups. Until now, TRUE 'backup_arena' meant that there is exactly one active backup of the THD arena. Now it means simply that the arena is used for backup, so that we can't accidentally overwrite an existing backup. This allows doing multiple backups, e.g. in sp_head::execute and Cursor::fetch, when THD arena is already backed up but we want to set yet another arena (usually the 'permanent' arena, to save permanent transformations/optimizations of a parsed tree). sql/sp_head.cc: - use Query_arena support in sp_head::execute() as now sp_instr inherites from it. sql/sp_head.h: - inherite sp_instr from Query_arena sql/sql_class.cc: - changed the principle of Query_arena::backup_arena; free_items is now a member of Query_arena. sql/sql_class.h: - changed the principle of Query_arena::backup_arena; free_items is now a member of Query_arena. sql/sql_prepare.cc: free_items() is now a member of Query_arena. sql/sql_select.cc: free_items() now automatically sets free_list to zero. --- sql/sp_head.cc | 71 ++++++++++++++++++++-------------------------- sql/sp_head.h | 7 ++--- sql/sql_class.cc | 27 +++++++++++++----- sql/sql_class.h | 13 +++++++-- sql/sql_prepare.cc | 2 +- sql/sql_select.cc | 3 +- 6 files changed, 65 insertions(+), 58 deletions(-) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 29cee6da4d3..825ec34e410 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -509,7 +509,7 @@ sp_head::destroy() delete i; delete_dynamic(&m_instr); m_pcont->destroy(); - free_items(free_list); + free_items(); /* If we have non-empty LEX stack then we just came out of parser with @@ -596,7 +596,6 @@ sp_head::execute(THD *thd) ctx->clear_handler(); thd->query_error= 0; old_arena= thd->current_arena; - thd->current_arena= this; /* We have to save/restore this info when we are changing call level to @@ -636,23 +635,18 @@ sp_head::execute(THD *thd) break; DBUG_PRINT("execute", ("Instruction %u", ip)); thd->set_time(); // Make current_time() et al work - { - /* - We have to substitute free_list of executing statement to - current_arena to store there all new items created during execution - (for example '*' expanding, or items made during permanent subquery - transformation) - Note: Every statement have to have all its items listed in free_list - for correct cleaning them up - */ - Item *save_free_list= thd->current_arena->free_list; - thd->current_arena->free_list= i->free_list; - ret= i->execute(thd, &ip); - i->free_list= thd->current_arena->free_list; - thd->current_arena->free_list= save_free_list; - } + /* + We have to set thd->current_arena before executing the instruction + to store in the instruction free_list all new items, created + during the first execution (for example expanding of '*' or the + items made during other permanent subquery transformations). + */ + thd->current_arena= i; + ret= i->execute(thd, &ip); if (i->free_list) cleanup_items(i->free_list); + i->state= Query_arena::EXECUTED; + // Check if an exception has occurred and a handler has been found // Note: We havo to check even if ret==0, since warnings (and some // errors don't return a non-zero value. @@ -694,7 +688,6 @@ sp_head::execute(THD *thd) DBUG_ASSERT(!thd->derived_tables); thd->derived_tables= old_derived_tables; - cleanup_items(thd->current_arena->free_list); thd->current_arena= old_arena; state= EXECUTED; @@ -728,8 +721,8 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) sp_rcontext *nctx = NULL; uint i; int ret; - MEM_ROOT *old_mem_root, call_mem_root; - Item *old_free_list, *call_free_list; + MEM_ROOT call_mem_root; + Query_arena call_arena(&call_mem_root, INITIALIZED_FOR_SP), backup_arena; if (argcount != params) { @@ -741,14 +734,12 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) } init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0); - old_mem_root= thd->mem_root; - thd->mem_root= &call_mem_root; - old_free_list= thd->free_list; // Keep the old list - thd->free_list= NULL; // Start a new one + + thd->set_n_backup_item_arena(&call_arena, &backup_arena); // QQ Should have some error checking here? (types, etc...) nctx= new sp_rcontext(csize, hmax, cmax); - nctx->callers_mem_root= old_mem_root; + nctx->callers_mem_root= backup_arena.mem_root; for (i= 0 ; i < argcount ; i++) { sp_pvar_t *pvar = m_pcont->find_pvar(i); @@ -780,9 +771,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) // Partially restore context now. // We still need the call mem root and free list for processing // of the result. - call_free_list= thd->free_list; - thd->free_list= old_free_list; - thd->mem_root= old_mem_root; + thd->restore_backup_item_arena(&call_arena, &backup_arena); if (m_type == TYPE_ENUM_FUNCTION && ret == 0) { @@ -802,8 +791,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) thd->spcont= octx; // Now get rid of the rest of the callee context - cleanup_items(call_free_list); - free_items(call_free_list); + call_arena.free_items(); free_root(&call_mem_root, MYF(0)); DBUG_RETURN(ret); @@ -835,8 +823,8 @@ sp_head::execute_procedure(THD *thd, List *args) sp_rcontext *octx = thd->spcont; sp_rcontext *nctx = NULL; my_bool tmp_octx = FALSE; // True if we have allocated a temporary octx - MEM_ROOT *old_mem_root, call_mem_root; - Item *old_free_list, *call_free_list; + MEM_ROOT call_mem_root; + Query_arena call_arena(&call_mem_root, INITIALIZED_FOR_SP), backup_arena; if (args->elements != params) { @@ -846,10 +834,7 @@ sp_head::execute_procedure(THD *thd, List *args) } init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0); - old_mem_root= thd->mem_root; - thd->mem_root= &call_mem_root; - old_free_list= thd->free_list; // Keep the old list - thd->free_list= NULL; // Start a new one + thd->set_n_backup_item_arena(&call_arena, &backup_arena); if (csize > 0 || hmax > 0 || cmax > 0) { @@ -919,9 +904,7 @@ sp_head::execute_procedure(THD *thd, List *args) // Partially restore context now. // We still need the call mem root and free list for processing // of out parameters. - call_free_list= thd->free_list; - thd->free_list= old_free_list; - thd->mem_root= old_mem_root; + thd->restore_backup_item_arena(&call_arena, &backup_arena); if (!ret && csize > 0) { @@ -996,8 +979,7 @@ sp_head::execute_procedure(THD *thd, List *args) thd->spcont= octx; // Now get rid of the rest of the callee context - cleanup_items(call_free_list); - free_items(call_free_list); + call_arena.free_items(); thd->lex->unit.cleanup(); free_root(&call_mem_root, MYF(0)); @@ -1291,6 +1273,13 @@ void sp_head::add_instr(sp_instr *instr) { instr->free_list= m_thd->free_list; m_thd->free_list= 0; + /* + Memory root of every instruction is designated for permanent + transformations (optimizations) made on the parsed tree during + the first execution. It points to the memory root of the + entire stored procedure, as their life span is equal. + */ + instr->mem_root= &main_mem_root; insert_dynamic(&m_instr, (gptr)&instr); } diff --git a/sql/sp_head.h b/sql/sp_head.h index 2c75a320f30..aaef5a3d50e 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -274,7 +274,7 @@ private: // "Instructions"... // -class sp_instr : public Sql_alloc +class sp_instr :public Query_arena, public Sql_alloc { sp_instr(const sp_instr &); /* Prevent use of these */ void operator=(sp_instr &); @@ -282,17 +282,16 @@ class sp_instr : public Sql_alloc public: uint marked; - Item *free_list; // My Items uint m_ip; // My index sp_pcontext *m_ctx; // My parse context // Should give each a name or type code for debugging purposes? sp_instr(uint ip, sp_pcontext *ctx) - :Sql_alloc(), marked(0), free_list(0), m_ip(ip), m_ctx(ctx) + :Query_arena(0, INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx) {} virtual ~sp_instr() - { free_items(free_list); } + { free_items(); } // Execute this instrution. '*nextp' will be set to the index of the next // instruction to execute. (For most instruction this will be the diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 8abd7cbbe7d..20f48da9283 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -171,9 +171,6 @@ THD::THD() spcont(NULL) { current_arena= this; -#ifndef DBUG_OFF - backup_arena= 0; -#endif host= user= priv_user= db= ip= 0; catalog= (char*)"std"; // the only catalog we have for now host_or_ip= "connecting host"; @@ -528,7 +525,7 @@ void THD::cleanup_after_query() next_insert_id= 0; } /* Free Items that were created during this execution */ - free_items(free_list); + free_items(); /* In the rest of code we assume that free_list never points to garbage: Keep this predicate true. @@ -1485,6 +1482,21 @@ Query_arena::Type Query_arena::type() const } +void Query_arena::free_items() +{ + Item *next; + DBUG_ENTER("Query_arena::free_items"); + /* This works because items are allocated with sql_alloc() */ + for (; free_list; free_list= next) + { + next= free_list->next; + free_list->delete_self(); + } + /* Postcondition: free_list is 0 */ + DBUG_VOID_RETURN; +} + + /* Statement functions */ @@ -1556,11 +1568,11 @@ void THD::end_statement() void Query_arena::set_n_backup_item_arena(Query_arena *set, Query_arena *backup) { DBUG_ENTER("Query_arena::set_n_backup_item_arena"); - DBUG_ASSERT(backup_arena == 0); + DBUG_ASSERT(backup->is_backup_arena == FALSE); backup->set_item_arena(this); set_item_arena(set); #ifndef DBUG_OFF - backup_arena= 1; + backup->is_backup_arena= TRUE; #endif DBUG_VOID_RETURN; } @@ -1569,10 +1581,11 @@ void Query_arena::set_n_backup_item_arena(Query_arena *set, Query_arena *backup) void Query_arena::restore_backup_item_arena(Query_arena *set, Query_arena *backup) { DBUG_ENTER("Query_arena::restore_backup_item_arena"); + DBUG_ASSERT(backup->is_backup_arena); set->set_item_arena(this); set_item_arena(backup); #ifndef DBUG_OFF - backup_arena= 0; + backup->is_backup_arena= FALSE; #endif DBUG_VOID_RETURN; } diff --git a/sql/sql_class.h b/sql/sql_class.h index a635a126f84..adc164085f9 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -663,7 +663,10 @@ public: Item *free_list; MEM_ROOT *mem_root; // Pointer to current memroot #ifndef DBUG_OFF - bool backup_arena; + bool is_backup_arena; /* True if this arena is used for backup. */ +#define INIT_ARENA_DBUG_INFO is_backup_arena= 0 +#else +#define INIT_ARENA_DBUG_INFO #endif enum enum_state { @@ -681,12 +684,14 @@ public: Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) : free_list(0), mem_root(mem_root_arg), state(state_arg) - {} + { INIT_ARENA_DBUG_INFO; } /* This constructor is used only when Query_arena is created as backup storage for another instance of Query_arena. */ - Query_arena() {}; + Query_arena() { INIT_ARENA_DBUG_INFO; } + +#undef INIT_ARENA_DBUG_INFO virtual Type type() const; virtual ~Query_arena() {}; @@ -726,6 +731,8 @@ public: void set_n_backup_item_arena(Query_arena *set, Query_arena *backup); void restore_backup_item_arena(Query_arena *set, Query_arena *backup); void set_item_arena(Query_arena *set); + + void free_items(); }; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index eeea493d868..c97cb037f15 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2429,7 +2429,7 @@ Prepared_statement::~Prepared_statement() { if (cursor) cursor->Cursor::~Cursor(); - free_items(free_list); + free_items(); delete lex->result; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1487dfbb436..96a25c7919b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1914,8 +1914,7 @@ Cursor::close() } join= 0; unit= 0; - free_items(free_list); - free_list= 0; + free_items(); /* Must be last, as some memory might be allocated for free purposes, like in free_tmp_table() (TODO: fix this issue) From 74307f39ebee0a1e4a14d9a989fbc92fa97a8f16 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 21:29:44 +0500 Subject: [PATCH 040/216] WL#2286 - Compile MySQL w/YASSL support Fix for compilation failure with Forte Developer C++. configure.in: Export ARFLAGS, so innobase could pick it up. innobase/configure.in: Use ARFLAGS exported by parent configure script. --- configure.in | 2 +- innobase/configure.in | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index ae26a0c44df..58682063593 100644 --- a/configure.in +++ b/configure.in @@ -342,7 +342,7 @@ AC_SUBST(CXXFLAGS) AC_SUBST(LD) AC_SUBST(INSTALL_SCRIPT) -export CC CXX CFLAGS LD LDFLAGS AR +export CC CXX CFLAGS LD LDFLAGS AR ARFLAGS if test "$GCC" = "yes" then diff --git a/innobase/configure.in b/innobase/configure.in index baf11272ab9..c56bd8274c4 100644 --- a/innobase/configure.in +++ b/innobase/configure.in @@ -117,6 +117,13 @@ case "$target" in CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";; esac +# must go in pair with AR as set by MYSQL_CHECK_AR +if test -z "$ARFLAGS" +then + ARFLAGS="cru" +fi +AC_SUBST(ARFLAGS) + AC_OUTPUT(Makefile os/Makefile ut/Makefile btr/Makefile dnl buf/Makefile data/Makefile dnl dict/Makefile dyn/Makefile dnl From 2460a01b684edc9e064991d2cd4e64985765c449 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 19:33:19 +0300 Subject: [PATCH 041/216] removed unneed line --- sql/item_func.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/sql/item_func.cc b/sql/item_func.cc index de497014240..1dbf28b67cb 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4828,7 +4828,6 @@ Item_func_sp::execute(Item **itp) thd->net.no_send_ok= TRUE; #endif - res= -1; #ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_routine_access(thd, EXECUTE_ACL, m_sp->m_db.str, m_sp->m_name.str, 0, 0)) From 624cc5223c09bf5863667e8f2da69ac23ed7a819 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 19:03:55 +0200 Subject: [PATCH 042/216] - reverted to using the shell version of mysql-test-run for "make test" until the remaining bugs in the Perl version have been resolved Makefile.am: - reverted to using the shell version of mysql-test-run until the remaining bugs in the Perl version have been resolved --- Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 9a6fcf3c95a..d7059c6adaf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -101,12 +101,12 @@ tags: test: cd mysql-test; \ - perl mysql-test-run.pl && perl mysql-test-run.pl --ps-protocol + ./mysql-test-run && ./mysql-test-run --ps-protocol test-force: cd mysql-test; \ - perl mysql-test-run.pl --force ;\ - perl mysql-test-run.pl --ps-protocol --force + ./mysql-test-run --force ;\ + ./mysql-test-run --ps-protocol --force # Don't update the files from bitkeeper %::SCCS/s.% From d06446af84a875faa5b642cd21e759ef9fa9fa20 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 21:06:33 +0400 Subject: [PATCH 043/216] sql_parse.cc: Fix for fix for bug #9728 Error caused server hang on prepared insert ... select sql/sql_parse.cc: Fix for fix for bug #9728 Error caused server hang on prepared insert ... select --- sql/sql_parse.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 233104c9a90..2eeae8f7332 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2882,7 +2882,6 @@ unsent_create_error: } else res= -1; - first_local_table->next= tables; lex->select_lex.table_list.first= (byte*) first_local_table; break; } From 0cc6dd83c469b105c6c4e9032d28b01dd208c532 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 20:06:35 +0300 Subject: [PATCH 044/216] temporary tables of subquery in the from clause just skipped during processing QC tables (BUG#11522) mysql-test/r/query_cache.result: queries with subquery in the FROM clause mysql-test/t/query_cache.test: queries with subquery in the FROM clause sql/sql_cache.cc: temporary tables of subquery in the from clause just skipped during processing QC tables --- mysql-test/r/query_cache.result | 52 +++++++++++++++++++++++++++++++++ mysql-test/t/query_cache.test | 26 +++++++++++++++++ sql/sql_cache.cc | 17 +++++++++-- 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 55f9bc6c224..ec996fb4128 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -971,4 +971,56 @@ abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab zyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcba flush query cache; drop table t1, t2; +create table t1 (a int); +insert into t1 values (1); +reset query cache; +flush status; +select * from (select * from t1) a; +a +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +select * from (select * from t1) a; +a +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +insert into t1 values (2); +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +select * from (select * from t1) a; +a +1 +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +drop table t1; set GLOBAL query_cache_size=0; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 170f150f7aa..ecb8fee9af1 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -730,4 +730,30 @@ flush query cache; drop table t1, t2; +create table t1 (a int); +insert into t1 values (1); +reset query cache; +flush status; + +# +# queries with subquery in the FROM clause (BUG#11522) +# +select * from (select * from t1) a; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +select * from (select * from t1) a; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +insert into t1 values (2); +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +select * from (select * from t1) a; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +drop table t1; + set GLOBAL query_cache_size=0; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 8deb3489782..366a13d59ba 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -2114,6 +2114,13 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, for (n=0; tables_used; tables_used=tables_used->next, n++, block_table++) { + if (tables_used->derived) + { + DBUG_PRINT("qcache", ("derived table skipped")); + n--; + block_table--; + continue; + } DBUG_PRINT("qcache", ("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx", tables_used->real_name, tables_used->db, @@ -2671,7 +2678,8 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, table_alias_charset used here because it depends of lower_case_table_names variable */ - if (tables_used->table->tmp_table != NO_TMP_TABLE || + if ((tables_used->table->tmp_table != NO_TMP_TABLE && + !tables_used->derived) || (*tables_type & HA_CACHE_TBL_NOCACHE) || (tables_used->db_length == 5 && my_strnncoll(table_alias_charset, (uchar*)tables_used->db, 6, @@ -2682,7 +2690,12 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, other non-cacheable table(s)")); DBUG_RETURN(0); } - if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM) + if (tables_used->derived) + { + table_count--; + DBUG_PRINT("qcache", ("derived table skipped")); + } + else if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM) { ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file; MYRG_INFO *file = handler->myrg_info(); From 9a03ad151da975badcccaf7bf3517057aef8e5b8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 22:41:26 +0200 Subject: [PATCH 045/216] - bumped up version number to 5.0.9 now that the 5.0.8 builds have been branched off --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 58682063593..9e294a35223 100644 --- a/configure.in +++ b/configure.in @@ -6,7 +6,7 @@ AC_PREREQ(2.50)dnl Minimum Autoconf version required. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # Don't forget to also update the NDB lines below. -AM_INIT_AUTOMAKE(mysql, 5.0.8-beta) +AM_INIT_AUTOMAKE(mysql, 5.0.9-beta) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -17,7 +17,7 @@ SHARED_LIB_VERSION=14:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=8 +NDB_VERSION_BUILD=9 NDB_VERSION_STATUS="beta" # Set all version vars based on $VERSION. How do we do this more elegant ? From 3d1172a10f3365b29bce370f37b8740d1798d11e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 00:24:11 +0300 Subject: [PATCH 046/216] fixed encrypt() print (BUG#7024) mysql-test/r/view.result: using encrypt & substring_index in view mysql-test/t/view.test: using encrypt & substring_index in view sql/item_strfunc.h: fixed encrypt() print --- mysql-test/r/view.result | 8 ++++++++ mysql-test/t/view.test | 12 ++++++++++++ sql/item_strfunc.h | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 68cc0c4cb57..d4d6eb08cad 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1831,3 +1831,11 @@ select * from v1; t 01:00 drop view v1; +CREATE VIEW v1 AS SELECT ENCRYPT("dhgdhgd"); +SELECT * FROM v1; +drop view v1; +CREATE VIEW v1 AS SELECT SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1); +SELECT * FROM v1; +SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1) +dkjhgd +drop view v1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 13a5f8cef1f..f131f9d2604 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1673,3 +1673,15 @@ create view v1(k, K) as select 1,2; create view v1 as SELECT TIME_FORMAT(SEC_TO_TIME(3600),'%H:%i') as t; select * from v1; drop view v1; + +# +# using encrypt & substring_index in view (BUG#7024) +# +CREATE VIEW v1 AS SELECT ENCRYPT("dhgdhgd"); +disable_result_log; +SELECT * FROM v1; +enable_result_log; +drop view v1; +CREATE VIEW v1 AS SELECT SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1); +SELECT * FROM v1; +drop view v1; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 8d2eb269915..c4beb3b08cb 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -322,7 +322,7 @@ public: Item_func_encrypt(Item *a, Item *b): Item_str_func(a,b) {} String *val_str(String *); void fix_length_and_dec() { maybe_null=1; max_length = 13; } - const char *func_name() const { return "ecrypt"; } + const char *func_name() const { return "encrypt"; } }; #include "sql_crypt.h" From fe80b7b5bf7a3d2191d268db7bff4704c9fdb022 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 01:30:52 +0300 Subject: [PATCH 047/216] fixed encrypt() name --- mysql-test/r/subselect.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 736559f8569..400a2be01f1 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1025,7 +1025,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found 2 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 0 const row not found Warnings: -Note 1003 select sql_no_cache (select sql_no_cache ecrypt(_latin1'test') AS `ENCRYPT('test')` from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1` +Note 1003 select sql_no_cache (select sql_no_cache encrypt(_latin1'test') AS `ENCRYPT('test')` from `test`.`t1`) AS `(SELECT ENCRYPT('test') FROM t1)` from `test`.`t1` EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found From 86d8abdb26e35a5920eea0e55fadd89295f05df6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 23 Jun 2005 18:29:56 -0700 Subject: [PATCH 048/216] Make status of NO_BACKSLASH_ESCAPES mode known to the client so it can use it to switch to only quoting apostrophes by doubling them when it is in effect. (Bug #10214) include/my_sys.h: Add new escape_quotes_for_mysql() function include/mysql_com.h: Add SERVER_STATUS_NO_BACKSLASH_ESCAPES libmysql/libmysql.c: Use SERVER_STATUS_NO_BACKSLASH_ESCAPES in server_status to determine how mysql_real_escape_string() should do quoting. mysys/charset.c: Add new escape_quotes_for_mysql() function that only quotes apostrophes by doubling them up. sql/set_var.cc: Set SERVER_STATUS_NO_BACKSLASH_ESCAPES when MODE_NO_BACKSLASH_ESCAPES changes. sql/sql_class.cc: Set SERVER_STATUS_NO_BACKSLASH_ESCAPES when necessary on thread creation. tests/mysql_client_test.c: Add new test for sending NO_BACKSLASH_ESCAPES as part of server_status. --- include/my_sys.h | 3 ++ include/mysql_com.h | 1 + libmysql/libmysql.c | 9 +++++- mysys/charset.c | 64 +++++++++++++++++++++++++++++++++++++++ sql/set_var.cc | 9 ++++++ sql/sql_class.cc | 2 ++ tests/mysql_client_test.c | 30 ++++++++++++++++++ 7 files changed, 117 insertions(+), 1 deletion(-) diff --git a/include/my_sys.h b/include/my_sys.h index ee4312be058..e7e90d6ed78 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -865,6 +865,9 @@ extern void add_compiled_collation(CHARSET_INFO *cs); extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to, ulong to_length, const char *from, ulong length); +extern ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info, + char *to, ulong to_length, + const char *from, ulong length); extern void thd_increment_bytes_sent(ulong length); extern void thd_increment_bytes_received(ulong length); diff --git a/include/mysql_com.h b/include/mysql_com.h index 2293476c76c..8da17d21b2d 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -148,6 +148,7 @@ enum enum_server_command */ #define SERVER_STATUS_LAST_ROW_SENT 128 #define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */ +#define SERVER_STATUS_NO_BACKSLASH_ESCAPES 512 #define MYSQL_ERRMSG_SIZE 512 #define NET_READ_TIMEOUT 30 /* Timeout on read */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 8ee11519615..ce47ea21485 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1616,7 +1616,14 @@ ulong STDCALL mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, ulong length) { - return escape_string_for_mysql(mysql->charset, to, 0, from, length); + if (mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) + { + return escape_quotes_for_mysql(mysql->charset, to, 0, from, length); + } + else + { + return escape_string_for_mysql(mysql->charset, to, 0, from, length); + } } diff --git a/mysys/charset.c b/mysys/charset.c index cbd9ba16b4c..53d9c4a72a4 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -656,3 +656,67 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, return overflow ? (ulong)~0 : (ulong) (to - to_start); } + +/* + NOTE + to be consistent with escape_string_for_mysql(), to_length may be 0 to + mean "big enough" + RETURN + the length of the escaped string or ~0 if it did not fit. +*/ +ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info, + char *to, ulong to_length, + const char *from, ulong length) +{ + const char *to_start= to; + const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length); + my_bool overflow=0; +#ifdef USE_MB + my_bool use_mb_flag= use_mb(charset_info); +#endif + for (end= from + length; from < end; from++) + { + char escape=0; +#ifdef USE_MB + int tmp_length; + if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end))) + { + if (to + tmp_length > to_end) + { + overflow=1; + break; + } + while (tmp_length--) + *to++= *from++; + from--; + continue; + } + /* + We don't have the same issue here with a non-multi-byte character being + turned into a multi-byte character by the addition of an escaping + character, because we are only escaping the ' character with itself. + */ +#endif + if (*from == '\'') + { + if (to + 2 > to_end) + { + overflow=1; + break; + } + *to++= '\''; + *to++= '\''; + } + else + { + if (to + 1 > to_end) + { + overflow=1; + break; + } + *to++= *from; + } + } + *to= 0; + return overflow ? (ulong)~0 : (ulong) (to - to_start); +} diff --git a/sql/set_var.cc b/sql/set_var.cc index 1c0de702e4e..9c35e10026a 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -3238,7 +3238,16 @@ void fix_sql_mode_var(THD *thd, enum_var_type type) global_system_variables.sql_mode= fix_sql_mode(global_system_variables.sql_mode); else + { thd->variables.sql_mode= fix_sql_mode(thd->variables.sql_mode); + /* + Update thd->server_status + */ + if (thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) + thd->server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; + else + thd->server_status&= ~SERVER_STATUS_NO_BACKSLASH_ESCAPES; + } } /* Map database specific bits to function bits */ diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 20f48da9283..6f61b086314 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -282,6 +282,8 @@ void THD::init(void) #endif pthread_mutex_unlock(&LOCK_global_system_variables); server_status= SERVER_STATUS_AUTOCOMMIT; + if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) + server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; options= thd_startup_options; open_options=ha_open_options; update_lock_default= (variables.low_priority_updates ? diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 8debf7614a3..bb9e693b8ec 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13332,6 +13332,35 @@ static void test_bug9992() mysql_close(mysql1); } + +/* + Check that the server signals when NO_BACKSLASH_ESCAPES mode is in effect, + and mysql_real_escape_string() does the right thing as a result. +*/ + +static void test_bug10214() +{ + MYSQL_RES* res ; + int len; + char out[8]; + + myheader("test_bug10214"); + + DIE_UNLESS(!(mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)); + + len= mysql_real_escape_string(mysql, out, "a'b\\c", 5); + DIE_UNLESS(memcmp(out, "a\\'b\\\\c", len) == 0); + + mysql_query(mysql, "set sql_mode='NO_BACKSLASH_ESCAPES'"); + DIE_UNLESS(mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES); + + len= mysql_real_escape_string(mysql, out, "a'b\\c", 5); + DIE_UNLESS(memcmp(out, "a''b\\c", len) == 0); + + mysql_query(mysql, "set sql_mode=''"); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -13567,6 +13596,7 @@ static struct my_tests_st my_tests[]= { { "test_bug10729", test_bug10729 }, { "test_bug11111", test_bug11111 }, { "test_bug9992", test_bug9992 }, + { "test_bug10214", test_bug10214 }, { 0, 0 } }; From 3c14168865716d329058876c284bf0e29538ab32 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 09:56:58 +0300 Subject: [PATCH 049/216] Fixed test result for BUG#11185. --- mysql-test/r/innodb.result | 5 +++-- mysql-test/r/range.result | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index b07a6b03c8a..838e02c3a89 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1721,12 +1721,13 @@ count(*) 0 explain select count(*) from t1 where x > -16; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL 1 Using where; Using index +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 2 Using where; Using index select count(*) from t1 where x > -16; count(*) -1 +2 select * from t1 where x > -16; x +18446744073709551600 18446744073709551601 select count(*) from t1 where x = 18446744073709551601; count(*) diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index 16bf9a8247a..ae7d0474e24 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -544,7 +544,7 @@ count(*) 1 select count(*) from t2 where x > -16; count(*) -2 +1 select count(*) from t2 where x = 18446744073709551601; count(*) 0 From 77dc5c423fb9f22dfc931d1fd1a00715c1fca0e2 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 12:51:11 +0500 Subject: [PATCH 050/216] an improvement (bug #7851: C++ 'new' conflicts with kernel header asm/system.h). include/my_global.h: an improvement (bug #7851: C++ 'new' conflicts with kernel header asm/system.h). redefine 'new' before #include in any case. --- include/my_global.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index f8ba555b150..9b53be66db0 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -274,10 +274,8 @@ C_MODE_START int __cxa_pure_virtual() {\ #include #endif #ifdef HAVE_ATOMIC_ADD -#if defined(__ia64__) #define new my_arg_new #define need_to_restore_new 1 -#endif C_MODE_START #include C_MODE_END From a60233121f524fc326d90bff7dcbf08dbd1cc959 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 01:21:18 -0700 Subject: [PATCH 051/216] field.cc: Correction after manula merge. sql/field.cc: Correction after manula merge. --- sql/field.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/field.cc b/sql/field.cc index 81f695454ff..fb244de4275 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3317,7 +3317,7 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) } if (error) { - error= 1; + error= error != MY_ERRNO_EDOM ? 1 : 2; set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); } else if (from+len != end && table->in_use->count_cuted_fields && From 5aa793f72bfdf5e5903ad4999691fdb72f507de3 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 14:04:48 +0500 Subject: [PATCH 052/216] backport for #10568: Function 'LAST_DAY(date)' does not return NULL for invalid argument. --- mysql-test/r/func_time.result | 15 +++++++++++++++ mysql-test/t/func_time.test | 7 +++++++ sql/item_timefunc.cc | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 4dd00ab74a1..fc872285acb 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -611,3 +611,18 @@ SELECT count(*) FROM t1 WHERE d>FROM_DAYS(TO_DAYS(@TMP)) AND d<=FROM_DAYS(TO_DAY count(*) 3 DROP TABLE t1; +select last_day('2005-00-00'); +last_day('2005-00-00') +NULL +Warnings: +Warning 1292 Truncated incorrect datetime value: '2005-00-00' +select last_day('2005-00-01'); +last_day('2005-00-01') +NULL +Warnings: +Warning 1292 Truncated incorrect datetime value: '2005-00-01' +select last_day('2005-01-00'); +last_day('2005-01-00') +NULL +Warnings: +Warning 1292 Truncated incorrect datetime value: '2005-01-00' diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 0f495ef891d..9e2703da110 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -307,3 +307,10 @@ INSERT INTO t1 VALUES (NOW()); SELECT count(*) FROM t1 WHERE d>FROM_DAYS(TO_DAYS(@TMP)) AND d<=FROM_DAYS(TO_DAYS(@TMP)+1); DROP TABLE t1; +# +# Bug #10568 +# + +select last_day('2005-00-00'); +select last_day('2005-00-01'); +select last_day('2005-01-00'); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index a3cf69035f3..0e1a8766e8f 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2817,7 +2817,7 @@ String *Item_func_str_to_date::val_str(String *str) bool Item_func_last_day::get_date(TIME *ltime, uint fuzzy_date) { - if (get_arg0_date(ltime,fuzzy_date)) + if (get_arg0_date(ltime, fuzzy_date & ~TIME_FUZZY_DATE)) return 1; uint month_idx= ltime->month-1; ltime->day= days_in_month[month_idx]; From b743e2b4faedd59f655fa8cb31ee1bfcae430c70 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 11:56:20 +0200 Subject: [PATCH 053/216] mysql-test-run.sh: Corrected path to CA certificate mysql-test/mysql-test-run.sh: Corrected path to CA certificate --- mysql-test/mysql-test-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index e3fcfdf2b1e..376946eb8aa 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -307,7 +307,7 @@ while test $# -gt 0; do --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem \ --ssl-cert=$MYSQL_TEST_DIR/std_data/server-cert.pem \ --ssl-key=$MYSQL_TEST_DIR/std_data/server-key.pem" - MYSQL_TEST_SSL_OPTS="--ssl-ca=$BASEDIR/SSL/cacert.pem \ + MYSQL_TEST_SSL_OPTS="--ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem \ --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem \ --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem" ;; --no-manager | --skip-manager) USE_MANAGER=0 ;; From a7e66efc2cc37b8ca32868ac8c8e3e3c05675e48 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 17:47:09 +0200 Subject: [PATCH 054/216] Bug#10178 - failure to find a row in heap table by concurrent UPDATEs Moved the key statistics update to info(). The table is not locked in open(). This made wrong stats possible. No test case for the test suite. This happens only with heavy concurrency. A test script is added to the bug report. mysql-test/r/heap_hash.result: Bug#10178 - failure to find a row in heap table by concurrent UPDATEs Updated test results to reflect the new statistics behaviour. mysql-test/t/heap_hash.test: Bug#10178 - failure to find a row in heap table by concurrent UPDATEs Added a FLUSH TABLES to avoid statistics differences between normal and ps-protocol tests. sql/ha_heap.cc: Bug#10178 - failure to find a row in heap table by concurrent UPDATEs Moved the key statistics update to info(). The table is not locked in open(). This made wrong stats possible. sql/ha_heap.h: Bug#10178 - failure to find a row in heap table by concurrent UPDATEs Added an element to track the validity of the key statistics. --- mysql-test/r/heap_hash.result | 23 ++++++++++++----------- mysql-test/t/heap_hash.test | 2 ++ sql/ha_heap.cc | 31 ++++++++++++++++++++++++++----- sql/ha_heap.h | 4 +++- 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result index d3673cd2a63..e5098ab8c87 100644 --- a/mysql-test/r/heap_hash.result +++ b/mysql-test/r/heap_hash.result @@ -231,18 +231,19 @@ explain select * from t1 where a='aaad'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref a a 8 const 1 Using where insert into t1 select * from t1; +flush tables; explain select * from t1 where a='aaaa'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaab'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaac'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaad'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where flush tables; explain select * from t1 where a='aaaa'; id select_type table type possible_keys key key_len ref rows Extra @@ -261,16 +262,16 @@ delete from t1; insert into t1 select * from t2; explain select * from t1 where a='aaaa'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaab'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaac'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaad'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where drop table t1, t2; create table t1 ( id int unsigned not null primary key auto_increment, @@ -345,15 +346,15 @@ insert into t3 select name, name from t1; show index from t3; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t3 1 a 1 a NULL NULL NULL NULL HASH -t3 1 a 2 b NULL 15 NULL NULL HASH +t3 1 a 2 b NULL 13 NULL NULL HASH show index from t3; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t3 1 a 1 a NULL NULL NULL NULL HASH -t3 1 a 2 b NULL 15 NULL NULL HASH +t3 1 a 2 b NULL 13 NULL NULL HASH explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a = concat('',t1.name) and t3.b=t1.name; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref heap_idx heap_idx 20 const 7 Using where -1 SIMPLE t3 ref a a 40 func,const 6 Using where +1 SIMPLE t3 ref a a 40 func,const 7 Using where drop table t1, t2, t3; create temporary table t1 ( a int, index (a) ) engine=memory; insert into t1 values (1),(2),(3),(4),(5); diff --git a/mysql-test/t/heap_hash.test b/mysql-test/t/heap_hash.test index 6d27f19dfad..59af50da932 100644 --- a/mysql-test/t/heap_hash.test +++ b/mysql-test/t/heap_hash.test @@ -169,6 +169,8 @@ explain select * from t1 where a='aaac'; explain select * from t1 where a='aaad'; insert into t1 select * from t1; +# avoid statistics differences between normal and ps-protocol tests +flush tables; explain select * from t1 where a='aaaa'; explain select * from t1 where a='aaab'; explain select * from t1 where a='aaac'; diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 4fc0116a26a..f8c2e6cc338 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -60,7 +60,15 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked) { /* Initialize variables for the opened table */ set_keys_for_scanning(); - update_key_stats(); + /* + We cannot run update_key_stats() here because we do not have a + lock on the table. The 'records' count might just be changed + temporarily at this moment and we might get wrong statistics (Bug + #10178). Instead we request for update. This will be done in + ha_heap::info(), which is always called before key statistics are + used. + */ + key_stats_ok= FALSE; } return (file ? 0 : 1); } @@ -112,6 +120,8 @@ void ha_heap::update_key_stats() } } records_changed= 0; + /* At the end of update_key_stats() we can proudly claim they are OK. */ + key_stats_ok= TRUE; } int ha_heap::write_row(byte * buf) @@ -125,7 +135,7 @@ int ha_heap::write_row(byte * buf) res= heap_write(file,buf); if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) - update_key_stats(); + key_stats_ok= FALSE; return res; } @@ -138,7 +148,7 @@ int ha_heap::update_row(const byte * old_data, byte * new_data) res= heap_update(file,old_data,new_data); if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) - update_key_stats(); + key_stats_ok= FALSE; return res; } @@ -149,7 +159,7 @@ int ha_heap::delete_row(const byte * buf) res= heap_delete(file,buf); if (!res && table->tmp_table == NO_TMP_TABLE && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) - update_key_stats(); + key_stats_ok= FALSE; return res; } @@ -262,6 +272,13 @@ void ha_heap::info(uint flag) delete_length= info.deleted * info.reclength; if (flag & HA_STATUS_AUTO) auto_increment_value= info.auto_increment; + /* + If info() is called for the first time after open(), we will still + have to update the key statistics. Hoping that a table lock is now + in place. + */ + if (! key_stats_ok) + update_key_stats(); } int ha_heap::extra(enum ha_extra_function operation) @@ -273,7 +290,7 @@ int ha_heap::delete_all_rows() { heap_clear(file); if (table->tmp_table == NO_TMP_TABLE) - update_key_stats(); + key_stats_ok= FALSE; return 0; } @@ -433,7 +450,11 @@ ha_rows ha_heap::records_in_range(uint inx, key_range *min_key, max_key->flag != HA_READ_AFTER_KEY) return HA_POS_ERROR; // Can only use exact keys else + { + /* Assert that info() did run. We need current statistics here. */ + DBUG_ASSERT(key_stats_ok); return key->rec_per_key[key->key_parts-1]; + } } diff --git a/sql/ha_heap.h b/sql/ha_heap.h index 33de0156074..cbe2474492d 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -29,8 +29,10 @@ class ha_heap: public handler key_map btree_keys; /* number of records changed since last statistics update */ uint records_changed; + bool key_stats_ok; public: - ha_heap(TABLE *table): handler(table), file(0), records_changed(0) {} + ha_heap(TABLE *table): handler(table), file(0), records_changed(0), + key_stats_ok(0) {} ~ha_heap() {} const char *table_type() const { return "HEAP"; } const char *index_type(uint inx) From fd3ac3829bec048fa7cfeae5c8d1fb88d16e6380 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 20:16:52 +0400 Subject: [PATCH 055/216] Fix bug#11325 Wrong date comparison in views Wrong comparing method were choosen which results in false comparison. Make Item_bool_func2::fix_length_and_dec() to get type and field from real_item() to make REF_ITEM pass the check. sql/item_cmpfunc.cc: Fix bug#11325 Wrong date comparison in views mysql-test/t/view.test: Test case for bug#11325 Wrong date comparison in views. mysql-test/r/view.result: Test case for bug#11325 Wrong date comparison in views. --- mysql-test/r/view.result | 11 +++++++++++ mysql-test/t/view.test | 11 +++++++++++ sql/item_cmpfunc.cc | 10 ++++++---- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 68cc0c4cb57..7c25608aa49 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1831,3 +1831,14 @@ select * from v1; t 01:00 drop view v1; +create table t1 (f1 date); +insert into t1 values ('2005-01-01'),('2005-02-02'); +create view v1 as select * from t1; +select * from v1 where f1='2005.02.02'; +f1 +2005-02-02 +select * from v1 where '2005.02.02'=f1; +f1 +2005-02-02 +drop view v1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 13a5f8cef1f..e32f2c09575 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1673,3 +1673,14 @@ create view v1(k, K) as select 1,2; create view v1 as SELECT TIME_FORMAT(SEC_TO_TIME(3600),'%H:%i') as t; select * from v1; drop view v1; + +# +# bug #11325 Wrong date comparison in views +# +create table t1 (f1 date); +insert into t1 values ('2005-01-01'),('2005-02-02'); +create view v1 as select * from t1; +select * from v1 where f1='2005.02.02'; +select * from v1 where '2005.02.02'=f1; +drop view v1; +drop table t1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 0442865b7f9..58a7f3316d7 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -238,9 +238,10 @@ void Item_bool_func2::fix_length_and_dec() return; } - if (args[0]->type() == FIELD_ITEM) + Item *real_item= args[0]->real_item(); + if (real_item->type() == FIELD_ITEM) { - Field *field=((Item_field*) args[0])->field; + Field *field= ((Item_field*) real_item)->field; if (field->can_be_compared_as_longlong()) { if (convert_constant_item(thd, field,&args[1])) @@ -251,9 +252,10 @@ void Item_bool_func2::fix_length_and_dec() } } } - if (args[1]->type() == FIELD_ITEM /* && !args[1]->const_item() */) + real_item= args[1]->real_item(); + if (real_item->type() == FIELD_ITEM) { - Field *field=((Item_field*) args[1])->field; + Field *field= ((Item_field*) real_item)->field; if (field->can_be_compared_as_longlong()) { if (convert_constant_item(thd, field,&args[0])) From a01d110680c6cf0cbf86d3de9b3ca777b870635b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 18:23:59 +0200 Subject: [PATCH 056/216] mysql-test-run.pl: Corrected master server id's mysql-test/mysql-test-run.pl: Corrected master server id's --- mysql-test/mysql-test-run.pl | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 2051afc7745..74d1a8dc6f2 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1554,11 +1554,12 @@ sub do_before_start_master ($$) { } } + # FIXME only remove the ones that are tied to this master # Remove old master.info and relay-log.info files - unlink("$opt_vardir/master-data/master.info"); - unlink("$opt_vardir/master-data/relay-log.info"); - unlink("$opt_vardir/master1-data/master.info"); - unlink("$opt_vardir/master1-data/relay-log.info"); + unlink("$master->[0]->{'path_myddir'}/master.info"); + unlink("$master->[0]->{'path_myddir'}/relay-log.info"); + unlink("$master->[1]->{'path_myddir'}/master.info"); + unlink("$master->[1]->{'path_myddir'}/relay-log.info"); # Run master initialization shell script if one exists if ( $init_script ) @@ -1652,12 +1653,15 @@ sub mysqld_arguments ($$$$$) { if ( $type eq 'master' ) { - mtr_add_arg($args, "%s--log-bin=%s/log/master-bin", $prefix, $opt_vardir); + my $id= $idx > 0 ? $idx + 101 : 1; + + mtr_add_arg($args, "%s--log-bin=%s/log/master-bin%s", $prefix, + $opt_vardir, $sidx); mtr_add_arg($args, "%s--pid-file=%s", $prefix, $master->[$idx]->{'path_mypid'}); mtr_add_arg($args, "%s--port=%d", $prefix, $master->[$idx]->{'path_myport'}); - mtr_add_arg($args, "%s--server-id=1", $prefix); + mtr_add_arg($args, "%s--server-id=%d", $prefix, $id); mtr_add_arg($args, "%s--socket=%s", $prefix, $master->[$idx]->{'path_mysock'}); mtr_add_arg($args, "%s--innodb_data_file_path=ibdata1:128M:autoextend", $prefix); @@ -1665,6 +1669,11 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--datadir=%s", $prefix, $master->[$idx]->{'path_myddir'}); + if ( $idx > 0 ) + { + mtr_add_arg($args, "%s--skip-innodb", $prefix); + } + if ( $opt_skip_ndbcluster ) { mtr_add_arg($args, "%s--skip-ndbcluster", $prefix); @@ -1674,7 +1683,7 @@ sub mysqld_arguments ($$$$$) { if ( $type eq 'slave' ) { my $slave_server_id= 2 + $idx; - my $slave_rpl_rank= $idx > 0 ? 2 : $slave_server_id; + my $slave_rpl_rank= $slave_server_id; mtr_add_arg($args, "%s--datadir=%s", $prefix, $slave->[$idx]->{'path_myddir'}); From 12a640e28023d9d1333fcecb387e7e3915762b2b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 19:34:55 +0200 Subject: [PATCH 057/216] Bug#8321 - myisampack bug in compression algorithm Added 64-bit extensions, comments, extended statistics and trace prints. include/my_base.h: Bug#8321 - myisampack bug in compression algorithm Added a comment. myisam/mi_packrec.c: Bug#8321 - myisampack bug in compression algorithm Fixed a function comment. myisam/myisampack.c: Bug#8321 - myisampack bug in compression algorithm Enlarged the variables which hold Huffman codes to ulonglong and adjusted the functions accordingly. Added test code for long Huffman codes. Enlarged the distinct column values buffer (tree_buff) and added checks to stay in its range. Added statistics and trace prints. Added a lot of comments. mysys/tree.c: Bug#8321 - myisampack bug in compression algorithm Added a check against overflow of the tree element count. The tree element count is only 31 bits, but sometimes used for big numbers. There is however no application yet, which relies on exact tree element counts. --- include/my_base.h | 1 + myisam/mi_packrec.c | 15 +- myisam/myisampack.c | 1280 ++++++++++++++++++++++++++++++++++++++----- mysys/tree.c | 3 + 4 files changed, 1155 insertions(+), 144 deletions(-) diff --git a/include/my_base.h b/include/my_base.h index 25fa683744e..c76cf8c604e 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -367,6 +367,7 @@ enum ha_base_keytype { #define HA_STATE_EXTEND_BLOCK 2048 #define HA_STATE_RNEXT_SAME 4096 /* rnext_same was called */ +/* myisampack expects no more than 32 field types. */ enum en_fieldtype { FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIP_ENDSPACE,FIELD_SKIP_PRESPACE, FIELD_SKIP_ZERO,FIELD_BLOB,FIELD_CONSTANT,FIELD_INTERVALL,FIELD_ZERO, diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index 4b512dd89dd..c251e4dda4a 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -416,8 +416,19 @@ static uint find_longest_bitstream(uint16 *table, uint16 *end) } - /* Read record from datafile */ - /* Returns length of packed record, -1 if error */ +/* + Read record from datafile. + + SYNOPSIS + _mi_read_pack_record() + info A pointer to MI_INFO. + filepos File offset of the record. + buf RETURN The buffer to receive the record. + + RETURN + 0 on success + HA_ERR_WRONG_IN_RECORD or -1 on error +*/ int _mi_read_pack_record(MI_INFO *info, my_off_t filepos, byte *buf) { diff --git a/myisam/myisampack.c b/myisam/myisampack.c index 74bb541b220..70a32902da6 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -33,10 +33,10 @@ #include #include -#if INT_MAX > 32767 -#define BITS_SAVED 32 +#if SIZEOF_LONG_LONG > 4 +#define BITS_SAVED 64 #else -#define BITS_SAVED 16 +#define BITS_SAVED 32 #endif #define IS_OFFSET ((uint) 32768) /* Bit if offset or char in tree */ @@ -49,10 +49,10 @@ struct st_file_buffer { File file; - char *buffer,*pos,*end; + uchar *buffer,*pos,*end; my_off_t pos_in_file; int bits; - uint current_byte; + ulonglong bitbucket; }; struct st_huff_tree; @@ -69,13 +69,17 @@ typedef struct st_huff_counts { my_off_t end_space[8]; my_off_t pre_space[8]; my_off_t tot_end_space,tot_pre_space,zero_fields,empty_fields,bytes_packed; - TREE int_tree; - byte *tree_buff; - byte *tree_pos; + TREE int_tree; /* Tree for detecting distinct column values. */ + byte *tree_buff; /* Column values, 'field_length' each. */ + byte *tree_pos; /* Points to end of column values in 'tree_buff'. */ } HUFF_COUNTS; typedef struct st_huff_element HUFF_ELEMENT; +/* + WARNING: It is crucial for the optimizations in calc_packed_length() + that 'count' is the first element of 'HUFF_ELEMENT'. +*/ struct st_huff_element { my_off_t count; union un_element { @@ -98,7 +102,7 @@ typedef struct st_huff_tree { my_off_t bytes_packed; uint tree_pack_length; uint min_chr,max_chr,char_bits,offset_bits,max_offset,height; - ulong *code; + ulonglong *code; uchar *code_len; } HUFF_TREE; @@ -146,7 +150,7 @@ static uint join_same_trees(HUFF_COUNTS *huff_counts,uint trees); static int make_huff_decode_table(HUFF_TREE *huff_tree,uint trees); static void make_traverse_code_tree(HUFF_TREE *huff_tree, HUFF_ELEMENT *element,uint size, - ulong code); + ulonglong code); static int write_header(PACK_MRG_INFO *isam_file, uint header_length,uint trees, my_off_t tot_elements,my_off_t filelength); static void write_field_info(HUFF_COUNTS *counts, uint fields,uint trees); @@ -161,7 +165,7 @@ static char *make_old_name(char *new_name,char *old_name); static void init_file_buffer(File file,pbool read_buffer); static int flush_buffer(ulong neaded_length); static void end_file_buffer(void); -static void write_bits(ulong value,uint bits); +static void write_bits(ulonglong value, uint bits); static void flush_bits(void); static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length, ha_checksum crc); @@ -170,13 +174,23 @@ static int save_state_mrg(File file,PACK_MRG_INFO *isam_file,my_off_t new_length static int mrg_close(PACK_MRG_INFO *mrg); static int mrg_rrnd(PACK_MRG_INFO *info,byte *buf); static void mrg_reset(PACK_MRG_INFO *mrg); +#if !defined(DBUG_OFF) +static void fakebigcodes(HUFF_COUNTS *huff_counts, HUFF_COUNTS *end_count); +static int fakecmp(my_off_t **count1, my_off_t **count2); +#endif static int error_on_write=0,test_only=0,verbose=0,silent=0, write_loop=0,force_pack=0, isamchk_neaded=0; static int tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL; static my_bool backup, opt_wait; -static uint tree_buff_length=8196-MALLOC_OVERHEAD; +/* + tree_buff_length is somewhat arbitrary. The bigger it is the better + the chance to win in terms of compression factor. On the other hand, + this table becomes part of the compressed file header. And its length + is coded with 16 bits in the header. Hence the limit is 2**16 - 1. +*/ +static uint tree_buff_length= 65536 - MALLOC_OVERHEAD; static char tmp_dir[FN_REFLEN]={0},*join_table; static my_off_t intervall_length; static ha_checksum glob_crc; @@ -225,7 +239,8 @@ int main(int argc, char **argv) } if (ok && isamchk_neaded && !silent) puts("Remember to run myisamchk -rq on compressed tables"); - VOID(fflush(stdout)); VOID(fflush(stderr)); + VOID(fflush(stdout)); + VOID(fflush(stderr)); free_defaults(default_argv); my_end(verbose ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); exit(error ? 2 : 0); @@ -260,7 +275,7 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"test", 't', "Don't pack table, only test packing it.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"verbose", 'v', "Write info about progress and packing result.", + {"verbose", 'v', "Write info about progress and packing result. Use many -v for more verbosity!", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -273,7 +288,8 @@ static struct my_option my_long_options[] = static void print_version(void) { - printf("%s Ver 1.22 for %s on %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE); + VOID(printf("%s Ver 1.22 for %s on %s\n", + my_progname, SYSTEM_TYPE, MACHINE_TYPE)); NETWARE_SET_SCREEN_MODE(1); } @@ -290,7 +306,7 @@ static void usage(void) puts("afterwards to update the keys."); puts("You should give the .MYI file as the filename argument."); - printf("\nUsage: %s [OPTIONS] filename...\n", my_progname); + VOID(printf("\nUsage: %s [OPTIONS] filename...\n", my_progname)); my_print_help(my_long_options); print_defaults("my", load_default_groups); my_print_variables(my_long_options); @@ -314,7 +330,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), silent= 1; break; case 't': - test_only= verbose= 1; + test_only= 1; + /* Avoid to reset 'verbose' if it was already set > 1. */ + if (! verbose) + verbose= 1; break; case 'T': length= (uint) (strmov(tmp_dir, argument) - tmp_dir); @@ -325,7 +344,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } break; case 'v': - verbose= 1; + verbose++; /* Allow for selecting the level of verbosity. */ silent= 0; break; case '#': @@ -380,7 +399,7 @@ static MI_INFO *open_isam_file(char *name,int mode) (opt_wait ? HA_OPEN_WAIT_IF_LOCKED : HA_OPEN_ABORT_IF_LOCKED)))) { - VOID(fprintf(stderr,"%s gave error %d on open\n",name,my_errno)); + VOID(fprintf(stderr, "%s gave error %d on open\n", name, my_errno)); DBUG_RETURN(0); } share=isam_file->s; @@ -388,7 +407,7 @@ static MI_INFO *open_isam_file(char *name,int mode) { if (!force_pack) { - VOID(fprintf(stderr,"%s is already compressed\n",name)); + VOID(fprintf(stderr, "%s is already compressed\n", name)); VOID(mi_close(isam_file)); DBUG_RETURN(0); } @@ -400,7 +419,7 @@ static MI_INFO *open_isam_file(char *name,int mode) (share->state.state.records <= 1 || share->state.state.data_file_length < 1024)) { - VOID(fprintf(stderr,"%s is too small to compress\n",name)); + VOID(fprintf(stderr, "%s is too small to compress\n", name)); VOID(mi_close(isam_file)); DBUG_RETURN(0); } @@ -446,8 +465,8 @@ static bool open_isam_files(PACK_MRG_INFO *mrg,char **names,uint count) return 0; diff_file: - fprintf(stderr,"%s: Tables '%s' and '%s' are not identical\n", - my_progname,names[j],names[j+1]); + VOID(fprintf(stderr, "%s: Tables '%s' and '%s' are not identical\n", + my_progname, names[j], names[j+1])); error: while (i--) mi_close(mrg->file[i]); @@ -518,16 +537,25 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) mrg->records=0; for (i=0 ; i < mrg->count ; i++) mrg->records+=mrg->file[i]->s->state.state.records; + + DBUG_PRINT("info", ("Compressing %s: (%lu records)", + result_table ? new_name : org_name, + (ulong) mrg->records)); if (write_loop || verbose) { - printf("Compressing %s: (%lu records)\n", - result_table ? new_name : org_name,(ulong) mrg->records); + VOID(printf("Compressing %s: (%lu records)\n", + result_table ? new_name : org_name, (ulong) mrg->records)); } trees=fields=share->base.fields; huff_counts=init_huff_count(isam_file,mrg->records); QUICK_SAFEMALLOC; + + /* + Read the whole data file(s) for statistics. + */ + DBUG_PRINT("info", ("- Calculating statistics")); if (write_loop || verbose) - printf("- Calculating statistics\n"); + VOID(printf("- Calculating statistics\n")); if (get_statistic(mrg,huff_counts)) goto err; NORMAL_SAFEMALLOC; @@ -536,29 +564,74 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) old_length+= (mrg->file[i]->s->state.state.data_file_length - mrg->file[i]->s->state.state.empty); + /* + Create a global priority queue in preparation for making + temporary Huffman trees. + */ if (init_queue(&queue,256,0,0,compare_huff_elements,0)) goto err; + + /* + Check each column if we should use pre-space-compress, end-space- + compress, empty-field-compress or zero-field-compress. + */ check_counts(huff_counts,fields,mrg->records); + + /* + Build a Huffman tree for each column. + */ huff_trees=make_huff_trees(huff_counts,trees); + + /* + If the packed lengths of combined columns is less then the sum of + the non-combined columns, then create common Huffman trees for them. + We do this only for byte compressed columns, not for distinct values + compressed columns. + */ if ((int) (used_trees=join_same_trees(huff_counts,trees)) < 0) goto err; + + /* + Assign codes to all byte or column values. + */ if (make_huff_decode_table(huff_trees,fields)) goto err; + /* Prepare a file buffer. */ init_file_buffer(new_file,0); + + /* + Reserve space in the target file for the fixed compressed file header. + */ file_buffer.pos_in_file=HEAD_LENGTH; if (! test_only) VOID(my_seek(new_file,file_buffer.pos_in_file,MY_SEEK_SET,MYF(0))); + /* + Write field infos: field type, pack type, length bits, tree number. + */ write_field_info(huff_counts,fields,used_trees); + + /* + Write decode trees. + */ if (!(tot_elements=write_huff_tree(huff_trees,trees))) goto err; + + /* + Calculate the total length of the compression info header. + This includes the fixed compressed file header, the column compression + type descriptions, and the decode trees. + */ header_length=(uint) file_buffer.pos_in_file+ (uint) (file_buffer.pos-file_buffer.buffer); - /* Compress file */ + /* + Compress the source file into the target file. + */ + DBUG_PRINT("info", ("- Compressing file")); if (write_loop || verbose) - printf("- Compressing file\n"); + VOID(printf("- Compressing file\n")); error=compress_isam_file(mrg,huff_counts); new_length=file_buffer.pos_in_file; if (!error && !test_only) @@ -568,16 +641,28 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) error=my_write(file_buffer.file,buff,sizeof(buff), MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0; } + + /* + Write the fixed compressed file header. + */ if (!error) error=write_header(mrg,header_length,used_trees,tot_elements, new_length); + + /* Flush the file buffer. */ end_file_buffer(); + /* Display statistics. */ + DBUG_PRINT("info", ("Min record length: %6d Max length: %6d " + "Mean total length: %6ld\n", + mrg->min_pack_length, mrg->max_pack_length, + (ulong) (mrg->records ? (new_length/mrg->records) : 0))); if (verbose && mrg->records) - printf("Min record length: %6d Max length: %6d Mean total length: %6ld\n", - mrg->min_pack_length,mrg->max_pack_length, - (ulong) (new_length/mrg->records)); + VOID(printf("Min record length: %6d Max length: %6d " + "Mean total length: %6ld\n", mrg->min_pack_length, + mrg->max_pack_length, (ulong) (new_length/mrg->records))); + /* Close source and target file. */ if (!test_only) { error|=my_close(new_file,MYF(MY_WME)); @@ -588,6 +673,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) } } + /* Cleanup. */ free_counts_and_tree_and_queue(huff_trees,trees,huff_counts,fields); if (! test_only && ! error) { @@ -629,15 +715,16 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) error|=my_close(join_isam_file,MYF(MY_WME)); if (error) { - VOID(fprintf(stderr,"Aborting: %s is not compressed\n",org_name)); + VOID(fprintf(stderr, "Aborting: %s is not compressed\n", org_name)); VOID(my_delete(new_name,MYF(MY_WME))); DBUG_RETURN(-1); } if (write_loop || verbose) { if (old_length) - printf("%.4g%% \n", (((longlong) (old_length -new_length))*100.0/ - (longlong) old_length)); + VOID(printf("%.4g%% \n", + (((longlong) (old_length - new_length)) * 100.0 / + (longlong) old_length))); else puts("Empty file saved in compressed format"); } @@ -650,7 +737,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table) if (join_isam_file >= 0) VOID(my_close(join_isam_file,MYF(0))); mrg_close(mrg); - VOID(fprintf(stderr,"Aborted: %s is not compressed\n",org_name)); + VOID(fprintf(stderr, "Aborted: %s is not compressed\n", org_name)); DBUG_RETURN(-1); } @@ -677,6 +764,12 @@ static HUFF_COUNTS *init_huff_count(MI_INFO *info,my_off_t records) (type == FIELD_NORMAL || type == FIELD_SKIP_ZERO)) count[i].max_zero_fill= count[i].field_length; + /* + For every column initialize a tree, which is used to detect distinct + column values. 'int_tree' works together with 'tree_buff' and + 'tree_pos'. It's keys are implemented by pointers into 'tree_buff'. + This is accomplished by '-1' as the element size. + */ init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0, NULL, NULL); if (records && type != FIELD_BLOB && type != FIELD_VARCHAR) @@ -762,10 +855,13 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) ulong tot_blob_length=0; if (! error) { + /* glob_crc is a checksum over all bytes of all records. */ if (static_row_size) glob_crc+=mi_static_checksum(mrg->file[0],record); else glob_crc+=mi_checksum(mrg->file[0],record); + + /* Count the incidence of values separately for every column. */ for (pos=record,count=huff_counts ; count < end_count ; count++, @@ -773,15 +869,48 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) { next_pos=end_pos=(start_pos=pos)+count->field_length; - /* Put value in tree if there is room for it */ + /* + Put the whole column value in a tree if there is room for it. + 'int_tree' is used to quickly check for duplicate values. + 'tree_buff' collects as many distinct column values as + possible. If the field length is > 1, it is tree_buff_length, + else 2 bytes. Each value is 'field_length' bytes big. If there + are more distinct column values than fit into the buffer, we + give up with this tree. BLOBs and VARCHARs do not have a + tree_buff as it can only be used with fixed length columns. + For the special case of field length == 1, we handle only the + case that there is only one distinct value in the table(s). + Otherwise, we can have a maximum of 256 distinct values. This + is then handled by the normal Huffman tree build. + + Another limit for collecting distinct column values is the + number of values itself. Since we would need to build a + Huffman tree for the values, we are limited by the 'IS_OFFSET' + constant. This constant expresses a bit which is used to + determine if a tree element holds a final value or an offset + to a child element. Hence, all values and offsets need to be + smaller than 'IS_OFFSET'. A tree element is implemented with + two integer values, one for the left branch and one for the + right branch. For the extreme case that the first element + points to the last element, the number of integers in the tree + must be less or equal to IS_OFFSET. So the number of elements + must be less or equal to IS_OFFSET / 2. + + WARNING: At first, we insert a pointer into the record buffer + as the key for the tree. If we got a new distinct value, which + is really inserted into the tree, instead of being counted + only, we will copy the column value from the record buffer to + 'tree_buff' and adjust the key pointer of the tree accordingly. + */ if (count->tree_buff) { global_count=count; if (!(element=tree_insert(&count->int_tree,pos, 0, count->int_tree.custom_arg)) || (element->count == 1 && - count->tree_buff + tree_buff_length < - count->tree_pos + count->field_length) || + (count->tree_buff + tree_buff_length < + count->tree_pos + count->field_length)) || + (count->int_tree.elements_in_tree > IS_OFFSET / 2) || (count->field_length == 1 && count->int_tree.elements_in_tree > 1)) { @@ -791,10 +920,17 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) } else { + /* + If tree_insert() succeeds, it either creates a new element + or increments the counter of an existing element. + */ if (element->count == 1) - { /* New element */ + { + /* Copy the new column value into 'tree_buff'. */ memcpy(count->tree_pos,pos,(size_t) count->field_length); + /* Adjust the key pointer in the tree. */ tree_set_pointer(element,count->tree_pos); + /* Point behind the last column value so far. */ count->tree_pos+=count->field_length; } } @@ -804,15 +940,21 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) if (count->field_type == FIELD_NORMAL || count->field_type == FIELD_SKIP_ENDSPACE) { + /* Ignore trailing space. */ for ( ; end_pos > pos ; end_pos--) if (end_pos[-1] != ' ') break; + /* Empty fields are just counted. Go to the next record. */ if (end_pos == pos) { count->empty_fields++; count->max_zero_fill=0; continue; } + /* + Count the total of all trailing spaces and the number of + short trailing spaces. Remember the longest trailing space. + */ length= (uint) (next_pos-end_pos); count->tot_end_space+=length; if (length < 8) @@ -820,18 +962,25 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) if (count->max_end_space < length) count->max_end_space = length; } + if (count->field_type == FIELD_NORMAL || count->field_type == FIELD_SKIP_PRESPACE) { + /* Ignore leading space. */ for (pos=start_pos; pos < end_pos ; pos++) if (pos[0] != ' ') break; + /* Empty fields are just counted. Go to the next record. */ if (end_pos == pos) { count->empty_fields++; count->max_zero_fill=0; continue; } + /* + Count the total of all leading spaces and the number of + short leading spaces. Remember the longest leading space. + */ length= (uint) (pos-start_pos); count->tot_pre_space+=length; if (length < 8) @@ -839,6 +988,8 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) if (count->max_pre_space < length) count->max_pre_space = length; } + + /* Calculate pos, end_pos, and max_length for variable length fields. */ if (count->field_type == FIELD_BLOB) { uint field_length=count->field_length -mi_portable_sizeof_char_ptr; @@ -857,45 +1008,121 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts) end_pos= pos+length; set_if_bigger(count->max_length,length); } + + /* Evaluate 'max_zero_fill' for short fields. */ if (count->field_length <= 8 && (count->field_type == FIELD_NORMAL || count->field_type == FIELD_SKIP_ZERO)) { uint i; + /* Zero fields are just counted. Go to the next record. */ if (!memcmp((byte*) start_pos,zero_string,count->field_length)) { count->zero_fields++; continue; } + /* + max_zero_fill starts with field_length. It is decreased every + time a shorter "zero trailer" is found. It is set to zero when + an empty field is found (see above). This suggests that the + variable should be called 'min_zero_fill'. + */ for (i =0 ; i < count->max_zero_fill && ! end_pos[-1 - (int) i] ; i++) ; if (i < count->max_zero_fill) count->max_zero_fill=i; } + + /* Ignore zero fields and check fields. */ if (count->field_type == FIELD_ZERO || count->field_type == FIELD_CHECK) continue; + + /* + Count the incidence of every byte value in the + significant field value. + */ for ( ; pos < end_pos ; pos++) count->counts[(uchar) *pos]++; + + /* Step to next field. */ } + if (tot_blob_length > max_blob_length) max_blob_length=tot_blob_length; record_count++; if (write_loop && record_count % WRITE_COUNT == 0) { - printf("%lu\r",(ulong) record_count); VOID(fflush(stdout)); + VOID(printf("%lu\r", (ulong) record_count)); + VOID(fflush(stdout)); } } else if (error != HA_ERR_RECORD_DELETED) { - fprintf(stderr,"Got error %d while reading rows",error); + VOID(fprintf(stderr, "Got error %d while reading rows", error)); break; } + + /* Step to next record. */ } if (write_loop) { - printf(" \r"); VOID(fflush(stdout)); + VOID(printf(" \r")); + VOID(fflush(stdout)); } + + /* + If --debug=d,fakebigcodes is set, fake the counts to get big Huffman + codes. + */ + DBUG_EXECUTE_IF("fakebigcodes", fakebigcodes(huff_counts, end_count);); + + DBUG_PRINT("info", ("Found the following number of incidents " + "of the byte codes:")); + if (verbose >= 2) + VOID(printf("Found the following number of incidents " + "of the byte codes:\n")); + for (count= huff_counts ; count < end_count; count++) + { + uint idx; + my_off_t total_count; + char llbuf[32]; + + DBUG_PRINT("info", ("column: %3u", count - huff_counts + 1)); + if (verbose >= 2) + VOID(printf("column: %3u\n", count - huff_counts + 1)); + if (count->tree_buff) + { + DBUG_PRINT("info", ("number of distinct values: %u", + (count->tree_pos - count->tree_buff) / + count->field_length)); + if (verbose >= 2) + VOID(printf("number of distinct values: %u\n", + (count->tree_pos - count->tree_buff) / + count->field_length)); + } + total_count= 0; + for (idx= 0; idx < 256; idx++) + { + if (count->counts[idx]) + { + total_count+= count->counts[idx]; + DBUG_PRINT("info", ("counts[0x%02x]: %12s", idx, + llstr((longlong) count->counts[idx], llbuf))); + if (verbose >= 2) + VOID(printf("counts[0x%02x]: %12s\n", idx, + llstr((longlong) count->counts[idx], llbuf))); + } + } + DBUG_PRINT("info", ("total: %12s", llstr((longlong) total_count, + llbuf))); + if ((verbose >= 2) && total_count) + { + VOID(printf("total: %12s\n", + llstr((longlong) total_count, llbuf))); + } + } + mrg->records=record_count; mrg->max_blob_length=max_blob_length; my_afree((gptr) record); @@ -944,9 +1171,14 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, huff_counts->field_type=FIELD_NORMAL; huff_counts->pack_type=0; + /* Check for zero-filled records (in this column), or zero records. */ if (huff_counts->zero_fields || ! records) { my_off_t old_space_count; + /* + If there are only zero filled records (in this column), + or no records at all, we are done. + */ if (huff_counts->zero_fields == records) { huff_counts->field_type= FIELD_ZERO; @@ -954,14 +1186,22 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, huff_counts->counts[0]=0; goto found_pack; } + /* Remeber the number of significant spaces. */ old_space_count=huff_counts->counts[' ']; - huff_counts->counts[' ']+=huff_counts->tot_end_space+ - huff_counts->tot_pre_space + - huff_counts->empty_fields * huff_counts->field_length; + /* Add all leading and trailing spaces. */ + huff_counts->counts[' ']+= (huff_counts->tot_end_space + + huff_counts->tot_pre_space + + huff_counts->empty_fields * + huff_counts->field_length); + /* Check, what the compressed length of this would be. */ old_length=calc_packed_length(huff_counts,0)+records/8; + /* Get the number of zero bytes. */ length=huff_counts->zero_fields*huff_counts->field_length; + /* Add it to the counts. */ huff_counts->counts[0]+=length; + /* Check, what the compressed length of this would be. */ new_length=calc_packed_length(huff_counts,0); + /* If the compression without the zeroes would be shorter, we are done. */ if (old_length < new_length && huff_counts->field_length > 1) { huff_counts->field_type=FIELD_SKIP_ZERO; @@ -969,9 +1209,16 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, huff_counts->bytes_packed=old_length- records/8; goto found_pack; } + /* Remove the insignificant spaces, but keep the zeroes. */ huff_counts->counts[' ']=old_space_count; } + /* Check, what the compressed length of this column would be. */ huff_counts->bytes_packed=calc_packed_length(huff_counts,0); + + /* + If there are enough empty records (in this column), + treating them specially may pay off. + */ if (huff_counts->empty_fields) { if (huff_counts->field_length > 2 && @@ -1003,6 +1250,11 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, } } } + + /* + If there are enough trailing spaces (in this column), + treating them specially may pay off. + */ if (huff_counts->tot_end_space) { huff_counts->counts[' ']+=huff_counts->tot_pre_space; @@ -1012,6 +1264,11 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, goto found_pack; huff_counts->counts[' ']-=huff_counts->tot_pre_space; } + + /* + If there are enough leading spaces (in this column), + treating them specially may pay off. + */ if (huff_counts->tot_pre_space) { if (test_space_compress(huff_counts,records,huff_counts->max_pre_space, @@ -1041,6 +1298,8 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, { HUFF_TREE tree; + DBUG_EXECUTE_IF("forceintervall", + huff_counts->bytes_packed= ~ (my_off_t) 0;); tree.element_buffer=0; if (!make_huff_tree(&tree,huff_counts) && tree.bytes_packed+tree.tree_pack_length < huff_counts->bytes_packed) @@ -1066,14 +1325,27 @@ static void check_counts(HUFF_COUNTS *huff_counts, uint trees, fill_zero_fields++; field_count[huff_counts->field_type]++; } + DBUG_PRINT("info", ("normal: %3d empty-space: %3d " + "empty-zero: %3d empty-fill: %3d", + field_count[FIELD_NORMAL],space_fields, + field_count[FIELD_SKIP_ZERO],fill_zero_fields)); + DBUG_PRINT("info", ("pre-space: %3d end-space: %3d " + "intervall-fields: %3d zero: %3d", + field_count[FIELD_SKIP_PRESPACE], + field_count[FIELD_SKIP_ENDSPACE], + field_count[FIELD_INTERVALL], + field_count[FIELD_ZERO])); if (verbose) - printf("\nnormal: %3d empty-space: %3d empty-zero: %3d empty-fill: %3d\npre-space: %3d end-space: %3d intervall-fields: %3d zero: %3d\n", - field_count[FIELD_NORMAL],space_fields, - field_count[FIELD_SKIP_ZERO],fill_zero_fields, - field_count[FIELD_SKIP_PRESPACE], - field_count[FIELD_SKIP_ENDSPACE], - field_count[FIELD_INTERVALL], - field_count[FIELD_ZERO]); + VOID(printf("\nnormal: %3d empty-space: %3d " + "empty-zero: %3d empty-fill: %3d\n" + "pre-space: %3d end-space: %3d " + "intervall-fields: %3d zero: %3d\n", + field_count[FIELD_NORMAL],space_fields, + field_count[FIELD_SKIP_ZERO],fill_zero_fields, + field_count[FIELD_SKIP_PRESPACE], + field_count[FIELD_SKIP_ENDSPACE], + field_count[FIELD_INTERVALL], + field_count[FIELD_ZERO])); DBUG_VOID_RETURN; } @@ -1170,8 +1442,24 @@ static HUFF_TREE* make_huff_trees(HUFF_COUNTS *huff_counts, uint trees) DBUG_RETURN(huff_tree); } - /* Update huff_tree according to huff_counts->counts or - huff_counts->tree_buff */ +/* + Build a Huffman tree. + + SYNOPSIS + make_huff_tree() + huff_tree The Huffman tree. + huff_counts The counts. + + DESCRIPTION + Build a Huffman tree according to huff_counts->counts or + huff_counts->tree_buff. tree_buff, if non-NULL contains up to + tree_buff_length of distinct column values. In that case, whole + values can be Huffman encoded instead of single bytes. + + RETURN + 0 OK + != 0 Error +*/ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts) { @@ -1182,12 +1470,14 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts) first=last=0; if (huff_counts->tree_buff) { + /* Calculate the number of distinct values in tree_buff. */ found= (uint) (huff_counts->tree_pos - huff_counts->tree_buff) / huff_counts->field_length; first=0; last=found-1; } else { + /* Count the number of byte codes found in the column. */ for (i=found=0 ; i < 256 ; i++) { if (huff_counts->counts[i]) @@ -1201,6 +1491,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts) found=2; } + /* When using 'tree_buff' we can have more that 256 values. */ if (queue.max_elements < found) { delete_queue(&queue); @@ -1208,6 +1499,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts) return -1; } + /* Allocate or reallocate an element buffer for the Huffman tree. */ if (!huff_tree->element_buffer) { if (!(huff_tree->element_buffer= @@ -1235,15 +1527,25 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts) if (huff_counts->tree_buff) { huff_tree->elements=0; - tree_walk(&huff_counts->int_tree, - (int (*)(void*, element_count,void*)) save_counts_in_queue, - (gptr) huff_tree, left_root_right); huff_tree->tree_pack_length=(1+15+16+5+5+ (huff_tree->char_bits+1)*found+ (huff_tree->offset_bits+1)* (found-2)+7)/8 + (uint) (huff_tree->counts->tree_pos- huff_tree->counts->tree_buff); + /* + Put a HUFF_ELEMENT into the queue for every distinct column value. + + tree_walk() calls save_counts_in_queue() for every element in + 'int_tree'. This takes elements from the target trees element + buffer and places references to them into the buffer of the + priority queue. We insert in column value order, but the order is + in fact irrelevant here. We will establish the correct order + later. + */ + tree_walk(&huff_counts->int_tree, + (int (*)(void*, element_count,void*)) save_counts_in_queue, + (gptr) huff_tree, left_root_right); } else { @@ -1252,7 +1554,15 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts) (huff_tree->char_bits+1)*found+ (huff_tree->offset_bits+1)* (found-2)+7)/8; + /* + Put a HUFF_ELEMENT into the queue for every byte code found in the column. + The elements are taken from the target trees element buffer. + Instead of using queue_insert(), we just place references to the + elements into the buffer of the priority queue. We insert in byte + value order, but the order is in fact irrelevant here. We will + establish the correct order later. + */ for (i=first, found=0 ; i <= last ; i++) { if (huff_counts->counts[i]) @@ -1264,8 +1574,13 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts) queue.root[found]=(byte*) new_huff_el; } } + /* + If there is only a single byte value in this field in all records, + add a second element with zero incidence. This is required to enter + the loop, which builds the Huffman tree. + */ while (found < 2) - { /* Our huff_trees request at least 2 elements */ + { new_huff_el=huff_tree->element_buffer+(found++); new_huff_el->count=0; new_huff_el->a.leaf.null=0; @@ -1276,21 +1591,53 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts) queue.root[found]=(byte*) new_huff_el; } } + + /* Make a queue from the queue buffer. */ queue.elements=found; + /* + Make a priority queue from the queue. Construct its index so that we + have a partially ordered tree. + */ for (i=found/2 ; i > 0 ; i--) _downheap(&queue,i); + + /* The Huffman algorithm. */ bytes_packed=0; bits_packed=0; for (i=1 ; i < found ; i++) { + /* + Pop the top element from the queue (the one with the least incidence). + Popping from a priority queue includes a re-ordering of the queue, + to get the next least incidence element to the top. + */ a=(HUFF_ELEMENT*) queue_remove(&queue,0); + /* + Copy the next least incidence element. The queue implementation + reserves root[0] for temporary purposes. root[1] is the top. + */ b=(HUFF_ELEMENT*) queue.root[1]; + /* Get a new element from the element buffer. */ new_huff_el=huff_tree->element_buffer+found+i; + /* The new element gets the sum of the two least incidence elements. */ new_huff_el->count=a->count+b->count; + /* + The Huffman algorithm assigns another bit to the code for a byte + every time that bytes incidence is combined (directly or indirectly) + to a new element as one of the two least incidence elements. + This means that one more bit per incidence of that byte is required + in the resulting file. So we add the new combined incidence as the + number of bits by which the result grows. + */ bits_packed+=(uint) (new_huff_el->count & 7); bytes_packed+=new_huff_el->count/8; - new_huff_el->a.nod.left=a; /* lesser in left */ + /* The new element points to its children, lesser in left. */ + new_huff_el->a.nod.left=a; new_huff_el->a.nod.right=b; + /* + Replace the copied top element by the new element and re-order the + queue. + */ queue.root[1]=(byte*) new_huff_el; queue_replaced(&queue); } @@ -1309,7 +1656,26 @@ static int compare_tree(void* cmp_arg __attribute__((unused)), return 0; } - /* Used by make_huff_tree to save intervall-counts in queue */ +/* + Organize distinct column values and their incidences into a priority queue. + + SYNOPSIS + save_counts_in_queue() + key The column value. + count The incidence of this value. + tree The Huffman tree to be built later. + + DESCRIPTION + We use the element buffer of the targeted tree. The distinct column + values are organized in a priority queue first. The Huffman + algorithm will later organize the elements into a Huffman tree. For + the time being, we just place references to the elements into the + queue buffer. The buffer will later be organized into a priority + queue. + + RETURN + 0 + */ static int save_counts_in_queue(byte *key, element_count count, HUFF_TREE *tree) @@ -1326,8 +1692,23 @@ static int save_counts_in_queue(byte *key, element_count count, } - /* Calculate length of file if given counts should be used */ - /* Its actually a faster version of make_huff_tree */ +/* + Calculate length of file if given counts should be used. + + SYNOPSIS + calc_packed_length() + huff_counts The counts for a column of the table(s). + add_tree_lenght If the decode tree length should be added. + + DESCRIPTION + We need to follow the Huffman algorithm until we know, how many bits + are required for each byte code. But we do not need the resulting + Huffman tree. Hence, we can leave out some steps which are essential + in make_huff_tree(). + + RETURN + Number of bytes required to compress this table column. +*/ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts, uint add_tree_lenght) @@ -1337,6 +1718,23 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts, HUFF_ELEMENT element_buffer[256]; DBUG_ENTER("calc_packed_length"); + /* + WARNING: We use a small hack for efficiency: Instead of placing + references to HUFF_ELEMENTs into the queue, we just insert + references to the counts of the byte codes which appeared in this + table column. During the Huffman algorithm they are successively + replaced by references to HUFF_ELEMENTs. This works, because + HUFF_ELEMENTs have the incidence count at their beginning. + Regardless, wether the queue array contains references to counts of + type my_off_t or references to HUFF_ELEMENTs which have the count of + type my_off_t at their beginning, it always points to a count of the + same type. + + Instead of using queue_insert(), we just copy the references into + the buffer of the priority queue. We insert in byte value order, but + the order is in fact irrelevant here. We will establish the correct + order later. + */ first=last=0; for (i=found=0 ; i < 256 ; i++) { @@ -1345,31 +1743,73 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts, if (! found++) first=i; last=i; + /* We start with root[1], which is the queues top element. */ queue.root[found]=(byte*) &huff_counts->counts[i]; } } if (!found) DBUG_RETURN(0); /* Empty tree */ + /* + If there is only a single byte value in this field in all records, + add a second element with zero incidence. This is required to enter + the loop, which follows the Huffman algorithm. + */ if (found < 2) queue.root[++found]=(byte*) &huff_counts->counts[last ? 0 : 1]; + /* Make a queue from the queue buffer. */ queue.elements=found; bytes_packed=0; bits_packed=0; + /* Add the length of the coding table, which would become part of the file. */ if (add_tree_lenght) bytes_packed=(8+9+5+5+(max_bit(last-first)+1)*found+ (max_bit(found-1)+1+1)*(found-2) +7)/8; + + /* + Make a priority queue from the queue. Construct its index so that we + have a partially ordered tree. + */ for (i=(found+1)/2 ; i > 0 ; i--) _downheap(&queue,i); + + /* The Huffman algorithm. */ for (i=0 ; i < found-1 ; i++) { - HUFF_ELEMENT *a,*b,*new_huff_el; - a=(HUFF_ELEMENT*) queue_remove(&queue,0); - b=(HUFF_ELEMENT*) queue.root[1]; - new_huff_el=element_buffer+i; - new_huff_el->count=a->count+b->count; + my_off_t *a; + my_off_t *b; + HUFF_ELEMENT *new_huff_el; + + /* + Pop the top element from the queue (the one with the least + incidence). Popping from a priority queue includes a re-ordering + of the queue, to get the next least incidence element to the top. + */ + a= (my_off_t*) queue_remove(&queue, 0); + /* + Copy the next least incidence element. The queue implementation + reserves root[0] for temporary purposes. root[1] is the top. + */ + b= (my_off_t*) queue.root[1]; + /* Create a new element in a local (automatic) buffer. */ + new_huff_el= element_buffer + i; + /* The new element gets the sum of the two least incidence elements. */ + new_huff_el->count= *a + *b; + /* + The Huffman algorithm assigns another bit to the code for a byte + every time that bytes incidence is combined (directly or indirectly) + to a new element as one of the two least incidence elements. + This means that one more bit per incidence of that byte is required + in the resulting file. So we add the new combined incidence as the + number of bits by which the result grows. + */ bits_packed+=(uint) (new_huff_el->count & 7); bytes_packed+=new_huff_el->count/8; + /* + Replace the copied top element by the new element and re-order the + queue. This successively replaces the references to counts by + references to HUFF_ELEMENTs. + */ queue.root[1]=(byte*) new_huff_el; queue_replaced(&queue); } @@ -1417,13 +1857,26 @@ static uint join_same_trees(HUFF_COUNTS *huff_counts, uint trees) } } } + DBUG_PRINT("info", ("Original trees: %d After join: %d", + trees, tree_number)); if (verbose) - printf("Original trees: %d After join: %d\n",trees,tree_number); + VOID(printf("Original trees: %d After join: %d\n", trees, tree_number)); return tree_number; /* Return trees left */ } - /* Fill in huff_tree decode tables */ +/* + Fill in huff_tree encode tables. + + SYNOPSIS + make_huff_decode_table() + huff_tree An array of HUFF_TREE which are to be encoded. + trees The number of HUFF_TREE in the array. + + RETURN + 0 success + != 0 error +*/ static int make_huff_decode_table(HUFF_TREE *huff_tree, uint trees) { @@ -1434,12 +1887,13 @@ static int make_huff_decode_table(HUFF_TREE *huff_tree, uint trees) { elements=huff_tree->counts->tree_buff ? huff_tree->elements : 256; if (!(huff_tree->code = - (ulong*) my_malloc(elements* - (sizeof(ulong)+sizeof(uchar)), - MYF(MY_WME | MY_ZEROFILL)))) + (ulonglong*) my_malloc(elements* + (sizeof(ulonglong) + sizeof(uchar)), + MYF(MY_WME | MY_ZEROFILL)))) return 1; huff_tree->code_len=(uchar*) (huff_tree->code+elements); - make_traverse_code_tree(huff_tree,huff_tree->root,32,0); + make_traverse_code_tree(huff_tree, huff_tree->root, + 8 * sizeof(ulonglong), LL(0)); } } return 0; @@ -1448,28 +1902,90 @@ static int make_huff_decode_table(HUFF_TREE *huff_tree, uint trees) static void make_traverse_code_tree(HUFF_TREE *huff_tree, HUFF_ELEMENT *element, - uint size, ulong code) + uint size, ulonglong code) { uint chr; if (!element->a.leaf.null) { chr=element->a.leaf.element_nr; - huff_tree->code_len[chr]=(uchar) (32-size); - huff_tree->code[chr]= (code >> size); - if (huff_tree->height < 32-size) - huff_tree->height= 32-size; + huff_tree->code_len[chr]= (uchar) (8 * sizeof(ulonglong) - size); + huff_tree->code[chr]= (code >> size); + if (huff_tree->height < 8 * sizeof(ulonglong) - size) + huff_tree->height= 8 * sizeof(ulonglong) - size; } else { size--; make_traverse_code_tree(huff_tree,element->a.nod.left,size,code); - make_traverse_code_tree(huff_tree,element->a.nod.right,size, - code+((ulong) 1L << size)); + make_traverse_code_tree(huff_tree, element->a.nod.right, size, + code + (((ulonglong) 1) << size)); } return; } +/* + Convert a value into binary digits. + + SYNOPSIS + bindigits() + value The value. + length The number of low order bits to convert. + + NOTE + The result string is in static storage. It is reused on every call. + So you cannot use it twice in one expression. + + RETURN + A pointer to a static NUL-terminated string. + */ + +static char *bindigits(ulonglong value, uint bits) +{ + static char digits[72]; + char *ptr= digits; + uint idx= bits; + + DBUG_ASSERT(idx < sizeof(digits)); + while (idx) + *(ptr++)= '0' + ((value >> (--idx)) & 1); + *ptr= '\0'; + return digits; +} + + +/* + Convert a value into hexadecimal digits. + + SYNOPSIS + hexdigits() + value The value. + + NOTE + The result string is in static storage. It is reused on every call. + So you cannot use it twice in one expression. + + RETURN + A pointer to a static NUL-terminated string. + */ + +static char *hexdigits(ulonglong value) +{ + static char digits[20]; + char *ptr= digits; + uint idx= 2 * sizeof(value); /* Two hex digits per byte. */ + + DBUG_ASSERT(idx < sizeof(digits)); + while (idx) + { + if ((*(ptr++)= '0' + ((value >> (4 * (--idx))) & 0xf)) > '9') + *(ptr - 1)+= 'a' - '9' - 1; + } + *ptr= '\0'; + return digits; +} + + /* Write header to new packed data file */ static int write_header(PACK_MRG_INFO *mrg,uint head_length,uint trees, @@ -1503,15 +2019,64 @@ static void write_field_info(HUFF_COUNTS *counts, uint fields, uint trees) uint huff_tree_bits; huff_tree_bits=max_bit(trees ? trees-1 : 0); + DBUG_PRINT("info", ("")); + DBUG_PRINT("info", ("column types:")); + DBUG_PRINT("info", ("FIELD_NORMAL 0")); + DBUG_PRINT("info", ("FIELD_SKIP_ENDSPACE 1")); + DBUG_PRINT("info", ("FIELD_SKIP_PRESPACE 2")); + DBUG_PRINT("info", ("FIELD_SKIP_ZERO 3")); + DBUG_PRINT("info", ("FIELD_BLOB 4")); + DBUG_PRINT("info", ("FIELD_CONSTANT 5")); + DBUG_PRINT("info", ("FIELD_INTERVALL 6")); + DBUG_PRINT("info", ("FIELD_ZERO 7")); + DBUG_PRINT("info", ("FIELD_VARCHAR 8")); + DBUG_PRINT("info", ("FIELD_CHECK 9")); + DBUG_PRINT("info", ("")); + DBUG_PRINT("info", ("pack type as a set of flags:")); + DBUG_PRINT("info", ("PACK_TYPE_SELECTED 1")); + DBUG_PRINT("info", ("PACK_TYPE_SPACE_FIELDS 2")); + DBUG_PRINT("info", ("PACK_TYPE_ZERO_FILL 4")); + DBUG_PRINT("info", ("")); + if (verbose >= 2) + { + VOID(printf("\n")); + VOID(printf("column types:\n")); + VOID(printf("FIELD_NORMAL 0\n")); + VOID(printf("FIELD_SKIP_ENDSPACE 1\n")); + VOID(printf("FIELD_SKIP_PRESPACE 2\n")); + VOID(printf("FIELD_SKIP_ZERO 3\n")); + VOID(printf("FIELD_BLOB 4\n")); + VOID(printf("FIELD_CONSTANT 5\n")); + VOID(printf("FIELD_INTERVALL 6\n")); + VOID(printf("FIELD_ZERO 7\n")); + VOID(printf("FIELD_VARCHAR 8\n")); + VOID(printf("FIELD_CHECK 9\n")); + VOID(printf("\n")); + VOID(printf("pack type as a set of flags:\n")); + VOID(printf("PACK_TYPE_SELECTED 1\n")); + VOID(printf("PACK_TYPE_SPACE_FIELDS 2\n")); + VOID(printf("PACK_TYPE_ZERO_FILL 4\n")); + VOID(printf("\n")); + } for (i=0 ; i++ < fields ; counts++) { - write_bits((ulong) (int) counts->field_type,5); + write_bits((ulonglong) (int) counts->field_type, 5); write_bits(counts->pack_type,6); if (counts->pack_type & PACK_TYPE_ZERO_FILL) write_bits(counts->max_zero_fill,5); else write_bits(counts->length_bits,5); - write_bits((ulong) counts->tree->tree_number-1,huff_tree_bits); + write_bits((ulonglong) counts->tree->tree_number - 1, huff_tree_bits); + DBUG_PRINT("info", ("column: %3u type: %2u pack: %2u zero: %4u " + "lbits: %2u tree: %2u length: %4u", + i , counts->field_type, counts->pack_type, + counts->max_zero_fill, counts->length_bits, + counts->tree->tree_number, counts->field_length)); + if (verbose >= 2) + VOID(printf("column: %3u type: %2u pack: %2u zero: %4u lbits: %2u " + "tree: %2u length: %4u\n", i , counts->field_type, + counts->pack_type, counts->max_zero_fill, counts->length_bits, + counts->tree->tree_number, counts->field_length)); } flush_bits(); return; @@ -1524,45 +2089,72 @@ static void write_field_info(HUFF_COUNTS *counts, uint fields, uint trees) static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees) { uint i,int_length; + uint tree_no; + uint codes; + uint errors= 0; uint *packed_tree,*offset,length; my_off_t elements; + /* Find the highest number of elements in the trees. */ for (i=length=0 ; i < trees ; i++) if (huff_tree[i].tree_number > 0 && huff_tree[i].elements > length) length=huff_tree[i].elements; + /* + Allocate a buffer for packing a decode tree. Two numbers per element + (left child and right child). + */ if (!(packed_tree=(uint*) my_alloca(sizeof(uint)*length*2))) { my_error(EE_OUTOFMEMORY,MYF(ME_BELL),sizeof(uint)*length*2); return 0; } + DBUG_PRINT("info", ("")); + if (verbose >= 2) + VOID(printf("\n")); + tree_no= 0; intervall_length=0; for (elements=0; trees-- ; huff_tree++) { + /* Skip columns that have been joined with other columns. */ if (huff_tree->tree_number == 0) continue; /* Deleted tree */ + tree_no++; + DBUG_PRINT("info", ("")); + if (verbose >= 3) + VOID(printf("\n")); + /* Count the total number of elements (byte codes or column values). */ elements+=huff_tree->elements; huff_tree->max_offset=2; + /* Build a tree of offsets and codes for decoding in 'packed_tree'. */ if (huff_tree->elements <= 1) offset=packed_tree; else offset=make_offset_code_tree(huff_tree,huff_tree->root,packed_tree); + + /* This should be the same as 'length' above. */ huff_tree->offset_bits=max_bit(huff_tree->max_offset); + + /* + Since we check this during collecting the distinct column values, + this should never happen. + */ if (huff_tree->max_offset >= IS_OFFSET) { /* This should be impossible */ - VOID(fprintf(stderr,"Tree offset got too big: %d, aborted\n", - huff_tree->max_offset)); + VOID(fprintf(stderr, "Tree offset got too big: %d, aborted\n", + huff_tree->max_offset)); my_afree((gptr) packed_tree); return 0; } -#ifdef EXTRA_DBUG - printf("pos: %d elements: %d tree-elements: %d char_bits: %d\n", - (uint) (file_buffer.pos-file_buffer.buffer), - huff_tree->elements, (offset-packed_tree),huff_tree->char_bits); -#endif + DBUG_PRINT("info", ("pos: %lu elements: %u tree-elements: %lu " + "char_bits: %u\n", + (ulong) (file_buffer.pos - file_buffer.buffer), + huff_tree->elements, (ulong) (offset - packed_tree), + huff_tree->char_bits)); if (!huff_tree->counts->tree_buff) { + /* We do a byte compression on this column. Mark with bit 0. */ write_bits(0,1); write_bits(huff_tree->min_chr,8); write_bits(huff_tree->elements,9); @@ -1574,6 +2166,7 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees) { int_length=(uint) (huff_tree->counts->tree_pos - huff_tree->counts->tree_buff); + /* We have distinct column values for this column. Mark with bit 1. */ write_bits(1,1); write_bits(huff_tree->elements,15); write_bits(int_length,16); @@ -1581,10 +2174,29 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees) write_bits(huff_tree->offset_bits,5); intervall_length+=int_length; } + DBUG_PRINT("info", ("tree: %2u elements: %4u char_bits: %2u " + "offset_bits: %2u %s: %5u codelen: %2u", + tree_no, huff_tree->elements, huff_tree->char_bits, + huff_tree->offset_bits, huff_tree->counts->tree_buff ? + "bufflen" : "min_chr", huff_tree->counts->tree_buff ? + int_length : huff_tree->min_chr, huff_tree->height)); + if (verbose >= 2) + VOID(printf("tree: %2u elements: %4u char_bits: %2u offset_bits: %2u " + "%s: %5u codelen: %2u\n", tree_no, huff_tree->elements, + huff_tree->char_bits, huff_tree->offset_bits, + huff_tree->counts->tree_buff ? "bufflen" : "min_chr", + huff_tree->counts->tree_buff ? int_length : + huff_tree->min_chr, huff_tree->height)); + + /* Check that the code tree length matches the element count. */ length=(uint) (offset-packed_tree); if (length != huff_tree->elements*2-2) - printf("error: Huff-tree-length: %d != calc_length: %d\n", - length,huff_tree->elements*2-2); + { + VOID(fprintf(stderr, "error: Huff-tree-length: %d != calc_length: %d\n", + length, huff_tree->elements * 2 - 2)); + errors++; + break; + } for (i=0 ; i < length ; i++) { @@ -1593,16 +2205,122 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees) huff_tree->offset_bits+1); else write_bits(packed_tree[i]-huff_tree->min_chr,huff_tree->char_bits+1); + DBUG_PRINT("info", ("tree[0x%04x]: %s0x%04x", + i, (packed_tree[i] & IS_OFFSET) ? + " -> " : "", (packed_tree[i] & IS_OFFSET) ? + packed_tree[i] - IS_OFFSET + i : packed_tree[i])); + if (verbose >= 3) + VOID(printf("tree[0x%04x]: %s0x%04x\n", + i, (packed_tree[i] & IS_OFFSET) ? " -> " : "", + (packed_tree[i] & IS_OFFSET) ? + packed_tree[i] - IS_OFFSET + i : packed_tree[i])); } flush_bits(); + + /* + Display coding tables and check their correctness. + */ + codes= huff_tree->counts->tree_buff ? huff_tree->elements : 256; + for (i= 0; i < codes; i++) + { + ulonglong code; + uint bits; + uint len; + uint idx; + + if (! (len= huff_tree->code_len[i])) + continue; + DBUG_PRINT("info", ("code[0x%04x]: 0x%s bits: %2u bin: %s", i, + hexdigits(huff_tree->code[i]), huff_tree->code_len[i], + bindigits(huff_tree->code[i], + huff_tree->code_len[i]))); + if (verbose >= 3) + VOID(printf("code[0x%04x]: 0x%s bits: %2u bin: %s\n", i, + hexdigits(huff_tree->code[i]), huff_tree->code_len[i], + bindigits(huff_tree->code[i], huff_tree->code_len[i]))); + + /* Check that the encode table decodes correctly. */ + code= 0; + bits= 0; + idx= 0; + DBUG_EXECUTE_IF("forcechkerr1", len--;); + DBUG_EXECUTE_IF("forcechkerr2", bits= 8 * sizeof(code);); + DBUG_EXECUTE_IF("forcechkerr3", idx= length;); + for (;;) + { + if (! len) + { + VOID(fflush(stdout)); + VOID(fprintf(stderr, "error: code 0x%s with %u bits not found\n", + hexdigits(huff_tree->code[i]), huff_tree->code_len[i])); + errors++; + break; + } + code<<= 1; + code|= (huff_tree->code[i] >> (--len)) & 1; + bits++; + if (bits > 8 * sizeof(code)) + { + VOID(fflush(stdout)); + VOID(fprintf(stderr, "error: Huffman code too long: %u/%u\n", + bits, 8 * sizeof(code))); + errors++; + break; + } + idx+= code & 1; + if (idx >= length) + { + VOID(fflush(stdout)); + VOID(fprintf(stderr, "error: illegal tree offset: %u/%u\n", + idx, length)); + errors++; + break; + } + if (packed_tree[idx] & IS_OFFSET) + idx+= packed_tree[idx] & ~IS_OFFSET; + else + break; /* Hit a leaf. This contains the result value. */ + } + if (errors) + break; + + DBUG_EXECUTE_IF("forcechkerr4", packed_tree[idx]++;); + if (packed_tree[idx] != i) + { + VOID(fflush(stdout)); + VOID(fprintf(stderr, "error: decoded value 0x%04x should be: 0x%04x\n", + packed_tree[idx], i)); + errors++; + break; + } + } /*end for (codes)*/ + if (errors) + break; + + /* Write column values in case of distinct column value compression. */ if (huff_tree->counts->tree_buff) { for (i=0 ; i < int_length ; i++) - write_bits((uint) (uchar) huff_tree->counts->tree_buff[i],8); + { + write_bits((ulonglong) (uchar) huff_tree->counts->tree_buff[i], 8); + DBUG_PRINT("info", ("column_values[0x%04x]: 0x%02x", + i, (uchar) huff_tree->counts->tree_buff[i])); + if (verbose >= 3) + VOID(printf("column_values[0x%04x]: 0x%02x\n", + i, (uchar) huff_tree->counts->tree_buff[i])); + } } flush_bits(); } + DBUG_PRINT("info", ("")); + if (verbose >= 2) + VOID(printf("\n")); my_afree((gptr) packed_tree); + if (errors) + { + VOID(fprintf(stderr, "Error: Generated decode trees are corrupt. Stop.\n")); + return 0; + } return elements; } @@ -1613,23 +2331,43 @@ static uint *make_offset_code_tree(HUFF_TREE *huff_tree, HUFF_ELEMENT *element, uint *prev_offset; prev_offset= offset; + /* + 'a.leaf.null' takes the same place as 'a.nod.left'. If this is null, + then there is no left child and, hence no right child either. This + is a property of a binary tree. An element is either a node with two + childs, or a leaf without childs. + + The current element is always a node with two childs. Go left first. + */ if (!element->a.nod.left->a.leaf.null) { - offset[0] =(uint) element->a.nod.left->a.leaf.element_nr; + /* Store the byte code or the index of the column value. */ + prev_offset[0] =(uint) element->a.nod.left->a.leaf.element_nr; offset+=2; } else { + /* + Recursively traverse the tree to the left. Mark it as an offset to + another tree node (in contrast to a byte code or column value index). + */ prev_offset[0]= IS_OFFSET+2; offset=make_offset_code_tree(huff_tree,element->a.nod.left,offset+2); } + + /* Now, check the right child. */ if (!element->a.nod.right->a.leaf.null) { + /* Store the byte code or the index of the column value. */ prev_offset[1]=element->a.nod.right->a.leaf.element_nr; return offset; } else { + /* + Recursively traverse the tree to the right. Mark it as an offset to + another tree node (in contrast to a byte code or column value index). + */ uint temp=(uint) (offset-prev_offset-1); prev_offset[1]= IS_OFFSET+ temp; if (huff_tree->max_offset < temp) @@ -1656,6 +2394,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) uint i,max_calc_length,pack_ref_length,min_record_length,max_record_length, intervall,field_length,max_pack_length,pack_blob_length; my_off_t record_count; + char llbuf[32]; ulong length,pack_length; byte *record,*pos,*end_pos,*record_pos,*start_pos; HUFF_COUNTS *count,*end_count; @@ -1663,12 +2402,23 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) MI_INFO *isam_file=mrg->file[0]; DBUG_ENTER("compress_isam_file"); + /* Allocate a buffer for the records (excluding blobs). */ if (!(record=(byte*) my_alloca(isam_file->s->base.reclength))) return -1; + end_count=huff_counts+isam_file->s->base.fields; min_record_length= (uint) ~0; max_record_length=0; + /* + Calculate the maximum number of bits required to pack the records. + Remember to understand 'max_zero_fill' as 'min_zero_fill'. + The tree height determines the maximum number of bits per value. + Some fields skip leading or trailing spaces or zeroes. The skipped + number of bytes is encoded by 'length_bits' bits. + Empty blobs and varchar are encoded with a single 1 bit. Other blobs + and varchar get a leading 0 bit. + */ for (i=max_calc_length=0 ; i < isam_file->s->base.fields ; i++) { if (!(huff_counts[i].pack_type & PACK_TYPE_ZERO_FILL)) @@ -1687,14 +2437,16 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) (huff_counts[i].field_length - huff_counts[i].max_zero_fill)* huff_counts[i].tree->height+huff_counts[i].length_bits; } - max_calc_length/=8; + max_calc_length= (max_calc_length + 7) / 8; if (max_calc_length < 254) pack_ref_length=1; else if (max_calc_length <= 65535) pack_ref_length=3; else pack_ref_length=4; + record_count=0; + /* 'max_blob_length' is the max length of all blobs of a record. */ pack_blob_length=0; if (isam_file->s->base.blobs) { @@ -1707,6 +2459,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) } max_pack_length=pack_ref_length+pack_blob_length; + DBUG_PRINT("fields", ("===")); mrg_reset(mrg); while ((error=mrg_rrnd(mrg,record)) != HA_ERR_END_OF_FILE) { @@ -1722,15 +2475,29 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) end_pos=start_pos+(field_length=count->field_length); tree=count->tree; + DBUG_PRINT("fields", ("column: %3lu type: %2u pack: %2u zero: %4u " + "lbits: %2u tree: %2u length: %4u", + (ulong) (count - huff_counts + 1), + count->field_type, + count->pack_type, count->max_zero_fill, + count->length_bits, count->tree->tree_number, + count->field_length)); + + /* Check if the column contains spaces only. */ if (count->pack_type & PACK_TYPE_SPACE_FIELDS) { for (pos=start_pos ; *pos == ' ' && pos < end_pos; pos++) ; if (pos == end_pos) { + DBUG_PRINT("fields", + ("PACK_TYPE_SPACE_FIELDS spaces only, bits: 1")); + DBUG_PRINT("fields", ("---")); write_bits(1,1); start_pos=end_pos; continue; } + DBUG_PRINT("fields", + ("PACK_TYPE_SPACE_FIELDS not only spaces, bits: 1")); write_bits(0,1); } end_pos-=count->max_zero_fill; @@ -1740,65 +2507,129 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) case FIELD_SKIP_ZERO: if (!memcmp((byte*) start_pos,zero_string,field_length)) { + DBUG_PRINT("fields", ("FIELD_SKIP_ZERO zeroes only, bits: 1")); write_bits(1,1); start_pos=end_pos; break; } + DBUG_PRINT("fields", ("FIELD_SKIP_ZERO not only zeroes, bits: 1")); write_bits(0,1); /* Fall through */ case FIELD_NORMAL: + DBUG_PRINT("fields", ("FIELD_NORMAL %lu bytes", + (ulong) (end_pos - start_pos))); for ( ; start_pos < end_pos ; start_pos++) + { + DBUG_PRINT("fields", + ("value: 0x%02x code: 0x%s bits: %2u bin: %s", + (uchar) *start_pos, + hexdigits(tree->code[(uchar) *start_pos]), + (uint) tree->code_len[(uchar) *start_pos], + bindigits(tree->code[(uchar) *start_pos], + (uint) tree->code_len[(uchar) *start_pos]))); write_bits(tree->code[(uchar) *start_pos], (uint) tree->code_len[(uchar) *start_pos]); + } break; case FIELD_SKIP_ENDSPACE: for (pos=end_pos ; pos > start_pos && pos[-1] == ' ' ; pos--) ; - length=(uint) (end_pos-pos); + length= (ulong) (end_pos - pos); if (count->pack_type & PACK_TYPE_SELECTED) { if (length > count->min_space) { + DBUG_PRINT("fields", + ("FIELD_SKIP_ENDSPACE more than min_space, bits: 1")); + DBUG_PRINT("fields", + ("FIELD_SKIP_ENDSPACE skip %lu/%u bytes, bits: %2u", + length, field_length, count->length_bits)); write_bits(1,1); write_bits(length,count->length_bits); } else { + DBUG_PRINT("fields", + ("FIELD_SKIP_ENDSPACE not more than min_space, " + "bits: 1")); write_bits(0,1); pos=end_pos; } } else + { + DBUG_PRINT("fields", + ("FIELD_SKIP_ENDSPACE skip %lu/%u bytes, bits: %2u", + length, field_length, count->length_bits)); write_bits(length,count->length_bits); + } + /* Encode all significant bytes. */ + DBUG_PRINT("fields", ("FIELD_SKIP_ENDSPACE %lu bytes", + (ulong) (pos - start_pos))); for ( ; start_pos < pos ; start_pos++) + { + DBUG_PRINT("fields", + ("value: 0x%02x code: 0x%s bits: %2u bin: %s", + (uchar) *start_pos, + hexdigits(tree->code[(uchar) *start_pos]), + (uint) tree->code_len[(uchar) *start_pos], + bindigits(tree->code[(uchar) *start_pos], + (uint) tree->code_len[(uchar) *start_pos]))); write_bits(tree->code[(uchar) *start_pos], (uint) tree->code_len[(uchar) *start_pos]); + } start_pos=end_pos; break; case FIELD_SKIP_PRESPACE: for (pos=start_pos ; pos < end_pos && pos[0] == ' ' ; pos++) ; - length=(uint) (pos-start_pos); + length= (ulong) (pos - start_pos); if (count->pack_type & PACK_TYPE_SELECTED) { if (length > count->min_space) { + DBUG_PRINT("fields", + ("FIELD_SKIP_PRESPACE more than min_space, bits: 1")); + DBUG_PRINT("fields", + ("FIELD_SKIP_PRESPACE skip %lu/%u bytes, bits: %2u", + length, field_length, count->length_bits)); write_bits(1,1); write_bits(length,count->length_bits); } else { + DBUG_PRINT("fields", + ("FIELD_SKIP_PRESPACE not more than min_space, " + "bits: 1")); pos=start_pos; write_bits(0,1); } } else + { + DBUG_PRINT("fields", + ("FIELD_SKIP_PRESPACE skip %lu/%u bytes, bits: %2u", + length, field_length, count->length_bits)); write_bits(length,count->length_bits); + } + /* Encode all significant bytes. */ + DBUG_PRINT("fields", ("FIELD_SKIP_PRESPACE %lu bytes", + (ulong) (end_pos - start_pos))); for (start_pos=pos ; start_pos < end_pos ; start_pos++) + { + DBUG_PRINT("fields", + ("value: 0x%02x code: 0x%s bits: %2u bin: %s", + (uchar) *start_pos, + hexdigits(tree->code[(uchar) *start_pos]), + (uint) tree->code_len[(uchar) *start_pos], + bindigits(tree->code[(uchar) *start_pos], + (uint) tree->code_len[(uchar) *start_pos]))); write_bits(tree->code[(uchar) *start_pos], (uint) tree->code_len[(uchar) *start_pos]); + } break; case FIELD_CONSTANT: case FIELD_ZERO: case FIELD_CHECK: + DBUG_PRINT("fields", ("FIELD_CONSTANT/ZERO/CHECK")); start_pos=end_pos; break; case FIELD_INTERVALL: @@ -1806,6 +2637,10 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) pos=(byte*) tree_search(&count->int_tree, start_pos, count->int_tree.custom_arg); intervall=(uint) (pos - count->tree_buff)/field_length; + DBUG_PRINT("fields", ("FIELD_INTERVALL")); + DBUG_PRINT("fields", ("index: %4u code: 0x%s bits: %2u", + intervall, hexdigits(tree->code[intervall]), + (uint) tree->code_len[intervall])); write_bits(tree->code[intervall],(uint) tree->code_len[intervall]); start_pos=end_pos; break; @@ -1814,21 +2649,36 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) ulong blob_length=_mi_calc_blob_length(field_length- mi_portable_sizeof_char_ptr, start_pos); + /* Empty blobs are encoded with a single 1 bit. */ if (!blob_length) { - write_bits(1,1); /* Empty blob */ + DBUG_PRINT("fields", ("FIELD_BLOB empty, bits: 1")); + write_bits(1,1); } else { byte *blob,*blob_end; + DBUG_PRINT("fields", ("FIELD_BLOB not empty, bits: 1")); write_bits(0,1); + /* Write the blob length. */ + DBUG_PRINT("fields", ("FIELD_BLOB %lu bytes, bits: %2u", + blob_length, count->length_bits)); write_bits(blob_length,count->length_bits); memcpy_fixed(&blob,end_pos-mi_portable_sizeof_char_ptr, sizeof(char*)); blob_end=blob+blob_length; + /* Encode the blob bytes. */ for ( ; blob < blob_end ; blob++) + { + DBUG_PRINT("fields", + ("value: 0x%02x code: 0x%s bits: %2u bin: %s", + (uchar) *blob, hexdigits(tree->code[(uchar) *blob]), + (uint) tree->code_len[(uchar) *blob], + bindigits(tree->code[(uchar) *start_pos], + (uint)tree->code_len[(uchar) *start_pos]))); write_bits(tree->code[(uchar) *blob], (uint) tree->code_len[(uchar) *blob]); + } tot_blob_length+=blob_length; } start_pos= end_pos; @@ -1839,18 +2689,34 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) uint pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1); ulong col_length= (pack_length == 1 ? (uint) *(uchar*) start_pos : uint2korr(start_pos)); + /* Empty varchar are encoded with a single 1 bit. */ if (!col_length) { + DBUG_PRINT("fields", ("FIELD_VARCHAR empty, bits: 1")); write_bits(1,1); /* Empty varchar */ } else { byte *end=start_pos+pack_length+col_length; + DBUG_PRINT("fields", ("FIELD_VARCHAR not empty, bits: 1")); write_bits(0,1); + /* Write the varchar length. */ + DBUG_PRINT("fields", ("FIELD_VARCHAR %lu bytes, bits: %2u", + col_length, count->length_bits)); write_bits(col_length,count->length_bits); + /* Encode the varchar bytes. */ for (start_pos+=pack_length ; start_pos < end ; start_pos++) + { + DBUG_PRINT("fields", + ("value: 0x%02x code: 0x%s bits: %2u bin: %s", + (uchar) *start_pos, + hexdigits(tree->code[(uchar) *start_pos]), + (uint) tree->code_len[(uchar) *start_pos], + bindigits(tree->code[(uchar) *start_pos], + (uint)tree->code_len[(uchar) *start_pos]))); write_bits(tree->code[(uchar) *start_pos], (uint) tree->code_len[(uchar) *start_pos]); + } } start_pos= end_pos; break; @@ -1859,12 +2725,17 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) abort(); /* Impossible */ } start_pos+=count->max_zero_fill; + DBUG_PRINT("fields", ("---")); } flush_bits(); - length=(ulong) (file_buffer.pos-record_pos)-max_pack_length; + length=(ulong) ((byte*) file_buffer.pos - record_pos) - max_pack_length; pack_length=save_pack_length(record_pos,length); if (pack_blob_length) pack_length+=save_pack_length(record_pos+pack_length,tot_blob_length); + DBUG_PRINT("fields", ("record: %lu length: %lu blob-length: %lu " + "length-bytes: %lu", (ulong) record_count, length, + tot_blob_length, pack_length)); + DBUG_PRINT("fields", ("===")); /* Correct file buffer if the header was smaller */ if (pack_length != max_pack_length) @@ -1876,9 +2747,11 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) min_record_length=(uint) length; if (length > (ulong) max_record_length) max_record_length=(uint) length; - if (write_loop && ++record_count % WRITE_COUNT == 0) + record_count++; + if (write_loop && record_count % WRITE_COUNT == 0) { - printf("%lu\r",(ulong) record_count); VOID(fflush(stdout)); + VOID(printf("%lu\r", (ulong) record_count)); + VOID(fflush(stdout)); } } else if (error != HA_ERR_RECORD_DELETED) @@ -1888,8 +2761,11 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts) error=0; else { - fprintf(stderr,"%s: Got error %d reading records\n",my_progname,error); + VOID(fprintf(stderr, "%s: Got error %d reading records\n", + my_progname, error)); } + if (verbose >= 2) + VOID(printf("wrote %s records.\n", llstr((longlong) record_count, llbuf))); my_afree((gptr) record); mrg->ref_length=max_pack_length; @@ -1929,7 +2805,7 @@ static void init_file_buffer(File file, pbool read_buffer) file_buffer.pos=file_buffer.buffer; file_buffer.bits=BITS_SAVED; } - file_buffer.current_byte=0; + file_buffer.bitbucket= 0; } @@ -1972,7 +2848,8 @@ static int flush_buffer(ulong neaded_length) tmp=my_realloc(file_buffer.buffer, neaded_length,MYF(MY_WME)); if (!tmp) return 1; - file_buffer.pos= tmp + (ulong) (file_buffer.pos - file_buffer.buffer); + file_buffer.pos= ((uchar*) tmp + + (ulong) (file_buffer.pos - file_buffer.buffer)); file_buffer.buffer=tmp; file_buffer.end=tmp+neaded_length-8; } @@ -1987,68 +2864,59 @@ static void end_file_buffer(void) /* output `bits` low bits of `value' */ -static void write_bits (register ulong value, register uint bits) +static void write_bits(register ulonglong value, register uint bits) { - if ((file_buffer.bits-=(int) bits) >= 0) + DBUG_ASSERT(((bits < 8 * sizeof(value)) && ! (value >> bits)) || + (bits == 8 * sizeof(value))); + + if ((file_buffer.bits-= (int) bits) >= 0) { - file_buffer.current_byte|=value << file_buffer.bits; + file_buffer.bitbucket|= value << file_buffer.bits; } else { - reg3 uint byte_buff; + reg3 ulonglong bit_buffer; bits= (uint) -file_buffer.bits; - DBUG_ASSERT(bits <= 8 * sizeof(value)); - byte_buff= (file_buffer.current_byte | - ((bits != 8 * sizeof(value)) ? (uint) (value >> bits) : 0)); -#if BITS_SAVED == 32 - *file_buffer.pos++= (byte) (byte_buff >> 24) ; - *file_buffer.pos++= (byte) (byte_buff >> 16) ; + bit_buffer= (file_buffer.bitbucket | + ((bits != 8 * sizeof(value)) ? (value >> bits) : 0)); +#if BITS_SAVED == 64 + *file_buffer.pos++= (uchar) (bit_buffer >> 56); + *file_buffer.pos++= (uchar) (bit_buffer >> 48); + *file_buffer.pos++= (uchar) (bit_buffer >> 40); + *file_buffer.pos++= (uchar) (bit_buffer >> 32); #endif - *file_buffer.pos++= (byte) (byte_buff >> 8) ; - *file_buffer.pos++= (byte) byte_buff; + *file_buffer.pos++= (uchar) (bit_buffer >> 24); + *file_buffer.pos++= (uchar) (bit_buffer >> 16); + *file_buffer.pos++= (uchar) (bit_buffer >> 8); + *file_buffer.pos++= (uchar) (bit_buffer); - DBUG_ASSERT(bits <= 8 * sizeof(ulong)); if (bits != 8 * sizeof(value)) - value&= (((ulong) 1) << bits) - 1; -#if BITS_SAVED == 16 - if (bits >= sizeof(uint)) - { - bits-=8; - *file_buffer.pos++= (uchar) (value >> bits); - value&= (1 << bits)-1; - if (bits >= sizeof(uint)) - { - bits-=8; - *file_buffer.pos++= (uchar) (value >> bits); - value&= (1 << bits)-1; - } - } -#endif + value&= (((ulonglong) 1) << bits) - 1; if (file_buffer.pos >= file_buffer.end) VOID(flush_buffer(~ (ulong) 0)); file_buffer.bits=(int) (BITS_SAVED - bits); - file_buffer.current_byte=(uint) (value << (BITS_SAVED - bits)); + file_buffer.bitbucket= value << (BITS_SAVED - bits); } return; } /* Flush bits in bit_buffer to buffer */ -static void flush_bits (void) +static void flush_bits(void) { - uint bits,byte_buff; + int bits; + ulonglong bit_buffer; - bits=(file_buffer.bits) & ~7; - byte_buff = file_buffer.current_byte >> bits; - bits=BITS_SAVED - bits; + bits= file_buffer.bits & ~7; + bit_buffer= file_buffer.bitbucket >> bits; + bits= BITS_SAVED - bits; while (bits > 0) { - bits-=8; - *file_buffer.pos++= (byte) (uchar) (byte_buff >> bits) ; + bits-= 8; + *file_buffer.pos++= (uchar) (bit_buffer >> bits); } - file_buffer.bits=BITS_SAVED; - file_buffer.current_byte=0; - return; + file_buffer.bits= BITS_SAVED; + file_buffer.bitbucket= 0; } @@ -2196,3 +3064,131 @@ static int mrg_close(PACK_MRG_INFO *mrg) my_free((gptr) mrg->file,MYF(0)); return error; } + + +#if !defined(DBUG_OFF) +/* + Fake the counts to get big Huffman codes. + + SYNOPSIS + fakebigcodes() + huff_counts A pointer to the counts array. + end_count A pointer past the counts array. + + DESCRIPTION + + Huffman coding works by removing the two least frequent values from + the list of values and add a new value with the sum of their + incidences in a loop until only one value is left. Every time a + value is reused for a new value, it gets one more bit for its + encoding. Hence, the least frequent values get the longest codes. + + To get a maximum code length for a value, two of the values must + have an incidence of 1. As their sum is 2, the next infrequent value + must have at least an incidence of 2, then 4, 8, 16 and so on. This + means that one needs 2**n bytes (values) for a code length of n + bits. However, using more distinct values forces the use of longer + codes, or reaching the code length with less total bytes (values). + + To get 64(32)-bit codes, I sort the counts by decreasing incidence. + I assign counts of 1 to the two most frequent values, a count of 2 + for the next one, then 4, 8, and so on until 2**64-1(2**30-1). All + the remaining values get 1. That way every possible byte has an + assigned code, though not all codes are used if not all byte values + are present in the column. + + This strategy would work with distinct column values too, but + requires that at least 64(32) values are present. To make things + easier here, I cancel all distinct column values and force byte + compression for all columns. + + RETURN + void +*/ + +static void fakebigcodes(HUFF_COUNTS *huff_counts, HUFF_COUNTS *end_count) +{ + HUFF_COUNTS *count; + my_off_t *cur_count_p; + my_off_t *end_count_p; + my_off_t **cur_sort_p; + my_off_t **end_sort_p; + my_off_t *sort_counts[256]; + my_off_t total; + DBUG_ENTER("fakebigcodes"); + + for (count= huff_counts; count < end_count; count++) + { + /* + Remove distinct column values. + */ + if (huff_counts->tree_buff) + { + my_free((gptr) huff_counts->tree_buff, MYF(0)); + delete_tree(&huff_counts->int_tree); + huff_counts->tree_buff= NULL; + DBUG_PRINT("fakebigcodes", ("freed distinct column values")); + } + + /* + Sort counts by decreasing incidence. + */ + cur_count_p= count->counts; + end_count_p= cur_count_p + 256; + cur_sort_p= sort_counts; + while (cur_count_p < end_count_p) + *(cur_sort_p++)= cur_count_p++; + (void) qsort(sort_counts, 256, sizeof(my_off_t*), (qsort_cmp) fakecmp); + + /* + Assign faked counts. + */ + cur_sort_p= sort_counts; +#if SIZEOF_LONG_LONG > 4 + end_sort_p= sort_counts + 8 * sizeof(ulonglong) - 1; +#else + end_sort_p= sort_counts + 8 * sizeof(ulonglong) - 2; +#endif + /* Most frequent value gets a faked count of 1. */ + **(cur_sort_p++)= 1; + total= 1; + while (cur_sort_p < end_sort_p) + { + **(cur_sort_p++)= total; + total<<= 1; + } + /* Set the last value. */ + **(cur_sort_p++)= --total; + /* + Set the remaining counts. + */ + end_sort_p= sort_counts + 256; + while (cur_sort_p < end_sort_p) + **(cur_sort_p++)= 1; + } + DBUG_VOID_RETURN; +} + + +/* + Compare two counts for reverse sorting. + + SYNOPSIS + fakecmp() + count1 One count. + count2 Another count. + + RETURN + 1 count1 < count2 + 0 count1 == count2 + -1 count1 > count2 +*/ + +static int fakecmp(my_off_t **count1, my_off_t **count2) +{ + return ((**count1 < **count2) ? 1 : + (**count1 > **count2) ? -1 : 0); +} +#endif + + diff --git a/mysys/tree.c b/mysys/tree.c index bec1ec680f1..1780913961e 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -263,6 +263,9 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size, if (tree->flag & TREE_NO_DUPS) return(NULL); element->count++; + /* Avoid a wrap over of the count. */ + if (! element->count) + element->count--; } DBUG_EXECUTE("check_tree", test_rb_tree(tree->root);); return element; From 1960fbcf3d9dae7eb08833bdcf5b898224c2b817 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 19:47:19 +0200 Subject: [PATCH 058/216] Bug#10178 - failure to find a row in heap table by concurrent UPDATEs After merge fixes of test result. --- mysql-test/r/heap.result | 8 ++++---- mysql-test/r/heap_hash.result | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result index 22304c4a93d..b905dae3aba 100644 --- a/mysql-test/r/heap.result +++ b/mysql-test/r/heap.result @@ -367,13 +367,13 @@ count(*) 9 explain select count(*) from t1 where v='a '; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 13 const 9 Using where +1 SIMPLE t1 ref v v 13 const 10 Using where explain select count(*) from t1 where c='a '; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref c c 11 const 9 Using where +1 SIMPLE t1 ref c c 11 const 10 Using where explain select count(*) from t1 where t='a '; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref t t 13 const 9 Using where +1 SIMPLE t1 ref t t 13 const 10 Using where explain select count(*) from t1 where v like 'a%'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL v NULL NULL NULL 271 Using where @@ -399,7 +399,7 @@ qq *a *a*a * explain select * from t1 where v='a'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref v v 13 const 9 Using where +1 SIMPLE t1 ref v v 13 const 10 Using where select v,count(*) from t1 group by v limit 10; v count(*) a 1 diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result index 346fdd640ca..d8d89b786b5 100644 --- a/mysql-test/r/heap_hash.result +++ b/mysql-test/r/heap_hash.result @@ -353,8 +353,8 @@ t3 1 a 1 a NULL NULL NULL NULL HASH t3 1 a 2 b NULL 13 NULL NULL HASH explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a = concat('',t1.name) and t3.b=t1.name; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 ref a a 44 const,const 7 Using where 1 SIMPLE t1 ref heap_idx heap_idx 22 const 7 Using where +1 SIMPLE t3 ref a a 44 const,const 7 Using where drop table t1, t2, t3; create temporary table t1 ( a int, index (a) ) engine=memory; insert into t1 values (1),(2),(3),(4),(5); From 97e78d60177b7e06040827902a9a91bc3d104c9d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 22:48:12 +0400 Subject: [PATCH 059/216] - don't call JOIN::join_free(1) twice for every join in JOIN::cleanup(). The reason it happened was that both, JOIN::cleanup() and JOIN::join_free(), went over all nested joins and called cleanup/join_free for them. For that: - split recursive and non-recursive parts of JOIN::cleanup() and JOIN::join_free() - rename JOIN::cleanup to JOIN::destroy, as it actually destroys its argument - move the recursive part of JOIN::cleanup to st_select_lex::cleanup - move the non-recursive part of JOIN::join_free to the introduced method JOIN::cleanup(). sql/sql_lex.h: Add st_select_lex::cleanup, a counterpart of st_select_lex_unit::cleanup() sql/sql_select.cc: - remove two unused arguments from return_zero_rows - split JOIN::join_free and JOIN::cleanup to recursive and non-recursive parts. - note, the assert in JOIN::join_free _does_ fail in having.test. We have two options: a) propagate `full' flag to the nested joins. We did it before, and this patch didn't change it. If so, we can end up cleaning up an uncacheable JOIN (that is, the join that we might need again). b) evaluate own 'full' flag on every level. In this case, we might end up with tables freed in mysql_unlock_read_tables, but not cleaned up properly, and this may be even worse. The test suite passes with both approaches, but not with the assert. sql/sql_select.h: - declarations for JOIN::cleanup() and JOIN::join_free() sql/sql_union.cc: Add st_select_lex::cleanup, a counterpart of st_select_lex_unit::cleanup(): move the recursive part of JOIN::cleanup to it. --- sql/sql_lex.h | 5 ++ sql/sql_select.cc | 135 ++++++++++++++++++++++++---------------------- sql/sql_select.h | 10 +++- sql/sql_union.cc | 50 +++++++++-------- 4 files changed, 115 insertions(+), 85 deletions(-) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a9bfb6da926..5cf0b66598f 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -642,6 +642,11 @@ public: static void print_order(String *str, ORDER *order); void print_limit(THD *thd, String *str); void fix_prepare_information(THD *thd, Item **conds); + /* + Destroy the used execution plan (JOIN) of this subtree (this + SELECT_LEX and all nested SELECT_LEXes and SELECT_LEX_UNITs). + */ + bool cleanup(); }; typedef class st_select_lex SELECT_LEX; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 96a25c7919b..61234125d18 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -87,10 +87,9 @@ static void update_depend_map(JOIN *join, ORDER *order); static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond, bool change_list, bool *simple_order); static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables, - List &fields, bool send_row, - uint select_options, const char *info, - Item *having, Procedure *proc, - SELECT_LEX_UNIT *unit); + List &fields, bool send_row, + uint select_options, const char *info, + Item *having); static COND *build_equal_items(THD *thd, COND *cond, COND_EQUAL *inherited, List *join_list, @@ -1227,8 +1226,7 @@ JOIN::exec() send_row_on_empty_set(), select_options, zero_result_cause, - having, procedure, - unit); + having); DBUG_VOID_RETURN; } @@ -1437,7 +1435,7 @@ JOIN::exec() DBUG_VOID_RETURN; } end_read_record(&curr_join->join_tab->read_record); - curr_join->const_tables= curr_join->tables; // Mark free for join_free() + curr_join->const_tables= curr_join->tables; // Mark free for cleanup() curr_join->join_tab[0].table= 0; // Table is freed // No sum funcs anymore @@ -1667,9 +1665,9 @@ JOIN::exec() */ int -JOIN::cleanup() +JOIN::destroy() { - DBUG_ENTER("JOIN::cleanup"); + DBUG_ENTER("JOIN::destroy"); select_lex->join= 0; if (tmp_join) @@ -1684,12 +1682,11 @@ JOIN::cleanup() } tmp_join->tmp_join= 0; tmp_table_param.copy_field=0; - DBUG_RETURN(tmp_join->cleanup()); + DBUG_RETURN(tmp_join->destroy()); } cond_equal= 0; - lock=0; // It's faster to unlock later - join_free(1); + cleanup(1); if (exec_tmp_table1) free_tmp_table(thd, exec_tmp_table1); if (exec_tmp_table2) @@ -1697,12 +1694,6 @@ JOIN::cleanup() delete select; delete_dynamic(&keyuse); delete procedure; - for (SELECT_LEX_UNIT *lex_unit= select_lex->first_inner_unit(); - lex_unit != 0; - lex_unit= lex_unit->next_unit()) - { - error|= lex_unit->cleanup(); - } DBUG_RETURN(error); } @@ -1885,17 +1876,14 @@ Cursor::close() THD *thd= join->thd; DBUG_ENTER("Cursor::close"); - join->join_free(0); + /* + In case of UNIONs JOIN is freed inside of unit->cleanup(), + otherwise in select_lex->cleanup(). + */ if (unit) - { - /* In case of UNIONs JOIN is freed inside unit->cleanup() */ - unit->cleanup(); - } + (void) unit->cleanup(); else - { - join->cleanup(); - delete join; - } + (void) join->select_lex->cleanup(); { /* XXX: Another hack: closing tables used in the cursor */ DBUG_ASSERT(lock || open_tables || derived_tables); @@ -2071,8 +2059,7 @@ err: if (free_join) { thd->proc_info="end"; - err= join->cleanup(); - delete join; + err= select_lex->cleanup(); DBUG_RETURN(err || thd->net.report_error); } DBUG_RETURN(join->error); @@ -5905,29 +5892,75 @@ void JOIN_TAB::cleanup() } +void JOIN::join_free(bool full) +{ + SELECT_LEX_UNIT *unit; + SELECT_LEX *sl; + DBUG_ENTER("JOIN::join_free"); + + /* + Optimization: if not EXPLAIN and we are done with the JOIN, + free all tables. + */ + full= full || (!select_lex->uncacheable && !thd->lex->subqueries && + !thd->lex->describe); + + cleanup(full); + + for (unit= select_lex->first_inner_unit(); unit; unit= unit->next_unit()) + for (sl= unit->first_select_in_union(); sl; sl= sl->next_select()) + { + JOIN *join= sl->join; + if (join) + { + /* Check that we don't occasionally clean up an uncacheable JOIN */ +#if 0 + DBUG_ASSERT(! (!select_lex->uncacheable && sl->uncacheable)); +#endif + join->join_free(full); + } + } + + /* + We are not using tables anymore + Unlock all tables. We may be in an INSERT .... SELECT statement. + */ + if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK) && + !select_lex->subquery_in_having && + (select_lex == (thd->lex->unit.fake_select_lex ? + thd->lex->unit.fake_select_lex : &thd->lex->select_lex))) + { + /* + TODO: unlock tables even if the join isn't top level select in the + tree. + */ + mysql_unlock_read_tables(thd, lock); // Don't free join->lock + lock= 0; + } + + DBUG_VOID_RETURN; +} + + /* Free resources of given join SYNOPSIS - JOIN::join_free() + JOIN::cleanup() fill - true if we should free all resources, call with full==1 should be last, before it this function can be called with full==0 NOTE: with subquery this function definitely will be called several times, but even for simple query it can be called several times. */ -void -JOIN::join_free(bool full) -{ - JOIN_TAB *tab,*end; - DBUG_ENTER("JOIN::join_free"); - full= full || (!select_lex->uncacheable && - !thd->lex->subqueries && - !thd->lex->describe); // do not cleanup too early on EXPLAIN +void JOIN::cleanup(bool full) +{ + DBUG_ENTER("JOIN::cleanup"); if (table) { + JOIN_TAB *tab,*end; /* Only a sorted table may be cached. This sorted table is always the first non const table in join->table @@ -5938,16 +5971,6 @@ JOIN::join_free(bool full) filesort_free_buffers(table[const_tables]); } - for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); unit; - unit= unit->next_unit()) - { - JOIN *join; - for (SELECT_LEX *sl= unit->first_select_in_union(); sl; - sl= sl->next_select()) - if ((join= sl->join)) - join->join_free(full); - } - if (full) { for (tab= join_tab, end= tab+tables; tab != end; tab++) @@ -5964,23 +5987,10 @@ JOIN::join_free(bool full) } } } - /* We are not using tables anymore Unlock all tables. We may be in an INSERT .... SELECT statement. */ - if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK) && - !select_lex->subquery_in_having) - { - // TODO: unlock tables even if the join isn't top level select in the tree - if (select_lex == (thd->lex->unit.fake_select_lex ? - thd->lex->unit.fake_select_lex : &thd->lex->select_lex)) - { - mysql_unlock_read_tables(thd, lock); // Don't free join->lock - lock=0; - } - } - if (full) { group_fields.delete_elements(); @@ -6217,8 +6227,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, static int return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables, List &fields, bool send_row, uint select_options, - const char *info, Item *having, Procedure *procedure, - SELECT_LEX_UNIT *unit) + const char *info, Item *having) { DBUG_ENTER("return_zero_rows"); diff --git a/sql/sql_select.h b/sql/sql_select.h index e5266944251..d88fbbfc73f 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -325,7 +325,7 @@ class JOIN :public Sql_alloc int optimize(); int reinit(); void exec(); - int cleanup(); + int destroy(); void restore_tmp(); bool alloc_func_list(); bool make_sum_func_list(List &all_fields, List &send_fields, @@ -349,7 +349,15 @@ class JOIN :public Sql_alloc int rollup_send_data(uint idx); int rollup_write_data(uint idx, TABLE *table); bool test_in_subselect(Item **where); + /* + Release memory and, if possible, the open tables held by this execution + plan (and nested plans). It's used to release some tables before + the end of execution in order to increase concurrency and reduce + memory consumption. + */ void join_free(bool full); + /* Cleanup this JOIN, possibly for reuse */ + void cleanup(bool full); void clear(); bool save_join_tab(); bool send_row_on_empty_set() diff --git a/sql/sql_union.cc b/sql/sql_union.cc index f59d7fffe85..87b67a5127a 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -553,7 +553,6 @@ bool st_select_lex_unit::exec() bool st_select_lex_unit::cleanup() { int error= 0; - JOIN *join; DBUG_ENTER("st_select_lex_unit::cleanup"); if (cleaned) @@ -572,29 +571,17 @@ bool st_select_lex_unit::cleanup() } for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select()) + error|= sl->cleanup(); + + if (fake_select_lex) { - if ((join= sl->join)) + JOIN *join; + if ((join= fake_select_lex->join)) { - error|= sl->join->cleanup(); - delete join; + join->tables_list= 0; + join->tables= 0; } - else - { - // it can be DO/SET with subqueries - for (SELECT_LEX_UNIT *lex_unit= sl->first_inner_unit(); - lex_unit != 0; - lex_unit= lex_unit->next_unit()) - { - error|= lex_unit->cleanup(); - } - } - } - if (fake_select_lex && (join= fake_select_lex->join)) - { - join->tables_list= 0; - join->tables= 0; - error|= join->cleanup(); - delete join; + error|= fake_select_lex->cleanup(); } DBUG_RETURN(error); @@ -650,3 +637,24 @@ bool st_select_lex_unit::change_result(select_subselect *result, res= fake_select_lex->join->change_result(result); return (res); } + + +bool st_select_lex::cleanup() +{ + bool error= FALSE; + DBUG_ENTER("st_select_lex::cleanup()"); + + if (join) + { + error|= join->destroy(); + delete join; + join= 0; + } + for (SELECT_LEX_UNIT *lex_unit= first_inner_unit(); lex_unit ; + lex_unit= lex_unit->next_unit()) + { + error|= lex_unit->cleanup(); + } + DBUG_RETURN(error); +} + From 024d232af5baef385f3c2fbe23bbab0ffb55620a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 23:29:00 +0400 Subject: [PATCH 060/216] Remove an unrelevant assert. sql/sql_select.cc: This assert is not relevant because: - the correct assert is DBUG_ASSERT(! (full && sl->uncacheable)) (prevents freeing of uncacheable JOINs), it breaks view.test - it seems we can free internal JOINs, even if they are uncacheable: if the top level join is evaluated, we're not going to need the internal joins any more --- sql/sql_select.cc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6feb495c940..da89fdf1675 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5912,13 +5912,7 @@ void JOIN::join_free(bool full) { JOIN *join= sl->join; if (join) - { - /* Check that we don't occasionally clean up an uncacheable JOIN */ -#if 0 - DBUG_ASSERT(! (!select_lex->uncacheable && sl->uncacheable)); -#endif join->join_free(full); - } } /* From f6edb3f5c2a3030d0bbf3f22d3e6528fb95596f3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 25 Jun 2005 00:27:40 +0400 Subject: [PATCH 061/216] Free unused JOINs early even if using subqueries. sql/sql_select.cc: According to the conclusion made in the previous patch, we can widen the range of cases when JOINs are fully freed early, and include subqueries to it. --- sql/sql_select.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index da89fdf1675..b487637ba9c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5902,8 +5902,7 @@ void JOIN::join_free(bool full) Optimization: if not EXPLAIN and we are done with the JOIN, free all tables. */ - full= full || (!select_lex->uncacheable && !thd->lex->subqueries && - !thd->lex->describe); + full= full || (!select_lex->uncacheable && !thd->lex->describe); cleanup(full); From 11d2bb945f676b15da65f197de49b076d2d75258 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Jun 2005 17:59:19 -0700 Subject: [PATCH 062/216] If mysql_config is a symlink, resolve it before trying to find the lib and include directories relative to where it is located. (Bug #10986) scripts/mysql_config.sh: If mysql_config is a symlink, try to resolve it --- scripts/mysql_config.sh | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh index a5c8af5ecb2..16e50c044ca 100644 --- a/scripts/mysql_config.sh +++ b/scripts/mysql_config.sh @@ -60,11 +60,19 @@ fix_path () get_full_path () { - case $1 in - /*) echo "$1";; - ./*) tmp=`pwd`/$1; echo $tmp | sed -e 's;/\./;/;' ;; - *) which $1 ;; - esac + file=$1 + + # if the file is a symlink, try to resolve it + if [ -h $file ]; + then + file=`ls -l $file | awk '{ print $NF }'` + fi + + case $file in + /*) echo "$file";; + */*) tmp=`pwd`/$file; echo $tmp | sed -e 's;/\./;/;' ;; + *) which $file ;; + esac } me=`get_full_path $0` From 3bdac0a06e0310c2961c7c6f446db2c54a824566 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 09:36:43 +0200 Subject: [PATCH 063/216] Fix for Intel compiler --- extra/yassl/taocrypt/src/integer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index 0f06bb4e044..460b2d31426 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -35,7 +35,8 @@ #endif -#if defined(_MSC_VER) && defined(_WIN64) // 64 bit X overflow intrinsic +#if defined(_MSC_VER) && defined(_WIN64) && \ + !defined(__INTEL_COMPILER) // 64 bit X overflow intrinsic #ifdef __ia64__ #define myUMULH __UMULH #elif __x86_64__ From 48cb6de7d9c89bbe85f6676c31f5c4fbfcc6af00 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 14:10:56 +0400 Subject: [PATCH 064/216] Fix the broken test suite in -debug build. sql/sql_select.cc: If we use subqueries, we can have double-free of tmp_table_param.copy_field in JOIN::destroy and in JOIN::join_free because. --- sql/sql_select.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b487637ba9c..13c5c7cd716 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5986,6 +5986,8 @@ void JOIN::cleanup(bool full) */ if (full) { + if (tmp_join) + tmp_table_param.copy_field= 0; group_fields.delete_elements(); /* We can't call delete_elements() on copy_funcs as this will cause From 74586e95fc3065e33162364886672ac49c5ea54e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 12:25:15 +0200 Subject: [PATCH 065/216] Merge problem fixes mysql-test/r/client_xml.result: Update testresult mysql-test/r/ndb_autodiscover.result: Moving order opf test results to match test execution order --- mysql-test/r/client_xml.result | 2 +- mysql-test/r/ndb_autodiscover.result | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/client_xml.result b/mysql-test/r/client_xml.result index a4164148159..24c05c7f9d6 100644 --- a/mysql-test/r/client_xml.result +++ b/mysql-test/r/client_xml.result @@ -15,7 +15,7 @@ insert into t1 values (1, 2, 'a&b ab'); - + diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result index fb1fae7809c..babe3d0fe41 100644 --- a/mysql-test/r/ndb_autodiscover.result +++ b/mysql-test/r/ndb_autodiscover.result @@ -373,6 +373,16 @@ use test2; drop table t2; drop database test2; use test; +drop database if exists test_only_ndb_tables; +create database test_only_ndb_tables; +use test_only_ndb_tables; +create table t1 (a int primary key) engine=ndb; +select * from t1; +a +select * from t1; +ERROR HY000: Can't lock file (errno: 4009) +use test; +drop database test_only_ndb_tables; CREATE TABLE sys.SYSTAB_0 (a int); ERROR 42S01: Table 'SYSTAB_0' already exists select * from sys.SYSTAB_0; @@ -387,16 +397,6 @@ ERROR 42S02: Unknown table 'SYSTAB_0' drop table IF EXISTS sys.SYSTAB_0; Warnings: Note 1051 Unknown table 'SYSTAB_0' -drop database if exists test_only_ndb_tables; -create database test_only_ndb_tables; -use test_only_ndb_tables; -create table t1 (a int primary key) engine=ndb; -select * from t1; -a -select * from t1; -ERROR HY000: Can't lock file (errno: 4009) -use test; -drop database test_only_ndb_tables; CREATE TABLE t9 ( a int NOT NULL PRIMARY KEY, b int From d8ee99b4c4bdcf9b668e3cfdc0e09515d098e19f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 14:26:07 +0200 Subject: [PATCH 066/216] Simpler impl. sql/sql_parse.cc: Just do a simple sprintf to format error message. --- sql/sql_parse.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 461ce1e3c94..d6a719e65f9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5499,15 +5499,13 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, In other words, for declarations such as TIMESTAMP(2), TIMESTAMP(4), and so on, the display width is ignored. */ - char buff[32]; - String str(buff,(uint32) sizeof(buff), system_charset_info); - str.append("TIMESTAMP("); - str.append(length); - str.append(")"); + char buf[32]; + my_snprintf(buf, sizeof(buf), + "TIMESTAMP(%s)", length, system_charset_info); push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX), - str.c_ptr(), "TIMESTAMP"); + buf, "TIMESTAMP"); } if (!(new_field= new_create_field(thd, field_name, type, length, decimals, From 8478223a6db0bd78b07cb3c678e5f288941e671c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 15:01:49 +0200 Subject: [PATCH 067/216] Add "#include " to define WEXITSTATUS --- client/mysqltest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/mysqltest.c b/client/mysqltest.c index 77736fc1fcc..903a4b85e1c 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -60,6 +60,7 @@ #include #include #include /* Our own version of lib */ +#include #define MAX_QUERY 131072 #define MAX_VAR_NAME 256 #define MAX_COLUMNS 256 From e00981bb5ff6d310e411fc58acc1369e0899285b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 15:11:40 +0200 Subject: [PATCH 068/216] Include to get WEXITSTATUS --- client/mysqltest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 903a4b85e1c..fd8f19332ec 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -60,7 +60,7 @@ #include #include #include /* Our own version of lib */ -#include +#include #define MAX_QUERY 131072 #define MAX_VAR_NAME 256 #define MAX_COLUMNS 256 From d10877ce8ce4f939f88f79e6ad42af251fd51ebe Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 16:46:41 +0300 Subject: [PATCH 069/216] Better bug fix for: #9728 'Decreased functionality in "on duplicate key update #8147 'a column proclaimed ambigous in INSERT ... SELECT .. ON DUPLICATE' This ensures fields are uniquely qualified and also that one can't update other tables in the ON DUPLICATE KEY UPDATE part mysql-test/r/insert_select.result: More tests for bug #9728 and #8147 mysql-test/r/insert_update.result: Updated tests after changing how INSERT ... SELECT .. ON DUPLICATE KEY works mysql-test/t/insert_select.test: More tests for bug #9728 and #8147 mysql-test/t/insert_update.test: Updated tests after changing how INSERT ... SELECT .. ON DUPLICATE KEY works mysys/my_access.c: Cleanup (shorter loop variable names) sql/ha_ndbcluster.cc: Indentation fixes sql/item.cc: Remove item_flags sql/item.h: Remove item_flags sql/mysql_priv.h: New arguments to mysql_prepare_insert sql/sql_base.cc: Remove old fix for bug #8147 sql/sql_insert.cc: Extend mysql_prepare_insert() with new field list for tables that can be used in the values port of ON DUPLICATE KEY UPDATE sql/sql_parse.cc: Revert fix for #9728 Allow one to use other tables in ON DUPLICATE_KEY for INSERT ... SELECT if there is no GROUP BY clause sql/sql_prepare.cc: New arguments to mysql_prepare_insert sql/sql_yacc.yy: Revert bug fix for #9728 --- mysql-test/r/insert_select.result | 27 +++++++++++++++++--- mysql-test/r/insert_update.result | 10 +++++--- mysql-test/t/insert_select.test | 22 +++++++++++++--- mysql-test/t/insert_update.test | 10 +++++--- mysys/my_access.c | 9 +++---- sql/ha_ndbcluster.cc | 4 ++- sql/item.cc | 4 +-- sql/item.h | 11 -------- sql/mysql_priv.h | 3 ++- sql/sql_base.cc | 9 +++---- sql/sql_insert.cc | 34 ++++++++++++++++++------- sql/sql_parse.cc | 42 +++++++++++++++++++++---------- sql/sql_prepare.cc | 1 + sql/sql_yacc.yy | 15 ----------- 14 files changed, 123 insertions(+), 78 deletions(-) diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 69eb64f08ea..2ac73fe7662 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -1,4 +1,4 @@ -drop table if exists t1,t2; +drop table if exists t1,t2,t3; create table t1 (bandID MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY, payoutID SMALLINT UNSIGNED NOT NULL); insert into t1 (bandID,payoutID) VALUES (1,6),(2,6),(3,4),(4,9),(5,10),(6,1),(7,12),(8,12); create table t2 (payoutID SMALLINT UNSIGNED NOT NULL PRIMARY KEY); @@ -636,16 +636,35 @@ ff1 ff2 drop table t1, t2; create table t1 (a int unique); create table t2 (a int, b int); +create table t3 (c int, d int); insert into t1 values (1),(2); insert into t2 values (1,2); +insert into t3 values (1,6),(3,7); select * from t1; a 1 2 -insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b; +insert into t1 select a from t2 on duplicate key update a= t1.a + t2.b; select * from t1; a 2 3 -drop table t1; -drop table t2; +insert into t1 select a+1 from t2 on duplicate key update t1.a= t1.a + t2.b+1; +select * from t1; +a +3 +5 +insert into t1 select t3.c from t3 on duplicate key update a= a + t3.d; +select * from t1; +a +1 +5 +10 +insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= a + 10; +insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b; +ERROR 23000: Column 'a' in field list is ambiguous +insert into t1 select t2.a from t2 on duplicate key update t2.a= a + t2.b; +ERROR 42S02: Unknown table 't2' in field list +insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b; +ERROR 42S02: Unknown table 't2' in field list +drop table t1,t2,t3; diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index 2143538469b..150f4ef26c7 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -143,7 +143,7 @@ INSERT t1 VALUES (1,2,10), (3,4,20); CREATE TABLE t2 (a INT, b INT, c INT, d INT); INSERT t2 VALUES (5,6,30,1), (7,4,40,1), (8,9,60,1); INSERT t2 VALUES (2,1,11,2), (7,4,40,2); -INSERT t1 SELECT a,b,c FROM t2 WHERE d=1 ON DUPLICATE KEY UPDATE c=c+100; +INSERT t1 SELECT a,b,c FROM t2 WHERE d=1 ON DUPLICATE KEY UPDATE c=t1.c+100; SELECT * FROM t1; a b c 1 2 10 @@ -158,6 +158,8 @@ a b c 5 0 30 8 9 60 INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a); +ERROR 23000: Column 'c' in field list is ambiguous +INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=t1.c+VALUES(t1.a); SELECT *, VALUES(a) FROM t1; a b c VALUES(a) 1 2 10 NULL @@ -174,7 +176,7 @@ select * from t1; a 1 2 -insert ignore into t1 select a from t1 on duplicate key update a=a+1 ; +insert ignore into t1 select a from t1 as t2 on duplicate key update a=t1.a+1 ; select * from t1; a 1 @@ -185,5 +187,7 @@ a 2 3 insert into t1 select a from t1 on duplicate key update a=a+1 ; -ERROR 23000: Duplicate entry '3' for key 1 +ERROR 23000: Column 'a' in field list is ambiguous +insert ignore into t1 select a from t1 on duplicate key update a=t1.a+1 ; +ERROR 23000: Column 't1.a' in field list is ambiguous drop table t1; diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 7402940fa52..67799873b73 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -3,7 +3,7 @@ # --disable_warnings -drop table if exists t1,t2; +drop table if exists t1,t2,t3; --enable_warnings create table t1 (bandID MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY, payoutID SMALLINT UNSIGNED NOT NULL); @@ -182,10 +182,24 @@ drop table t1, t2; # create table t1 (a int unique); create table t2 (a int, b int); +create table t3 (c int, d int); insert into t1 values (1),(2); insert into t2 values (1,2); +insert into t3 values (1,6),(3,7); select * from t1; +insert into t1 select a from t2 on duplicate key update a= t1.a + t2.b; +select * from t1; +insert into t1 select a+1 from t2 on duplicate key update t1.a= t1.a + t2.b+1; +select * from t1; +insert into t1 select t3.c from t3 on duplicate key update a= a + t3.d; +select * from t1; +insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= a + 10; + +#Some error cases +--error 1052 insert into t1 select t2.a from t2 on duplicate key update a= a + t2.b; -select * from t1; -drop table t1; -drop table t2; +--error 1109 +insert into t1 select t2.a from t2 on duplicate key update t2.a= a + t2.b; +--error 1109 +insert into t1 select t2.a from t2 group by t2.a on duplicate key update a= t1.a + t2.b; +drop table t1,t2,t3; diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test index f5857840588..3d6297d8d7a 100644 --- a/mysql-test/t/insert_update.test +++ b/mysql-test/t/insert_update.test @@ -72,11 +72,13 @@ CREATE TABLE t2 (a INT, b INT, c INT, d INT); # column names deliberately clash with columns in t1 (Bug#8147) INSERT t2 VALUES (5,6,30,1), (7,4,40,1), (8,9,60,1); INSERT t2 VALUES (2,1,11,2), (7,4,40,2); -INSERT t1 SELECT a,b,c FROM t2 WHERE d=1 ON DUPLICATE KEY UPDATE c=c+100; +INSERT t1 SELECT a,b,c FROM t2 WHERE d=1 ON DUPLICATE KEY UPDATE c=t1.c+100; SELECT * FROM t1; INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0; SELECT * FROM t1; +--error 1052 INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=c+VALUES(a); +INSERT t1 SELECT a,b,c FROM t2 WHERE d=2 ON DUPLICATE KEY UPDATE c=t1.c+VALUES(t1.a); SELECT *, VALUES(a) FROM t1; DROP TABLE t1; DROP TABLE t2; @@ -89,10 +91,12 @@ create table t1 (a int not null unique) engine=myisam; insert into t1 values (1),(2); insert ignore into t1 select 1 on duplicate key update a=2; select * from t1; -insert ignore into t1 select a from t1 on duplicate key update a=a+1 ; +insert ignore into t1 select a from t1 as t2 on duplicate key update a=t1.a+1 ; select * from t1; insert into t1 select 1 on duplicate key update a=2; select * from t1; ---error 1062 +--error 1052 insert into t1 select a from t1 on duplicate key update a=a+1 ; +--error 1052 +insert ignore into t1 select a from t1 on duplicate key update a=t1.a+1 ; drop table t1; diff --git a/mysys/my_access.c b/mysys/my_access.c index 1b9ad6ff380..8fc83a020cf 100644 --- a/mysys/my_access.c +++ b/mysys/my_access.c @@ -98,17 +98,16 @@ int check_if_legal_filename(const char *path) for (reserved_name= reserved_names; *reserved_name; reserved_name++) { + const char *reserved= *reserved_name; /* never empty */ const char *name= path; - const char *current_reserved_name= *reserved_name; - while (name != end && *current_reserved_name) + do { - if (*current_reserved_name != my_toupper(&my_charset_latin1, *name)) + if (*reserved != my_toupper(&my_charset_latin1, *name)) break; - current_reserved_name++; if (++name == end) DBUG_RETURN(1); /* Found wrong path */ - } + } while (*++reserved); } DBUG_RETURN(0); } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 88b7ff4dcb8..d5153269843 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -439,8 +439,10 @@ int ha_ndbcluster::ndb_err(NdbConnection *trans) if (m_rows_to_insert == 1) m_dupkey= table->primary_key; else - // We are batching inserts, offending key is not available + { + /* We are batching inserts, offending key is not available */ m_dupkey= (uint) -1; + } } DBUG_RETURN(res); } diff --git a/sql/item.cc b/sql/item.cc index 9c5bf499d11..c96794ff482 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -65,7 +65,6 @@ Item::Item(): place == IN_HAVING) thd->lex->current_select->select_n_having_items++; } - item_flags= 0; } /* @@ -84,8 +83,7 @@ Item::Item(THD *thd, Item *item): unsigned_flag(item->unsigned_flag), with_sum_func(item->with_sum_func), fixed(item->fixed), - collation(item->collation), - item_flags(item->item_flags) + collation(item->collation) { next= thd->free_list; // Put in free list thd->free_list= this; diff --git a/sql/item.h b/sql/item.h index 82ab5a66cfb..8de2adeb730 100644 --- a/sql/item.h +++ b/sql/item.h @@ -107,11 +107,6 @@ public: typedef bool (Item::*Item_processor)(byte *arg); -/* - See comments for sql_yacc.yy: insert_update_elem rule - */ -#define MY_ITEM_PREFER_1ST_TABLE 1 - class Item { Item(const Item &); /* Prevent use of these */ void operator=(Item &); @@ -147,7 +142,6 @@ public: my_bool with_sum_func; my_bool fixed; /* If item fixed with fix_fields */ DTCollation collation; - uint8 item_flags; /* Flags on how item should be processed */ // alloc & destruct is done as start of select using sql_alloc Item(); @@ -333,11 +327,6 @@ public: cleanup(); delete this; } - virtual bool set_flags_processor(byte *args) - { - this->item_flags|= *((uint8*)args); - return false; - } }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 2bcaa1ecc2d..cc58e34d582 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -576,7 +576,8 @@ int mysql_multi_update_lock(THD *thd, List *fields, SELECT_LEX *select_lex); int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, - TABLE_LIST *insert_table_list, TABLE *table, + TABLE_LIST *insert_table_list, + TABLE_LIST *dup_table_list, TABLE *table, List &fields, List_item *values, List &update_fields, List &update_values, enum_duplicates duplic); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 84c03bee917..9a5b2522be9 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1993,7 +1993,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, const char *name=item->field_name; uint length=(uint) strlen(name); char name_buff[NAME_LEN+1]; - + bool allow_rowid; if (item->cached_table) { @@ -2085,9 +2085,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, return (Field*) not_found_field; return (Field*) 0; } - bool allow_rowid= tables && !tables->next; // Only one table - uint table_idx= 0; - for (; tables ; tables=tables->next, table_idx++) + allow_rowid= tables && !tables->next; // Only one table + for (; tables ; tables=tables->next) { if (!tables->table) { @@ -2116,8 +2115,6 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, return (Field*) 0; } found= field; - if (table_idx == 0 && item->item_flags & MY_ITEM_PREFER_1ST_TABLE) - break; } } if (found) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index f09d3214c74..deccc1d4dca 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -271,7 +271,8 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, thd->used_tables=0; values= its++; - if (mysql_prepare_insert(thd, table_list, insert_table_list, table, + if (mysql_prepare_insert(thd, table_list, insert_table_list, + insert_table_list, table, fields, values, update_fields, update_values, duplic)) goto abort; @@ -499,22 +500,37 @@ abort: SYNOPSIS mysql_prepare_insert() - thd - thread handler - table_list - global table list - insert_table_list - local table list of INSERT SELECT_LEX - values - values to insert. NULL for INSERT ... SELECT + thd thread handler + table_list global table list (not including first table for + INSERT ... SELECT) + insert_table_list Table we are inserting into (for INSERT ... SELECT) + dup_table_list Tables to be used in ON DUPLICATE KEY + It's either all global tables or only the table we + insert into, depending on if we are using GROUP BY + in the SELECT clause). + values Values to insert. NULL for INSERT ... SELECT + + TODO (in far future) + In cases of: + INSERT INTO t1 SELECT a, sum(a) as sum1 from t2 GROUP BY a + ON DUPLICATE KEY ... + we should be able to refer to sum1 in the ON DUPLICATE KEY part RETURN VALUE - 0 - OK - -1 - error (message is not sent to user) + 0 OK + -1 error (message is not sent to user) */ + int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, - TABLE_LIST *insert_table_list, TABLE *table, + TABLE_LIST *insert_table_list, + TABLE_LIST *dup_table_list, + TABLE *table, List &fields, List_item *values, List &update_fields, List &update_values, enum_duplicates duplic) { DBUG_ENTER("mysql_prepare_insert"); + if (duplic == DUP_UPDATE && !table->insert_values) { /* it should be allocated before Item::fix_fields() */ @@ -528,7 +544,7 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, (values && setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0)) || (duplic == DUP_UPDATE && (check_update_fields(thd, table, insert_table_list, update_fields) || - setup_fields(thd, 0, insert_table_list, update_values, 1, 0, 0)))) + setup_fields(thd, 0, dup_table_list, update_values, 1, 0, 0)))) DBUG_RETURN(-1); if (values && find_real_table_in_list(table_list->next, table_list->db, table_list->real_name)) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 233104c9a90..c0283f81315 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1943,10 +1943,10 @@ mysql_execute_command(THD *thd) if (tables || &lex->select_lex != lex->all_selects_list) mysql_reset_errors(thd); - /* - When subselects or time_zone info is used in a query - we create a new TABLE_LIST containing all referenced tables - and set local variable 'tables' to point to this list. + /* + When subselects or time_zone info is used in a query + we create a new TABLE_LIST containing all referenced tables + and set local variable 'tables' to point to this list. */ if ((&lex->select_lex != lex->all_selects_list || lex->time_zone_tables_used) && @@ -2831,6 +2831,8 @@ unsent_create_error: case SQLCOM_INSERT_SELECT: { TABLE_LIST *first_local_table= (TABLE_LIST *) select_lex->table_list.first; + TABLE_LIST dup_tables; + TABLE *insert_table; if ((res= insert_precheck(thd, tables))) break; @@ -2856,14 +2858,27 @@ unsent_create_error: if ((res= open_and_lock_tables(thd, tables))) break; + insert_table= tables->table; /* Skip first table, which is the table we are inserting in */ select_lex->table_list.first= (byte*) first_local_table->next; - - if (!(res= mysql_prepare_insert(thd, tables, first_local_table, - tables->table, lex->field_list, 0, + tables= (TABLE_LIST *) select_lex->table_list.first; + dup_tables= *first_local_table; + first_local_table->next= 0; + if (select_lex->group_list.elements != 0) + { + /* + When we are using GROUP BY we can't refere to other tables in the + ON DUPLICATE KEY part + */ + dup_tables.next= 0; + } + + if (!(res= mysql_prepare_insert(thd, tables, first_local_table, + &dup_tables, insert_table, + lex->field_list, 0, lex->update_list, lex->value_list, lex->duplicates)) && - (result= new select_insert(tables->table, &lex->field_list, + (result= new select_insert(insert_table, &lex->field_list, &lex->update_list, &lex->value_list, lex->duplicates, lex->ignore))) { @@ -2876,7 +2891,7 @@ unsent_create_error: /* revert changes for SP */ lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; delete result; - tables->table->insert_values= 0; + insert_table->insert_values= 0; if (thd->net.report_error) res= -1; } @@ -4950,10 +4965,11 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, the slow query log, and the relay log (if it exists). */ - /* - Writing this command to the binlog may result in infinite loops when doing - mysqlbinlog|mysql, and anyway it does not really make sense to log it - automatically (would cause more trouble to users than it would help them) + /* + Writing this command to the binlog may result in infinite loops when + doing mysqlbinlog|mysql, and anyway it does not really make sense to + log it automatically (would cause more trouble to users than it would + help them) */ tmp_write_to_binlog= 0; mysql_log.new_file(1); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 1f5bb04c802..9e2612c5661 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -918,6 +918,7 @@ static int mysql_test_insert(Prepared_statement *stmt, table_list->table->insert_values=(byte *)1; // don't allocate insert_values if ((res= mysql_prepare_insert(thd, table_list, insert_table_list, + insert_table_list, table_list->table, fields, values, update_fields, update_values, duplic))) goto error; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 460234de156..bc21649fe54 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4239,24 +4239,9 @@ insert_update_elem: simple_ident equal expr_or_default { LEX *lex= Lex; - uint8 tmp= MY_ITEM_PREFER_1ST_TABLE; if (lex->update_list.push_back($1) || lex->value_list.push_back($3)) YYABORT; - /* - INSERT INTO a1(a) SELECT b1.a FROM b1 ON DUPLICATE KEY - UPDATE a= a + b1.b - - Set MY_ITEM_PREFER_1ST_TABLE flag to $1 and $3 items - to prevent find_field_in_tables() doing further item searching - if it finds item occurence in first table in insert_table_list. - This allows to avoid ambiguity in resolving 'a' field in - example above. - */ - $1->walk(&Item::set_flags_processor, - (byte *) &tmp); - $3->walk(&Item::set_flags_processor, - (byte *) &tmp); }; opt_low_priority: From 1084e540ee034ec2dda0645ea9fd78a13a231cbd Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 17:04:57 +0300 Subject: [PATCH 070/216] InnoDB: Optimize the extension of files. This will greatly speed up CREATE TABLE in innodb_file_per_table=1 mode. innobase/fil/fil0fil.c: fil_extend_space_to_desired_size(): Do not allocate or initialize more memory than is necessary. Write at most one megabyte at a time. innobase/include/os0file.h: os_file_set_size(): Corrected the synopsis innobase/os/os0file.c: os_file_set_size(): Corrected the synopsis and some comments. s/offset/current_size; s/low/desired_size/; Do not allocate or initialize more memory than is necessary. Write at most one megabyte at a time. --- innobase/fil/fil0fil.c | 24 +++++++++--------- innobase/include/os0file.h | 2 +- innobase/os/os0file.c | 50 ++++++++++++++++---------------------- 3 files changed, 33 insertions(+), 43 deletions(-) diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index 9d5def718a6..e83d2fcde32 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -3400,9 +3400,9 @@ fil_extend_space_to_desired_size( fil_space_t* space; byte* buf2; byte* buf; + ulint buf_size; ulint start_page_no; ulint file_start_page_no; - ulint n_pages; ulint offset_high; ulint offset_low; ibool success = TRUE; @@ -3427,22 +3427,20 @@ fil_extend_space_to_desired_size( fil_node_prepare_for_io(node, system, space); - /* Extend 1 MB at a time */ - - buf2 = mem_alloc(1024 * 1024 + UNIV_PAGE_SIZE); - buf = ut_align(buf2, UNIV_PAGE_SIZE); - - memset(buf, '\0', 1024 * 1024); - start_page_no = space->size; file_start_page_no = space->size - node->size; - while (start_page_no < size_after_extend) { - n_pages = size_after_extend - start_page_no; + /* Extend at most 64 pages at a time */ + buf_size = ut_min(64, size_after_extend - start_page_no) + * UNIV_PAGE_SIZE; + buf2 = mem_alloc(buf_size + UNIV_PAGE_SIZE); + buf = ut_align(buf2, UNIV_PAGE_SIZE); - if (n_pages > (1024 * 1024) / UNIV_PAGE_SIZE) { - n_pages = (1024 * 1024) / UNIV_PAGE_SIZE; - } + memset(buf, 0, buf_size); + + while (start_page_no < size_after_extend) { + ulint n_pages = ut_min(buf_size / UNIV_PAGE_SIZE, + size_after_extend - start_page_no); offset_high = (start_page_no - file_start_page_no) / (4096 * ((1024 * 1024) / UNIV_PAGE_SIZE)); diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index ebc014df9fd..63cd41a6d28 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -368,7 +368,7 @@ os_file_get_size_as_iblonglong( /* out: size in bytes, -1 if error */ os_file_t file); /* in: handle to a file */ /*************************************************************************** -Sets a file size. This function can be used to extend or truncate a file. */ +Write the specified number of zeros to a newly created file. */ ibool os_file_set_size( diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 15f5bf40e51..25123c47cb8 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -1642,7 +1642,7 @@ os_file_get_size_as_iblonglong( } /*************************************************************************** -Sets a file size. This function can be used to extend or truncate a file. */ +Write the specified number of zeros to a newly created file. */ ibool os_file_set_size( @@ -1655,47 +1655,39 @@ os_file_set_size( size */ ulint size_high)/* in: most significant 32 bits of size */ { - ib_longlong offset; - ib_longlong low; - ulint n_bytes; + ib_longlong current_size; + ib_longlong desired_size; ibool ret; byte* buf; byte* buf2; - ulint i; + ulint buf_size; ut_a(size == (size & 0xFFFFFFFF)); - /* We use a very big 8 MB buffer in writing because Linux may be - extremely slow in fsync on 1 MB writes */ + current_size = 0; + desired_size = (ib_longlong)size + (((ib_longlong)size_high) << 32); - buf2 = ut_malloc(UNIV_PAGE_SIZE * 513); + /* Write up to 1 megabyte at a time. */ + buf_size = ut_min(UNIV_PAGE_SIZE * 64, desired_size); + buf2 = ut_malloc(buf_size + UNIV_PAGE_SIZE); /* Align the buffer for possible raw i/o */ buf = ut_align(buf2, UNIV_PAGE_SIZE); /* Write buffer full of zeros */ - for (i = 0; i < UNIV_PAGE_SIZE * 512; i++) { - buf[i] = '\0'; - } + memset(buf, 0, buf_size); - offset = 0; - low = (ib_longlong)size + (((ib_longlong)size_high) << 32); - - if (low >= (ib_longlong)(100 * 1024 * 1024)) { + if (desired_size >= (ib_longlong)(100 * 1024 * 1024)) { fprintf(stderr, "InnoDB: Progress in MB:"); } - while (offset < low) { - if (low - offset < UNIV_PAGE_SIZE * 512) { - n_bytes = (ulint)(low - offset); - } else { - n_bytes = UNIV_PAGE_SIZE * 512; - } - + while (current_size < desired_size) { + ulint n_bytes = ut_min(buf_size, + (ulint) (desired_size - current_size)); ret = os_file_write(name, file, buf, - (ulint)(offset & 0xFFFFFFFF), - (ulint)(offset >> 32), + (ulint)(current_size & 0xFFFFFFFF), + (ulint)(current_size >> 32), n_bytes); if (!ret) { ut_free(buf2); @@ -1703,18 +1695,18 @@ os_file_set_size( } /* Print about progress for each 100 MB written */ - if ((offset + n_bytes) / (ib_longlong)(100 * 1024 * 1024) - != offset / (ib_longlong)(100 * 1024 * 1024)) { + if ((current_size + n_bytes) / (ib_longlong)(100 * 1024 * 1024) + != current_size / (ib_longlong)(100 * 1024 * 1024)) { fprintf(stderr, " %lu00", - (ulong) ((offset + n_bytes) + (ulong) ((current_size + n_bytes) / (ib_longlong)(100 * 1024 * 1024))); } - offset += n_bytes; + current_size += n_bytes; } - if (low >= (ib_longlong)(100 * 1024 * 1024)) { + if (desired_size >= (ib_longlong)(100 * 1024 * 1024)) { fprintf(stderr, "\n"); } From b608f091dbf628db32e67e9a62f3045f6dcf2ed7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 17:25:37 +0300 Subject: [PATCH 071/216] InnoDB: After review fixes innobase/os/os0file.c: os_file_set_size(): After review fixes (prevent overflows) --- innobase/os/os0file.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 25123c47cb8..4313b7f7019 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -1668,7 +1668,8 @@ os_file_set_size( desired_size = (ib_longlong)size + (((ib_longlong)size_high) << 32); /* Write up to 1 megabyte at a time. */ - buf_size = ut_min(UNIV_PAGE_SIZE * 64, desired_size); + buf_size = ut_min(64, (ulint) (desired_size / UNIV_PAGE_SIZE)) + * UNIV_PAGE_SIZE; buf2 = ut_malloc(buf_size + UNIV_PAGE_SIZE); /* Align the buffer for possible raw i/o */ @@ -1683,8 +1684,14 @@ os_file_set_size( } while (current_size < desired_size) { - ulint n_bytes = ut_min(buf_size, - (ulint) (desired_size - current_size)); + ulint n_bytes; + + if (desired_size - current_size < (ib_longlong) buf_size) { + n_bytes = (ulint) (desired_size - current_size); + } else { + n_bytes = buf_size; + } + ret = os_file_write(name, file, buf, (ulint)(current_size & 0xFFFFFFFF), (ulint)(current_size >> 32), From 49e38d31f7de5c0cbbf0f3489000f7eae89a5702 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 18:58:32 +0300 Subject: [PATCH 072/216] Many files: Remove compiler warnings on Windows - Bug #11580 innobase/btr/btr0btr.c: Remove compiler warnings on Windows - Bug #11580 innobase/btr/btr0cur.c: Remove compiler warnings on Windows - Bug #11580 innobase/fil/fil0fil.c: Remove compiler warnings on Windows - Bug #11580 innobase/ibuf/ibuf0ibuf.c: Remove compiler warnings on Windows - Bug #11580 innobase/log/log0recv.c: Remove compiler warnings on Windows - Bug #11580 innobase/os/os0file.c: Remove compiler warnings on Windows - Bug #11580 innobase/page/page0page.c: Remove compiler warnings on Windows - Bug #11580 innobase/row/row0upd.c: Remove compiler warnings on Windows - Bug #11580 --- innobase/btr/btr0btr.c | 6 +++--- innobase/btr/btr0cur.c | 4 ++-- innobase/fil/fil0fil.c | 2 +- innobase/ibuf/ibuf0ibuf.c | 2 +- innobase/log/log0recv.c | 21 ++++++++++++++------- innobase/os/os0file.c | 2 +- innobase/page/page0page.c | 6 +++--- innobase/row/row0upd.c | 2 +- 8 files changed, 26 insertions(+), 19 deletions(-) diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 2d84586216a..c27fb73ff8d 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -143,7 +143,7 @@ btr_root_get( root_page_no = dict_tree_get_page(tree); root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr); - ut_a(!!page_is_comp(root) == + ut_a((ibool)!!page_is_comp(root) == UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp); return(root); @@ -2014,7 +2014,7 @@ btr_compress( page = btr_cur_get_page(cursor); tree = btr_cur_get_tree(cursor); comp = page_is_comp(page); - ut_a(!!comp == cursor->index->table->comp); + ut_a((ibool)!!comp == cursor->index->table->comp); ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)); @@ -2508,7 +2508,7 @@ btr_index_rec_validate( return(TRUE); } - if (UNIV_UNLIKELY(!!page_is_comp(page) != index->table->comp)) { + if (UNIV_UNLIKELY((ibool)!!page_is_comp(page) != index->table->comp)) { btr_index_rec_validate_report(page, rec, index); fprintf(stderr, "InnoDB: compact flag=%lu, should be %lu\n", (ulong) !!page_is_comp(page), diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index 4ae27f007d6..30e85e021bc 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -507,7 +507,7 @@ retry_page_get: /* x-latch the page */ page = btr_page_get(space, page_no, RW_X_LATCH, mtr); - ut_a(!!page_is_comp(page) + ut_a((ibool)!!page_is_comp(page) == index->table->comp); } @@ -1385,7 +1385,7 @@ btr_cur_parse_update_in_place( goto func_exit; } - ut_a(!!page_is_comp(page) == index->table->comp); + ut_a((ibool)!!page_is_comp(page) == index->table->comp); rec = page + rec_offset; /* We do not need to reserve btr_search_latch, as the page is only diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index 299b55f3d2b..e236304b388 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -4034,7 +4034,7 @@ fil_aio_wait( if (os_aio_use_native_aio) { srv_set_io_thread_op_info(segment, "native aio handle"); #ifdef WIN_ASYNC_IO - ret = os_aio_windows_handle(segment, 0, (void**) &fil_node, + ret = os_aio_windows_handle(segment, 0, &fil_node, &message, &type); #elif defined(POSIX_ASYNC_IO) ret = os_aio_posix_handle(segment, &fil_node, &message); diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c index 712d43f916c..d7fa48b6e66 100644 --- a/innobase/ibuf/ibuf0ibuf.c +++ b/innobase/ibuf/ibuf0ibuf.c @@ -2810,7 +2810,7 @@ ibuf_insert_to_index_page( ut_ad(ibuf_inside()); ut_ad(dtuple_check_typed(entry)); - if (UNIV_UNLIKELY(index->table->comp != !!page_is_comp(page))) { + if (UNIV_UNLIKELY(index->table->comp != (ibool)!!page_is_comp(page))) { fputs( "InnoDB: Trying to insert a record from the insert buffer to an index page\n" "InnoDB: but the 'compact' flag does not match!\n", stderr); diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c index 8d9780bfbda..42e854398ba 100644 --- a/innobase/log/log0recv.c +++ b/innobase/log/log0recv.c @@ -768,7 +768,8 @@ recv_parse_or_apply_log_rec_body( case MLOG_REC_INSERT: case MLOG_COMP_REC_INSERT: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_INSERT, &index))) { - ut_a(!page||!!page_is_comp(page)==index->table->comp); + ut_a(!page + || (ibool)!!page_is_comp(page)==index->table->comp); ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr, index, page, mtr); } @@ -776,7 +777,8 @@ recv_parse_or_apply_log_rec_body( case MLOG_REC_CLUST_DELETE_MARK: case MLOG_COMP_REC_CLUST_DELETE_MARK: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_CLUST_DELETE_MARK, &index))) { - ut_a(!page||!!page_is_comp(page)==index->table->comp); + ut_a(!page + || (ibool)!!page_is_comp(page)==index->table->comp); ptr = btr_cur_parse_del_mark_set_clust_rec(ptr, end_ptr, index, page); } @@ -796,7 +798,8 @@ recv_parse_or_apply_log_rec_body( case MLOG_REC_UPDATE_IN_PLACE: case MLOG_COMP_REC_UPDATE_IN_PLACE: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_UPDATE_IN_PLACE, &index))) { - ut_a(!page||!!page_is_comp(page)==index->table->comp); + ut_a(!page + || (ibool)!!page_is_comp(page)==index->table->comp); ptr = btr_cur_parse_update_in_place(ptr, end_ptr, page, index); } @@ -806,7 +809,8 @@ recv_parse_or_apply_log_rec_body( if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_LIST_END_DELETE || type == MLOG_COMP_LIST_START_DELETE, &index))) { - ut_a(!page||!!page_is_comp(page)==index->table->comp); + ut_a(!page + || (ibool)!!page_is_comp(page)==index->table->comp); ptr = page_parse_delete_rec_list(type, ptr, end_ptr, index, page, mtr); } @@ -814,7 +818,8 @@ recv_parse_or_apply_log_rec_body( case MLOG_LIST_END_COPY_CREATED: case MLOG_COMP_LIST_END_COPY_CREATED: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_LIST_END_COPY_CREATED, &index))) { - ut_a(!page||!!page_is_comp(page)==index->table->comp); + ut_a(!page + || (ibool)!!page_is_comp(page)==index->table->comp); ptr = page_parse_copy_rec_list_to_created_page(ptr, end_ptr, index, page, mtr); } @@ -822,7 +827,8 @@ recv_parse_or_apply_log_rec_body( case MLOG_PAGE_REORGANIZE: case MLOG_COMP_PAGE_REORGANIZE: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_PAGE_REORGANIZE, &index))) { - ut_a(!page||!!page_is_comp(page)==index->table->comp); + ut_a(!page + || (ibool)!!page_is_comp(page)==index->table->comp); ptr = btr_parse_page_reorganize(ptr, end_ptr, index, page, mtr); } @@ -855,7 +861,8 @@ recv_parse_or_apply_log_rec_body( case MLOG_REC_DELETE: case MLOG_COMP_REC_DELETE: if (NULL != (ptr = mlog_parse_index(ptr, end_ptr, type == MLOG_COMP_REC_DELETE, &index))) { - ut_a(!page||!!page_is_comp(page)==index->table->comp); + ut_a(!page + || (ibool)!!page_is_comp(page)==index->table->comp); ptr = page_cur_parse_delete_rec(ptr, end_ptr, index, page, mtr); } diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index c68f5738798..d99b849157a 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -3296,7 +3296,7 @@ os_aio( ibool retval; BOOL ret = TRUE; DWORD len = (DWORD) n; - void* dummy_mess1; + struct fil_node_struct * dummy_mess1; void* dummy_mess2; ulint dummy_type; #endif diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c index 1fe7f1d9356..7e09cdf073e 100644 --- a/innobase/page/page0page.c +++ b/innobase/page/page0page.c @@ -483,7 +483,7 @@ page_copy_rec_list_end_no_locks( page_cur_move_to_next(&cur1); } - ut_a(!!page_is_comp(new_page) == index->table->comp); + ut_a((ibool)!!page_is_comp(new_page) == index->table->comp); ut_a(page_is_comp(new_page) == page_is_comp(page)); ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == (ulint) (page_is_comp(new_page) @@ -1347,7 +1347,7 @@ page_print_list( ulint* offsets = offsets_; *offsets_ = (sizeof offsets_) / sizeof *offsets_; - ut_a(!!page_is_comp(page) == index->table->comp); + ut_a((ibool)!!page_is_comp(page) == index->table->comp); fprintf(stderr, "--------------------------------\n" @@ -1741,7 +1741,7 @@ page_validate( ulint* offsets = NULL; ulint* old_offsets = NULL; - if (!!comp != index->table->comp) { + if ((ibool)!!comp != index->table->comp) { fputs("InnoDB: 'compact format' flag mismatch\n", stderr); goto func_exit2; } diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c index cf2b8db5d32..514fb6bd577 100644 --- a/innobase/row/row0upd.c +++ b/innobase/row/row0upd.c @@ -818,7 +818,7 @@ row_upd_build_difference_binary( extern_bit = upd_ext_vec_contains(ext_vec, n_ext_vec, i); if (UNIV_UNLIKELY(extern_bit == - !rec_offs_nth_extern(offsets, i)) + (ibool)!rec_offs_nth_extern(offsets, i)) || !dfield_data_is_binary_equal(dfield, len, data)) { upd_field = upd_get_nth_field(update, n_diff); From 76d444fcb64d0272c0f8efd450edc7087a105723 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 20:31:00 +0300 Subject: [PATCH 073/216] Portability fixes Fixes while reviewing new pushed code NULL as argument to encrypt/decrypt should return NULL without a warning client/mysqldump.c: Cleanup Ensure we free allocated memory Portability fixes client/mysqltest.c: Cleanup of code during review Portability fixes (Don't use 'bool') mysql-test/r/func_encrypt.result: NULL as argument to encrypt/decrypt should return NULL without a warning mysql-test/r/func_encrypt_nossl.result: Added test of NULL argument mysql-test/t/func_encrypt_nossl.test: Added test of NULL argument sql/handler.cc: Cleanup during code review sql/item_strfunc.cc: NULL as argument to encrypt/decrypt should return NULL without a warning sql/sql_parse.cc: Fix wrong merge (fix was not needed as the previous code was reverted) sql/sql_table.cc: Removed extra new line --- client/mysqldump.c | 55 +++++++++++++++----------- client/mysqltest.c | 37 +++++++++-------- mysql-test/r/func_encrypt.result | 12 ------ mysql-test/r/func_encrypt_nossl.result | 4 ++ mysql-test/t/func_encrypt_nossl.test | 1 + sql/handler.cc | 16 +++----- sql/item_strfunc.cc | 6 +-- sql/sql_parse.cc | 1 + sql/sql_table.cc | 1 - 9 files changed, 65 insertions(+), 68 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 04f2f40068f..fb5270c3222 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -533,6 +533,12 @@ static void write_footer(FILE *sql_file) } } /* write_footer */ +static void free_table_ent(char *key) + +{ + my_free((gptr) key, MYF(0)); +} + byte* get_table_key(const char *entry, uint *length, my_bool not_used __attribute__((unused))) @@ -544,8 +550,9 @@ byte* get_table_key(const char *entry, uint *length, void init_table_rule_hash(HASH* h) { - if(hash_init(h, charset_info, 16, 0, 0, - (hash_get_key) get_table_key, 0, 0)) + if (hash_init(h, charset_info, 16, 0, 0, + (hash_get_key) get_table_key, + (hash_free_key) free_table_ent, 0)) exit(EX_EOM); } @@ -933,13 +940,14 @@ static char *quote_name(const char *name, char *buff, my_bool force) return buff; } /* quote_name */ + /* Quote a table name so it can be used in "SHOW TABLES LIKE " SYNOPSIS - quote_for_like - name - name of the table - buff - quoted name of the table + quote_for_like() + name name of the table + buff quoted name of the table DESCRIPTION Quote \, _, ' and % characters @@ -955,7 +963,6 @@ static char *quote_name(const char *name, char *buff, my_bool force) Example: "t\1" => "t\\\\1" */ - static char *quote_for_like(const char *name, char *buff) { char *to= buff; @@ -2228,17 +2235,17 @@ static int get_actual_table_name(const char *old_table_name, retval = 1; if (tableRes != NULL) { - my_ulonglong numRows = mysql_num_rows(tableRes); - if (numRows > 0) - { - row= mysql_fetch_row( tableRes ); - strmake(new_table_name, row[0], buf_size-1); - retval = 0; - DBUG_PRINT("info", ("new_table_name: %s", new_table_name)); - } - mysql_free_result(tableRes); + my_ulonglong numRows= mysql_num_rows(tableRes); + if (numRows > 0) + { + row= mysql_fetch_row( tableRes ); + strmake(new_table_name, row[0], buf_size-1); + retval= 0; + DBUG_PRINT("info", ("new_table_name: %s", new_table_name)); + } + mysql_free_result(tableRes); } - DBUG_PRINT("exit", ("retval: %d", retval)); + DBUG_PRINT("exit", ("retval: %d", retval)); DBUG_RETURN(retval); } @@ -2250,7 +2257,6 @@ static int dump_selected_tables(char *db, char **table_names, int tables) char new_table_name[NAME_LEN]; DYNAMIC_STRING lock_tables_query; HASH dump_tables; - DBUG_ENTER("dump_selected_tables"); if (init_dumping(db)) @@ -2258,7 +2264,8 @@ static int dump_selected_tables(char *db, char **table_names, int tables) /* Init hash table for storing the actual name of tables to dump */ if (hash_init(&dump_tables, charset_info, 16, 0, 0, - (hash_get_key) get_table_key, 0, 0)) + (hash_get_key) get_table_key, (hash_free_key) free_table_ent, + 0)) exit(EX_EOM); init_dynamic_string(&lock_tables_query, "LOCK TABLES ", 256, 1024); @@ -2266,8 +2273,8 @@ static int dump_selected_tables(char *db, char **table_names, int tables) { /* the table name passed on commandline may be wrong case */ - if (!get_actual_table_name( *table_names, - new_table_name, sizeof(new_table_name) )) + if (!get_actual_table_name(*table_names, + new_table_name, sizeof(new_table_name) )) { /* Add found table name to lock_tables_query */ if (lock_tables) @@ -2310,12 +2317,11 @@ static int dump_selected_tables(char *db, char **table_names, int tables) print_xml_tag1(md_result_file, "", "database name=", db, "\n"); /* Dump each selected table */ - const char *table_name; for (i= 0 ; i < dump_tables.records ; i++) { - table_name= hash_element(&dump_tables, i); + const char *table_name= hash_element(&dump_tables, i); DBUG_PRINT("info",("Dumping table %s", table_name)); - numrows = getTableStructure(table_name, db); + numrows= getTableStructure(table_name, db); if (!dFlag && numrows > 0) dumpTable(numrows, table_name); } @@ -2620,6 +2626,7 @@ int main(int argc, char **argv) { compatible_mode_normal_str[0]= 0; default_charset= (char *)mysql_universal_client_charset; + bzero((char*) &ignore_table, sizeof(ignore_table)); MY_INIT("mysqldump"); if (get_options(&argc, &argv)) @@ -2678,6 +2685,8 @@ err: if (md_result_file != stdout) my_fclose(md_result_file, MYF(0)); my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); + if (hash_inited(&ignore_table)) + hash_free(&ignore_table); if (extended_insert) dynstr_free(&extended_row); if (insert_pat_inited) diff --git a/client/mysqltest.c b/client/mysqltest.c index fd8f19332ec..87c34591b89 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -964,28 +964,27 @@ static void do_exec(struct st_query* q) error= pclose(res_file); if (error != 0) { - uint status= WEXITSTATUS(error); - if(q->abort_on_error) + uint status= WEXITSTATUS(error), i; + my_bool ok= 0; + + if (q->abort_on_error) die("At line %u: command \"%s\" failed", start_lineno, cmd); - else + + DBUG_PRINT("info", + ("error: %d, status: %d", error, status)); + for (i=0 ; (uint) i < q->expected_errors ; i++) { - DBUG_PRINT("info", - ("error: %d, status: %d", error, status)); - bool ok= 0; - uint i; - for (i=0 ; (uint) i < q->expected_errors ; i++) - { - DBUG_PRINT("info", ("expected error: %d", q->expected_errno[i].code.errnum)); - if ((q->expected_errno[i].type == ERR_ERRNO) && - (q->expected_errno[i].code.errnum == status)) - ok= 1; - verbose_msg("At line %u: command \"%s\" failed with expected error: %d", - start_lineno, cmd, status); - } - if (!ok) - die("At line: %u: command \"%s\" failed with wrong error: %d", - start_lineno, cmd, status); + DBUG_PRINT("info", ("expected error: %d", + q->expected_errno[i].code.errnum)); + if ((q->expected_errno[i].type == ERR_ERRNO) && + (q->expected_errno[i].code.errnum == status)) + ok= 1; + verbose_msg("At line %u: command \"%s\" failed with expected error: %d", + start_lineno, cmd, status); } + if (!ok) + die("At line: %u: command \"%s\" failed with wrong error: %d", + start_lineno, cmd, status); } else if (q->expected_errno[0].type == ERR_ERRNO && q->expected_errno[0].code.errnum != 0) diff --git a/mysql-test/r/func_encrypt.result b/mysql-test/r/func_encrypt.result index 992d01c66cd..3eb8ec4354c 100644 --- a/mysql-test/r/func_encrypt.result +++ b/mysql-test/r/func_encrypt.result @@ -128,18 +128,12 @@ Error 1108 Incorrect parameters to procedure 'des_encrypt' select des_encrypt(NULL); des_encrypt(NULL) NULL -Warnings: -Error 1108 Incorrect parameters to procedure 'des_encrypt' select des_encrypt(NULL, 10); des_encrypt(NULL, 10) NULL -Warnings: -Error 1108 Incorrect parameters to procedure 'des_encrypt' select des_encrypt(NULL, NULL); des_encrypt(NULL, NULL) NULL -Warnings: -Error 1108 Incorrect parameters to procedure 'des_encrypt' select des_encrypt(10, NULL); des_encrypt(10, NULL) NULL @@ -156,18 +150,12 @@ hello select des_decrypt(NULL); des_decrypt(NULL) NULL -Warnings: -Error 1108 Incorrect parameters to procedure 'des_decrypt' select des_decrypt(NULL, 10); des_decrypt(NULL, 10) NULL -Warnings: -Error 1108 Incorrect parameters to procedure 'des_decrypt' select des_decrypt(NULL, NULL); des_decrypt(NULL, NULL) NULL -Warnings: -Error 1108 Incorrect parameters to procedure 'des_decrypt' select des_decrypt(10, NULL); des_decrypt(10, NULL) 10 diff --git a/mysql-test/r/func_encrypt_nossl.result b/mysql-test/r/func_encrypt_nossl.result index fea752f4a4a..e3ae6a5192a 100644 --- a/mysql-test/r/func_encrypt_nossl.result +++ b/mysql-test/r/func_encrypt_nossl.result @@ -23,6 +23,10 @@ des_encrypt("test", NULL) NULL Warnings: Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +des_encrypt(NULL, NULL) +NULL +Warnings: +Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working select des_decrypt("test", 'anotherkeystr'); des_decrypt("test", 'anotherkeystr') NULL diff --git a/mysql-test/t/func_encrypt_nossl.test b/mysql-test/t/func_encrypt_nossl.test index 0e9d93f5968..95c104ce046 100644 --- a/mysql-test/t/func_encrypt_nossl.test +++ b/mysql-test/t/func_encrypt_nossl.test @@ -9,6 +9,7 @@ select des_encrypt("test", 1); select des_encrypt("test", 9); select des_encrypt("test", 100); select des_encrypt("test", NULL); +select des_encrypt(NULL, NULL); select des_decrypt("test", 'anotherkeystr'); select des_decrypt(1, 1); select des_decrypt(des_encrypt("test", 'thekey')); diff --git a/sql/handler.cc b/sql/handler.cc index dacfc7d9ac5..cb1d88a30d4 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1357,14 +1357,12 @@ int ha_create_table_from_engine(THD* thd, HA_CREATE_INFO create_info; TABLE table; DBUG_ENTER("ha_create_table_from_engine"); - DBUG_PRINT("enter", ("name '%s'.'%s'", - db, name)); + DBUG_PRINT("enter", ("name '%s'.'%s'", db, name)); bzero((char*) &create_info,sizeof(create_info)); - - if(error= ha_discover(thd, db, name, &frmblob, &frmlen)) + if ((error= ha_discover(thd, db, name, &frmblob, &frmlen))) { - // Table could not be discovered and thus not created + /* Table could not be discovered and thus not created */ DBUG_RETURN(error); } @@ -1375,11 +1373,10 @@ int ha_create_table_from_engine(THD* thd, (void)strxnmov(path,FN_REFLEN,mysql_data_home,"/",db,"/",name,NullS); // Save the frm file - if (writefrm(path, frmblob, frmlen)) - { - my_free((char*) frmblob, MYF(MY_ALLOW_ZERO_PTR)); + error= writefrm(path, frmblob, frmlen); + my_free((char*) frmblob, MYF(0)); + if (error) DBUG_RETURN(2); - } if (openfrm(path,"",0,(uint) READ_ALL, 0, &table)) DBUG_RETURN(3); @@ -1395,7 +1392,6 @@ int ha_create_table_from_engine(THD* thd, } error=table.file->create(path,&table,&create_info); VOID(closefrm(&table)); - my_free((char*) frmblob, MYF(MY_ALLOW_ZERO_PTR)); DBUG_RETURN(error != 0); } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index ceb925be4d2..881a8a7c915 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -381,8 +381,8 @@ String *Item_func_des_encrypt::val_str(String *str) uint key_number, res_length, tail; String *res= args[0]->val_str(str); - if ((null_value=args[0]->null_value)) - goto error; + if ((null_value= args[0]->null_value)) + return 0; // ENCRYPT(NULL) == NULL if ((res_length=res->length()) == 0) return &my_empty_string; @@ -474,7 +474,7 @@ String *Item_func_des_decrypt::val_str(String *str) uint length=res->length(),tail; if ((null_value=args[0]->null_value)) - goto error; + return 0; length=res->length(); if (length < 9 || (length % 8) != 1 || !((*res)[0] & 128)) return res; // Skip decryption if not encrypted diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c7442f06891..c0283f81315 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2897,6 +2897,7 @@ unsent_create_error: } else res= -1; + first_local_table->next= tables; lex->select_lex.table_list.first= (byte*) first_local_table; break; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index d7a07d17761..b68b20c32a3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -255,7 +255,6 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, table->real_name); else error= 1; - } else { From f3dd8151569f301d5201d073ba2d94a692353044 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 20:31:02 +0300 Subject: [PATCH 074/216] Fix test after last push --- mysql-test/r/func_encrypt_nossl.result | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/r/func_encrypt_nossl.result b/mysql-test/r/func_encrypt_nossl.result index e3ae6a5192a..d0df2335afa 100644 --- a/mysql-test/r/func_encrypt_nossl.result +++ b/mysql-test/r/func_encrypt_nossl.result @@ -23,6 +23,7 @@ des_encrypt("test", NULL) NULL Warnings: Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working +select des_encrypt(NULL, NULL); des_encrypt(NULL, NULL) NULL Warnings: From feffe571eb0044817cee8d53019081a9f1025662 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Jun 2005 10:49:40 -0700 Subject: [PATCH 075/216] Fix typo in --default-store-engine help. (Bug #11534) sql/mysqld.cc: Fix typo --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3e0b496f05f..2dbc8fdac96 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4458,7 +4458,7 @@ Disable with --skip-bdb (will save memory).", (gptr*) &default_collation_name, (gptr*) &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"default-storage-engine", OPT_STORAGE_ENGINE, - "Set the default storage engine (table tyoe) for tables.", 0, 0, + "Set the default storage engine (table type) for tables.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-table-type", OPT_STORAGE_ENGINE, "(deprecated) Use --default-storage-engine.", 0, 0, From e45709dfbdb7e834fc46fa8c112452ac9218b9f7 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 00:52:21 +0300 Subject: [PATCH 076/216] abort storing query to query cache if warnings appeared (BUG#9414) mysql-test/r/query_cache.result: Query with warning prohibited to query cache mysql-test/t/query_cache.test: Query with warning prohibited to query cache sql/sql_error.cc: abort storing query to query cache if warnings appeared --- mysql-test/r/query_cache.result | 35 +++++++++++++++++++++++++++++++++ mysql-test/t/query_cache.test | 19 ++++++++++++++++++ sql/sql_error.cc | 2 ++ 3 files changed, 56 insertions(+) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 55f9bc6c224..a60b3cdbb1b 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -971,4 +971,39 @@ abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab zyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcba flush query cache; drop table t1, t2; +flush status; +CREATE TABLE t1 ( +`date` datetime NOT NULL default '0000-00-00 00:00:00', +KEY `date` (`date`) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('20050326'); +INSERT INTO t1 VALUES ('20050325'); +SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 0:0:0'; +COUNT(*) +0 +Warnings: +Warning 1292 Truncated incorrect datetime value: '20050327 0:0:0' +Warning 1292 Truncated incorrect datetime value: '20050327 0:0:0' +SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 0:0:0'; +COUNT(*) +0 +Warnings: +Warning 1292 Truncated incorrect datetime value: '20050328 0:0:0' +Warning 1292 Truncated incorrect datetime value: '20050328 0:0:0' +SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 0:0:0'; +COUNT(*) +0 +Warnings: +Warning 1292 Truncated incorrect datetime value: '20050327 0:0:0' +Warning 1292 Truncated incorrect datetime value: '20050327 0:0:0' +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +drop table t1; set GLOBAL query_cache_size=0; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 170f150f7aa..db78060ae2b 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -730,4 +730,23 @@ flush query cache; drop table t1, t2; +# +# Query with warning prohibited to query cache (BUG#9414) +# +flush status; +CREATE TABLE t1 ( + `date` datetime NOT NULL default '0000-00-00 00:00:00', + KEY `date` (`date`) +) ENGINE=MyISAM; + +INSERT INTO t1 VALUES ('20050326'); +INSERT INTO t1 VALUES ('20050325'); +SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 0:0:0'; +SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 0:0:0'; +SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 0:0:0'; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +drop table t1; + set GLOBAL query_cache_size=0; diff --git a/sql/sql_error.cc b/sql/sql_error.cc index a31e15d0745..b24d15b6e3b 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -108,6 +108,8 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, if (level == MYSQL_ERROR::WARN_LEVEL_NOTE && !(thd->options & OPTION_SQL_NOTES)) return(0); + query_cache_abort(&thd->net); + if (thd->query_id != thd->warn_id) mysql_reset_errors(thd); From f7780a1cc2da33dd7527b9708c49deb6175a067c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 04:33:06 +0200 Subject: [PATCH 077/216] opt_range.cc: Added missing `;' to DBUG_RETURN() sql/opt_range.cc: Added missing `;' to DBUG_RETURN() --- sql/opt_range.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 75cf9e6b3f0..9f268804cc3 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -982,7 +982,7 @@ get_mm_parts(PARAM *param, COND *cond_func, Field *field, field, Item_func::GT_FUNC, value, cmp_type); if (!tree2) - DBUG_RETURN(0) + DBUG_RETURN(0); tree= tree_or(param,tree,tree2); } DBUG_RETURN(tree); From 9c41fbda76cb86f545046b1bf1dbc07710ab7927 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 04:37:01 +0200 Subject: [PATCH 078/216] mysqld.dsp: Corrected quoting of string "pro-nt" VC++Files/sql/mysqld.dsp: Corrected quoting of string "pro-nt" --- VC++Files/sql/mysqld.dsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index 3508e6b31d0..034c8350c67 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -272,7 +272,7 @@ LINK32=xilink6.exe # PROP Target_Dir "" # ADD BASE CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "DBUG_OFF" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "USE_SYMDIR" /D "HAVE_DLOPEN" /D "NDEBUG" /FD /c # SUBTRACT BASE CPP /YX -# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "__NT__" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D LICENSE=Commercial /D "NDEBUG" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-pro-nt" /FD +# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../regex" /I "../zlib" /D "__NT__" /D "DBUG_OFF" /D "HAVE_INNOBASE_DB" /D LICENSE=Commercial /D "NDEBUG" /D "MYSQL_SERVER" /D "_WINDOWS" /D "_CONSOLE" /D "_MBCS" /D "HAVE_DLOPEN" /D MYSQL_SERVER_SUFFIX=-pro-nt /FD # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe From c7e157e71ed71a3f024280c4b3997b79c903db97 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 04:44:27 +0200 Subject: [PATCH 079/216] configure.in: Enable build with CXX=gcc and gcc version 4 configure.in: Enable build with CXX=gcc and gcc version 4 --- configure.in | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index d454d23b38c..0889e9a3257 100644 --- a/configure.in +++ b/configure.in @@ -419,9 +419,14 @@ then if echo $CXX | grep gcc > /dev/null 2>&1 then - if $CXX -v 2>&1 | grep 'version 3' > /dev/null 2>&1 + AC_MSG_CHECKING([if CXX is gcc 3 or 4]) + if $CXX -v 2>&1 | grep 'version [[34]]' > /dev/null 2>&1 then + AC_MSG_RESULT([yes]) + AC_MSG_NOTICE([using MySQL tricks to avoid linking C++ code with C++ libraries]) CXXFLAGS="$CXXFLAGS -DUSE_MYSYS_NEW -DDEFINE_CXA_PURE_VIRTUAL" + else + AC_MSG_RESULT([no]) fi fi fi From 0037781f05b81f01cdd88ca893f200d2a5664c48 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 04:49:03 +0200 Subject: [PATCH 080/216] Makefile.am: Bug#9873, reenabled --without-man option to work Makefile.am: Bug#9873, reenabled --without-man option to work --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index ffa27220611..96f3561e31c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,7 @@ EXTRA_DIST = INSTALL-SOURCE README COPYING EXCEPTIONS-CLIENT SUBDIRS = . include @docs_dirs@ @zlib_dir@ \ @readline_topdir@ sql-common \ @thread_dirs@ pstack \ - @sql_union_dirs@ scripts man tests \ + @sql_union_dirs@ scripts @man_dirs@ tests \ netware @libmysqld_dirs@ \ @bench_dirs@ support-files @fs_dirs@ @tools_dirs@ From 5c429181187d28a76a555f85aa68425d50bc303f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 05:25:29 +0200 Subject: [PATCH 081/216] make_win_src_distribution.sh: Bug#11009, some more cleanup of unneded files from bootstrap scripts/make_win_src_distribution.sh: Bug#11009, some more cleanup of unneded files from bootstrap --- scripts/make_win_src_distribution.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh index b8dd907920c..71d61b7a02d 100644 --- a/scripts/make_win_src_distribution.sh +++ b/scripts/make_win_src_distribution.sh @@ -357,6 +357,9 @@ if [ -d $BASE/SSL/SCCS ] then find $BASE/ -type d -name SCCS -printf " \"%p\"" | xargs rm -r -f fi +find $BASE/ -type d -name .deps -printf " \"%p\"" | xargs rm -r -f +find $BASE/ -type d -name .libs -printf " \"%p\"" | xargs rm -r -f +rm -r -f "$BASE/mysql-test/var" # # Initialize the initial data directory From 2776aa35b7abc4c0f742eaa94c04b4072e2ba83d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 15:00:22 +0500 Subject: [PATCH 082/216] ctype_ucs.result, ctype_ucs.test, ctype_utf8.result, ctype_utf8.test: Fixing tests accordingly. ctype-ucs2.c: The same fix for UCS2. ctype-utf8.c: Bug #9557 MyISAM utf8 table crash The problem was that my_strnncollsp_xxx could return big value in the range 0..0xffff. for some constant pairs it could return 32738, which is defined as MI_FOUND_WRONG_KEY in myisamdef.h. As a result, table considered to be crashed. Fix to return -1,0 or 1. strings/ctype-utf8.c: Bug #9557 MyISAM utf8 table crash The problem was that my_strnncollsp_xxx could return big value in the range 0..0xffff. for some constant pairs it could return 32738, which is defined as MI_FOUND_WRONG_KEY in myisamdef.h. As a result, table considered to be crashed. Fix to return -1,0 or 1. strings/ctype-ucs2.c: The same fix for UCS2. mysql-test/t/ctype_utf8.test: Fixing tests accordingly. mysql-test/r/ctype_utf8.result: Fixing tests accordingly. mysql-test/t/ctype_ucs.test: Fixing tests accordingly. mysql-test/r/ctype_ucs.result: Fixing tests accordingly. --- mysql-test/r/ctype_ucs.result | 11 +++++++++++ mysql-test/r/ctype_utf8.result | 11 +++++++++++ mysql-test/t/ctype_ucs.test | 12 ++++++++++++ mysql-test/t/ctype_utf8.test | 12 ++++++++++++ strings/ctype-ucs2.c | 6 +++--- strings/ctype-utf8.c | 4 ++-- 6 files changed, 51 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 5902dd247ce..6d00f13737d 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -630,3 +630,14 @@ Warnings: Warning 1265 Data truncated for column 'Field1' at row 1 DROP TABLE t1; SET NAMES latin1; +CREATE TABLE t1 ( +a varchar(255) NOT NULL default '', +KEY a (a) +) ENGINE=MyISAM DEFAULT CHARSET=ucs2 COLLATE ucs2_general_ci; +insert into t1 values (0x803d); +insert into t1 values (0x005b); +select hex(a) from t1; +hex(a) +005B +803D +drop table t1; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 12ef8dfb8e8..3a8265b01f7 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -939,3 +939,14 @@ content msisdn ERR Имри.Афимим.Аеимимримдмримрмрирор имримримримр имридм ирбднримрфмририримрфмфмим.Ад.Д имдимримрад.Адимримримрмдиримримримр м.Дадимфшьмримд им.Адимимрн имадми 1234567890 11 g 1234567890 DROP TABLE t1,t2; +CREATE TABLE t1 ( +a varchar(255) NOT NULL default '', +KEY a (a) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE utf8_general_ci; +insert into t1 values (_utf8 0xe880bd); +insert into t1 values (_utf8 0x5b); +select hex(a) from t1; +hex(a) +5B +E880BD +drop table t1; diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 6c72c409463..8dd8d02d018 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -404,3 +404,15 @@ CREATE TABLE t1 (Field1 int(10) unsigned default '0'); INSERT INTO t1 VALUES ('-1'); DROP TABLE t1; SET NAMES latin1; + +# +# Bug#9557 MyISAM utf8 table crash +# +CREATE TABLE t1 ( + a varchar(255) NOT NULL default '', + KEY a (a) +) ENGINE=MyISAM DEFAULT CHARSET=ucs2 COLLATE ucs2_general_ci; +insert into t1 values (0x803d); +insert into t1 values (0x005b); +select hex(a) from t1; +drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 343b7c867e7..0a847057258 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -788,3 +788,15 @@ INSERT INTO t2 VALUES ('1234567890',2,'2005-05-24 13:53:25'); SELECT content, t2.msisdn FROM t1, t2 WHERE t1.msisdn = '1234567890'; DROP TABLE t1,t2; + +# +# Bug#9557 MyISAM utf8 table crash +# +CREATE TABLE t1 ( + a varchar(255) NOT NULL default '', + KEY a (a) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE utf8_general_ci; +insert into t1 values (_utf8 0xe880bd); +insert into t1 values (_utf8 0x5b); +select hex(a) from t1; +drop table t1; diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 12c1ae905cf..c3caaeadfb3 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -209,7 +209,7 @@ static int my_strnncoll_ucs2(CHARSET_INFO *cs, t_wc = uni_plane[plane] ? uni_plane[plane][t_wc & 0xFF].sort : t_wc; if ( s_wc != t_wc ) { - return ((int) s_wc) - ((int) t_wc); + return s_wc > t_wc ? 1 : -1; } s+=s_res; @@ -267,7 +267,7 @@ static int my_strnncollsp_ucs2(CHARSET_INFO *cs __attribute__((unused)), int t_wc = uni_plane[t[0]] ? (int) uni_plane[t[0]][t[1]].sort : (((int) t[0]) << 8) + (int) t[1]; if ( s_wc != t_wc ) - return s_wc - t_wc; + return s_wc > t_wc ? 1 : -1; s+= 2; t+= 2; @@ -1343,7 +1343,7 @@ int my_strnncoll_ucs2_bin(CHARSET_INFO *cs, } if ( s_wc != t_wc ) { - return ((int) s_wc) - ((int) t_wc); + return s_wc > t_wc ? 1 : -1; } s+=s_res; diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 230b44796e8..f5192b26ce2 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2000,7 +2000,7 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs, t_wc = uni_plane[plane] ? uni_plane[plane][t_wc & 0xFF].sort : t_wc; if ( s_wc != t_wc ) { - return ((int) s_wc) - ((int) t_wc); + return s_wc > t_wc ? 1 : -1; } s+=s_res; @@ -2065,7 +2065,7 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs, t_wc = uni_plane[plane] ? uni_plane[plane][t_wc & 0xFF].sort : t_wc; if ( s_wc != t_wc ) { - return ((int) s_wc) - ((int) t_wc); + return s_wc > t_wc ? 1 : -1; } s+=s_res; From 67abd491a1d5c631b0e72ea89941fafd9ac2fa34 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 03:18:37 -0700 Subject: [PATCH 083/216] group_by.result, group_by.test: Added a test case for bug #11414. sql_select.cc: Fixed bug #11414: crash on Windows with some simple GROUP BY queries. It happened to an allocation of an array containing 0 Copy_field elements in setup_copy_fields. The bug had been already fixed in 5.0. sql/sql_select.cc: Fixed bug #11414: crash on Windows with some simple GROUP BY queries. It happened to an allocation of an array containing 0 Copy_field elements in setup_copy_fields. The bug had been already fixed in 5.0. mysql-test/t/group_by.test: Added a test case for bug #11414. mysql-test/r/group_by.result: Added a test case for bug #11414. --- mysql-test/r/group_by.result | 6 ++++++ mysql-test/t/group_by.test | 12 ++++++++++++ sql/sql_select.cc | 5 +++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 7f78b8bda9b..295663fe1d3 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -751,3 +751,9 @@ COUNT(DISTINCT(t1.id)) err_comment 1 NULL 1 a problem DROP TABLE t1, t2; +CREATE TABLE t1 (n int); +INSERT INTO t1 VALUES (1); +SELECT n+1 AS n FROM t1 GROUP BY n; +n +2 +DROP TABLE t1; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 694aa8d7411..23d51b0f297 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -580,3 +580,15 @@ SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS err_comment FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY err_comment; DROP TABLE t1, t2; + +# +# Test for bug #11414: crash on Windows for a simple GROUP BY query +# + +CREATE TABLE t1 (n int); +INSERT INTO t1 VALUES (1); + +SELECT n+1 AS n FROM t1 GROUP BY n; + +DROP TABLE t1; + diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2f165565ce1..f2db5adfdda 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8727,7 +8727,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, { Item *pos; List_iterator_fast li(all_fields); - Copy_field *copy; + Copy_field *copy= NULL; res_selected_fields.empty(); res_all_fields.empty(); List_iterator_fast itr(res_all_fields); @@ -8735,7 +8735,8 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, uint i, border= all_fields.elements - elements; DBUG_ENTER("setup_copy_fields"); - if (!(copy=param->copy_field= new Copy_field[param->field_count])) + if (param->field_count && + !(copy=param->copy_field= new Copy_field[param->field_count])) goto err2; param->copy_funcs.empty(); From 05c7edf64801efa5b0d99ca779eb0b31a4d92462 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 15:06:16 +0300 Subject: [PATCH 084/216] Move reset of insert_values to ensure it's done also during error conditions This fixed a failure of insert_update.test on some platforms mysys/thr_alarm.c: Fixed problem noticed by valgrind sql/opt_range.cc: Simple optimization for common case sql/sql_base.cc: Safety assert sql/sql_insert.cc: Added comment --- mysys/thr_alarm.c | 1 + sql/opt_range.cc | 3 +-- sql/sql_base.cc | 1 + sql/sql_insert.cc | 4 ++++ sql/sql_parse.cc | 2 +- 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 19611a6027a..05d14073953 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -86,6 +86,7 @@ void init_thr_alarm(uint max_alarms) { struct sigaction sact; sact.sa_flags = 0; + bzero((char*) &sact, sizeof(sact)); sact.sa_handler = thread_alarm; sigaction(THR_CLIENT_ALARM, &sact, (struct sigaction*) 0); } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 9f268804cc3..2dd097cbaab 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -981,8 +981,7 @@ get_mm_parts(PARAM *param, COND *cond_func, Field *field, SEL_TREE *tree2= get_mm_parts(param, cond_func, field, Item_func::GT_FUNC, value, cmp_type); - if (!tree2) - DBUG_RETURN(0); + /* tree_or() will return 0 if tree2 is 0 */ tree= tree_or(param,tree,tree2); } DBUG_RETURN(tree); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c9861790b06..7a36d33a42c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -979,6 +979,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, if (table->timestamp_field) table->timestamp_field_type= table->timestamp_field->get_auto_set_type(); DBUG_ASSERT(table->key_read == 0); + DBUG_ASSERT(table->insert_values == 0); DBUG_RETURN(table); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index deccc1d4dca..7d613ad6fbf 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -516,6 +516,10 @@ abort: ON DUPLICATE KEY ... we should be able to refer to sum1 in the ON DUPLICATE KEY part + WARNING + You MUST set table->insert_values to 0 after calling this function + before releasing the table object. + RETURN VALUE 0 OK -1 error (message is not sent to user) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c0283f81315..d7fd3239df5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2891,12 +2891,12 @@ unsent_create_error: /* revert changes for SP */ lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; delete result; - insert_table->insert_values= 0; if (thd->net.report_error) res= -1; } else res= -1; + insert_table->insert_values= 0; // Set by mysql_prepare_insert() first_local_table->next= tables; lex->select_lex.table_list.first= (byte*) first_local_table; break; From 1031b871e7d3e5458d026f1811f671c5fd611212 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 07:27:00 -0700 Subject: [PATCH 085/216] range.result, range.test: Added a test case for bug #10031. opt_range.cc: Fixed bug #10031: range condition was not used with views. Range analyzer did not take into account that view columns were always referred through Item_ref. sql/opt_range.cc: Fixed bug #10031: range condition was not used with views. Range analyzer did not take into account that view columns were always referred through Item_ref. mysql-test/t/range.test: Added a test case for bug #10031. mysql-test/r/range.result: Added a test case for bug #10031. --- mysql-test/r/range.result | 24 ++++++++++++++++++++++++ mysql-test/t/range.test | 23 +++++++++++++++++++++++ sql/opt_range.cc | 11 ++++++----- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index ae7d0474e24..6f9b4e41b22 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -720,3 +720,27 @@ id status 59 C 60 C DROP TABLE t1; +CREATE TABLE t1 (a int, b int, primary key(a,b)); +INSERT INTO t1 VALUES +(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3),(4,1),(4,2),(4,3); +CREATE VIEW v1 as SELECT a,b FROM t1 WHERE b=3; +EXPLAIN SELECT a,b FROM t1 WHERE a < 2 and b=3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index +EXPLAIN SELECT a,b FROM v1 WHERE a < 2 and b=3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index +EXPLAIN SELECT a,b FROM t1 WHERE a < 2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index +EXPLAIN SELECT a,b FROM v1 WHERE a < 2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index +SELECT a,b FROM t1 WHERE a < 2 and b=3; +a b +1 3 +SELECT a,b FROM v1 WHERE a < 2 and b=3; +a b +1 3 +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index a285a4b312c..3d2285b1633 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -530,3 +530,26 @@ SELECT * FROM t1 WHERE status NOT BETWEEN 'A' AND 'B'; SELECT * FROM t1 WHERE status < 'A' OR status > 'B'; DROP TABLE t1; + +# +# Test for bug #10031: range to be used over a view +# + +CREATE TABLE t1 (a int, b int, primary key(a,b)); + +INSERT INTO t1 VALUES + (1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3),(4,1),(4,2),(4,3); + +CREATE VIEW v1 as SELECT a,b FROM t1 WHERE b=3; + +EXPLAIN SELECT a,b FROM t1 WHERE a < 2 and b=3; +EXPLAIN SELECT a,b FROM v1 WHERE a < 2 and b=3; + +EXPLAIN SELECT a,b FROM t1 WHERE a < 2; +EXPLAIN SELECT a,b FROM v1 WHERE a < 2; + +SELECT a,b FROM t1 WHERE a < 2 and b=3; +SELECT a,b FROM v1 WHERE a < 2 and b=3; + +DROP VIEW v1; +DROP TABLE t1; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 4c0c895f22a..632f1dea3c1 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3581,15 +3581,16 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) DBUG_RETURN(ftree); } default: - if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM) + if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM) { - field_item= (Item_field*) (cond_func->arguments()[0]); + field_item= (Item_field*) (cond_func->arguments()[0]->real_item()); value= cond_func->arg_count > 1 ? cond_func->arguments()[1] : 0; } else if (cond_func->have_rev_func() && - cond_func->arguments()[1]->type() == Item::FIELD_ITEM) + cond_func->arguments()[1]->real_item()->type() == + Item::FIELD_ITEM) { - field_item= (Item_field*) (cond_func->arguments()[1]); + field_item= (Item_field*) (cond_func->arguments()[1]->real_item()); value= cond_func->arguments()[0]; } else @@ -3610,7 +3611,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) for (uint i= 0; i < cond_func->arg_count; i++) { - Item *arg= cond_func->arguments()[i]; + Item *arg= cond_func->arguments()[i]->real_item(); if (arg != field_item) ref_tables|= arg->used_tables(); } From 79c1be9e442f3ba8f735e14a0454533f5914a817 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 20:52:15 +0400 Subject: [PATCH 086/216] A fix and a test case for Bug#10736 "mysql_stmt_attr_set CURSOR_TYPE_READ_ONLY select within select". The bug was caused by the reset of thd->mem_root to thd->main_mem_root in Item_subselect::exec, which in turn triggered too early free_root() for data which was needed on subsequent fetches from a cursor. This reset also caused a memory leak in stored procedures, as subsequent executions of instructions containing a subselect were allocating memory in thd->main_mem_root, which is not freed until the end of the entire SP, instead of the per-call mem_root, which is freed in the end of execution of the instruction. sql/item_subselect.cc: Don't try to protect subqueries from the code that assumes that it can reset thd->mem_root and get away with it: it's responsibility of the caller to ensure that no assumption about the life span of the allocated memory made by the called code is broken. Besides, this didn't work well with cursors and stored procedures, where the runtime memory root is not the same as &thd->main_mem_root. sql/opt_range.cc: In get_mm_leaf restore the original mem_root of the thd which has been temporarily reset with the quick select mem_root earlier: if thd->mem_root points to the QUICK...::mem_root, the memory allocated in JOIN::exec during evaluation of a subquery gets freed too early. tests/mysql_client_test.c: A test case for Bug#10736 "mysql_stmt_attr_set CURSOR_TYPE_READ_ONLY select within select" --- sql/item_subselect.cc | 7 ---- sql/opt_range.cc | 81 +++++++++++++++++++++++++-------------- tests/mysql_client_test.c | 59 ++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 35 deletions(-) diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 7ea72f3c858..c7587686ecd 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -194,15 +194,8 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) bool Item_subselect::exec() { int res; - MEM_ROOT *old_root= thd->mem_root; - /* - As this is execution, all objects should be allocated through the main - mem root - */ - thd->mem_root= &thd->main_mem_root; res= engine->exec(); - thd->mem_root= old_root; if (engine_changed) { diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 4c0c895f22a..86ad1e4aa06 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -325,7 +325,7 @@ typedef struct st_qsel_param { TABLE *table; KEY_PART *key_parts,*key_parts_end; KEY_PART *key[MAX_KEY]; /* First key parts of keys used in the query */ - MEM_ROOT *mem_root; + MEM_ROOT *mem_root, *old_root; table_map prev_tables,read_tables,current_table; uint baseflag, max_key_part, range_count; @@ -1665,7 +1665,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, keys_to_use.intersect(head->keys_in_use_for_query); if (!keys_to_use.is_clear_all()) { - MEM_ROOT *old_root,alloc; + MEM_ROOT alloc; SEL_TREE *tree= NULL; KEY_PART *key_parts; KEY *key_info; @@ -1680,6 +1680,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, param.table=head; param.keys=0; param.mem_root= &alloc; + param.old_root= thd->mem_root; param.needed_reg= &needed_reg; param.imerge_cost_buff_size= 0; @@ -1695,7 +1696,6 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, DBUG_RETURN(0); // Can't use range } key_parts= param.key_parts; - old_root= thd->mem_root; thd->mem_root= &alloc; /* @@ -1845,7 +1845,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, } } - thd->mem_root= old_root; + thd->mem_root= param.old_root; /* If we got a read plan, create a quick select from it. */ if (best_trp) @@ -1860,7 +1860,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, free_mem: free_root(&alloc,MYF(0)); // Return memory & allocator - thd->mem_root= old_root; + thd->mem_root= param.old_root; thd->no_errors=0; } @@ -3695,24 +3695,38 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, { uint maybe_null=(uint) field->real_maybe_null(); bool optimize_range; - SEL_ARG *tree; + SEL_ARG *tree= 0; + MEM_ROOT *alloc= param->mem_root; char *str; DBUG_ENTER("get_mm_leaf"); + /* + We need to restore the runtime mem_root of the thread in this + function becuase it evaluates the value of its argument, while + the argument can be any, e.g. a subselect. The subselect + items, in turn, assume that all the memory allocated during + the evaluation has the same life span as the item itself. + TODO: opt_range.cc should not reset thd->mem_root at all. + */ + param->thd->mem_root= param->old_root; if (!value) // IS NULL or IS NOT NULL { if (field->table->maybe_null) // Can't use a key on this - DBUG_RETURN(0); + goto end; if (!maybe_null) // Not null field - DBUG_RETURN(type == Item_func::ISNULL_FUNC ? &null_element : 0); - if (!(tree=new SEL_ARG(field,is_null_string,is_null_string))) - DBUG_RETURN(0); // out of memory + { + if (type == Item_func::ISNULL_FUNC) + tree= &null_element; + goto end; + } + if (!(tree= new (alloc) SEL_ARG(field,is_null_string,is_null_string))) + goto end; // out of memory if (type == Item_func::ISNOTNULL_FUNC) { tree->min_flag=NEAR_MIN; /* IS NOT NULL -> X > NULL */ tree->max_flag=NO_MAX_RANGE; } - DBUG_RETURN(tree); + goto end; } /* @@ -3732,7 +3746,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, key_part->image_type == Field::itRAW && ((Field_str*)field)->charset() != conf_func->compare_collation() && !(conf_func->compare_collation()->state & MY_CS_BINSORT)) - DBUG_RETURN(0); + goto end; optimize_range= field->optimize_range(param->real_keynr[key_part->key], key_part->part); @@ -3746,9 +3760,12 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, uint field_length= field->pack_length()+maybe_null; if (!optimize_range) - DBUG_RETURN(0); // Can't optimize this + goto end; if (!(res= value->val_str(&tmp))) - DBUG_RETURN(&null_element); + { + tree= &null_element; + goto end; + } /* TODO: @@ -3761,7 +3778,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, res= &tmp; } if (field->cmp_type() != STRING_RESULT) - DBUG_RETURN(0); // Can only optimize strings + goto end; // Can only optimize strings offset=maybe_null; length=key_part->store_length; @@ -3786,8 +3803,8 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, field_length= length; } length+=offset; - if (!(min_str= (char*) alloc_root(param->mem_root, length*2))) - DBUG_RETURN(0); + if (!(min_str= (char*) alloc_root(alloc, length*2))) + goto end; max_str=min_str+length; if (maybe_null) @@ -3802,20 +3819,21 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, min_str+offset, max_str+offset, &min_length, &max_length); if (like_error) // Can't optimize with LIKE - DBUG_RETURN(0); + goto end; if (offset != maybe_null) // BLOB or VARCHAR { int2store(min_str+maybe_null,min_length); int2store(max_str+maybe_null,max_length); } - DBUG_RETURN(new SEL_ARG(field,min_str,max_str)); + tree= new (alloc) SEL_ARG(field, min_str, max_str); + goto end; } if (!optimize_range && type != Item_func::EQ_FUNC && type != Item_func::EQUAL_FUNC) - DBUG_RETURN(0); // Can't optimize this + goto end; // Can't optimize this /* We can't always use indexes when comparing a string index to a number @@ -3824,21 +3842,22 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, if (field->result_type() == STRING_RESULT && value->result_type() != STRING_RESULT && field->cmp_type() != value->result_type()) - DBUG_RETURN(0); + goto end; if (value->save_in_field_no_warnings(field, 1) < 0) { /* This happens when we try to insert a NULL field in a not null column */ - DBUG_RETURN(&null_element); // cmp with NULL is never TRUE + tree= &null_element; // cmp with NULL is never TRUE + goto end; } - str= (char*) alloc_root(param->mem_root, key_part->store_length+1); + str= (char*) alloc_root(alloc, key_part->store_length+1); if (!str) - DBUG_RETURN(0); + goto end; if (maybe_null) *str= (char) field->is_real_null(); // Set to 1 if null field->get_key_image(str+maybe_null, key_part->length, key_part->image_type); - if (!(tree=new SEL_ARG(field,str,str))) - DBUG_RETURN(0); // out of memory + if (!(tree= new (alloc) SEL_ARG(field, str, str))) + goto end; // out of memory /* Check if we are comparing an UNSIGNED integer with a negative constant. @@ -3862,10 +3881,13 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, if (type == Item_func::LT_FUNC || type == Item_func::LE_FUNC) { tree->type= SEL_ARG::IMPOSSIBLE; - DBUG_RETURN(tree); + goto end; } if (type == Item_func::GT_FUNC || type == Item_func::GE_FUNC) - DBUG_RETURN(0); + { + tree= 0; + goto end; + } } } @@ -3928,6 +3950,9 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, default: break; } + +end: + param->thd->mem_root= alloc; DBUG_RETURN(tree); } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 8debf7614a3..585763c164d 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13332,6 +13332,64 @@ static void test_bug9992() mysql_close(mysql1); } + +/* Bug#10736: cursors and subqueries, memroot management */ + +static void test_bug10736() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + char a[21]; + int rc; + const char *stmt_text; + int i= 0; + ulong type; + + myheader("test_bug10736"); + + mysql_query(mysql, "drop table if exists t1"); + mysql_query(mysql, "create table t1 (id integer not null primary key," + "name VARCHAR(20) NOT NULL)"); + rc= mysql_query(mysql, "insert into t1 (id, name) values " + "(1, 'aaa'), (2, 'bbb'), (3, 'ccc')"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + + type= (ulong) CURSOR_TYPE_READ_ONLY; + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type); + check_execute(stmt, rc); + stmt_text= "select name from t1 where name=(select name from t1 where id=2)"; + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + check_execute(stmt, rc); + + bzero(bind, sizeof(bind)); + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer= (void*) a; + bind[0].buffer_length= sizeof(a); + mysql_stmt_bind_result(stmt, bind); + + for (i= 0; i < 3; i++) + { + int row_no= 0; + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + while ((rc= mysql_stmt_fetch(stmt)) == 0) + { + if (!opt_silent) + printf("%d: %s\n", row_no, a); + ++row_no; + } + DIE_UNLESS(rc == MYSQL_NO_DATA); + } + rc= mysql_stmt_close(stmt); + DIE_UNLESS(rc == 0); + + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -13567,6 +13625,7 @@ static struct my_tests_st my_tests[]= { { "test_bug10729", test_bug10729 }, { "test_bug11111", test_bug11111 }, { "test_bug9992", test_bug9992 }, + { "test_bug10736", test_bug10736 }, { 0, 0 } }; From 2637338014fc335ea872b3c0ca85bb75bc309b51 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 21:45:11 +0300 Subject: [PATCH 087/216] fixed substring() length calculation in case of constant negative argument (BUG#10269) mysql-test/r/func_str.result: Correct length reporting from substring() mysql-test/t/func_str.test: Correct length reporting from substring() sql/item_strfunc.cc: fixed substring() length calculation in case of constant negative argument --- mysql-test/r/func_str.result | 15 +++++++++++++++ mysql-test/t/func_str.test | 9 +++++++++ sql/item_strfunc.cc | 3 ++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 60c77d91ca5..91ee3be3b72 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -800,3 +800,18 @@ SELECT * FROM t1, t2 WHERE num=substring(str from 1 for 6); str num notnumber 0 DROP TABLE t1,t2; +create table t1 (b varchar(5)); +insert t1 values ('ab'), ('abc'), ('abcd'), ('abcde'); +select *,substring(b,1),substring(b,-1),substring(b,-2),substring(b,-3),substring(b,-4),substring(b,-5) from t1; +b substring(b,1) substring(b,-1) substring(b,-2) substring(b,-3) substring(b,-4) substring(b,-5) +ab ab b ab +abc abc c bc abc +abcd abcd d cd bcd abcd +abcde abcde e de cde bcde abcde +select * from (select *,substring(b,1),substring(b,-1),substring(b,-2),substring(b,-3),substring(b,-4),substring(b,-5) from t1) t; +b substring(b,1) substring(b,-1) substring(b,-2) substring(b,-3) substring(b,-4) substring(b,-5) +ab ab b ab +abc abc c bc abc +abcd abcd d cd bcd abcd +abcde abcde e de cde bcde abcde +drop table t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 36cfac16ff3..9a8ef7c1341 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -541,3 +541,12 @@ SELECT * FROM t1, t2 WHERE num=str; SELECT * FROM t1, t2 WHERE num=substring(str from 1 for 6); DROP TABLE t1,t2; + +# +# Correct length reporting from substring() (BUG#10269) +# +create table t1 (b varchar(5)); +insert t1 values ('ab'), ('abc'), ('abcd'), ('abcde'); +select *,substring(b,1),substring(b,-1),substring(b,-2),substring(b,-3),substring(b,-4),substring(b,-5) from t1; +select * from (select *,substring(b,1),substring(b,-1),substring(b,-2),substring(b,-3),substring(b,-4),substring(b,-5) from t1) t; +drop table t1; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 881a8a7c915..08e6a222c69 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1065,7 +1065,8 @@ void Item_func_substr::fix_length_and_dec() collation.set(args[0]->collation); if (args[1]->const_item()) { - int32 start=(int32) args[1]->val_int()-1; + int32 start= (int32) args[1]->val_int(); + start= (int32)((start < 0) ? max_length + start : start - 1); if (start < 0 || start >= (int32) max_length) max_length=0; /* purecov: inspected */ else From d2f7623d4525adcd7216ad2a0fad04fdc2e8495d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 22:49:14 +0400 Subject: [PATCH 088/216] Fixed comments. sql/opt_range.cc: comment fixed. sql/sp_head.cc: An obsolete comment removed. --- sql/opt_range.cc | 2 +- sql/sp_head.cc | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 86ad1e4aa06..1d32b978180 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3702,7 +3702,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, /* We need to restore the runtime mem_root of the thread in this - function becuase it evaluates the value of its argument, while + function because it evaluates the value of its argument, while the argument can be any, e.g. a subselect. The subselect items, in turn, assume that all the memory allocated during the evaluation has the same life span as the item itself. diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 825ec34e410..d075c86f8cd 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1474,13 +1474,6 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, they want to store some value in local variable, pass return value and etc... So their life time should be longer than one instruction. - Probably we can call destructors for most of them then we are leaving - routine. But this won't help much as they are allocated in main query - MEM_ROOT anyway. So they all go to global thd->free_list. - - May be we can use some other MEM_ROOT for this purprose ??? - - What else should we do for cleanup ? cleanup_items() is called in sp_head::execute() */ return res; From 19103bf364396d7a87581fb1faf01b70b852a46c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 12:00:38 -0700 Subject: [PATCH 089/216] opt_range.cc: Fixed a compilation error. sql/opt_range.cc: Fixed a compilation error. --- sql/opt_range.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 24a6b12e6c9..fef32dbb69d 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3871,9 +3871,8 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, negative integers (which otherwise fails because at query execution time negative integers are cast to unsigned if compared with unsigned). */ - Item_result field_result_type= field->result_type(); - Item_result value_result_type= value->result_type(); - if (field_result_type == INT_RESULT && value_result_type == INT_RESULT && + if (field->result_type() == INT_RESULT && + value->result_type() == INT_RESULT && ((Field_num*)field)->unsigned_flag && !((Item_int*)value)->unsigned_flag) { longlong item_val= value->val_int(); From 3aca0a0c62d8e2557dd366a9b2ecf0053bf1b832 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Jun 2005 22:20:25 +0300 Subject: [PATCH 090/216] fixed not_null_tables() for IN() (BUG#9393) (IN() remove NULL rows only for tables from first argument (value which we looking for in IN() list) but not for tables from IN() list) Also it will be better change Item::not_null_tables() to prohibit this optimisation by default for new created items in 5.0 or 5.1. mysql-test/r/select.result: IN with outer join condition mysql-test/t/select.test: IN with outer join condition sql/item_cmpfunc.h: correct not_null_tables() for IN --- mysql-test/r/select.result | 9 +++++++++ mysql-test/t/select.test | 15 +++++++++++++++ sql/item_cmpfunc.h | 6 ++++++ 3 files changed, 30 insertions(+) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index f828759672a..abf5c8c87ad 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2515,3 +2515,12 @@ SELECT b FROM t1 WHERE b=0x8000000000000000; b 9223372036854775808 DROP TABLE t1; +CREATE TABLE `t1` ( `gid` int(11) default NULL, `uid` int(11) default NULL); +CREATE TABLE `t2` ( `ident` int(11) default NULL, `level` char(16) default NULL); +INSERT INTO `t2` VALUES (0,'READ'); +CREATE TABLE `t3` ( `id` int(11) default NULL, `name` char(16) default NULL); +INSERT INTO `t3` VALUES (1,'fs'); +select * from t3 left join t1 on t3.id = t1.uid, t2 where t2.ident in (0, t1.gid, t3.id, 0); +id name gid uid ident level +1 fs NULL NULL 0 READ +drop table t1,t2,t3; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 3877e67de41..baaab6e4189 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2060,3 +2060,18 @@ CREATE TABLE t1 (b BIGINT(20) UNSIGNED NOT NULL, PRIMARY KEY (b)); INSERT INTO t1 VALUES (0x8000000000000000); SELECT b FROM t1 WHERE b=0x8000000000000000; DROP TABLE t1; + +# +# IN with outer join condition (BUG#9393) +# +CREATE TABLE `t1` ( `gid` int(11) default NULL, `uid` int(11) default NULL); + +CREATE TABLE `t2` ( `ident` int(11) default NULL, `level` char(16) default NULL); +INSERT INTO `t2` VALUES (0,'READ'); + +CREATE TABLE `t3` ( `id` int(11) default NULL, `name` char(16) default NULL); +INSERT INTO `t3` VALUES (1,'fs'); + +select * from t3 left join t1 on t3.id = t1.uid, t2 where t2.ident in (0, t1.gid, t3.id, 0); + +drop table t1,t2,t3; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index bea8250de9d..525f269e528 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -769,6 +769,12 @@ class Item_func_in :public Item_int_func bool nulls_in_row(); bool is_bool_func() { return 1; } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } + /* + IN() protect from NULL only first argument, if construction like + "expression IN ()" will be allowed, we will need to check number of + argument here, because "NOT(NULL IN ())" is TRUE. + */ + table_map not_null_tables() const { return args[0]->not_null_tables(); } }; /* Functions used by where clause */ From e29f5221973ad7bf48f0e4152c5bb8a4491de7c1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 02:24:31 +0400 Subject: [PATCH 091/216] post review fixes to a patch mysys/default_modify.c: post revew fixes to a patch --- mysys/default_modify.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/mysys/default_modify.c b/mysys/default_modify.c index d40529817cd..e2bc12a2c95 100644 --- a/mysys/default_modify.c +++ b/mysys/default_modify.c @@ -70,8 +70,9 @@ int modify_defaults_file(const char *file_location, const char *option, char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer; uint opt_len, optval_len, sect_len, nr_newlines= 0, buffer_size; my_bool in_section= FALSE, opt_applied= 0; - int reserve_occupied= 0, reserve_extended= 1, old_opt_len; - int new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN; + uint reserve_extended= 1, old_opt_len= 0; + uint new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN; + int reserve_occupied= 0; DBUG_ENTER("modify_defaults_file"); if (!(cnf_file= my_fopen(file_location, O_RDWR | O_BINARY, MYF(0)))) @@ -133,14 +134,20 @@ int modify_defaults_file(const char *file_location, const char *option, */ if (opt_applied) { - old_opt_len= strlen(linebuff); + src_ptr+= opt_len; /* If we correct an option, we know it's name */ + old_opt_len= opt_len; + + while (*src_ptr++) /* Find the end of the line */ + old_opt_len++; + /* could be negative */ - reserve_occupied+= new_opt_len - old_opt_len; - if (reserve_occupied > RESERVE*reserve_extended) + reserve_occupied+= (int) new_opt_len - (int) old_opt_len; + if ((int) reserve_occupied > (int) (RESERVE*reserve_extended)) { - file_buffer= (char*) my_realloc(file_buffer, buffer_size + - RESERVE*reserve_extended, - MYF(MY_WME)); + if (!(file_buffer= (char*) my_realloc(file_buffer, buffer_size + + RESERVE*reserve_extended, + MYF(MY_WME|MY_FREE_ON_ERROR)))) + goto malloc_err; reserve_extended++; } } From 36f34c1c7edbd9f0f4e40cf616acfad77738d573 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 10:35:49 +0400 Subject: [PATCH 092/216] Added test for bug #5893 "Triggers with dropped functions cause crashes" (The bug itself was fixed earlier by the patch that fixed bug #5860 "Multi-table UPDATE does not activate update triggers" and several other bugs). mysql-test/r/trigger.result: Added test for bug #5893 "Triggers with dropped functions cause crashes" mysql-test/t/trigger.test: Added test for bug #5893 "Triggers with dropped functions cause crashes" --- mysql-test/r/trigger.result | 9 +++++++++ mysql-test/t/trigger.test | 14 ++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 996a692d531..0bb1fd1d550 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -482,3 +482,12 @@ i k ts 1 1 0000-00-00 00:00:00 2 2 0000-00-00 00:00:00 drop table t1, t2; +drop function if exists bug5893; +create table t1 (col1 int, col2 int); +insert into t1 values (1, 2); +create function bug5893 () returns int return 5; +create trigger t1_bu before update on t1 for each row set new.col1= bug5893(); +drop function bug5893; +update t1 set col2 = 4; +ERROR 42000: FUNCTION test.bug5893 does not exist +drop table t1; diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 0c5ef077159..05241772693 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -494,3 +494,17 @@ replace into t1 (i, k) values (2, 11); select * from t1; # Also drops all triggers drop table t1, t2; + +# Test for bug #5893 "Triggers with dropped functions cause crashes" +# Appropriate error should be reported instead of crash. +--disable_warnings +drop function if exists bug5893; +--enable_warnings +create table t1 (col1 int, col2 int); +insert into t1 values (1, 2); +create function bug5893 () returns int return 5; +create trigger t1_bu before update on t1 for each row set new.col1= bug5893(); +drop function bug5893; +--error 1305 +update t1 set col2 = 4; +drop table t1; From a3d07b1c3e1e67bdac333006d22e50b9caa61422 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 12:03:38 +0500 Subject: [PATCH 093/216] a fix (bug #11215: BIGINT: can't set DEFAULT to minimum end-range) sql/item.cc: a fix (bug #11215: BIGINT: can't set DEFAULT to minimum end-range) Pass unsig=1 to the constructor. --- mysql-test/r/type_newdecimal.result | 6 ++++++ mysql-test/t/type_newdecimal.test | 9 +++++++++ sql/item.cc | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index b406dbab82f..79943df18c5 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -928,3 +928,9 @@ select * from t1 where a = -0.00; a 0.00 drop table t1; +create table t1 (col1 bigint default -9223372036854775808); +insert into t1 values (default); +select * from t1; +col1 +-9223372036854775808 +drop table t1; diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 6199bd34fa9..5c4f288983b 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -964,3 +964,12 @@ insert into t1 values (0.00); select * from t1 where a > -0.00; select * from t1 where a = -0.00; drop table t1; + +# +# Bug #11215: a problem with LONGLONG_MIN +# + +create table t1 (col1 bigint default -9223372036854775808); +insert into t1 values (default); +select * from t1; +drop table t1; diff --git a/sql/item.cc b/sql/item.cc index d3888cef9d5..82edc05c721 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3573,7 +3573,7 @@ Item *Item_int_with_ref::new_item() Item_num *Item_uint::neg() { - Item_decimal *item= new Item_decimal(value, 0); + Item_decimal *item= new Item_decimal(value, 1); return item->neg(); } From c35625416ce62a653716e761acdee97fcd56b8fd Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 11:50:29 +0300 Subject: [PATCH 094/216] fixed SP parameter execution sql/sp_head.cc: execute parameters in statement mem_root sql/sql_union.cc: additional assert --- sql/sp_head.cc | 16 ++++++++-------- sql/sql_union.cc | 1 + 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index d075c86f8cd..e4dc64c993d 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -735,11 +735,10 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0); - thd->set_n_backup_item_arena(&call_arena, &backup_arena); // QQ Should have some error checking here? (types, etc...) nctx= new sp_rcontext(csize, hmax, cmax); - nctx->callers_mem_root= backup_arena.mem_root; + nctx->callers_mem_root= thd->mem_root; for (i= 0 ; i < argcount ; i++) { sp_pvar_t *pvar = m_pcont->find_pvar(i); @@ -765,6 +764,9 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) } } thd->spcont= nctx; + thd->set_n_backup_item_arena(&call_arena, &backup_arena); + /* mem_root was moved to backup_arena */ + DBUG_ASSERT(nctx->callers_mem_root == backup_arena.mem_root); ret= execute(thd); @@ -834,7 +836,6 @@ sp_head::execute_procedure(THD *thd, List *args) } init_alloc_root(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0); - thd->set_n_backup_item_arena(&call_arena, &backup_arena); if (csize > 0 || hmax > 0 || cmax > 0) { @@ -899,12 +900,11 @@ sp_head::execute_procedure(THD *thd, List *args) } if (! ret) + { + thd->set_n_backup_item_arena(&call_arena, &backup_arena); ret= execute(thd); - - // Partially restore context now. - // We still need the call mem root and free list for processing - // of out parameters. - thd->restore_backup_item_arena(&call_arena, &backup_arena); + thd->restore_backup_item_arena(&call_arena, &backup_arena); + } if (!ret && csize > 0) { diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 87b67a5127a..6e307dda5be 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -646,6 +646,7 @@ bool st_select_lex::cleanup() if (join) { + DBUG_ASSERT((st_select_lex*)join->select_lex == this); error|= join->destroy(); delete join; join= 0; From d9e54b04c5e3dd73e60a31a313a74975aebf4995 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 13:27:27 +0400 Subject: [PATCH 095/216] post review fixes (second review) mysys/default_modify.c: post review fixes --- mysys/default_modify.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mysys/default_modify.c b/mysys/default_modify.c index e2bc12a2c95..ea384f9f27a 100644 --- a/mysys/default_modify.c +++ b/mysys/default_modify.c @@ -71,7 +71,7 @@ int modify_defaults_file(const char *file_location, const char *option, uint opt_len, optval_len, sect_len, nr_newlines= 0, buffer_size; my_bool in_section= FALSE, opt_applied= 0; uint reserve_extended= 1, old_opt_len= 0; - uint new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN; + uint new_opt_len; int reserve_occupied= 0; DBUG_ENTER("modify_defaults_file"); @@ -80,11 +80,13 @@ int modify_defaults_file(const char *file_location, const char *option, /* my_fstat doesn't use the flag parameter */ if (my_fstat(fileno(cnf_file), &file_stat, MYF(0))) - goto err; + goto malloc_err; opt_len= (uint) strlen(option); optval_len= (uint) strlen(option_value); + new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN; + /* calculate the size of the buffer we need */ buffer_size= sizeof(char) * (file_stat.st_size + /* option name len */ From 3dcf7083a9518a4d4bb6c0c6cd3aad12e6864d02 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 02:40:25 -0700 Subject: [PATCH 096/216] func_str.test: Added test cases for bug #11469. item_strfunc.h: Fixed bug #11469: wrong implementation of the not_null_tables method for CONCAT_WS. sql/item_strfunc.h: Fixed bug #11469: wrong implementation of the not_null_tables method for CONCAT_WS. mysql-test/t/func_str.test: Added test cases for bug #11469. --- mysql-test/r/func_str.result | 50 ++++++++++++++++++++++++++++++++ mysql-test/t/func_str.test | 56 ++++++++++++++++++++++++++++++++++++ sql/item_strfunc.h | 1 + 3 files changed, 107 insertions(+) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 60c77d91ca5..cbedf4370ff 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -800,3 +800,53 @@ SELECT * FROM t1, t2 WHERE num=substring(str from 1 for 6); str num notnumber 0 DROP TABLE t1,t2; +CREATE TABLE t1( +id int(11) NOT NULL auto_increment, +pc int(11) NOT NULL default '0', +title varchar(20) default NULL, +PRIMARY KEY (id) +); +INSERT INTO t1 VALUES +(1, 0, 'Main'), +(2, 1, 'Toys'), +(3, 1, 'Games'); +SELECT t1.id, CONCAT_WS('->', t3.title, t2.title, t1.title) as col1 +FROM t1 LEFT JOIN t1 AS t2 ON t1.pc=t2.id +LEFT JOIN t1 AS t3 ON t2.pc=t3.id; +id col1 +1 Main +2 Main->Toys +3 Main->Games +SELECT t1.id, CONCAT_WS('->', t3.title, t2.title, t1.title) as col1 +FROM t1 LEFT JOIN t1 AS t2 ON t1.pc=t2.id +LEFT JOIN t1 AS t3 ON t2.pc=t3.id +WHERE CONCAT_WS('->', t3.title, t2.title, t1.title) LIKE '%Toys%'; +id col1 +2 Main->Toys +DROP TABLE t1; +CREATE TABLE t1( +trackid int(10) unsigned NOT NULL auto_increment, +trackname varchar(100) NOT NULL default '', +PRIMARY KEY (trackid) +); +CREATE TABLE t2( +artistid int(10) unsigned NOT NULL auto_increment, +artistname varchar(100) NOT NULL default '', +PRIMARY KEY (artistid) +); +CREATE TABLE t3( +trackid int(10) unsigned NOT NULL, +artistid int(10) unsigned NOT NULL, +PRIMARY KEY (trackid,artistid) +); +INSERT INTO t1 VALUES (1, 'April In Paris'), (2, 'Autumn In New York'); +INSERT INTO t2 VALUES (1, 'Vernon Duke'); +INSERT INTO t3 VALUES (1,1); +SELECT CONCAT_WS(' ', trackname, artistname) trackname, artistname +FROM t1 LEFT JOIN t3 ON t1.trackid=t3.trackid +LEFT JOIN t2 ON t2.artistid=t3.artistid +WHERE CONCAT_WS(' ', trackname, artistname) LIKE '%In%'; +trackname artistname +April In Paris Vernon Duke Vernon Duke +Autumn In New York NULL +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 36cfac16ff3..f5f9ddac3b5 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -541,3 +541,59 @@ SELECT * FROM t1, t2 WHERE num=str; SELECT * FROM t1, t2 WHERE num=substring(str from 1 for 6); DROP TABLE t1,t2; + +# +# Bug #11469: NOT NULL optimization wrongly used for arguments of CONCAT_WS +# + +CREATE TABLE t1( + id int(11) NOT NULL auto_increment, + pc int(11) NOT NULL default '0', + title varchar(20) default NULL, + PRIMARY KEY (id) +); + +INSERT INTO t1 VALUES + (1, 0, 'Main'), + (2, 1, 'Toys'), + (3, 1, 'Games'); + +SELECT t1.id, CONCAT_WS('->', t3.title, t2.title, t1.title) as col1 + FROM t1 LEFT JOIN t1 AS t2 ON t1.pc=t2.id + LEFT JOIN t1 AS t3 ON t2.pc=t3.id; +SELECT t1.id, CONCAT_WS('->', t3.title, t2.title, t1.title) as col1 + FROM t1 LEFT JOIN t1 AS t2 ON t1.pc=t2.id + LEFT JOIN t1 AS t3 ON t2.pc=t3.id + WHERE CONCAT_WS('->', t3.title, t2.title, t1.title) LIKE '%Toys%'; + +DROP TABLE t1; + + +CREATE TABLE t1( + trackid int(10) unsigned NOT NULL auto_increment, + trackname varchar(100) NOT NULL default '', + PRIMARY KEY (trackid) +); + +CREATE TABLE t2( + artistid int(10) unsigned NOT NULL auto_increment, + artistname varchar(100) NOT NULL default '', + PRIMARY KEY (artistid) +); + +CREATE TABLE t3( + trackid int(10) unsigned NOT NULL, + artistid int(10) unsigned NOT NULL, + PRIMARY KEY (trackid,artistid) +); + +INSERT INTO t1 VALUES (1, 'April In Paris'), (2, 'Autumn In New York'); +INSERT INTO t2 VALUES (1, 'Vernon Duke'); +INSERT INTO t3 VALUES (1,1); + +SELECT CONCAT_WS(' ', trackname, artistname) trackname, artistname + FROM t1 LEFT JOIN t3 ON t1.trackid=t3.trackid + LEFT JOIN t2 ON t2.artistid=t3.artistid + WHERE CONCAT_WS(' ', trackname, artistname) LIKE '%In%'; + +DROP TABLE t1,t2,t3; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 6f6af415086..b01d75b8e02 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -95,6 +95,7 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "concat_ws"; } + table_map not_null_tables() const { return 0; } }; class Item_func_reverse :public Item_str_func From 1aa6343fe8d9a1d61aa7fcd4246fb5858b3dfa16 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 12:44:40 +0300 Subject: [PATCH 097/216] Simple optimization nsure that delete works not only on table->record[0] for federated tables sql/field.cc: Test OOM condition sql/ha_federated.cc: Simple optimizations Ensure that delete works not only on table->record[0] sql/opt_range.cc: Simplify code --- sql/field.cc | 7 ++++++- sql/ha_federated.cc | 24 ++++++++++-------------- sql/opt_range.cc | 12 +++++------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/sql/field.cc b/sql/field.cc index fb244de4275..2cfd162899c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6822,7 +6822,12 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) ¬_used))) { uint conv_errors; - tmpstr.copy(from, length, cs, field_charset, &conv_errors); + if (tmpstr.copy(from, length, cs, field_charset, &conv_errors)) + { + /* Fatal OOM error */ + bzero(ptr,Field_blob::pack_length()); + return -1; + } from= tmpstr.ptr(); length= tmpstr.length(); if (conv_errors) diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 77db17608bc..6754a1a8707 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -1399,27 +1399,25 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) int ha_federated::delete_row(const byte *buf) { - uint x= 0; char delete_buffer[IO_SIZE]; char data_buffer[IO_SIZE]; - String delete_string(delete_buffer, sizeof(delete_buffer), &my_charset_bin); - delete_string.length(0); String data_string(data_buffer, sizeof(data_buffer), &my_charset_bin); - data_string.length(0); - DBUG_ENTER("ha_federated::delete_row"); + delete_string.length(0); delete_string.append("DELETE FROM `"); delete_string.append(share->table_base_name); delete_string.append("`"); delete_string.append(" WHERE "); - for (Field **field= table->field; *field; field++, x++) + for (Field **field= table->field; *field; field++) { - delete_string.append((*field)->field_name); + Field *cur_field= *field; + data_string.length(0); + delete_string.append(cur_field->field_name); - if ((*field)->is_null()) + if (cur_field->is_null_in_record((const uchar*) buf)) { delete_string.append(" IS "); data_string.append("NULL"); @@ -1427,17 +1425,15 @@ int ha_federated::delete_row(const byte *buf) else { delete_string.append("="); - (*field)->val_str(&data_string); - (*field)->quote_data(&data_string); + cur_field->val_str(&data_string, (char*) buf+ cur_field->offset()); + cur_field->quote_data(&data_string); } delete_string.append(data_string); - data_string.length(0); - - if (x + 1 < table->s->fields) - delete_string.append(" AND "); + delete_string.append(" AND "); } + delete_string.length(delete_string.length()-5); // Remove AND delete_string.append(" LIMIT 1"); DBUG_PRINT("info", ("Delete sql: %s", delete_string.c_ptr_quick())); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 4c0c895f22a..05028c4e2a5 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -8556,23 +8556,21 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range() if ((result == HA_ERR_KEY_NOT_FOUND) && (cur_range->flag & EQ_RANGE)) continue; /* Check the next range. */ - else if (result) + if (result) + { /* In no key was found with this upper bound, there certainly are no keys in the ranges to the left. */ return result; - + } /* A key was found. */ if (cur_range->flag & EQ_RANGE) - return result; /* No need to perform the checks below for equal keys. */ + return 0; /* No need to perform the checks below for equal keys. */ /* Check if record belongs to the current group. */ if (key_cmp(index_info->key_part, group_prefix, real_prefix_len)) - { - result = HA_ERR_KEY_NOT_FOUND; - continue; - } + continue; // Row not found /* If there is a lower limit, check if the found key is in the range. */ if ( !(cur_range->flag & NO_MIN_RANGE) ) From 84aa570ddfc8a0ad04ecbf0a163492f1209b336b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 14:02:11 +0300 Subject: [PATCH 098/216] Applied some Netware related patches. include/config-netware.h: Netware related fix. Some changes needed when building against latest libc (June 2005) netware/my_print_defaults.def: Stack size increase. sql/mysqld.cc: Needed with latest libc. --- include/config-netware.h | 10 ++++++++++ netware/my_print_defaults.def | 3 ++- sql/mysqld.cc | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/config-netware.h b/include/config-netware.h index 4a6dc3b1bb9..906f557f608 100644 --- a/include/config-netware.h +++ b/include/config-netware.h @@ -46,11 +46,21 @@ extern "C" { #undef HAVE_SYS_MMAN_H #undef HAVE_SYNCH_H #undef HAVE_MMAP + #define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1 #define HAVE_PTHREAD_SIGMASK 1 #define HAVE_PTHREAD_YIELD_ZERO_ARG 1 #define HAVE_BROKEN_REALPATH 1 +#undef HAVE_POSIX_SIGNALS +#undef HAVE_PTHREAD_ATTR_SETSCOPE +#undef HAVE_ALLOC_A +#undef HAVE_FINITE +#undef HAVE_GETPWNAM +#undef HAVE_GETPWUID +#undef HAVE_PTHREAD_SETSCHEDPARAM +#undef HAVE_READLINK +#undef HAVE_STPCPY /* no libc crypt() function */ #ifdef HAVE_OPENSSL #define HAVE_CRYPT 1 diff --git a/netware/my_print_defaults.def b/netware/my_print_defaults.def index 826981256b5..d88c5adf4cc 100644 --- a/netware/my_print_defaults.def +++ b/netware/my_print_defaults.def @@ -4,7 +4,8 @@ MODULE libc.nlm COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Print Defaults Tool" -VERSION 4, 0 +VERSION 5, 0, 8 +STACKSIZE 32767 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 2dbc8fdac96..bc4cc81506e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -140,6 +140,7 @@ int deny_severity = LOG_WARNING; #define zVOLSTATE_DEACTIVE 2 #define zVOLSTATE_MAINTENANCE 3 +#include #include #include #include From 4b0f98747727bafe604b073e3ad6ce416a184400 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 14:23:43 +0200 Subject: [PATCH 099/216] Fixed compiler errors (i.e. changed C++-isms into C) client/mysqldump.c: Moved variable declaration to beginning of block (and removed const to get rid of warnings). client/mysqltest.c: Moved DBUG_PRINT after variable declarations. --- client/mysqldump.c | 2 +- client/mysqltest.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 66bc4fcb896..c75f02353b4 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2398,6 +2398,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) char new_table_name[NAME_LEN]; DYNAMIC_STRING lock_tables_query; HASH dump_tables; + char *table_name; DBUG_ENTER("dump_selected_tables"); @@ -2457,7 +2458,6 @@ static int dump_selected_tables(char *db, char **table_names, int tables) print_xml_tag1(md_result_file, "", "database name=", db, "\n"); /* Dump each selected table */ - const char *table_name; for (i= 0; i < dump_tables.records; i++) { table_name= hash_element(&dump_tables, i); diff --git a/client/mysqltest.c b/client/mysqltest.c index 7fdaf1098c2..a7f9420df6d 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -994,10 +994,10 @@ static void do_exec(struct st_query* q) die("At line %u: command \"%s\" failed", start_lineno, cmd); else { - DBUG_PRINT("info", - ("error: %d, status: %d", error, status)); bool ok= 0; uint i; + DBUG_PRINT("info", + ("error: %d, status: %d", error, status)); for (i=0 ; (uint) i < q->expected_errors ; i++) { DBUG_PRINT("info", ("expected error: %d", q->expected_errno[i].code.errnum)); From 3378673653108ee89e8011e1d18cd394aea13039 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 15:31:43 +0200 Subject: [PATCH 100/216] Moved connections first in test, to reduce risk of connecting before servers are fully connected --- mysql-test/t/ndb_alter_table.test | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test index 9cc1426554f..d6a1ef5e25f 100644 --- a/mysql-test/t/ndb_alter_table.test +++ b/mysql-test/t/ndb_alter_table.test @@ -7,6 +7,13 @@ DROP TABLE IF EXISTS t1; drop database if exists mysqltest; --enable_warnings +connect (con1,localhost,root,,test); +connect (con2,localhost,root,,test); + +connection con2; +-- sleep 2 +connection con1; + # # Basic test to show that the ALTER TABLE # is working @@ -88,10 +95,6 @@ CREATE TABLE t1 ( INSERT INTO t1 VALUES (9410,9412); -connect (con1,localhost,,,test); -connect (con2,localhost,,,test); - -connection con1; ALTER TABLE t1 ADD COLUMN c int not null; select * from t1 order by a; From e0c17446e0f9243bbf57264c29408470b07bff4f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 16:13:50 +0200 Subject: [PATCH 101/216] Changed delete_row to always get key from record argument --- sql/ha_ndbcluster.cc | 28 ++++++++++++---------------- sql/ha_ndbcluster.h | 5 ++--- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 65c5fcb7de4..0fe2d56a93a 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1113,12 +1113,12 @@ int ha_ndbcluster::set_primary_key(NdbOperation *op, const byte *key) } -int ha_ndbcluster::set_primary_key_from_old_data(NdbOperation *op, const byte *old_data) +int ha_ndbcluster::set_primary_key_from_record(NdbOperation *op, const byte *old_data) { KEY* key_info= table->key_info + table->primary_key; KEY_PART_INFO* key_part= key_info->key_part; KEY_PART_INFO* end= key_part+key_info->key_parts; - DBUG_ENTER("set_primary_key_from_old_data"); + DBUG_ENTER("set_primary_key_from_record"); for (; key_part != end; key_part++) { @@ -1130,7 +1130,7 @@ int ha_ndbcluster::set_primary_key_from_old_data(NdbOperation *op, const byte *o DBUG_RETURN(0); } - +/* int ha_ndbcluster::set_primary_key(NdbOperation *op) { DBUG_ENTER("set_primary_key"); @@ -1147,7 +1147,7 @@ int ha_ndbcluster::set_primary_key(NdbOperation *op) } DBUG_RETURN(0); } - +*/ /* Read one record from NDB using primary key @@ -1242,7 +1242,7 @@ int ha_ndbcluster::complemented_pk_read(const byte *old_data, byte *new_data) ERR_RETURN(trans->getNdbError()); int res; - if ((res= set_primary_key_from_old_data(op, old_data))) + if ((res= set_primary_key_from_record(op, old_data))) ERR_RETURN(trans->getNdbError()); // Read all unreferenced non-key field(s) @@ -1273,7 +1273,7 @@ int ha_ndbcluster::complemented_pk_read(const byte *old_data, byte *new_data) Peek to check if a particular row already exists */ -int ha_ndbcluster::peek_row() +int ha_ndbcluster::peek_row(const byte *record) { NdbConnection *trans= m_active_trans; NdbOperation *op; @@ -1287,7 +1287,7 @@ int ha_ndbcluster::peek_row() ERR_RETURN(trans->getNdbError()); int res; - if ((res= set_primary_key(op))) + if ((res= set_primary_key_from_record(op, record))) ERR_RETURN(trans->getNdbError()); if (execute_no_commit_ie(this,trans) != 0) @@ -1841,7 +1841,7 @@ int ha_ndbcluster::write_row(byte *record) if(m_ignore_dup_key && table->primary_key != MAX_KEY) { - int peek_res= peek_row(); + int peek_res= peek_row(record); if (!peek_res) { @@ -1891,9 +1891,7 @@ int ha_ndbcluster::write_row(byte *record) m_skip_auto_increment= !auto_increment_column_changed; } - if ((res= (m_primary_key_update ? - set_primary_key_from_old_data(op, record) - : set_primary_key(op)))) + if ((res= set_primary_key_from_record(op, record))) return res; } @@ -2110,7 +2108,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) else { int res; - if ((res= set_primary_key_from_old_data(op, old_data))) + if ((res= set_primary_key_from_record(op, old_data))) DBUG_RETURN(res); } } @@ -2191,10 +2189,8 @@ int ha_ndbcluster::delete_row(const byte *record) else { int res; - if ((res= (m_primary_key_update ? - set_primary_key_from_old_data(op, record) - : set_primary_key(op)))) - return res; + if ((res= set_primary_key_from_record(op, record))) + return res; } } diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 5c1d121a157..8e44733f905 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -168,7 +168,7 @@ class ha_ndbcluster: public handler int pk_read(const byte *key, uint key_len, byte *buf); int complemented_pk_read(const byte *old_data, byte *new_data); - int peek_row(); + int peek_row(const byte *record); int unique_index_read(const byte *key, uint key_len, byte *buf); int ordered_index_scan(const key_range *start_key, @@ -196,8 +196,7 @@ class ha_ndbcluster: public handler friend int g_get_ndb_blobs_value(NdbBlob *ndb_blob, void *arg); int get_ndb_blobs_value(NdbBlob *last_ndb_blob); int set_primary_key(NdbOperation *op, const byte *key); - int set_primary_key(NdbOperation *op); - int set_primary_key_from_old_data(NdbOperation *op, const byte *old_data); + int set_primary_key_from_record(NdbOperation *op, const byte *old_data); int set_bounds(NdbIndexScanOperation *ndb_op, const key_range *keys[2]); int key_cmp(uint keynr, const byte * old_row, const byte * new_row); void print_results(); From 80089d532b324cd71404bf25b779373fc8216c01 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 16:17:47 +0200 Subject: [PATCH 102/216] Changed delete_row to always get key from record argument, removed unused function --- sql/ha_ndbcluster.cc | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 0fe2d56a93a..462670df64c 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1130,25 +1130,6 @@ int ha_ndbcluster::set_primary_key_from_record(NdbOperation *op, const byte *old DBUG_RETURN(0); } -/* -int ha_ndbcluster::set_primary_key(NdbOperation *op) -{ - DBUG_ENTER("set_primary_key"); - KEY* key_info= table->key_info + table->primary_key; - KEY_PART_INFO* key_part= key_info->key_part; - KEY_PART_INFO* end= key_part+key_info->key_parts; - - for (; key_part != end; key_part++) - { - Field* field= key_part->field; - if (set_ndb_key(op, field, - key_part->fieldnr-1, field->ptr)) - ERR_RETURN(op->getNdbError()); - } - DBUG_RETURN(0); -} -*/ - /* Read one record from NDB using primary key */ From 5b3a52ac14a5e9ce9ce92033b31fa465b3b1cdbe Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 16:41:49 +0200 Subject: [PATCH 103/216] Bump required version of autoconf to 2.58 configure.in: Bump required version of autoconf to 2.58(same as in 4.1 and as in the manual) --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 9e294a35223..a37963911b9 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ dnl -*- ksh -*- dnl Process this file with autoconf to produce a configure script. -AC_PREREQ(2.50)dnl Minimum Autoconf version required. +AC_PREREQ(2.58)dnl Minimum Autoconf version required. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM From f9469777913ff48a1ea7157e7dcac27db99ca5fb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 29 Jun 2005 20:52:22 +0300 Subject: [PATCH 104/216] ha_innodb.cc: Let InnoDB use a consistent read when it initializes the auto-inc counter for a table: this will eliminate spurious deadlocks, but will ignore an UPDATE if that happens at the same time that we init the auto-inc counter; this has to be documented; this path also fixes most of Bug #11633, but not all: if ::external_lock() is not called on the table in SHOW TABLE STATUS, that might cause a crash if someone simultaneously DROPs the table sql/ha_innodb.cc: Let InnoDB use a consistent read when it initializes the auto-inc counter for a table: this will eliminate spurious deadlocks, but will ignore an UPDATE if that happens at the same time that we init the auto-inc counter; this has to be documented; this path also fixes most of Bug #11633, but not all: if ::external_lock() is not called on the table in SHOW TABLE STATUS, that might cause a crash if someone simultaneously DROPs the table --- sql/ha_innodb.cc | 73 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index db354066849..f4c53f2b3da 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1496,8 +1496,8 @@ innobase_start_trx_and_assign_read_view( /********************************************************************* Commits a transaction in an InnoDB database or marks an SQL statement ended. */ - -static int +static +int innobase_commit( /*============*/ /* out: 0 */ @@ -5991,6 +5991,7 @@ ha_innobase::external_lock( reads. */ prebuilt->select_lock_type = LOCK_S; + prebuilt->stored_select_lock_type = LOCK_S; } /* Starting from 4.1.9, no InnoDB table lock is taken in LOCK @@ -6030,7 +6031,6 @@ ha_innobase::external_lock( trx->n_mysql_tables_in_use--; prebuilt->mysql_has_locked = FALSE; - /* If the MySQL lock count drops to zero we know that the current SQL statement has ended */ @@ -6563,12 +6563,14 @@ the value of the auto-inc counter. */ int ha_innobase::innobase_read_and_init_auto_inc( /*=========================================*/ - /* out: 0 or error code: deadlock or - lock wait timeout */ + /* out: 0 or error code: deadlock or lock wait + timeout */ longlong* ret) /* out: auto-inc value */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; longlong auto_inc; + ulint old_select_lock_type; + ibool trx_was_not_started = FALSE; int error; ut_a(prebuilt); @@ -6576,6 +6578,10 @@ ha_innobase::innobase_read_and_init_auto_inc( (trx_t*) current_thd->ha_data[innobase_hton.slot]); ut_a(prebuilt->table); + if (prebuilt->trx->conc_state == TRX_NOT_STARTED) { + trx_was_not_started = TRUE; + } + /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads */ @@ -6587,7 +6593,9 @@ ha_innobase::innobase_read_and_init_auto_inc( /* Already initialized */ *ret = auto_inc; - return(0); + error = 0; + + goto func_exit_early; } error = row_lock_table_autoinc_for_mysql(prebuilt); @@ -6595,7 +6603,7 @@ ha_innobase::innobase_read_and_init_auto_inc( if (error != DB_SUCCESS) { error = convert_error_code_to_mysql(error, user_thd); - goto func_exit; + goto func_exit_early; } /* Check again if someone has initialized the counter meanwhile */ @@ -6604,30 +6612,37 @@ ha_innobase::innobase_read_and_init_auto_inc( if (auto_inc != 0) { *ret = auto_inc; - return(0); + error = 0; + + goto func_exit_early; } (void) extra(HA_EXTRA_KEYREAD); index_init(table->s->next_number_index); - /* We use an exclusive lock when we read the max key value from the - auto-increment column index. This is because then build_template will - advise InnoDB to fetch all columns. In SHOW TABLE STATUS the query - id of the auto-increment column is not changed, and previously InnoDB - did not fetch it, causing SHOW TABLE STATUS to show wrong values - for the autoinc column. */ + /* Starting from 5.0.9, we use a consistent read to read the auto-inc + column maximum value. This eliminates the spurious deadlocks caused + by the row X-lock that we previously used. Note the following flaw + in our algorithm: if some other user meanwhile UPDATEs the auto-inc + column, our consistent read will not return the largest value. We + accept this flaw, since the deadlocks were a bigger trouble. */ - prebuilt->select_lock_type = LOCK_X; - - /* Play safe and also give in another way the hint to fetch - all columns in the key: */ + /* Fetch all the columns in the key */ prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS; - prebuilt->trx->mysql_n_tables_locked += 1; - + old_select_lock_type = prebuilt->select_lock_type; + prebuilt->select_lock_type = LOCK_NONE; + + /* Eliminate an InnoDB error print that happens when we try to SELECT + from a table when no table has been locked in ::external_lock(). */ + prebuilt->trx->n_mysql_tables_in_use++; + error = index_last(table->record[1]); + prebuilt->trx->n_mysql_tables_in_use--; + prebuilt->select_lock_type = old_select_lock_type; + if (error) { if (error == HA_ERR_END_OF_FILE) { /* The table was empty, initialize to 1 */ @@ -6635,7 +6650,10 @@ ha_innobase::innobase_read_and_init_auto_inc( error = 0; } else { - /* Deadlock or a lock wait timeout */ + /* This should not happen in a consistent read */ + fprintf(stderr, +"InnoDB: Error: consistent read of auto-inc column returned %lu\n", + (ulong)error); auto_inc = -1; goto func_exit; @@ -6655,7 +6673,18 @@ func_exit: *ret = auto_inc; - return(error); +func_exit_early: + /* Since MySQL does not seem to call autocommit after SHOW TABLE + STATUS (even if we would register the trx here), we must commit our + transaction here if it was started here. This is to eliminate a + dangling transaction. */ + + if (trx_was_not_started) { + + innobase_commit_low(prebuilt->trx); + } + + return(error); } /*********************************************************************** From 384a0c0a0f7391b3e243f6811acd19acd6e2d006 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 11:15:06 +0300 Subject: [PATCH 105/216] InnoDB: Optimize page_cur_search_with_match(). innobase/btr/btr0cur.c: Disable the mode PAGE_CUR_LE_OR_EXTENDS at compile-time innobase/include/page0cur.h: Disable the mode PAGE_CUR_LE_OR_EXTENDS at compile-time Do not define PAGE_CUR_DBG unless #ifdef UNIV_SEARCH_DEBUG innobase/page/page0cur.c: Disable the mode PAGE_CUR_LE_OR_EXTENDS at compile-time Disable PAGE_CUR_DBG unless #ifdef UNIV_SEARCH_DEBUG page_cur_try_search_shortcut(): Optimize the predicates (compare the result of page_cmp_dtuple_rec_with_match() against 0, use page_rec_is_supremum()). page_cur_search_with_match(): Compare the result of cmp_dtuple_rec_with_match() against zero, add UNIV_LIKELY hints, replace duplicated code with gotos. --- innobase/btr/btr0cur.c | 8 ++- innobase/include/page0cur.h | 6 ++- innobase/page/page0cur.c | 100 ++++++++++++++++++++---------------- 3 files changed, 66 insertions(+), 48 deletions(-) diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index 30e85e021bc..d76b139c3c8 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -316,7 +316,9 @@ btr_cur_search_to_nth_level( if (btr_search_latch.writer == RW_LOCK_NOT_LOCKED && latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ && !estimate +#ifdef PAGE_CUR_LE_OR_EXTENDS && mode != PAGE_CUR_LE_OR_EXTENDS +#endif /* PAGE_CUR_LE_OR_EXTENDS */ && srv_use_adaptive_hash_indexes && btr_search_guess_on_hash(index, info, tuple, mode, latch_mode, cursor, @@ -391,8 +393,10 @@ btr_cur_search_to_nth_level( break; default: ut_ad(mode == PAGE_CUR_L - || mode == PAGE_CUR_LE - || mode == PAGE_CUR_LE_OR_EXTENDS); +#ifdef PAGE_CUR_LE_OR_EXTENDS + || mode == PAGE_CUR_LE_OR_EXTENDS +#endif /* PAGE_CUR_LE_OR_EXTENDS */ + || mode == PAGE_CUR_LE); page_mode = mode; break; } diff --git a/innobase/include/page0cur.h b/innobase/include/page0cur.h index e89e740e775..b03302b0e77 100644 --- a/innobase/include/page0cur.h +++ b/innobase/include/page0cur.h @@ -26,11 +26,13 @@ Created 10/4/1994 Heikki Tuuri #define PAGE_CUR_GE 2 #define PAGE_CUR_L 3 #define PAGE_CUR_LE 4 -#define PAGE_CUR_LE_OR_EXTENDS 5 /* This is a search mode used in +/*#define PAGE_CUR_LE_OR_EXTENDS 5*/ /* This is a search mode used in "column LIKE 'abc%' ORDER BY column DESC"; we have to find strings which are <= 'abc' or which extend it */ -#define PAGE_CUR_DBG 6 +#ifdef UNIV_SEARCH_DEBUG +# define PAGE_CUR_DBG 6 /* As PAGE_CUR_LE, but skips search shortcut */ +#endif /* UNIV_SEARCH_DEBUG */ #ifdef PAGE_CUR_ADAPT # ifdef UNIV_SEARCH_PERF_STAT diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c index df6d898d4ac..562ef545e41 100644 --- a/innobase/page/page0cur.c +++ b/innobase/page/page0cur.c @@ -47,7 +47,6 @@ page_cur_try_search_shortcut( not yet completely matched */ page_cur_t* cursor) /* out: page cursor */ { - int cmp; rec_t* rec; rec_t* next_rec; ulint low_match; @@ -79,9 +78,8 @@ page_cur_try_search_shortcut( up_match = low_match; up_bytes = low_bytes; - cmp = page_cmp_dtuple_rec_with_match(tuple, rec, offsets, &low_match, - &low_bytes); - if (cmp == -1) { + if (page_cmp_dtuple_rec_with_match(tuple, rec, offsets, + &low_match, &low_bytes) < 0) { goto exit_func; } @@ -89,9 +87,8 @@ page_cur_try_search_shortcut( offsets = rec_get_offsets(next_rec, index, offsets, dtuple_get_n_fields(tuple), &heap); - cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec, offsets, - &up_match, &up_bytes); - if (cmp != -1) { + if (page_cmp_dtuple_rec_with_match(tuple, next_rec, offsets, + &up_match, &up_bytes) >= 0) { goto exit_func; } @@ -115,7 +112,7 @@ page_cur_try_search_shortcut( ut_a(*ilow_matched_fields == low_match); ut_a(*ilow_matched_bytes == low_bytes); #endif - if (next_rec != page_get_supremum_rec(page)) { + if (!page_rec_is_supremum(next_rec)) { *iup_matched_fields = up_match; *iup_matched_bytes = up_bytes; @@ -137,6 +134,7 @@ exit_func: #endif +#ifdef PAGE_CUR_LE_OR_EXTENDS /******************************************************************** Checks if the nth field in a record is a character type field which extends the nth field in tuple, i.e., the field is longer or equal in length and has @@ -185,6 +183,7 @@ page_cur_rec_field_extends( return(FALSE); } +#endif /* PAGE_CUR_LE_OR_EXTENDS */ /******************************************************************** Searches the right position for a page cursor. */ @@ -240,9 +239,14 @@ page_cur_search_with_match( ut_ad(dtuple_validate(tuple)); ut_ad(dtuple_check_typed(tuple)); ut_ad((mode == PAGE_CUR_L) || (mode == PAGE_CUR_LE) - || (mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE) - || (mode == PAGE_CUR_LE_OR_EXTENDS) || (mode == PAGE_CUR_DBG)); - +#ifdef PAGE_CUR_DBG + || (mode == PAGE_CUR_DBG) +#endif /* PAGE_CUR_DBG */ +#ifdef PAGE_CUR_LE_OR_EXTENDS + || (mode == PAGE_CUR_LE_OR_EXTENDS) +#endif /* PAGE_CUR_LE_OR_EXTENDS */ + || (mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)); + page_check_dir(page); #ifdef PAGE_CUR_ADAPT @@ -261,16 +265,18 @@ page_cur_search_with_match( return; } } -/*#ifdef UNIV_SEARCH_DEBUG */ +# ifdef PAGE_CUR_DBG if (mode == PAGE_CUR_DBG) { mode = PAGE_CUR_LE; } -/*#endif */ +# endif #endif /* The following flag does not work for non-latin1 char sets because cmp_full_field does not tell how many bytes matched */ +#ifdef PAGE_CUR_LE_OR_EXTENDS ut_a(mode != PAGE_CUR_LE_OR_EXTENDS); +#endif /* PAGE_CUR_LE_OR_EXTENDS */ /* If mode PAGE_CUR_G is specified, we are trying to position the cursor to answer a query of the form "tuple < X", where tuple is @@ -308,33 +314,36 @@ page_cur_search_with_match( cmp = cmp_dtuple_rec_with_match(tuple, mid_rec, offsets, &cur_matched_fields, &cur_matched_bytes); - if (cmp == 1) { + if (UNIV_LIKELY(cmp > 0)) { +low_slot_match: low = mid; low_matched_fields = cur_matched_fields; low_matched_bytes = cur_matched_bytes; - } else if (cmp == -1) { + } else if (UNIV_LIKELY(cmp /* == -1 */)) { +#ifdef PAGE_CUR_LE_OR_EXTENDS if (mode == PAGE_CUR_LE_OR_EXTENDS && page_cur_rec_field_extends(tuple, mid_rec, offsets, cur_matched_fields)) { - low = mid; - low_matched_fields = cur_matched_fields; - low_matched_bytes = cur_matched_bytes; - } else { - up = mid; - up_matched_fields = cur_matched_fields; - up_matched_bytes = cur_matched_bytes; - } - } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE - || mode == PAGE_CUR_LE_OR_EXTENDS) { - low = mid; - low_matched_fields = cur_matched_fields; - low_matched_bytes = cur_matched_bytes; - } else { + goto low_slot_match; + } +#endif /* PAGE_CUR_LE_OR_EXTENDS */ +up_slot_match: up = mid; up_matched_fields = cur_matched_fields; up_matched_bytes = cur_matched_bytes; + + } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE +#ifdef PAGE_CUR_LE_OR_EXTENDS + || mode == PAGE_CUR_LE_OR_EXTENDS +#endif /* PAGE_CUR_LE_OR_EXTENDS */ + ) { + + goto low_slot_match; + } else { + + goto up_slot_match; } } @@ -360,32 +369,35 @@ page_cur_search_with_match( cmp = cmp_dtuple_rec_with_match(tuple, mid_rec, offsets, &cur_matched_fields, &cur_matched_bytes); - if (cmp == 1) { + if (UNIV_LIKELY(cmp > 0)) { +low_rec_match: low_rec = mid_rec; low_matched_fields = cur_matched_fields; low_matched_bytes = cur_matched_bytes; - } else if (cmp == -1) { + } else if (UNIV_LIKELY(cmp /* == -1 */)) { +#ifdef PAGE_CUR_LE_OR_EXTENDS if (mode == PAGE_CUR_LE_OR_EXTENDS && page_cur_rec_field_extends(tuple, mid_rec, offsets, cur_matched_fields)) { - low_rec = mid_rec; - low_matched_fields = cur_matched_fields; - low_matched_bytes = cur_matched_bytes; - } else { - up_rec = mid_rec; - up_matched_fields = cur_matched_fields; - up_matched_bytes = cur_matched_bytes; + + goto low_rec_match; } - } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE - || mode == PAGE_CUR_LE_OR_EXTENDS) { - low_rec = mid_rec; - low_matched_fields = cur_matched_fields; - low_matched_bytes = cur_matched_bytes; - } else { +#endif /* PAGE_CUR_LE_OR_EXTENDS */ +up_rec_match: up_rec = mid_rec; up_matched_fields = cur_matched_fields; up_matched_bytes = cur_matched_bytes; + } else if (mode == PAGE_CUR_G || mode == PAGE_CUR_LE +#ifdef PAGE_CUR_LE_OR_EXTENDS + || mode == PAGE_CUR_LE_OR_EXTENDS +#endif /* PAGE_CUR_LE_OR_EXTENDS */ + ) { + + goto low_rec_match; + } else { + + goto up_rec_match; } } From 9996c3d8f1ec01198afb54c8fbf852f5d8ed2d05 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 13:38:29 +0500 Subject: [PATCH 106/216] a fix. bug #10617: Insert from same table to same table give incorrect result for bit(4) column. bug #11091: union involving BIT: assertion failure in Item::tmp_table_field_from_field_type bug #11572: MYSQL_TYPE_BIT not taken care of in temp. table creation for VIEWs mysql-test/r/type_bit.result: test case. bug #10617: Insert from same table to same table give incorrect result for bit(4) column. bug #11091: union involving BIT: assertion failure in Item::tmp_table_field_from_field_type bug #11572: MYSQL_TYPE_BIT not taken care of in temp. table creation for VIEWs mysql-test/t/type_bit.test: test case. bug #10617: Insert from same table to same table give incorrect result for bit(4) column. bug #11091: union involving BIT: assertion failure in Item::tmp_table_field_from_field_type bug #11572: MYSQL_TYPE_BIT not taken care of in temp. table creation for VIEWs sql/field.h: a fix. bug #10617: Insert from same table to same table give incorrect result for bit(4) column. bug #11091: union involving BIT: assertion failure in Item::tmp_table_field_from_field_type bug #11572: MYSQL_TYPE_BIT not taken care of in temp. table creation for VIEWs - max_length() returns length in bits. - introduced set_bit_ptr() function, which sets bit_ptr and bit_ofs. sql/item.cc: a fix. bug #10617: Insert from same table to same table give incorrect result for bit(4) column. bug #11091: union involving BIT: assertion failure in Item::tmp_table_field_from_field_type bug #11572: MYSQL_TYPE_BIT not taken care of in temp. table creation for VIEWs - create Field_bit_as_char in case of MYSQL_TYPE_BIT in the Item::tmp_table_field_from_field_type() (we cannot create Field_bit here because of lack of information: bit_ptr, bit_ofs) sql/mysql_priv.h: a fix. bug #10617: Insert from same table to same table give incorrect result for bit(4) column. bug #11091: union involving BIT: assertion failure in Item::tmp_table_field_from_field_type bug #11572: MYSQL_TYPE_BIT not taken care of in temp. table creation for VIEWs - table_cant_handle_bit_fields parameter added to the create_tmp_field() sql/sql_select.cc: a fix. bug #10617: Insert from same table to same table give incorrect result for bit(4) column. bug #11091: union involving BIT: assertion failure in Item::tmp_table_field_from_field_type bug #11572: MYSQL_TYPE_BIT not taken care of in temp. table creation for VIEWs - create_tmp_field() changes to return create_tmp_field_from_item() result (actually, Field_bit_as_char) if table_cant_handle_bit_fields=1 for bit fields. - create_tmp_field() calls accordingly changed - call set_bit_ptr() for bit fields after the move_field() call during temporary table creation. sql/sql_table.cc: a fix. bug #10617: Insert from same table to same table give incorrect result for bit(4) column. bug #11091: union involving BIT: assertion failure in Item::tmp_table_field_from_field_type bug #11572: MYSQL_TYPE_BIT not taken care of in temp. table creation for VIEWs - changed the create_tmp_field() call --- mysql-test/r/type_bit.result | 87 ++++++++++++++++++++++++++++++++++++ mysql-test/t/type_bit.test | 53 ++++++++++++++++++++++ sql/field.h | 8 +++- sql/item.cc | 3 ++ sql/mysql_priv.h | 1 + sql/sql_select.cc | 17 ++++++- sql/sql_table.cc | 2 +- 7 files changed, 167 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result index 4d9bc0c7fe1..4aa8587d6e1 100644 --- a/mysql-test/r/type_bit.result +++ b/mysql-test/r/type_bit.result @@ -466,3 +466,90 @@ select a+0 from t1; a+0 255 drop table t1; +create table t1 (a bit(7)); +insert into t1 values (120), (0), (111); +select a+0 from t1 union select a+0 from t1; +a+0 +120 +0 +111 +select a+0 from t1 union select NULL; +a+0 +120 +0 +111 +NULL +select NULL union select a+0 from t1; +NULL +NULL +120 +0 +111 +create table t2 select a from t1 union select a from t1; +select a+0 from t2; +a+0 +120 +0 +111 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` bit(7) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1, t2; +create table t1 (id1 int(11), b1 bit(1)); +create table t2 (id2 int(11), b2 bit(1)); +insert into t1 values (1, 1), (2, 0), (3, 1); +insert into t2 values (2, 1), (3, 0), (4, 0); +create algorithm=undefined view v1 as +select b1+0, b2+0 from t1, t2 where id1 = id2 and b1 = 0 +union +select b1+0, b2+0 from t1, t2 where id1 = id2 and b2 = 1; +select * from v1; +b1+0 b2+0 +0 1 +drop table t1, t2; +drop view v1; +create table t1(a bit(4)); +insert into t1(a) values (1), (2), (5), (4), (3); +insert into t1 select * from t1; +select a+0 from t1; +a+0 +1 +2 +5 +4 +3 +1 +2 +5 +4 +3 +drop table t1; +create table t1 (a1 int(11), b1 bit(2)); +create table t2 (a2 int(11), b2 bit(2)); +insert into t1 values (1, 1), (2, 0), (3, 1), (4, 2); +insert into t2 values (2, 1), (3, 0), (4, 1), (5, 2); +select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2; +a1 a2 b1+0 b2+0 +2 2 0 1 +3 3 1 0 +4 4 2 1 +select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2 order by a1; +a1 a2 b1+0 b2+0 +2 2 0 1 +3 3 1 0 +4 4 2 1 +select a1, a2, b1+0, b2+0 from t1 join t2 on b1 = b2; +a1 a2 b1+0 b2+0 +1 2 1 1 +3 2 1 1 +2 3 0 0 +1 4 1 1 +3 4 1 1 +4 5 2 2 +select sum(a1), b1+0, b2+0 from t1 join t2 on b1 = b2 group by b1 order by 1; +sum(a1) b1+0 b2+0 +2 0 0 +4 2 2 +8 1 1 diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test index 2df5f0ed05d..fd5eb49858c 100644 --- a/mysql-test/t/type_bit.test +++ b/mysql-test/t/type_bit.test @@ -171,3 +171,56 @@ create table t1 (a bit(8)) engine=heap; insert into t1 values ('1111100000'); select a+0 from t1; drop table t1; + +# +# Bug #11091: union +# + +create table t1 (a bit(7)); +insert into t1 values (120), (0), (111); +select a+0 from t1 union select a+0 from t1; +select a+0 from t1 union select NULL; +select NULL union select a+0 from t1; +create table t2 select a from t1 union select a from t1; +select a+0 from t2; +show create table t2; +drop table t1, t2; + +# +# Bug #11572: view +# + +create table t1 (id1 int(11), b1 bit(1)); +create table t2 (id2 int(11), b2 bit(1)); +insert into t1 values (1, 1), (2, 0), (3, 1); +insert into t2 values (2, 1), (3, 0), (4, 0); +create algorithm=undefined view v1 as + select b1+0, b2+0 from t1, t2 where id1 = id2 and b1 = 0 + union + select b1+0, b2+0 from t1, t2 where id1 = id2 and b2 = 1; +select * from v1; +drop table t1, t2; +drop view v1; + +# +# Bug #10617: bulk-insert +# + +create table t1(a bit(4)); +insert into t1(a) values (1), (2), (5), (4), (3); +insert into t1 select * from t1; +select a+0 from t1; +drop table t1; + +# +# join +# + +create table t1 (a1 int(11), b1 bit(2)); +create table t2 (a2 int(11), b2 bit(2)); +insert into t1 values (1, 1), (2, 0), (3, 1), (4, 2); +insert into t2 values (2, 1), (3, 0), (4, 1), (5, 2); +select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2; +select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2 order by a1; +select a1, a2, b1+0, b2+0 from t1 join t2 on b1 = b2; +select sum(a1), b1+0, b2+0 from t1 join t2 on b1 = b2 group by b1 order by 1; diff --git a/sql/field.h b/sql/field.h index ebf48568c04..2b1229744c2 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1288,7 +1288,7 @@ public: enum_field_types type() const { return FIELD_TYPE_BIT; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; } uint32 key_length() const { return (uint32) field_length + (bit_len > 0); } - uint32 max_length() { return (uint32) field_length + (bit_len > 0); } + uint32 max_length() { return (uint32) field_length * 8 + bit_len; } uint size_of() const { return sizeof(*this); } Item_result result_type () const { return INT_RESULT; } void reset(void) { bzero(ptr, field_length); } @@ -1320,6 +1320,11 @@ public: Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, char *new_ptr, uchar *new_null_ptr, uint new_null_bit); + void set_bit_ptr(uchar *bit_ptr_arg, uchar bit_ofs_arg) + { + bit_ptr= bit_ptr_arg; + bit_ofs= bit_ofs_arg; + } }; @@ -1331,6 +1336,7 @@ public: enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg); enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } + uint32 max_length() { return (uint32) create_length; } uint size_of() const { return sizeof(*this); } int store(const char *to, uint length, CHARSET_INFO *charset); int store(double nr) { return Field_bit::store(nr); } diff --git a/sql/item.cc b/sql/item.cc index 82edc05c721..b6f8b7ebc51 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3347,6 +3347,9 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table) case MYSQL_TYPE_YEAR: return new Field_year((char*) 0, max_length, null_ptr, 0, Field::NONE, name, table); + case MYSQL_TYPE_BIT: + return new Field_bit_as_char(NULL, max_length, null_ptr, 0, NULL, 0, + Field::NONE, name, table); default: /* This case should never be chosen */ DBUG_ASSERT(0); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 2add9ac9269..805af08b76a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -667,6 +667,7 @@ int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t); Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item ***copy_func, Field **from_field, bool group, bool modify_item, + bool table_cant_handle_bit_fields, uint convert_blob_length); void sp_prepare_create_field(THD *thd, create_field *sql_field); int prepare_create_field(create_field *sql_field, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 13c5c7cd716..cf8d7b1b83c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7957,7 +7957,9 @@ Field *create_tmp_field_for_schema(THD *thd, Item *item, TABLE *table) Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item ***copy_func, Field **from_field, - bool group, bool modify_item, uint convert_blob_length) + bool group, bool modify_item, + bool table_cant_handle_bit_fields, + uint convert_blob_length) { switch (type) { case Item::SUM_FUNC_ITEM: @@ -7972,6 +7974,9 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, case Item::DEFAULT_VALUE_ITEM: { Item_field *field= (Item_field*) item; + if (table_cant_handle_bit_fields && field->field->type() == FIELD_TYPE_BIT) + return create_tmp_field_from_item(thd, item, table, copy_func, + modify_item, convert_blob_length); return create_tmp_field_from_field(thd, (*from_field= field->field), item->name, table, modify_item ? (Item_field*) item : NULL, @@ -8192,6 +8197,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, Field *new_field= create_tmp_field(thd, table, arg, arg->type(), ©_func, tmp_from_field, group != 0,not_all_columns, + group || distinct, param->convert_blob_length); if (!new_field) goto err; // Should be OOM @@ -8239,7 +8245,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, create_tmp_field_for_schema(thd, item, table) : create_tmp_field(thd, table, item, type, ©_func, tmp_from_field, group != 0, - not_all_columns || group !=0, + not_all_columns || group != 0, 0, param->convert_blob_length); if (!new_field) @@ -8377,6 +8383,13 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, } else field->move_field((char*) pos,(uchar*) 0,0); + if (field->type() == FIELD_TYPE_BIT) + { + /* We have to reserve place for extra bits among null bits */ + ((Field_bit*) field)->set_bit_ptr(null_flags + null_count / 8, + null_count & 7); + null_count+= (field->field_length & 7); + } field->reset(); if (from_field[i]) { /* Not a table Item */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e03a6c24d42..553a853bede 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1734,7 +1734,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, field=item->tmp_table_field(&tmp_table); else field=create_tmp_field(thd, &tmp_table, item, item->type(), - (Item ***) 0, &tmp_field,0,0,0); + (Item ***) 0, &tmp_field, 0, 0, 0, 0); if (!field || !(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ? ((Item_field *)item)->field : From 85036af7edc44167fdb8ed73136089440af42cf9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 13:20:38 +0300 Subject: [PATCH 107/216] InnoDB: Fix a bug in BLOB handling; optimize null flag handling. innobase/rem/rem0rec.c: rec_set_nth_field_extern_bit_new(): Fix a bug (read the "extern" flag from the correct position). rec_set_nth_field_extern_bit_new(), rec_convert_dtuple_to_rec_new(), rec_copy_prefix_to_buf(): Eliminate variables, reduce branching, optimize the handling of the null flags. --- innobase/rem/rem0rec.c | 107 ++++++++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 39 deletions(-) diff --git a/innobase/rem/rem0rec.c b/innobase/rem/rem0rec.c index 580a7bfe509..fbc33aea669 100644 --- a/innobase/rem/rem0rec.c +++ b/innobase/rem/rem0rec.c @@ -601,30 +601,38 @@ rec_set_nth_field_extern_bit_new( /* read the lengths of fields 0..n */ for (i = 0; i < n_fields; i++) { - ibool is_null; - ulint len; field = dict_index_get_nth_field(index, i); type = dict_col_get_type(dict_field_get_col(field)); - is_null = !(dtype_get_prtype(type) & DATA_NOT_NULL); - if (is_null) { - /* nullable field => read the null flag */ - is_null = !!(*nulls & null_mask); + if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) { + if (UNIV_UNLIKELY(!(byte) null_mask)) { + nulls--; + null_mask = 1; + } + + if (*nulls & null_mask) { + null_mask <<= 1; + /* NULL fields cannot be external. */ + ut_ad(i != ith); + continue; + } + null_mask <<= 1; - if (null_mask == 0x100) - nulls--, null_mask = 1; } - if (is_null || field->fixed_len) { - /* No length (or extern bit) is stored for - fields that are NULL or fixed-length. */ + if (field->fixed_len) { + /* fixed-length fields cannot be external + (Fixed-length fields longer than + DICT_MAX_COL_PREFIX_LEN will be treated as + variable-length ones in dict_index_add_col().) */ ut_ad(i != ith); continue; } - len = *lens--; + lens--; if (dtype_get_len(type) > 255 || dtype_get_mtype(type) == DATA_BLOB) { + ulint len = lens[1]; if (len & 0x80) { /* 1exxxxxx: 2-byte length */ if (i == ith) { - if (!val == !(len & 0x20)) { + if (!val == !(len & 0x40)) { return; /* no change */ } /* toggle the extern bit */ @@ -823,6 +831,7 @@ rec_convert_dtuple_to_rec_new( byte* lens; ulint len; ulint i; + ulint n_node_ptr_field; ulint fixed_len; ulint null_mask = 1; const ulint n_fields = dtuple_get_n_fields(dtuple); @@ -831,16 +840,26 @@ rec_convert_dtuple_to_rec_new( ut_ad(index->table->comp); ut_ad(n_fields > 0); - switch (status) { + + /* Try to ensure that the memset() between the for() loops + completes fast. The address is not exact, but UNIV_PREFETCH + should never generate a memory fault. */ + UNIV_PREFETCH_RW(rec - REC_N_NEW_EXTRA_BYTES - n_fields); + UNIV_PREFETCH_RW(rec); + + switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) { case REC_STATUS_ORDINARY: ut_ad(n_fields <= dict_index_get_n_fields(index)); + n_node_ptr_field = ULINT_UNDEFINED; break; case REC_STATUS_NODE_PTR: ut_ad(n_fields == dict_index_get_n_unique_in_tree(index) + 1); + n_node_ptr_field = n_fields - 1; break; case REC_STATUS_INFIMUM: case REC_STATUS_SUPREMUM: ut_ad(n_fields == 1); + n_node_ptr_field = ULINT_UNDEFINED; goto init; default: ut_a(0); @@ -852,15 +871,18 @@ rec_convert_dtuple_to_rec_new( rec += (index->n_nullable + 7) / 8; for (i = 0; i < n_fields; i++) { + if (UNIV_UNLIKELY(i == n_node_ptr_field)) { +#ifdef UNIV_DEBUG + field = dtuple_get_nth_field(dtuple, i); + type = dfield_get_type(field); + ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL); + ut_ad(dfield_get_len(field) == 4); +#endif /* UNIV_DEBUG */ + goto init; + } field = dtuple_get_nth_field(dtuple, i); type = dfield_get_type(field); len = dfield_get_len(field); - if (status == REC_STATUS_NODE_PTR && i == n_fields - 1) { - fixed_len = 4; - ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL); - ut_ad(len == 4); - continue; - } fixed_len = dict_index_get_nth_field(index, i)->fixed_len; if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) { @@ -902,27 +924,33 @@ init: type = dfield_get_type(field); len = dfield_get_len(field); - if (status == REC_STATUS_NODE_PTR && i == n_fields - 1) { - fixed_len = 4; + if (UNIV_UNLIKELY(i == n_node_ptr_field)) { ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL); ut_ad(len == 4); - goto copy; + memcpy(end, dfield_get_data(field), len); + break; } fixed_len = dict_index_get_nth_field(index, i)->fixed_len; if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) { /* nullable field */ ut_ad(index->n_nullable > 0); + + if (UNIV_UNLIKELY(!(byte) null_mask)) { + nulls--; + null_mask = 1; + } + ut_ad(*nulls < null_mask); + /* set the null flag if necessary */ if (len == UNIV_SQL_NULL) { *nulls |= null_mask; - } - null_mask <<= 1; - if (null_mask == 0x100) - nulls--, null_mask = 1; - if (len == UNIV_SQL_NULL) + null_mask <<= 1; continue; + } + + null_mask <<= 1; } /* only nullable fields can be null */ ut_ad(len != UNIV_SQL_NULL); @@ -942,7 +970,7 @@ init: *lens-- = (byte) len; } } - copy: + memcpy(end, dfield_get_data(field), len); end += len; } @@ -1105,7 +1133,6 @@ rec_copy_prefix_to_buf( dtype_t* type; ulint i; ulint prefix_len; - ibool is_null; ulint null_mask; ulint status; @@ -1146,20 +1173,22 @@ rec_copy_prefix_to_buf( for (i = 0; i < n_fields; i++) { field = dict_index_get_nth_field(index, i); type = dict_col_get_type(dict_field_get_col(field)); - is_null = !(dtype_get_prtype(type) & DATA_NOT_NULL); - if (is_null) { + if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) { /* nullable field => read the null flag */ - is_null = !!(*nulls & null_mask); - null_mask <<= 1; - if (null_mask == 0x100) { - --nulls; - UNIV_PREFETCH_R(nulls); + if (UNIV_UNLIKELY(!(byte) null_mask)) { + nulls--; null_mask = 1; } + + if (*nulls & null_mask) { + null_mask <<= 1; + continue; + } + + null_mask <<= 1; } - if (is_null) { - } else if (field->fixed_len) { + if (field->fixed_len) { prefix_len += field->fixed_len; } else { ulint len = *lens--; From ec9ac3fe5c823b6ae7ccb0902c267b811bf732e7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 16:17:10 +0400 Subject: [PATCH 108/216] A fix and a test case for Bug#10794 "mysql_stmt_attr_set no open cursor after mysql_stmt_execute" + post-review fixes. The bug was caused by wrong flags in stmt->server_status on the client side: if there was no cursor, the server didn't send server_status flags to the client, and the old flags were used to set up the fetch function of a statement. Consequently, stmt_read_row_from_cursor was used when there was no cursor. The fix fixes the server to always send server flags to the client. include/mysql_com.h: Update stale comments. libmysql/libmysql.c: Remove an extra assignment. libmysqld/lib_sql.cc: Update to correspond to the changed signature of send_eof sql/protocol.cc: Actual fix for bug#10794: create a function that writes the eof packet to network and use it from send_fields. We need to send a full eof packet from send_fields to inform the client about the cursor status (that there is no cursor in this case). sql/protocol.h: Remove an unused parameter for send_eof. tests/mysql_client_test.c: A test case for Bug#10794 "mysql_stmt_attr_set no open cursor after mysql_stmt_execute" --- include/mysql_com.h | 10 ++--- libmysql/libmysql.c | 1 - libmysqld/lib_sql.cc | 2 +- sql/protocol.cc | 64 ++++++++++++++++------------ sql/protocol.h | 2 +- tests/mysql_client_test.c | 88 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 132 insertions(+), 35 deletions(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index 2293476c76c..88a614bc4a3 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -137,14 +137,14 @@ enum enum_server_command #define SERVER_QUERY_NO_GOOD_INDEX_USED 16 #define SERVER_QUERY_NO_INDEX_USED 32 /* - The server was able to fulfill client request and open read-only - non-scrollable cursor for the query. This flag comes in server - status with reply to COM_EXECUTE and COM_EXECUTE_DIRECT commands. + The server was able to fulfill the clients request and opened a + read-only non-scrollable cursor for a query. This flag comes + in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands. */ #define SERVER_STATUS_CURSOR_EXISTS 64 /* - This flag is sent with last row of read-only cursor, in reply to - COM_FETCH command. + This flag is sent when a read-only cursor is exhausted, in reply to + COM_STMT_FETCH command. */ #define SERVER_STATUS_LAST_ROW_SENT 128 #define SERVER_STATUS_DB_DROPPED 256 /* A database was dropped */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 8ee11519615..e33fd470582 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2726,7 +2726,6 @@ stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row) set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); return 1; } - stmt->server_status= mysql->server_status; if (cli_read_binary_rows(stmt)) return 1; stmt->server_status= mysql->server_status; diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index dd4ba939ebe..c3b239ac7b9 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -773,7 +773,7 @@ send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message) } void -send_eof(THD *thd, bool no_flush) +send_eof(THD *thd) { } diff --git a/sql/protocol.cc b/sql/protocol.cc index 1c399a89a99..ade94a483a8 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -28,6 +28,7 @@ #include static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024; +static void write_eof_packet(THD *thd, NET *net); #ifndef EMBEDDED_LIBRARY bool Protocol::net_store_data(const char *from, uint length) @@ -362,43 +363,52 @@ static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */ */ void -send_eof(THD *thd, bool no_flush) +send_eof(THD *thd) { NET *net= &thd->net; DBUG_ENTER("send_eof"); if (net->vio != 0 && !net->no_send_eof) { - if (thd->client_capabilities & CLIENT_PROTOCOL_41) - { - uchar buff[5]; - /* Don't send warn count during SP execution, as the warn_list - is cleared between substatements, and mysqltest gets confused */ - uint tmp= (thd->spcont ? 0 : min(thd->total_warn_count, 65535)); - buff[0]=254; - int2store(buff+1, tmp); - /* - The following test should never be true, but it's better to do it - because if 'is_fatal_error' is set the server is not going to execute - other queries (see the if test in dispatch_command / COM_QUERY) - */ - if (thd->is_fatal_error) - thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; - int2store(buff+3, thd->server_status); - VOID(my_net_write(net,(char*) buff,5)); - VOID(net_flush(net)); - } - else - { - VOID(my_net_write(net,eof_buff,1)); - if (!no_flush) - VOID(net_flush(net)); - } + write_eof_packet(thd, net); + VOID(net_flush(net)); thd->net.no_send_error= 1; DBUG_PRINT("info", ("EOF sent, so no more error sending allowed")); } DBUG_VOID_RETURN; } + +/* + Format EOF packet according to the current protocol and + write it to the network output buffer. +*/ + +static void write_eof_packet(THD *thd, NET *net) +{ + if (thd->client_capabilities & CLIENT_PROTOCOL_41) + { + uchar buff[5]; + /* + Don't send warn count during SP execution, as the warn_list + is cleared between substatements, and mysqltest gets confused + */ + uint tmp= (thd->spcont ? 0 : min(thd->total_warn_count, 65535)); + buff[0]= 254; + int2store(buff+1, tmp); + /* + The following test should never be true, but it's better to do it + because if 'is_fatal_error' is set the server is not going to execute + other queries (see the if test in dispatch_command / COM_QUERY) + */ + if (thd->is_fatal_error) + thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; + int2store(buff+3, thd->server_status); + VOID(my_net_write(net, (char*) buff, 5)); + } + else + VOID(my_net_write(net, eof_buff, 1)); +} + /* Please client to send scrambled_password in old format. SYNOPSYS @@ -640,7 +650,7 @@ bool Protocol::send_fields(List *list, uint flags) } if (flags & SEND_EOF) - my_net_write(&thd->net, eof_buff, 1); + write_eof_packet(thd, &thd->net); DBUG_RETURN(prepare_for_send(list)); err: diff --git a/sql/protocol.h b/sql/protocol.h index 5b402cb2669..2717d2258fa 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -179,7 +179,7 @@ void net_printf_error(THD *thd, uint sql_errno, ...); void net_send_error(THD *thd, uint sql_errno=0, const char *err=0); void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L, const char *info=0); -void send_eof(THD *thd, bool no_flush=0); +void send_eof(THD *thd); bool send_old_password_request(THD *thd); char *net_store_length(char *packet,uint length); char *net_store_data(char *to,const char *from, uint length); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 585763c164d..fa70168d0ef 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13389,6 +13389,93 @@ static void test_bug10736() myquery(rc); } +/* Bug#10794: cursors, packets out of order */ + +static void test_bug10794() +{ + MYSQL_STMT *stmt, *stmt1; + MYSQL_BIND bind[2]; + char a[21]; + int id_val; + ulong a_len; + int rc; + const char *stmt_text; + int i= 0; + ulong type; + + myheader("test_bug10794"); + + mysql_query(mysql, "drop table if exists t1"); + mysql_query(mysql, "create table t1 (id integer not null primary key," + "name varchar(20) not null)"); + stmt= mysql_stmt_init(mysql); + stmt_text= "insert into t1 (id, name) values (?, ?)"; + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + check_execute(stmt, rc); + bzero(bind, sizeof(bind)); + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= (void*) &id_val; + bind[1].buffer_type= MYSQL_TYPE_STRING; + bind[1].buffer= (void*) a; + bind[1].length= &a_len; + rc= mysql_stmt_bind_param(stmt, bind); + check_execute(stmt, rc); + for (i= 0; i < 34; i++) + { + id_val= (i+1)*10; + sprintf(a, "a%d", i); + a_len= strlen(a); /* safety against broken sprintf */ + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + } + stmt_text= "select name from t1"; + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + type= (ulong) CURSOR_TYPE_READ_ONLY; + mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type); + stmt1= mysql_stmt_init(mysql); + mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type); + bzero(bind, sizeof(bind)); + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer= (void*) a; + bind[0].buffer_length= sizeof(a); + bind[0].length= &a_len; + rc= mysql_stmt_bind_result(stmt, bind); + check_execute(stmt, rc); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + if (!opt_silent) + printf("Fetched row from stmt: %s\n", a); + /* Don't optimize: an attribute of the original test case */ + mysql_stmt_free_result(stmt); + mysql_stmt_reset(stmt); + stmt_text= "select name from t1 where id=10"; + rc= mysql_stmt_prepare(stmt1, stmt_text, strlen(stmt_text)); + check_execute(stmt1, rc); + rc= mysql_stmt_bind_result(stmt1, bind); + check_execute(stmt1, rc); + rc= mysql_stmt_execute(stmt1); + while (1) + { + rc= mysql_stmt_fetch(stmt1); + if (rc == MYSQL_NO_DATA) + { + if (!opt_silent) + printf("End of data in stmt1\n"); + break; + } + check_execute(stmt1, rc); + if (!opt_silent) + printf("Fetched row from stmt1: %s\n", a); + } + mysql_stmt_close(stmt); + mysql_stmt_close(stmt1); + + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + /* Read and parse arguments and MySQL options from my.cnf @@ -13626,6 +13713,7 @@ static struct my_tests_st my_tests[]= { { "test_bug11111", test_bug11111 }, { "test_bug9992", test_bug9992 }, { "test_bug10736", test_bug10736 }, + { "test_bug10794", test_bug10794 }, { 0, 0 } }; From 5a13f2a8a61e97453e69d2eeef14e95cf46c327b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 16:13:22 +0300 Subject: [PATCH 109/216] Fixed Bug#11226 and reverted fix for Bug#6993. Using 8 bytes for data pointer does not work at least on all computers. The result may become 0 or negative number. (mysqld, myisamchk) myisam/mi_create.c: Fixed Bug#11226, "Dynamic table >4GB issue". mysql-test/r/variables.result: Restricted myisam_data_pointer_size back to 7. mysql-test/t/variables.test: Restricted myisam_data_pointer_size back to 7. sql/mysqld.cc: Restricted myisam_data_pointer_size back to 7. --- myisam/mi_create.c | 7 +++---- mysql-test/r/variables.result | 4 ++-- mysql-test/t/variables.test | 6 +++++- sql/mysqld.cc | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/myisam/mi_create.c b/myisam/mi_create.c index d363f3d5b67..db614935321 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -194,11 +194,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD)); min_pack_length+=packed; - if (!ci->data_file_length) + if (!ci->data_file_length && ci->max_rows) { - if (ci->max_rows == 0 || pack_reclength == INT_MAX32) - ci->data_file_length= INT_MAX32-1; /* Should be enough */ - else if ((~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength) + if (pack_reclength == INT_MAX32 || + (~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength) ci->data_file_length= ~(ulonglong) 0; else ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 602750d5033..e370202cc9f 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -482,10 +482,10 @@ t1 CREATE TABLE `t1` ( `c3` longtext ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; -SET GLOBAL MYISAM_DATA_POINTER_SIZE= 8; +SET GLOBAL MYISAM_DATA_POINTER_SIZE= 7; SHOW VARIABLES LIKE 'MYISAM_DATA_POINTER_SIZE'; Variable_name Value -myisam_data_pointer_size 8 +myisam_data_pointer_size 7 SET GLOBAL table_cache=-1; SHOW VARIABLES LIKE 'table_cache'; Variable_name Value diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index e45218a9ed7..b8a12323cf9 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -363,9 +363,13 @@ drop table t1; # # Bug #6993: myisam_data_pointer_size +# Wrong bug report, data pointer size must be restricted to 7, +# setting to 8 will not work on all computers, myisamchk and +# the server may see a wrong value, such as 0 or negative number +# if 8 bytes is set. # -SET GLOBAL MYISAM_DATA_POINTER_SIZE= 8; +SET GLOBAL MYISAM_DATA_POINTER_SIZE= 7; SHOW VARIABLES LIKE 'MYISAM_DATA_POINTER_SIZE'; # diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 99c96a69ceb..a757c47366d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5153,7 +5153,7 @@ The minimum value for this variable is 4096.", "Default pointer size to be used for MyISAM tables.", (gptr*) &myisam_data_pointer_size, (gptr*) &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG, - 4, 2, 8, 0, 1, 0}, + 4, 2, 7, 0, 1, 0}, {"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, "Used to help MySQL to decide when to use the slow but safe key cache index create method.", (gptr*) &global_system_variables.myisam_max_extra_sort_file_size, From 0ff72e6019d8f9deec9159db87cf7947142539b3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 17:55:47 +0300 Subject: [PATCH 110/216] Don't allow 8bytes for data file pointers for now. --- myisam/mi_create.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/myisam/mi_create.c b/myisam/mi_create.c index db614935321..890ee61fd7f 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -723,10 +723,13 @@ err: uint mi_get_pointer_length(ulonglong file_length, uint def) { + DBUG_ASSERT(def >= 2 && def <= 7); if (file_length) /* If not default */ { +#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS if (file_length >= (longlong) 1 << 56) def=8; +#endif if (file_length >= (longlong) 1 << 48) def=7; if (file_length >= (longlong) 1 << 40) From 9d5a45c2f3e9f784ef94e9b3a9a5e6611043d908 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 17:33:23 +0200 Subject: [PATCH 111/216] - backport of a compile fix from 4.1 (ChangeSet@1.2260.23.2 2005/05/19 from reggie) "changed dl_name to udf->dl in mysql_create_function" --- sql/sql_udf.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 556e015e111..84156ff4022 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -405,7 +405,7 @@ int mysql_create_function(THD *thd,udf_func *udf) This is done to ensure that only approved dll from the system directories are used (to make this even remotely secure). */ - if (strchr(udf->dl, '/') || IF_WIN(strchr(dl_name, '\\'),0)) + if (strchr(udf->dl, '/') || IF_WIN(strchr(udf->dl, '\\'),0)) { send_error(&thd->net, ER_UDF_NO_PATHS,ER(ER_UDF_NO_PATHS)); DBUG_RETURN(1); From a95bb38a7fd03bc464d901300e2a9ef5710218c0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 18:07:06 +0200 Subject: [PATCH 112/216] Fixed BUG#11529: crash server after use stored procedure Make sure to cleanup the items for a cursor query after each open, otherwise it's done too late, after the run-time mem_root is freed. mysql-test/r/sp.result: New test case for BUG#11529. mysql-test/t/sp.test: New test case for BUG#11529. sql/sp_head.cc: Add a back pointer from a sp_cursor to its cpush instruction, and use it to set the arena and cleanup the items for the cursor's query when opening it. sql/sp_rcontext.cc: Store pointer in sp_cursor to its cpush instruction. sql/sp_rcontext.h: Store pointer in sp_cursor to its cpush instruction. --- mysql-test/r/sp.result | 25 +++++++++++++++++++++++++ mysql-test/t/sp.test | 38 +++++++++++++++++++++++++++++++++++++- sql/sp_head.cc | 14 +++++++++++++- sql/sp_rcontext.cc | 9 +++++---- sql/sp_rcontext.h | 12 ++++++++++-- 5 files changed, 90 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index ed858ba27ee..69ae64475d2 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3224,4 +3224,29 @@ bbbbb 2 ccccc 3 drop procedure bug10136| drop table t3| +drop procedure if exists bug11529| +create procedure bug11529() +begin +declare c cursor for select id, data from t1 where data in (10,13); +open c; +begin +declare vid char(16); +declare vdata int; +declare exit handler for not found begin end; +while true do +fetch c into vid, vdata; +end while; +end; +close c; +end| +insert into t1 values +('Name1', 10), +('Name2', 11), +('Name3', 12), +('Name4', 13), +('Name5', 14)| +call bug11529()| +call bug11529()| +delete from t1| +drop procedure bug11529| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index e7ee4b134ba..314ed58b5a9 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -3911,6 +3911,42 @@ call bug10136()| drop procedure bug10136| drop table t3| +# +# BUG#11529: crash server after use stored procedure +# +--disable_warnings +drop procedure if exists bug11529| +--enable_warnings +create procedure bug11529() +begin + declare c cursor for select id, data from t1 where data in (10,13); + + open c; + begin + declare vid char(16); + declare vdata int; + declare exit handler for not found begin end; + + while true do + fetch c into vid, vdata; + end while; + end; + close c; +end| + +insert into t1 values + ('Name1', 10), + ('Name2', 11), + ('Name3', 12), + ('Name4', 13), + ('Name5', 14)| + +call bug11529()| +call bug11529()| +delete from t1| +drop procedure bug11529| + + # # BUG#NNNN: New bug synopsis # @@ -3921,7 +3957,7 @@ drop table t3| # Add bugs above this line. Use existing tables t1 and t2 when -# practical, or create table t3, t3 etc temporarily (and drop them). +# practical, or create table t3, t4 etc temporarily (and drop them). delimiter ;| drop table t1,t2; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index e4dc64c993d..b586546bcfe 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1935,7 +1935,7 @@ int sp_instr_cpush::execute(THD *thd, uint *nextp) { DBUG_ENTER("sp_instr_cpush::execute"); - thd->spcont->push_cursor(&m_lex_keeper); + thd->spcont->push_cursor(&m_lex_keeper, this); *nextp= m_ip+1; DBUG_RETURN(0); } @@ -1994,7 +1994,19 @@ sp_instr_copen::execute(THD *thd, uint *nextp) } else { + Query_arena *old_arena= thd->current_arena; + + /* + Get the Query_arena from the cpush instruction, which contains + the free_list of the query, so new items (if any) are stored in + the right free_list, and we can cleanup after each open. + */ + thd->current_arena= c->get_instr(); res= lex_keeper->reset_lex_and_exec_core(thd, nextp, FALSE, this); + /* Cleanup the query's items */ + if (thd->current_arena->free_list) + cleanup_items(thd->current_arena->free_list); + thd->current_arena= old_arena; /* Work around the fact that errors in selects are not returned properly (but instead converted into a warning), so if a condition handler diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index aacb9254753..d0817e43790 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -148,9 +148,9 @@ sp_rcontext::restore_variables(uint fp) } void -sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper) +sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i) { - m_cstack[m_ccount++]= new sp_cursor(lex_keeper); + m_cstack[m_ccount++]= new sp_cursor(lex_keeper, i); } void @@ -169,8 +169,9 @@ sp_rcontext::pop_cursors(uint count) * */ -sp_cursor::sp_cursor(sp_lex_keeper *lex_keeper) - :m_lex_keeper(lex_keeper), m_prot(NULL), m_isopen(0), m_current_row(NULL) +sp_cursor::sp_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i) + :m_lex_keeper(lex_keeper), m_prot(NULL), m_isopen(0), m_current_row(NULL), + m_i(i) { /* currsor can't be stored in QC, so we should prevent opening QC for diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index b188805435f..856beb13f6d 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -26,6 +26,7 @@ struct sp_cond_type; class sp_cursor; struct sp_pvar; class sp_lex_keeper; +class sp_instr_cpush; #define SP_HANDLER_NONE 0 #define SP_HANDLER_EXIT 1 @@ -161,7 +162,7 @@ class sp_rcontext : public Sql_alloc restore_variables(uint fp); void - push_cursor(sp_lex_keeper *lex_keeper); + push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i); void pop_cursors(uint count); @@ -203,7 +204,7 @@ class sp_cursor : public Sql_alloc { public: - sp_cursor(sp_lex_keeper *lex_keeper); + sp_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i); virtual ~sp_cursor() { @@ -229,6 +230,12 @@ public: int fetch(THD *, List *vars); + inline sp_instr_cpush * + get_instr() + { + return m_i; + } + private: MEM_ROOT m_mem_root; // My own mem_root @@ -238,6 +245,7 @@ private: my_bool m_nseof; // Original no_send_eof Protocol *m_oprot; // Original protcol MYSQL_ROWS *m_current_row; + sp_instr_cpush *m_i; // My push instruction void destroy(); From 6a5ba8fdc2b5c2b5d9f94049c040c24566248461 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 18:36:13 +0200 Subject: [PATCH 113/216] Fixing comment format in sp_head.cc. sql/sp_head.cc: Fixing comment format. --- sql/sp_head.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index b586546bcfe..b2de24ca9b5 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1997,10 +1997,10 @@ sp_instr_copen::execute(THD *thd, uint *nextp) Query_arena *old_arena= thd->current_arena; /* - Get the Query_arena from the cpush instruction, which contains - the free_list of the query, so new items (if any) are stored in - the right free_list, and we can cleanup after each open. - */ + Get the Query_arena from the cpush instruction, which contains + the free_list of the query, so new items (if any) are stored in + the right free_list, and we can cleanup after each open. + */ thd->current_arena= c->get_instr(); res= lex_keeper->reset_lex_and_exec_core(thd, nextp, FALSE, this); /* Cleanup the query's items */ @@ -2011,7 +2011,7 @@ sp_instr_copen::execute(THD *thd, uint *nextp) Work around the fact that errors in selects are not returned properly (but instead converted into a warning), so if a condition handler caught, we have lost the result code. - */ + */ if (!res) { uint dummy1, dummy2; From 11dc2506bc3e2db294e847fabbad21adcbca96a2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 19:15:39 +0200 Subject: [PATCH 114/216] After review fixes client/mysqldump.c: Use uppercase for all SQL statements Use WHERE 0 instead of WHERE 1=0 --- client/mysqldump.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 6b7923fcd93..ae771ee591d 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1224,7 +1224,7 @@ static uint get_table_structure(char *table, char *db) /* Create temp table by selecting from the view */ my_snprintf(query_buff, sizeof(query_buff), - "create temporary table %s select * from %s where 1=0", + "CREATE TEMPORARY TABLE %s SELECT * FROM %s WHERE 0", result_table, result_table); if (mysql_query_with_error_report(sock, 0, query_buff)) { @@ -1233,7 +1233,7 @@ static uint get_table_structure(char *table, char *db) } /* Get CREATE statement for the temp table */ - my_snprintf(query_buff, sizeof(query_buff), "show create table %s", + my_snprintf(query_buff, sizeof(query_buff), "SHOW CREATE TABLE %s", result_table); if (mysql_query_with_error_report(sock, 0, query_buff)) { From d10debf667075033ed400553d5ac5b33a592cce6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 19:22:41 +0200 Subject: [PATCH 115/216] Should not be here, same procedure every time.. mysql-test/r/mysqldump.result: Will be removed mysql-test/t/mysqldump.test: Will be removed --- mysql-test/r/mysqldump.result | 39 +++++++++++++++++++++++++++++++---- mysql-test/t/mysqldump.test | 37 +++++++++++++++++++++++++++++++-- 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 573b2b54141..cc95f708355 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1,7 +1,7 @@ DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa; drop database if exists mysqldump_test_db; drop database if exists db1; -drop view if exists v1, v2; +drop view if exists v1, v2, v3; CREATE TABLE t1(a int); INSERT INTO t1 VALUES (1), (2); @@ -380,6 +380,11 @@ UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; DROP TABLE IF EXISTS `v1`; DROP VIEW IF EXISTS `v1`; +CREATE TABLE `v1` ( + `a` bigint(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS `v1`; +DROP VIEW IF EXISTS `v1`; CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` from `test`.`t1`; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -439,7 +444,7 @@ USE `mysqldump_test_db`; drop database mysqldump_test_db; CREATE TABLE t1 (a CHAR(10)); -INSERT INTO t1 VALUES (_latin1 ''); +INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -481,7 +486,7 @@ CREATE TABLE `t1` ( /*!40000 ALTER TABLE `t1` DISABLE KEYS */; LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES (''); +INSERT INTO `t1` VALUES ('Ž™šá'); UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; @@ -502,7 +507,7 @@ CREATE TABLE `t1` ( /*!40000 ALTER TABLE `t1` DISABLE KEYS */; LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES (''); +INSERT INTO `t1` VALUES ('Ž™šá'); UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; @@ -1423,6 +1428,32 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +create table t1(a int, b int, c varchar(30)); +insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); +create view v3 as +select * from t1; +create view v1 as +select * from v3 where b in (1, 2, 3, 4, 5, 6, 7); +create view v2 as +select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; +drop view v1, v2, v3; +drop table t1; +show full tables; +Tables_in_test Table_type +t1 BASE TABLE +v1 VIEW +v2 VIEW +v3 VIEW +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`v3`.`a` AS `a`,`test`.`v3`.`b` AS `b`,`test`.`v3`.`c` AS `c` from `test`.`v3` where (`test`.`v3`.`b` in (1,2,3,4,5,6,7)) +select * from v1; +a b c +1 2 one +2 4 two +3 6 three +drop view v1, v2, v3; +drop table t1; create database db1; use db1; CREATE TABLE t2 ( diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index ec49eec8b46..8b6b45870f9 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -5,7 +5,7 @@ DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa; drop database if exists mysqldump_test_db; drop database if exists db1; -drop view if exists v1, v2; +drop view if exists v1, v2, v3; --enable_warnings # XML output @@ -161,7 +161,7 @@ drop database mysqldump_test_db; # if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); -INSERT INTO t1 VALUES (_latin1 ''); +INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments test t1 # # Bug#8063: make test mysqldump [ fail ] @@ -565,6 +565,39 @@ INSERT INTO t1 VALUES (1),(2),(3); --exec $MYSQL_DUMP --add-drop-database --skip-comments --databases test DROP TABLE t1; + +# +# Bug #10927 mysqldump: Can't reload dump with view that consist of other view +# + +create table t1(a int, b int, c varchar(30)); + +insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); + +create view v3 as +select * from t1; + +create view v1 as +select * from v3 where b in (1, 2, 3, 4, 5, 6, 7); + +create view v2 as +select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; + +--exec $MYSQL_DUMP test > var/tmp/bug10927.sql +drop view v1, v2, v3; +drop table t1; +--exec $MYSQL test < var/tmp/bug10927.sql + +# Without dropping the original tables in between +--exec $MYSQL_DUMP test > var/tmp/bug10927.sql +--exec $MYSQL test < var/tmp/bug10927.sql +show full tables; +show create view v1; +select * from v1; + +drop view v1, v2, v3; +drop table t1; + # # Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) # From 0aecf3f26e272bc9aa117f116d3d21e5bf5df4ea Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 19:24:34 +0200 Subject: [PATCH 116/216] Cset exclude: msvensson@neptunus.(none)|ChangeSet|20050630172241|15421 mysql-test/r/mysqldump.result: Exclude mysql-test/t/mysqldump.test: Exclude --- mysql-test/r/mysqldump.result | 39 ++++------------------------------- mysql-test/t/mysqldump.test | 37 ++------------------------------- 2 files changed, 6 insertions(+), 70 deletions(-) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index cc95f708355..573b2b54141 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1,7 +1,7 @@ DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa; drop database if exists mysqldump_test_db; drop database if exists db1; -drop view if exists v1, v2, v3; +drop view if exists v1, v2; CREATE TABLE t1(a int); INSERT INTO t1 VALUES (1), (2); @@ -380,11 +380,6 @@ UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; DROP TABLE IF EXISTS `v1`; DROP VIEW IF EXISTS `v1`; -CREATE TABLE `v1` ( - `a` bigint(11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; -DROP TABLE IF EXISTS `v1`; -DROP VIEW IF EXISTS `v1`; CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` from `test`.`t1`; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -444,7 +439,7 @@ USE `mysqldump_test_db`; drop database mysqldump_test_db; CREATE TABLE t1 (a CHAR(10)); -INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); +INSERT INTO t1 VALUES (_latin1 ''); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -486,7 +481,7 @@ CREATE TABLE `t1` ( /*!40000 ALTER TABLE `t1` DISABLE KEYS */; LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES ('Ž™šá'); +INSERT INTO `t1` VALUES (''); UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; @@ -507,7 +502,7 @@ CREATE TABLE `t1` ( /*!40000 ALTER TABLE `t1` DISABLE KEYS */; LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES ('Ž™šá'); +INSERT INTO `t1` VALUES (''); UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; @@ -1428,32 +1423,6 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; -create table t1(a int, b int, c varchar(30)); -insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); -create view v3 as -select * from t1; -create view v1 as -select * from v3 where b in (1, 2, 3, 4, 5, 6, 7); -create view v2 as -select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; -drop view v1, v2, v3; -drop table t1; -show full tables; -Tables_in_test Table_type -t1 BASE TABLE -v1 VIEW -v2 VIEW -v3 VIEW -show create view v1; -View Create View -v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`v3`.`a` AS `a`,`test`.`v3`.`b` AS `b`,`test`.`v3`.`c` AS `c` from `test`.`v3` where (`test`.`v3`.`b` in (1,2,3,4,5,6,7)) -select * from v1; -a b c -1 2 one -2 4 two -3 6 three -drop view v1, v2, v3; -drop table t1; create database db1; use db1; CREATE TABLE t2 ( diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 8b6b45870f9..ec49eec8b46 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -5,7 +5,7 @@ DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa; drop database if exists mysqldump_test_db; drop database if exists db1; -drop view if exists v1, v2, v3; +drop view if exists v1, v2; --enable_warnings # XML output @@ -161,7 +161,7 @@ drop database mysqldump_test_db; # if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); -INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); +INSERT INTO t1 VALUES (_latin1 ''); --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments test t1 # # Bug#8063: make test mysqldump [ fail ] @@ -565,39 +565,6 @@ INSERT INTO t1 VALUES (1),(2),(3); --exec $MYSQL_DUMP --add-drop-database --skip-comments --databases test DROP TABLE t1; - -# -# Bug #10927 mysqldump: Can't reload dump with view that consist of other view -# - -create table t1(a int, b int, c varchar(30)); - -insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); - -create view v3 as -select * from t1; - -create view v1 as -select * from v3 where b in (1, 2, 3, 4, 5, 6, 7); - -create view v2 as -select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; - ---exec $MYSQL_DUMP test > var/tmp/bug10927.sql -drop view v1, v2, v3; -drop table t1; ---exec $MYSQL test < var/tmp/bug10927.sql - -# Without dropping the original tables in between ---exec $MYSQL_DUMP test > var/tmp/bug10927.sql ---exec $MYSQL test < var/tmp/bug10927.sql -show full tables; -show create view v1; -select * from v1; - -drop view v1, v2, v3; -drop table t1; - # # Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) # From 77532a6f578fb5fd3e48ded3ac0e05e2f8c7c44d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Jun 2005 20:44:31 +0200 Subject: [PATCH 117/216] Tests readded for bug 10927 mysql-test/r/mysqldump.result: Add tests for bug#10927 mysql-test/t/mysqldump.test: Add tests for bug#10927 --- mysql-test/r/mysqldump.result | 38 ++++++++++++++++++++++++++++++++++- mysql-test/t/mysqldump.test | 33 +++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 573b2b54141..091d21cfa20 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1,7 +1,7 @@ DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa; drop database if exists mysqldump_test_db; drop database if exists db1; -drop view if exists v1, v2; +drop view if exists v1, v2, v3; CREATE TABLE t1(a int); INSERT INTO t1 VALUES (1), (2); @@ -380,6 +380,11 @@ UNLOCK TABLES; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; DROP TABLE IF EXISTS `v1`; DROP VIEW IF EXISTS `v1`; +CREATE TABLE `v1` ( + `a` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS `v1`; +DROP VIEW IF EXISTS `v1`; CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` from `test`.`t1`; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -1458,6 +1463,11 @@ UNLOCK TABLES; /*!40000 ALTER TABLE `t2` ENABLE KEYS */; DROP TABLE IF EXISTS `v2`; DROP VIEW IF EXISTS `v2`; +CREATE TABLE `v2` ( + `a` varchar(30) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS `v2`; +DROP VIEW IF EXISTS `v2`; CREATE ALGORITHM=UNDEFINED VIEW `db1`.`v2` AS select `db1`.`t2`.`a` AS `a` from `db1`.`t2` where (`db1`.`t2`.`a` like _latin1'a%') WITH CASCADED CHECK OPTION; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -1637,3 +1647,29 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir drop table t1, t2; +create table t1(a int, b int, c varchar(30)); +insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); +create view v3 as +select * from t1; +create view v1 as +select * from v3 where b in (1, 2, 3, 4, 5, 6, 7); +create view v2 as +select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; +drop view v1, v2, v3; +drop table t1; +show full tables; +Tables_in_test Table_type +t1 BASE TABLE +v1 VIEW +v2 VIEW +v3 VIEW +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`v3`.`a` AS `a`,`test`.`v3`.`b` AS `b`,`test`.`v3`.`c` AS `c` from `test`.`v3` where (`test`.`v3`.`b` in (1,2,3,4,5,6,7)) +select * from v1; +a b c +1 2 one +2 4 two +3 6 three +drop view v1, v2, v3; +drop table t1; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index ec49eec8b46..811875a36f5 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -5,7 +5,7 @@ DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa; drop database if exists mysqldump_test_db; drop database if exists db1; -drop view if exists v1, v2; +drop view if exists v1, v2, v3; --enable_warnings # XML output @@ -678,3 +678,34 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir --exec $MYSQL_DUMP --skip-comments --xml --no-create-info test drop table t1, t2; +# +# Bug #10927 mysqldump: Can't reload dump with view that consist of other view +# + +create table t1(a int, b int, c varchar(30)); + +insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); + +create view v3 as +select * from t1; + +create view v1 as +select * from v3 where b in (1, 2, 3, 4, 5, 6, 7); + +create view v2 as +select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; + +--exec $MYSQL_DUMP test > var/tmp/bug10927.sql +drop view v1, v2, v3; +drop table t1; +--exec $MYSQL test < var/tmp/bug10927.sql + +# Without dropping the original tables in between +--exec $MYSQL_DUMP test > var/tmp/bug10927.sql +--exec $MYSQL test < var/tmp/bug10927.sql +show full tables; +show create view v1; +select * from v1; + +drop view v1, v2, v3; +drop table t1; From b4f595b95f1740b7153013431080ff77de8d867a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 07:05:42 +0300 Subject: [PATCH 118/216] Name resolution context added (BUG#6443) include/my_bitmap.h: new bitmap operation mysql-test/r/view.result: added warnings Correct inserting data check (absence of default value) for view underlying tables (BUG#6443) mysql-test/t/view.test: Correct inserting data check (absence of default value) for view underlying tables (BUG#6443) mysys/my_bitmap.c: new bitmap operation sql/field.h: index of field in table added sql/item.cc: Name resolution context added table list removed from fix_fields() arguments sql/item.h: Name resolution context added table list removed from fix_fields() arguments sql/item_cmpfunc.cc: table list removed from fix_fields() arguments sql/item_cmpfunc.h: table list removed from fix_fields() arguments sql/item_func.cc: table list removed from fix_fields() arguments sql/item_func.h: table list removed from fix_fields() arguments sql/item_row.cc: table list removed from fix_fields() arguments sql/item_row.h: table list removed from fix_fields() arguments sql/item_strfunc.cc: fixed server crash on NULL argument sql/item_strfunc.h: table list removed from fix_fields() arguments sql/item_subselect.cc: table list removed from fix_fields() arguments sql/item_subselect.h: table list removed from fix_fields() arguments sql/item_sum.cc: table list removed from fix_fields() arguments sql/item_sum.h: table list removed from fix_fields() arguments sql/item_timefunc.cc: table list removed from fix_fields() arguments sql/item_timefunc.h: table list removed from fix_fields() arguments sql/item_uniq.h: table list removed from fix_fields() arguments sql/log_event.cc: Name resolution context added sql/log_event.h: Name resolution context added sql/mysql_priv.h: Name resolution context added sql/set_var.cc: table list removed from fix_fields() arguments sql/share/errmsg.txt: new error message sql/sp.cc: Name resolution context added sql/sp_head.cc: table list removed from fix_fields() arguments sql/sp_head.h: Name resolution context added sql/sql_base.cc: table list removed from fix_fields() arguments Name resolution context added sql/sql_class.cc: renamed variable sql/sql_delete.cc: Name resolution context added sql/sql_derived.cc: Name resolution context added sql/sql_do.cc: table list removed from fix_fields() arguments sql/sql_handler.cc: Name resolution context added sql/sql_help.cc: Name resolution context added sql/sql_insert.cc: Name resolution context added table list removed from fix_fields() arguments sql/sql_lex.cc: Name resolution context added sql/sql_lex.h: removed resolve mode (information stored into name resolution context) sql/sql_load.cc: table list removed from fix_fields() arguments sql/sql_olap.cc: Name resolution context added sql/sql_parse.cc: Name resolution context added sql/sql_prepare.cc: table list removed from fix_fields() arguments sql/sql_select.cc: table list removed from fix_fields() arguments sql/sql_show.cc: Name resolution context added sql/sql_trigger.cc: table list removed from fix_fields() arguments sql/sql_udf.h: table list removed from fix_fields() arguments sql/sql_union.cc: Name resolution context added sql/sql_update.cc: Name resolution context added sql/sql_view.cc: Name resolution context added sql/sql_view.h: table list removed from fix_fields() arguments sql/sql_yacc.yy: Name resolution context added sql/table.cc: Name resolution context added merged view processing moved sql/table.h: merged view processing moved --- include/my_bitmap.h | 2 + mysql-test/r/view.result | 15 ++ mysql-test/t/view.test | 18 ++ mysys/my_bitmap.c | 45 ++++ sql/field.h | 1 + sql/item.cc | 514 +++++++++++++++++++++++---------------- sql/item.h | 227 +++++++++++++---- sql/item_cmpfunc.cc | 31 ++- sql/item_cmpfunc.h | 18 +- sql/item_func.cc | 47 ++-- sql/item_func.h | 76 +++--- sql/item_row.cc | 4 +- sql/item_row.h | 2 +- sql/item_strfunc.cc | 2 +- sql/item_strfunc.h | 6 +- sql/item_subselect.cc | 50 ++-- sql/item_subselect.h | 8 +- sql/item_sum.cc | 22 +- sql/item_sum.h | 70 ++++-- sql/item_timefunc.cc | 4 +- sql/item_timefunc.h | 2 +- sql/item_uniq.h | 2 +- sql/log_event.cc | 11 +- sql/log_event.h | 3 +- sql/mysql_priv.h | 24 +- sql/set_var.cc | 8 +- sql/share/errmsg.txt | 2 + sql/sp.cc | 10 +- sql/sp_head.cc | 8 +- sql/sp_head.h | 5 +- sql/sql_base.cc | 177 +++++++------- sql/sql_class.cc | 16 +- sql/sql_delete.cc | 7 +- sql/sql_derived.cc | 4 + sql/sql_do.cc | 2 +- sql/sql_handler.cc | 11 +- sql/sql_help.cc | 23 +- sql/sql_insert.cc | 174 ++++++++----- sql/sql_lex.cc | 54 +++- sql/sql_lex.h | 45 ++-- sql/sql_load.cc | 20 +- sql/sql_olap.cc | 12 +- sql/sql_parse.cc | 50 +++- sql/sql_prepare.cc | 57 +++-- sql/sql_select.cc | 51 ++-- sql/sql_show.cc | 41 +++- sql/sql_trigger.cc | 2 +- sql/sql_udf.h | 4 +- sql/sql_union.cc | 9 + sql/sql_update.cc | 39 ++- sql/sql_view.cc | 74 ++++-- sql/sql_view.h | 2 +- sql/sql_yacc.yy | 95 +++++--- sql/table.cc | 502 ++++++++++++++++++-------------------- sql/table.h | 49 +++- 55 files changed, 1688 insertions(+), 1069 deletions(-) diff --git a/include/my_bitmap.h b/include/my_bitmap.h index 4caa3b85456..84a5d8bd18a 100644 --- a/include/my_bitmap.h +++ b/include/my_bitmap.h @@ -45,6 +45,8 @@ extern my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size); extern my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit); extern my_bool bitmap_is_set_all(const MY_BITMAP *map); extern my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2); +extern my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit); +extern my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit); extern uint bitmap_set_next(MY_BITMAP *map); extern uint bitmap_get_first(const MY_BITMAP *map); extern uint bitmap_bits_set(const MY_BITMAP *map); diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 4c1db618b4b..e3431a3a466 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -754,6 +754,8 @@ create view v1 as select * from t1; create view v2 as select * from t2; insert into v1 values (1); insert into v2 values (1); +Warnings: +Warning 1423 Field of view 'test.v2' underlying table doesn't have a default value create view v3 (a,b) as select v1.col1 as a, v2.col1 as b from v1, v2 where v1.col1 = v2.col1; select * from v3; a b @@ -1850,3 +1852,16 @@ SELECT * FROM v1; SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1) dkjhgd drop view v1; +set sql_mode='strict_all_tables'; +CREATE TABLE t1 (col1 INT NOT NULL, col2 INT NOT NULL) ENGINE = INNODB; +CREATE VIEW v1 (vcol1) AS SELECT col1 FROM t1; +CREATE VIEW v2 (vcol1) AS SELECT col1 FROM t1 WHERE col2 > 2; +INSERT INTO t1 (col1) VALUES(12); +ERROR HY000: Field 'col2' doesn't have a default value +INSERT INTO v1 (vcol1) VALUES(12); +ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default value +INSERT INTO v2 (vcol1) VALUES(12); +ERROR HY000: Field of view 'test.v2' underlying table doesn't have a default value +set sql_mode=default; +drop view v2,v1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 06b523b3610..78d992163fe 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1696,3 +1696,21 @@ drop view v1; CREATE VIEW v1 AS SELECT SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1); SELECT * FROM v1; drop view v1; + +# +# Correct inserting data check (absence of default value) for view +# underlying tables (BUG#6443) +# +set sql_mode='strict_all_tables'; +CREATE TABLE t1 (col1 INT NOT NULL, col2 INT NOT NULL) ENGINE = INNODB; +CREATE VIEW v1 (vcol1) AS SELECT col1 FROM t1; +CREATE VIEW v2 (vcol1) AS SELECT col1 FROM t1 WHERE col2 > 2; +-- error 1364 +INSERT INTO t1 (col1) VALUES(12); +-- error 1423 +INSERT INTO v1 (vcol1) VALUES(12); +-- error 1423 +INSERT INTO v2 (vcol1) VALUES(12); +set sql_mode=default; +drop view v2,v1; +drop table t1; diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index c0eb6f15548..ba958b234d2 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -109,6 +109,51 @@ void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit) } +/* + test if bit already set and set it if it was not (thread unsafe method) + + SYNOPSIS + bitmap_fast_test_and_set() + MAP bit map struct + BIT bit number + + RETURN + 0 bit was not set + !=0 bit was set +*/ + +my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit) +{ + uchar *byte= map->bitmap + (bitmap_bit / 8); + uchar bit= 1 << ((bitmap_bit) & 7); + uchar res= (*byte) & bit; + *byte|= bit; + return res; +} + + +/* + test if bit already set and set it if it was not (thread safe method) + + SYNOPSIS + bitmap_fast_test_and_set() + map bit map struct + bitmap_bit bit number + + RETURN + 0 bit was not set + !=0 bit was set +*/ + +my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit) +{ + my_bool res; + DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); + bitmap_lock(map); + res= bitmap_fast_test_and_set(map, bitmap_bit); + bitmap_unlock(map); +} + uint bitmap_set_next(MY_BITMAP *map) { uchar *bitmap=map->bitmap; diff --git a/sql/field.h b/sql/field.h index 2b1229744c2..523cf444c30 100644 --- a/sql/field.h +++ b/sql/field.h @@ -86,6 +86,7 @@ public: utype unireg_check; uint32 field_length; // Length of field + uint field_index; // field number in fields array uint16 flags; uchar null_bit; // Bit used to test null bit diff --git a/sql/item.cc b/sql/item.cc index b6f8b7ebc51..00b93cfa270 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -440,16 +440,17 @@ void Item::rename(char *new_name) } -Item_ident::Item_ident(const char *db_name_par,const char *table_name_par, - const char *field_name_par) - :orig_db_name(db_name_par), orig_table_name(table_name_par), - orig_field_name(field_name_par), - db_name(db_name_par), table_name(table_name_par), - field_name(field_name_par), +Item_ident::Item_ident(Name_resolution_context *context_arg, + const char *db_name_arg,const char *table_name_arg, + const char *field_name_arg) + :orig_db_name(db_name_arg), orig_table_name(table_name_arg), + orig_field_name(field_name_arg), context(context_arg), + db_name(db_name_arg), table_name(table_name_arg), + field_name(field_name_arg), alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX), cached_table(0), depended_from(0) { - name = (char*) field_name_par; + name = (char*) field_name_arg; } @@ -460,6 +461,7 @@ Item_ident::Item_ident(THD *thd, Item_ident *item) orig_db_name(item->orig_db_name), orig_table_name(item->orig_table_name), orig_field_name(item->orig_field_name), + context(item->context), db_name(item->db_name), table_name(item->table_name), field_name(item->field_name), @@ -785,7 +787,7 @@ Item_splocal::type() const } -bool Item_splocal::fix_fields(THD *, struct st_table_list *, Item **) +bool Item_splocal::fix_fields(THD *, Item **) { Item *it= this_item(); DBUG_ASSERT(it->fixed); @@ -855,7 +857,8 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, uint el= fields.elements; Item *new_item; ref_pointer_array[el]= this; - if (!(new_item= new Item_ref(ref_pointer_array + el, 0, name))) + if (!(new_item= new Item_ref(&thd->lex->current_select->context, + ref_pointer_array + el, 0, name))) return; // fatal_error is set fields.push_front(this); ref_pointer_array[el]= this; @@ -995,7 +998,7 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags) } Item_field::Item_field(Field *f) - :Item_ident(NullS, *f->table_name, f->field_name), + :Item_ident(0, NullS, *f->table_name, f->field_name), item_equal(0), no_const_subst(0), have_privileges(0), any_privileges(0) { @@ -1007,8 +1010,9 @@ Item_field::Item_field(Field *f) orig_table_name= orig_field_name= ""; } -Item_field::Item_field(THD *thd, Field *f) - :Item_ident(f->table->s->db, *f->table_name, f->field_name), +Item_field::Item_field(THD *thd, Name_resolution_context *context_arg, + Field *f) + :Item_ident(context_arg, f->table->s->db, *f->table_name, f->field_name), item_equal(0), no_const_subst(0), have_privileges(0), any_privileges(0) { @@ -1043,6 +1047,17 @@ Item_field::Item_field(THD *thd, Field *f) set_field(f); } + +Item_field::Item_field(Name_resolution_context *context_arg, + const char *db_arg,const char *table_name_arg, + const char *field_name_arg) + :Item_ident(context_arg, db_arg,table_name_arg,field_name_arg), + field(0), result_field(0), item_equal(0), no_const_subst(0), + have_privileges(0), any_privileges(0) +{ + collation.set(DERIVATION_IMPLICIT); +} + // Constructor need to process subselect with temporary tables (see Item) Item_field::Item_field(THD *thd, Item_field *item) :Item_ident(thd, item), @@ -2233,7 +2248,7 @@ bool Item_param::convert_str_value(THD *thd) return rc; } -bool Item_param::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) +bool Item_param::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); SELECT_LEX *cursel= (SELECT_LEX *) thd->lex->current_select; @@ -2393,9 +2408,7 @@ int Item_copy_string::save_in_field(Field *field, bool no_conversions) */ /* ARGSUSED */ -bool Item::fix_fields(THD *thd, - struct st_table_list *list, - Item ** ref) +bool Item::fix_fields(THD *thd, Item ** ref) { // We do not check fields which are fixed during construction @@ -2762,7 +2775,6 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select) SYNOPSIS Item_field::fix_fields() thd [in] current thread - tables [in] the tables in a FROM clause reference [in/out] view column if this item was resolved to a view column DESCRIPTION @@ -2808,7 +2820,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select) FALSE on success */ -bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) +bool Item_field::fix_fields(THD *thd, Item **reference) { enum_parsing_place place= NO_MATTER; DBUG_ASSERT(fixed == 0); @@ -2821,135 +2833,129 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) expression to 'reference', i.e. it substitute that expression instead of this Item_field */ - if ((from_field= find_field_in_tables(thd, this, tables, reference, - IGNORE_EXCEPT_NON_UNIQUE, - !any_privileges)) == + if ((from_field= find_field_in_tables(thd, this, context->table_list, + reference, + IGNORE_EXCEPT_NON_UNIQUE, + !any_privileges && + context->check_privileges)) == not_found_field) { - SELECT_LEX *last= 0; - TABLE_LIST *table_list; - Item **ref= (Item **) not_found_item; - SELECT_LEX *current_sel= (SELECT_LEX *) thd->lex->current_select; /* - If there is an outer select, and it is not a derived table (which do - not support the use of outer fields for now), try to resolve this - reference in the outer select(s). - + If there is an outer contexts (outer selects, but current select is + not derived table or view) try to resolve this reference in the + outer contexts. + We treat each subselect as a separate namespace, so that different subselects may contain columns with the same names. The subselects are - searched starting from the innermost. + searched starting from the innermost. */ - if (current_sel->master_unit()->first_select()->linkage != - DERIVED_TABLE_TYPE) + Name_resolution_context *last_checked_context= context; + Item **ref= (Item **) not_found_item; + Name_resolution_context *outer_context= context->outer_context; + for (; + outer_context; + outer_context= outer_context->outer_context) { - SELECT_LEX_UNIT *prev_unit= current_sel->master_unit(); - SELECT_LEX *outer_sel= prev_unit->outer_select(); - for ( ; outer_sel ; - outer_sel= (prev_unit= outer_sel->master_unit())->outer_select()) - { - last= outer_sel; - Item_subselect *prev_subselect_item= prev_unit->item; - upward_lookup= TRUE; + SELECT_LEX *select= outer_context->select_lex; + Item_subselect *prev_subselect_item= + last_checked_context->select_lex->master_unit()->item; + last_checked_context= outer_context; + upward_lookup= TRUE; - /* Search in the tables of the FROM clause of the outer select. */ - table_list= outer_sel->get_table_list(); - if (outer_sel->resolve_mode == SELECT_LEX::INSERT_MODE && table_list) - { - /* - It is a primary INSERT st_select_lex => do not resolve against the - first table. - */ - table_list= table_list->next_local; - } - place= prev_subselect_item->parsing_place; - /* - Check table fields only if the subquery is used somewhere out of - HAVING, or the outer SELECT does not use grouping (i.e. tables are - accessible). + place= prev_subselect_item->parsing_place; + /* + Check table fields only if the subquery is used somewhere out of + HAVING, or the outer SELECT does not use grouping (i.e. tables are + accessible). - In case of view, find_field_in_tables() write pointer to view - field expression to 'reference', i.e. it substitute that - expression instead of this Item_field - */ - if ((place != IN_HAVING || - (outer_sel->with_sum_func == 0 && - outer_sel->group_list.elements == 0)) && - (from_field= find_field_in_tables(thd, this, table_list, - reference, - IGNORE_EXCEPT_NON_UNIQUE, - TRUE)) != - not_found_field) - { - if (from_field) - { - if (from_field != view_ref_found) - { - prev_subselect_item->used_tables_cache|= from_field->table->map; - prev_subselect_item->const_item_cache= 0; - } - else - { - Item::Type type= (*reference)->type(); - prev_subselect_item->used_tables_cache|= - (*reference)->used_tables(); - prev_subselect_item->const_item_cache&= - (*reference)->const_item(); - mark_as_dependent(thd, last, current_sel, this, - ((type == REF_ITEM || type == FIELD_ITEM) ? - (Item_ident*) (*reference) : - 0)); - /* - view reference found, we substituted it instead of this - Item (find_field_in_tables do it by assigning new value to - *reference), so can quit - */ - return FALSE; - } - } - break; - } - - /* Search in the SELECT and GROUP lists of the outer select. */ - if (outer_sel->resolve_mode == SELECT_LEX::SELECT_MODE) + In case of a view, find_field_in_tables() writes the pointer to + the found view field into '*reference', in other words, it + substitutes this Item_field with the found expression. + */ + if ((place != IN_HAVING || + (!select->with_sum_func && + select->group_list.elements == 0)) && + (from_field= find_field_in_tables(thd, this, + outer_context->table_list, + reference, + IGNORE_EXCEPT_NON_UNIQUE, + outer_context-> + check_privileges)) != + not_found_field) + { + if (from_field) { - if (!(ref= resolve_ref_in_select_and_group(thd, this, outer_sel))) - return TRUE; /* Some error occurred (e.g. ambiguous names). */ - if (ref != not_found_item) + if (from_field != view_ref_found) { - DBUG_ASSERT(*ref && (*ref)->fixed); - prev_subselect_item->used_tables_cache|= (*ref)->used_tables(); - prev_subselect_item->const_item_cache&= (*ref)->const_item(); - break; + prev_subselect_item->used_tables_cache|= from_field->table->map; + prev_subselect_item->const_item_cache= 0; } - } + else + { + Item::Type type= (*reference)->type(); + prev_subselect_item->used_tables_cache|= + (*reference)->used_tables(); + prev_subselect_item->const_item_cache&= + (*reference)->const_item(); + mark_as_dependent(thd, last_checked_context->select_lex, + context->select_lex, this, + ((type == REF_ITEM || type == FIELD_ITEM) ? + (Item_ident*) (*reference) : + 0)); + /* + A reference to a view field had been found and we + substituted it instead of this Item (find_field_in_tables + does it by assigning the new value to *reference), so now + we can return from this function. + */ + return FALSE; + } + } + break; + } - // Reference is not found => depend from outer (or just error) - prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; - prev_subselect_item->const_item_cache= 0; + /* Search in SELECT and GROUP lists of the outer select. */ + if (outer_context->resolve_in_select_list) + { + if (!(ref= resolve_ref_in_select_and_group(thd, this, select))) + goto error; /* Some error occurred (e.g. ambiguous names). */ + if (ref != not_found_item) + { + DBUG_ASSERT(*ref && (*ref)->fixed); + prev_subselect_item->used_tables_cache|= (*ref)->used_tables(); + prev_subselect_item->const_item_cache&= (*ref)->const_item(); + break; + } + } - if (outer_sel->master_unit()->first_select()->linkage == - DERIVED_TABLE_TYPE) - break; // do not look over derived table - } + /* + Reference is not found in this select => this subquery depend on + outer select (or we just trying to find wrong identifier, in this + case it does not matter which used tables bits we set) + */ + prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; + prev_subselect_item->const_item_cache= 0; } DBUG_ASSERT(ref != 0); if (!from_field) - return TRUE; + goto error; if (ref == not_found_item && from_field == not_found_field) { if (upward_lookup) { - // We can't say exactly what absent table or field + // We can't say exactly what absent table or field my_error(ER_BAD_FIELD_ERROR, MYF(0), full_name(), thd->where); } else { - // Call to report error - find_field_in_tables(thd, this, tables, reference, REPORT_ALL_ERRORS, - TRUE); + /* Call find_field_in_tables only to report the error */ + find_field_in_tables(thd, this, context->table_list, + reference, REPORT_ALL_ERRORS, + !any_privileges && + context->check_privileges); } - return TRUE; + goto error; } else if (ref != not_found_item) { @@ -2967,45 +2973,54 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) save= *ref; *ref= NULL; // Don't call set_properties() rf= (place == IN_HAVING ? - new Item_ref(ref, (char*) table_name, (char*) field_name) : - new Item_direct_ref(ref, (char*) table_name, (char*) field_name)); + new Item_ref(context, ref, (char*) table_name, + (char*) field_name) : + new Item_direct_ref(context, ref, (char*) table_name, + (char*) field_name)); *ref= save; if (!rf) - return TRUE; + goto error; thd->change_item_tree(reference, rf); /* rf is Item_ref => never substitute other items (in this case) during fix_fields() => we can use rf after fix_fields() */ DBUG_ASSERT(!rf->fixed); // Assured by Item_ref() - if (rf->fix_fields(thd, tables, reference) || rf->check_cols(1)) - return TRUE; + if (rf->fix_fields(thd, reference) || rf->check_cols(1)) + goto error; - mark_as_dependent(thd, last, current_sel, this, rf); + mark_as_dependent(thd, last_checked_context->select_lex, + context->select_lex, this, + rf); return FALSE; } else { - mark_as_dependent(thd, last, current_sel, this, this); - if (last->having_fix_field) + mark_as_dependent(thd, last_checked_context->select_lex, + context->select_lex, + this, this); + if (last_checked_context->select_lex->having_fix_field) { Item_ref *rf; - rf= new Item_ref((cached_table->db[0] ? cached_table->db : 0), + rf= new Item_ref(context, + (cached_table->db[0] ? cached_table->db : 0), (char*) cached_table->alias, (char*) field_name); if (!rf) - return TRUE; + goto error; thd->change_item_tree(reference, rf); /* rf is Item_ref => never substitute other items (in this case) during fix_fields() => we can use rf after fix_fields() */ DBUG_ASSERT(!rf->fixed); // Assured by Item_ref() - return (rf->fix_fields(thd, tables, reference) || rf->check_cols(1)); + if (rf->fix_fields(thd, reference) || rf->check_cols(1)) + goto error; + return FALSE; } } } else if (!from_field) - return TRUE; + goto error; /* if it is not expression from merged VIEW we will set this field. @@ -3053,12 +3068,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), "ANY", thd->priv_user, thd->host_or_ip, field_name, tab); - return TRUE; + goto error; } } #endif fixed= 1; return FALSE; + +error: + context->process_error(thd); + return TRUE; } @@ -3922,16 +3941,17 @@ bool Item_field::send(Protocol *protocol, String *buffer) } -Item_ref::Item_ref(Item **item, const char *table_name_par, - const char *field_name_par) - :Item_ident(NullS, table_name_par, field_name_par), result_field(0), - ref(item) +Item_ref::Item_ref(Name_resolution_context *context_arg, + Item **item, const char *table_name_arg, + const char *field_name_arg) + :Item_ident(context_arg, NullS, table_name_arg, field_name_arg), + result_field(0), ref(item) { /* This constructor used to create some internals references over fixed items */ DBUG_ASSERT(ref != 0); - if (*ref) + if (*ref && (*ref)->fixed) set_properties(); } @@ -3942,7 +3962,6 @@ Item_ref::Item_ref(Item **item, const char *table_name_par, SYNOPSIS Item_ref::fix_fields() thd [in] current thread - tables [in] the tables in a FROM clause reference [in/out] view column if this item was resolved to a view column DESCRIPTION @@ -3994,59 +4013,56 @@ Item_ref::Item_ref(Item **item, const char *table_name_par, FALSE on success */ -bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) +bool Item_ref::fix_fields(THD *thd, Item **reference) { - DBUG_ASSERT(fixed == 0); enum_parsing_place place= NO_MATTER; + DBUG_ASSERT(fixed == 0); SELECT_LEX *current_sel= thd->lex->current_select; if (!ref || ref == not_found_item) { - SELECT_LEX_UNIT *prev_unit= current_sel->master_unit(); - SELECT_LEX *outer_sel= prev_unit->outer_select(); - - if (!(ref= resolve_ref_in_select_and_group(thd, this, current_sel))) - return TRUE; /* Some error occurred (e.g. ambiguous names). */ + if (!(ref= resolve_ref_in_select_and_group(thd, this, + context->select_lex))) + goto error; /* Some error occurred (e.g. ambiguous names). */ if (ref == not_found_item) /* This reference was not resolved. */ { - TABLE_LIST *table_list; + Name_resolution_context *last_checked_context= context; + Name_resolution_context *outer_context= context->outer_context; Field *from_field; - SELECT_LEX *last; ref= 0; - if (!outer_sel || (current_sel->master_unit()->first_select()->linkage == - DERIVED_TABLE_TYPE)) + if (!outer_context) { /* The current reference cannot be resolved in this query. */ my_error(ER_BAD_FIELD_ERROR,MYF(0), this->full_name(), current_thd->where); - return TRUE; + goto error; } + /* - If there is an outer select, and it is not a derived table (which do - not support the use of outer fields for now), try to resolve this - reference in the outer select(s). + If there is an outer context (select), and it is not a derived table + (which do not support the use of outer fields for now), try to + resolve this reference in the outer select(s). We treat each subselect as a separate namespace, so that different subselects may contain columns with the same names. The subselects are searched starting from the innermost. */ from_field= (Field*) not_found_field; - last= 0; - /* The following loop will always be excuted at least once */ - for ( ; outer_sel ; - outer_sel= (prev_unit= outer_sel->master_unit())->outer_select()) + do { - last= outer_sel; - Item_subselect *prev_subselect_item= prev_unit->item; + SELECT_LEX *select= outer_context->select_lex; + Item_subselect *prev_subselect_item= + last_checked_context->select_lex->master_unit()->item; + last_checked_context= outer_context; /* Search in the SELECT and GROUP lists of the outer select. */ - if (outer_sel->resolve_mode == SELECT_LEX::SELECT_MODE) + if (outer_context->resolve_in_select_list) { - if (!(ref= resolve_ref_in_select_and_group(thd, this, outer_sel))) - return TRUE; /* Some error occurred (e.g. ambiguous names). */ + if (!(ref= resolve_ref_in_select_and_group(thd, this, select))) + goto error; /* Some error occurred (e.g. ambiguous names). */ if (ref != not_found_item) { DBUG_ASSERT(*ref && (*ref)->fixed); @@ -4062,43 +4078,33 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) ref= 0; } - /* Search in the tables of the FROM clause of the outer select. */ - table_list= outer_sel->get_table_list(); - if (outer_sel->resolve_mode == SELECT_LEX::INSERT_MODE && table_list) - { - /* - It is a primary INSERT st_select_lex => do not resolve against - the first table. - */ - table_list= table_list->next_local; - } - place= prev_subselect_item->parsing_place; /* Check table fields only if the subquery is used somewhere out of HAVING or the outer SELECT does not use grouping (i.e. tables are accessible). - TODO: + TODO: Here we could first find the field anyway, and then test this condition, so that we can give a better error message - ER_WRONG_FIELD_WITH_GROUP, instead of the less informative ER_BAD_FIELD_ERROR which we produce now. */ if ((place != IN_HAVING || - (!outer_sel->with_sum_func && - outer_sel->group_list.elements == 0))) + (!select->with_sum_func && + select->group_list.elements == 0))) { /* In case of view, find_field_in_tables() write pointer to view field expression to 'reference', i.e. it substitute that expression instead of this Item_ref */ - from_field= find_field_in_tables(thd, this, table_list, + from_field= find_field_in_tables(thd, this, + outer_context->table_list, reference, IGNORE_EXCEPT_NON_UNIQUE, - TRUE); + outer_context->check_privileges); if (! from_field) - return TRUE; + goto error; if (from_field == view_ref_found) { Item::Type type= (*reference)->type(); @@ -4107,7 +4113,8 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) prev_subselect_item->const_item_cache&= (*reference)->const_item(); DBUG_ASSERT((*reference)->type() == REF_ITEM); - mark_as_dependent(thd, last, current_sel, this, + mark_as_dependent(thd, last_checked_context->select_lex, + context->select_lex, this, ((type == REF_ITEM || type == FIELD_ITEM) ? (Item_ident*) (*reference) : 0)); @@ -4130,19 +4137,18 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT; prev_subselect_item->const_item_cache= 0; - if (outer_sel->master_unit()->first_select()->linkage == - DERIVED_TABLE_TYPE) - break; /* Do not consider derived tables. */ - } + outer_context= outer_context->outer_context; + } while (outer_context); DBUG_ASSERT(from_field != 0 && from_field != view_ref_found); if (from_field != not_found_field) { Item_field* fld; if (!(fld= new Item_field(from_field))) - return TRUE; + goto error; thd->change_item_tree(reference, fld); - mark_as_dependent(thd, last, thd->lex->current_select, this, fld); + mark_as_dependent(thd, last_checked_context->select_lex, + thd->lex->current_select, this, fld); return FALSE; } if (ref == 0) @@ -4150,11 +4156,12 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) /* The item was not a table field and not a reference */ my_error(ER_BAD_FIELD_ERROR, MYF(0), this->full_name(), current_thd->where); - return TRUE; + goto error; } /* Should be checked in resolve_ref_in_select_and_group(). */ DBUG_ASSERT(*ref && (*ref)->fixed); - mark_as_dependent(thd, last, current_sel, this, this); + mark_as_dependent(thd, last_checked_context->select_lex, + context->select_lex, this, this); } } @@ -4174,14 +4181,18 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference) name, ((*ref)->with_sum_func? "reference to group function": "forward reference in item list")); - return TRUE; + goto error; } set_properties(); if ((*ref)->check_cols(1)) - return TRUE; + goto error; return FALSE; + +error: + context->process_error(thd); + return TRUE; } @@ -4389,6 +4400,19 @@ int Item_ref::save_in_field(Field *to, bool no_conversions) } +void Item_ref::make_field(Send_field *field) +{ + (*ref)->make_field(field); + /* Non-zero in case of a view */ + if (name) + field->col_name= name; + if (table_name) + field->table_name= table_name; + if (db_name) + field->db_name= db_name; +}; + + void Item_ref_null_helper::print(String *str) { str->append("(", 18); @@ -4452,6 +4476,31 @@ bool Item_direct_ref::get_date(TIME *ltime,uint fuzzydate) } +/* + Prepare referenced view viewld then call usual Item_direct_ref::fix_fields + + SYNOPSIS + Item_direct_view_ref::fix_fields() + thd thread handler + reference reference on reference where this item stored + + RETURN + FALSE OK + TRUE Error +*/ + +bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference) +{ + /* view fild reference must be defined */ + DBUG_ASSERT(*ref); + /* (*ref)->check_cols() will be made in Item_direct_ref::fix_fields */ + if (!(*ref)->fixed && + ((*ref)->fix_fields(thd, ref))) + return TRUE; + return Item_direct_ref::fix_fields(thd, reference); +} + + void Item_null_helper::print(String *str) { str->append("(", 14); @@ -4467,9 +4516,7 @@ bool Item_default_value::eq(const Item *item, bool binary_cmp) const } -bool Item_default_value::fix_fields(THD *thd, - struct st_table_list *table_list, - Item **items) +bool Item_default_value::fix_fields(THD *thd, Item **items) { Item *real_arg; Item_field *field_arg; @@ -4481,29 +4528,34 @@ bool Item_default_value::fix_fields(THD *thd, fixed= 1; return FALSE; } - if (!arg->fixed && arg->fix_fields(thd, table_list, &arg)) - return TRUE; + if (!arg->fixed && arg->fix_fields(thd, &arg)) + goto error; + real_arg= arg->real_item(); if (real_arg->type() != FIELD_ITEM) { my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name); - return TRUE; + goto error; } field_arg= (Item_field *)real_arg; if (field_arg->field->flags & NO_DEFAULT_VALUE_FLAG) { my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name); - return TRUE; + goto error; } if (!(def_field= (Field*) sql_alloc(field_arg->field->size_of()))) - return TRUE; + goto error; memcpy(def_field, field_arg->field, field_arg->field->size_of()); def_field->move_field(def_field->table->s->default_values - def_field->table->record[0]); set_field(def_field); return FALSE; + +error: + context->process_error(thd); + return TRUE; } @@ -4526,11 +4578,27 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions) { if (field_arg->flags & NO_DEFAULT_VALUE_FLAG) { - push_warning_printf(field_arg->table->in_use, - MYSQL_ERROR::WARN_LEVEL_WARN, - ER_NO_DEFAULT_FOR_FIELD, - ER(ER_NO_DEFAULT_FOR_FIELD), - field_arg->field_name); + if (context->error_processor == &view_error_processor) + { + TABLE_LIST *view= (cached_table->belong_to_view ? + cached_table->belong_to_view : + cached_table); + // TODO: make correct error message + push_warning_printf(field_arg->table->in_use, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_NO_DEFAULT_FOR_VIEW_FIELD, + ER(ER_NO_DEFAULT_FOR_VIEW_FIELD), + view->view_db.str, + view->view_name.str); + } + else + { + push_warning_printf(field_arg->table->in_use, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_NO_DEFAULT_FOR_FIELD, + ER(ER_NO_DEFAULT_FOR_FIELD), + field_arg->field_name); + } return 1; } field_arg->set_default(); @@ -4547,12 +4615,10 @@ bool Item_insert_value::eq(const Item *item, bool binary_cmp) const } -bool Item_insert_value::fix_fields(THD *thd, - struct st_table_list *table_list, - Item **items) +bool Item_insert_value::fix_fields(THD *thd, Item **items) { DBUG_ASSERT(fixed == 0); - if (!arg->fixed && arg->fix_fields(thd, table_list, &arg)) + if (!arg->fixed && arg->fix_fields(thd, &arg)) return TRUE; if (arg->type() == REF_ITEM) @@ -4641,9 +4707,7 @@ bool Item_trigger_field::eq(const Item *item, bool binary_cmp) const } -bool Item_trigger_field::fix_fields(THD *thd, - TABLE_LIST *table_list, - Item **items) +bool Item_trigger_field::fix_fields(THD *thd, Item **items) { /* Since trigger is object tightly associated with TABLE object most @@ -5411,6 +5475,34 @@ void Item_result_field::cleanup() DBUG_VOID_RETURN; } +/* + Dummy error processor used by default by Name_resolution_context + + SYNOPSIS + dummy_error_processor() + + NOTE + do nothing +*/ + +void dummy_error_processor(THD *thd, void *data) +{} + +/* + Wrapper of hide_view_error call for Name_resolution_context error processor + + SYNOPSIS + view_error_processor() + + NOTE + hide view underlying tables details in error messages +*/ + +void view_error_processor(THD *thd, void *data) +{ + ((TABLE_LIST *)data)->hide_view_error(thd); +} + /***************************************************************************** ** Instantiate templates *****************************************************************************/ diff --git a/sql/item.h b/sql/item.h index c8180b4932a..22641b8edd4 100644 --- a/sql/item.h +++ b/sql/item.h @@ -24,7 +24,6 @@ struct st_table_list; void item_init(void); /* Init item functions */ class Item_field; - /* "Declared Type Collation" A combination of collation and its derivation. @@ -218,6 +217,97 @@ struct Hybrid_type_traits_integer: public Hybrid_type_traits static const Hybrid_type_traits_integer *instance(); }; + +void dummy_error_processor(THD *thd, void *data); + +void view_error_processor(THD *thd, void *data); + +/* + Instances of Name_resolution_context store the information necesary for + name resolution of Items and other context analysis of a query made in + fix_fields(). + + This structure is a part of SELECT_LEX, a pointer to this structure is + assigned when an item is created (which happens mostly during parsing + (sql_yacc.yy)), but the structure itself will be initialized after parsing + is complete + + TODO: move subquery of INSERT ... SELECT and CREATE ... SELECT to + separate SELECT_LEX which allow to remove tricks of changing this + structure before and after INSERT/CREATE and its SELECT to make correct + field name resolution. +*/ +struct Name_resolution_context +{ + /* + The name resolution context to search in when an Item cannot be + resolved in this context (the context of an outer select) + */ + Name_resolution_context *outer_context; + + /* + List of tables used to resolve the items of this context. Usually these + are tables from the FROM clause of SELECT statement. The exceptions are + INSERT ... SELECT and CREATE ... SELECT statements, where SELECT + subquery is not moved to a separate SELECT_LEX. For these types of + statements we have to change this member dynamically to ensure correct + name resolution of different parts of the statement. + */ + TABLE_LIST *table_list; + + /* + SELECT_LEX item belong to, in case of merged VIEW it can differ from + SELECT_LEX where item was created, so we can't use table_list/field_list + from there + */ + st_select_lex *select_lex; + + /* + Processor of errors caused during Item name resolving, now used only to + hide underlying tables in errors about views (i.e. it substitute some + errors for views) + */ + void (*error_processor)(THD *, void *); + void *error_processor_data; + + /* + When TRUE items are resolved in this context both against the + SELECT list and this->table_list. If FALSE, items are resolved + only against this->table_list. + */ + bool resolve_in_select_list; + + /* + When FALSE we do not check columns right of resolving items, used to + prevent rights check on underlying tables of view + */ + bool check_privileges; + + Name_resolution_context() + :outer_context(0), table_list(0), select_lex(0), + error_processor_data(0), + check_privileges(TRUE) + {} + + void init() + { + resolve_in_select_list= FALSE; + error_processor= &dummy_error_processor; + } + + void resolve_in_table_list_only(TABLE_LIST *tables) + { + table_list= tables; + resolve_in_select_list= FALSE; + } + + void process_error(THD *thd) + { + (*error_processor)(thd, error_processor_data); + } +}; + + /*************************************************************************/ typedef bool (Item::*Item_processor)(byte *arg); @@ -234,7 +324,8 @@ class Item { Item(const Item &); /* Prevent use of these */ void operator=(Item &); public: - static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } + static void *operator new(size_t size) + { return (void*) sql_alloc((uint) size); } static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, (uint) size); } /* Special for SP local variable assignment - reusing slots */ @@ -248,7 +339,8 @@ public: PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER, - PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM}; + PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM, + VIEW_FIXER_ITEM}; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; @@ -302,7 +394,7 @@ public: virtual void cleanup(); virtual void make_field(Send_field *field); Field *make_string_field(TABLE *table); - virtual bool fix_fields(THD *, struct st_table_list *, Item **); + virtual bool fix_fields(THD *, Item **); /* should be used in case where we are sure that we do not need complete fix_fields() procedure. @@ -554,6 +646,8 @@ public: virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; } virtual bool cleanup_processor(byte *arg); virtual bool collect_item_field_processor(byte * arg) { return 0; } + virtual bool change_context_processor(byte *context) { return 0; } + virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual Item *set_no_const_sub(byte *arg) { return this; } virtual Item *replace_equal_field(byte * arg) { return this; } @@ -631,7 +725,7 @@ public: Item **this_item_addr(THD *thd, Item **); Item *this_const_item() const; - bool fix_fields(THD *, struct st_table_list *, Item **); + bool fix_fields(THD *, Item **); void cleanup(); inline uint get_offset() @@ -704,7 +798,9 @@ protected: const char *orig_db_name; const char *orig_table_name; const char *orig_field_name; + public: + Name_resolution_context *context; const char *db_name; const char *table_name; const char *field_name; @@ -722,13 +818,16 @@ public: */ TABLE_LIST *cached_table; st_select_lex *depended_from; - Item_ident(const char *db_name_par,const char *table_name_par, - const char *field_name_par); + Item_ident(Name_resolution_context *context_arg, + const char *db_name_arg, const char *table_name_arg, + const char *field_name_arg); Item_ident(THD *thd, Item_ident *item); const char *full_name() const; void cleanup(); bool remove_dependence_processor(byte * arg); void print(String *str); + virtual bool change_context_processor(byte *cntx) + { context= (Name_resolution_context *)cntx; return FALSE; } }; class Item_equal; @@ -750,12 +849,9 @@ public: /* field need any privileges (for VIEW creation) */ bool any_privileges; - Item_field(const char *db_par,const char *table_name_par, - const char *field_name_par) - :Item_ident(db_par,table_name_par,field_name_par), - field(0), result_field(0), item_equal(0), no_const_subst(0), - have_privileges(0), any_privileges(0) - { collation.set(DERIVATION_IMPLICIT); } + Item_field(Name_resolution_context *context_arg, + const char *db_arg,const char *table_name_arg, + const char *field_name_arg); /* Constructor needed to process subselect with temporary tables (see Item) */ @@ -765,7 +861,7 @@ public: and database names will live as long as Item_field (this is important in prepared statements). */ - Item_field(THD *thd, Field *field); + Item_field(THD *thd, Name_resolution_context *context_arg, Field *field); /* If this constructor is used, fix_fields() won't work, because db_name, table_name and column_name are unknown. It's necessary to call @@ -785,7 +881,7 @@ public: bool val_bool_result(); bool send(Protocol *protocol, String *str_arg); void reset_field(Field *f); - bool fix_fields(THD *, struct st_table_list *, Item **); + bool fix_fields(THD *, Item **); void make_field(Send_field *tmp_field); int save_in_field(Field *field,bool no_conversions); void save_org_in_field(Field *field); @@ -946,7 +1042,7 @@ public: bool get_time(TIME *tm); bool get_date(TIME *tm, uint fuzzydate); int save_in_field(Field *field, bool no_conversions); - bool fix_fields(THD *, struct st_table_list *, Item **); + bool fix_fields(THD *, Item **); void set_null(); void set_int(longlong i, uint32 max_length_arg); @@ -1317,9 +1413,11 @@ protected: public: Field *result_field; /* Save result here */ Item **ref; - Item_ref(const char *db_par, const char *table_name_par, - const char *field_name_par) - :Item_ident(db_par, table_name_par, field_name_par), result_field(0), ref(0) {} + Item_ref(Name_resolution_context *context_arg, + const char *db_arg, const char *table_name_arg, + const char *field_name_arg) + :Item_ident(context_arg, db_arg, table_name_arg, field_name_arg), + result_field(0), ref(0) {} /* This constructor is used in two scenarios: A) *item = NULL @@ -1334,10 +1432,12 @@ public: TODO we probably fix a superset of problems like in BUG#6658. Check this with Bar, and if we have a more broader set of problems like this. */ - Item_ref(Item **item, const char *table_name_par, const char *field_name_par); + Item_ref(Name_resolution_context *context_arg, Item **item, + const char *table_name_arg, const char *field_name_arg); /* Constructor need to process subselect with temporary tables (see Item) */ - Item_ref(THD *thd, Item_ref *item) :Item_ident(thd, item), result_field(item->result_field), ref(item->ref) {} + Item_ref(THD *thd, Item_ref *item) + :Item_ident(thd, item), result_field(item->result_field), ref(item->ref) {} enum Type type() const { return REF_ITEM; } bool eq(const Item *item, bool binary_cmp) const { return ref && (*ref)->eq(item, binary_cmp); } @@ -1354,8 +1454,8 @@ public: my_decimal *val_decimal_result(my_decimal *); bool val_bool_result(); bool send(Protocol *prot, String *tmp); - void make_field(Send_field *field) { (*ref)->make_field(field); } - bool fix_fields(THD *, struct st_table_list *, Item **); + void make_field(Send_field *field); + bool fix_fields(THD *, Item **); int save_in_field(Field *field, bool no_conversions); void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); } enum Item_result result_type () const { return (*ref)->result_type(); } @@ -1380,6 +1480,8 @@ public: { return (*ref)->walk(processor, arg); } void print(String *str); void cleanup(); + Item_field *filed_for_view_update() + { return (*ref)->filed_for_view_update(); } }; @@ -1390,9 +1492,10 @@ public: class Item_direct_ref :public Item_ref { public: - Item_direct_ref(Item **item, const char *table_name_par, - const char *field_name_par) - :Item_ref(item, table_name_par, field_name_par) {} + Item_direct_ref(Name_resolution_context *context_arg, Item **item, + const char *table_name_arg, + const char *field_name_arg) + :Item_ref(context_arg, item, table_name_arg, field_name_arg) {} /* Constructor need to process subselect with temporary tables (see Item) */ Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {} @@ -1405,6 +1508,24 @@ public: bool get_date(TIME *ltime,uint fuzzydate); }; +/* + Class for view fields, the same as Item_direct_ref, but call fix_fields + of reference if it is not called yet +*/ +class Item_direct_view_ref :public Item_direct_ref +{ +public: + Item_direct_view_ref(Name_resolution_context *context_arg, Item **item, + const char *table_name_arg, + const char *field_name_arg) + :Item_direct_ref(context_arg, item, table_name_arg, field_name_arg) {} + /* Constructor need to process subselect with temporary tables (see Item) */ + Item_direct_view_ref(THD *thd, Item_direct_ref *item) + :Item_direct_ref(thd, item) {} + + bool fix_fields(THD *, Item **); +}; + class Item_in_subselect; @@ -1413,9 +1534,11 @@ class Item_ref_null_helper: public Item_ref protected: Item_in_subselect* owner; public: - Item_ref_null_helper(Item_in_subselect* master, Item **item, - const char *table_name_par, const char *field_name_par): - Item_ref(item, table_name_par, field_name_par), owner(master) {} + Item_ref_null_helper(Name_resolution_context *context_arg, + Item_in_subselect* master, Item **item, + const char *table_name_arg, const char *field_name_arg) + :Item_ref(context_arg, item, table_name_arg, field_name_arg), + owner(master) {} double val_real(); longlong val_int(); String* val_str(String* s); @@ -1429,10 +1552,11 @@ class Item_null_helper :public Item_ref_null_helper { Item *store; public: - Item_null_helper(Item_in_subselect* master, Item *item, - const char *table_name_par, const char *field_name_par) - :Item_ref_null_helper(master, (store= 0, &store), table_name_par, - field_name_par), + Item_null_helper(Name_resolution_context *context_arg, + Item_in_subselect* master, Item *item, + const char *table_name_arg, const char *field_name_arg) + :Item_ref_null_helper(context_arg, master, (store= 0, &store), + table_name_arg, field_name_arg), store(item) { ref= &store; } void print(String *str); @@ -1583,13 +1707,17 @@ class Item_default_value : public Item_field { public: Item *arg; - Item_default_value() : - Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(NULL) {} - Item_default_value(Item *a) : - Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {} + Item_default_value(Name_resolution_context *context_arg) + :Item_field(context_arg, (const char *)NULL, (const char *)NULL, + (const char *)NULL), + arg(NULL) {} + Item_default_value(Name_resolution_context *context_arg, Item *a) + :Item_field(context_arg, (const char *)NULL, (const char *)NULL, + (const char *)NULL), + arg(a) {} enum Type type() const { return DEFAULT_VALUE_ITEM; } bool eq(const Item *item, bool binary_cmp) const; - bool fix_fields(THD *, struct st_table_list *, Item **); + bool fix_fields(THD *, Item **); void print(String *str); int save_in_field(Field *field_arg, bool no_conversions); table_map used_tables() const { return (table_map)0L; } @@ -1618,10 +1746,12 @@ class Item_insert_value : public Item_field { public: Item *arg; - Item_insert_value(Item *a) : - Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {} + Item_insert_value(Name_resolution_context *context_arg, Item *a) + :Item_field(context_arg, (const char *)NULL, (const char *)NULL, + (const char *)NULL), + arg(a) {} bool eq(const Item *item, bool binary_cmp) const; - bool fix_fields(THD *, struct st_table_list *, Item **); + bool fix_fields(THD *, Item **); void print(String *str); int save_in_field(Field *field_arg, bool no_conversions) { @@ -1683,15 +1813,17 @@ public: /* Pointer to Table_trigger_list object for table of this trigger */ Table_triggers_list *triggers; - Item_trigger_field(row_version_type row_ver_par, - const char *field_name_par): - Item_field((const char *)NULL, (const char *)NULL, field_name_par), - row_version(row_ver_par), field_idx((uint)-1) + Item_trigger_field(Name_resolution_context *context_arg, + row_version_type row_ver_arg, + const char *field_name_arg) + :Item_field(context_arg, + (const char *)NULL, (const char *)NULL, field_name_arg), + row_version(row_ver_arg), field_idx((uint)-1) {} void setup_field(THD *thd, TABLE *table); enum Type type() const { return TRIGGER_FIELD_ITEM; } bool eq(const Item *item, bool binary_cmp) const; - bool fix_fields(THD *, struct st_table_list *, Item **); + bool fix_fields(THD *, Item **); void print(String *str); table_map used_tables() const { return (table_map)0L; } void cleanup(); @@ -1880,7 +2012,7 @@ public: Item_type_holder(THD*, Item*); Item_result result_type() const; - virtual enum_field_types field_type() const { return fld_type; }; + enum_field_types field_type() const { return fld_type; }; enum Type type() const { return TYPE_HOLDER; } double val_real(); longlong val_int(); @@ -1892,6 +2024,7 @@ public: static enum_field_types get_real_type(Item *); }; + class st_select_lex; void mark_select_range_as_dependent(THD *thd, st_select_lex *last_select, diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 58a7f3316d7..5e08c9f9cb7 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -638,11 +638,9 @@ int Arg_comparator::compare_e_row() } -bool Item_in_optimizer::fix_left(THD *thd, - struct st_table_list *tables, - Item **ref) +bool Item_in_optimizer::fix_left(THD *thd, Item **ref) { - if (!args[0]->fixed && args[0]->fix_fields(thd, tables, args) || + if (!args[0]->fixed && args[0]->fix_fields(thd, args) || !cache && !(cache= Item_cache::get_cache(args[0]->result_type()))) return 1; @@ -679,16 +677,15 @@ bool Item_in_optimizer::fix_left(THD *thd, } -bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables, - Item ** ref) +bool Item_in_optimizer::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); - if (fix_left(thd, tables, ref)) + if (fix_left(thd, ref)) return TRUE; if (args[0]->maybe_null) maybe_null=1; - if (!args[1]->fixed && args[1]->fix_fields(thd, tables, args+1)) + if (!args[1]->fixed && args[1]->fix_fields(thd, args+1)) return TRUE; Item_in_subselect * sub= (Item_in_subselect *)args[1]; if (args[0]->cols() != sub->engine->cols()) @@ -2312,7 +2309,7 @@ void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item) bool -Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) +Item_cond::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); List_iterator li(list); @@ -2360,7 +2357,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) // item can be substituted in fix_fields if ((!item->fixed && - item->fix_fields(thd, tables, li.ref())) || + item->fix_fields(thd, li.ref())) || (item= *li.ref())->check_cols(1)) return TRUE; /* purecov: inspected */ used_tables_cache|= item->used_tables(); @@ -2747,11 +2744,11 @@ Item_func::optimize_type Item_func_like::select_optimize() const } -bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref) +bool Item_func_like::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); - if (Item_bool_func2::fix_fields(thd, tlist, ref) || - escape_item->fix_fields(thd, tlist, &escape_item)) + if (Item_bool_func2::fix_fields(thd, ref) || + escape_item->fix_fields(thd, &escape_item)) return TRUE; if (!escape_item->const_during_execution()) @@ -2815,13 +2812,13 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref) #ifdef USE_REGEX bool -Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) +Item_func_regex::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); if ((!args[0]->fixed && - args[0]->fix_fields(thd, tables, args)) || args[0]->check_cols(1) || + args[0]->fix_fields(thd, args)) || args[0]->check_cols(1) || (!args[1]->fixed && - args[1]->fix_fields(thd,tables, args + 1)) || args[1]->check_cols(1)) + args[1]->fix_fields(thd, args + 1)) || args[1]->check_cols(1)) return TRUE; /* purecov: inspected */ with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func; max_length= 1; @@ -3481,7 +3478,7 @@ void Item_equal::sort(Item_field_cmpfunc cmp, void *arg) } while (swap); } -bool Item_equal::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) +bool Item_equal::fix_fields(THD *thd, Item **ref) { List_iterator_fast li(fields); Item *item; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 7a22e76b217..16dab3c1b46 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -108,8 +108,8 @@ public: Item_in_optimizer(Item *a, Item_in_subselect *b): Item_bool_func(a, my_reinterpret_cast(Item *)(b)), cache(0), save_cache(0) {} - bool fix_fields(THD *, struct st_table_list *, Item **); - bool fix_left(THD *thd, struct st_table_list *tables, Item **ref); + bool fix_fields(THD *, Item **); + bool fix_left(THD *thd, Item **ref); bool is_null(); /* Item_in_optimizer item is special boolean function. On value request @@ -502,11 +502,11 @@ public: String *val_str(String *str); my_decimal *val_decimal(my_decimal *); enum Item_result result_type () const { return cached_result_type; } - bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref) + bool fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); args[0]->top_level_item(); - return Item_func::fix_fields(thd, tlist, ref); + return Item_func::fix_fields(thd, ref); } void fix_length_and_dec(); uint decimal_precision() const; @@ -961,7 +961,7 @@ public: optimize_type select_optimize() const; cond_result eq_cmp_result() const { return COND_TRUE; } const char *func_name() const { return "like"; } - bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); + bool fix_fields(THD *thd, Item **ref); }; #ifdef USE_REGEX @@ -980,7 +980,7 @@ public: regex_compiled(0),regex_is_const(0) {} void cleanup(); longlong val_int(); - bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); + bool fix_fields(THD *thd, Item **ref); const char *func_name() const { return "regexp"; } void print(String *str) { print_op(str); } CHARSET_INFO *compare_collation() { return cmp_collation.collation; } @@ -1024,7 +1024,7 @@ public: :Item_bool_func(), list(nlist), abort_on_null(0) {} bool add(Item *item) { return list.push_back(item); } void add_at_head(List *nlist) { list.prepand(nlist); } - bool fix_fields(THD *, struct st_table_list *, Item **ref); + bool fix_fields(THD *, Item **ref); enum Type type() const { return COND_ITEM; } List* argument_list() { return &list; } @@ -1033,7 +1033,7 @@ public: void print(String *str); void split_sum_func(THD *thd, Item **ref_pointer_array, List &fields); friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, - COND **conds); + COND **conds); void top_level_item() { abort_on_null=1; } void copy_andor_arguments(THD *thd, Item_cond *item); bool walk(Item_processor processor, byte *arg); @@ -1141,7 +1141,7 @@ public: void sort(Item_field_cmpfunc cmp, void *arg); friend class Item_equal_iterator; void fix_length_and_dec(); - bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); + bool fix_fields(THD *thd, Item **ref); void update_used_tables(); bool walk(Item_processor processor, byte *arg); Item *transform(Item_transformer transformer, byte *arg); diff --git a/sql/item_func.cc b/sql/item_func.cc index 1dbf28b67cb..b29074a9504 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -194,11 +194,10 @@ bool Item_func::agg_arg_charsets(DTCollation &coll, ((Item_field *)(*arg))->no_const_subst= 1; /* We do not check conv->fixed, because Item_func_conv_charset which can - be return by safe_charset_converter can't be fixed at creation, also - it do not need tables (second argument) for name resolving + be return by safe_charset_converter can't be fixed at creation */ *arg= conv; - conv->fix_fields(thd, 0, arg); + conv->fix_fields(thd, arg); } if (arena) thd->restore_backup_item_arena(arena, &backup); @@ -261,7 +260,6 @@ Item_func::Item_func(THD *thd, Item_func *item) SYNOPSIS: fix_fields() thd Thread object - tables List of all open tables involved in the query ref Pointer to where this object is used. This reference is used if we want to replace this object with another one (for example in the summary functions). @@ -290,7 +288,7 @@ Item_func::Item_func(THD *thd, Item_func *item) */ bool -Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) +Item_func::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); Item **arg,**arg_end; @@ -312,7 +310,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) We can't yet set item to *arg as fix_fields may change *arg We shouldn't call fix_fields() twice, so check 'fixed' field first */ - if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg))) + if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg))) return TRUE; /* purecov: inspected */ item= *arg; @@ -2010,10 +2008,9 @@ my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value) } -bool Item_func_rand::fix_fields(THD *thd, struct st_table_list *tables, - Item **ref) +bool Item_func_rand::fix_fields(THD *thd,Item **ref) { - if (Item_real_func::fix_fields(thd, tables, ref)) + if (Item_real_func::fix_fields(thd, ref)) return TRUE; used_tables_cache|= RAND_TABLE_BIT; if (arg_count) @@ -2604,7 +2601,7 @@ void udf_handler::cleanup() bool -udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, +udf_handler::fix_fields(THD *thd, Item_result_field *func, uint arg_count, Item **arguments) { #ifndef EMBEDDED_LIBRARY // Avoid compiler warning @@ -2646,7 +2643,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, arg++,i++) { if (!(*arg)->fixed && - (*arg)->fix_fields(thd, tables, arg)) + (*arg)->fix_fields(thd, arg)) DBUG_RETURN(1); // we can't assign 'item' before, because fix_fields() can change arg Item *item= *arg; @@ -3458,12 +3455,11 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, SELECT @a:= ). */ -bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables, - Item **ref) +bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); /* fix_fields will call Item_func_set_user_var::fix_length_and_dec */ - if (Item_func::fix_fields(thd, tables, ref) || + if (Item_func::fix_fields(thd, ref) || !(entry= get_variable(&thd->user_vars, name, 1))) return TRUE; /* @@ -4127,11 +4123,10 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const } -bool Item_user_var_as_out_param::fix_fields(THD *thd, TABLE_LIST *tables, - Item **ref) +bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); - if (Item::fix_fields(thd, tables, ref) || + if (Item::fix_fields(thd, ref) || !(entry= get_variable(&thd->user_vars, name, 1))) return TRUE; entry->type= STRING_RESULT; @@ -4314,7 +4309,7 @@ void Item_func_match::init_search(bool no_order) } -bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) +bool Item_func_match::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); Item *item; @@ -4329,7 +4324,7 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) modifications to find_best and auto_close as complement to auto_init code above. */ - if (Item_func::fix_fields(thd, tlist, ref) || + if (Item_func::fix_fields(thd, ref) || !args[0]->const_during_execution()) { my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST"); @@ -4690,8 +4685,9 @@ longlong Item_func_row_count::val_int() } -Item_func_sp::Item_func_sp(sp_name *name) - :Item_func(), m_name(name), m_sp(NULL), result_field(NULL) +Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name) + :Item_func(), context(context_arg), m_name(name), m_sp(NULL), + result_field(NULL) { maybe_null= 1; m_name->init_qname(current_thd); @@ -4699,8 +4695,10 @@ Item_func_sp::Item_func_sp(sp_name *name) } -Item_func_sp::Item_func_sp(sp_name *name, List &list) - :Item_func(list), m_name(name), m_sp(NULL), result_field(NULL) +Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, + sp_name *name, List &list) + :Item_func(list), context(context_arg), m_name(name), m_sp(NULL), + result_field(NULL) { maybe_null= 1; m_name->init_qname(current_thd); @@ -4944,7 +4942,10 @@ Item_func_sp::fix_length_and_dec() } if (!(field= sp_result_field())) + { + context->process_error(current_thd); DBUG_VOID_RETURN; + } decimals= field->decimals(); max_length= field->field_length; maybe_null= 1; diff --git a/sql/item_func.h b/sql/item_func.h index e0f14ceac75..f6bc35e1617 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -116,7 +116,7 @@ public: Item_func(List &list); // Constructor used for Item_cond_and/or (see Item comment) Item_func(THD *thd, Item_func *item); - bool fix_fields(THD *,struct st_table_list *, Item **ref); + bool fix_fields(THD *, Item **ref); table_map used_tables() const; table_map not_null_tables() const; void update_used_tables(); @@ -630,7 +630,7 @@ public: const char *func_name() const { return "rand"; } bool const_item() const { return 0; } void update_used_tables(); - bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref); + bool fix_fields(THD *thd, Item **ref); }; @@ -885,14 +885,15 @@ protected: udf_handler udf; public: - Item_udf_func(udf_func *udf_arg) :Item_func(), udf(udf_arg) {} + Item_udf_func(udf_func *udf_arg) + :Item_func(), udf(udf_arg) {} Item_udf_func(udf_func *udf_arg, List &list) :Item_func(list), udf(udf_arg) {} const char *func_name() const { return udf.name(); } - bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref) + bool fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); - bool res= udf.fix_fields(thd, tables, this, arg_count, args); + bool res= udf.fix_fields(thd, this, arg_count, args); used_tables_cache= udf.used_tables_cache; const_item_cache= udf.const_item_cache; fixed= 1; @@ -907,9 +908,11 @@ public: class Item_func_udf_float :public Item_udf_func { public: - Item_func_udf_float(udf_func *udf_arg) :Item_udf_func(udf_arg) {} - Item_func_udf_float(udf_func *udf_arg, List &list) - :Item_udf_func(udf_arg,list) {} + Item_func_udf_float(udf_func *udf_arg) + :Item_udf_func(udf_arg) {} + Item_func_udf_float(udf_func *udf_arg, + List &list) + :Item_udf_func(udf_arg, list) {} longlong val_int() { DBUG_ASSERT(fixed == 1); @@ -932,9 +935,11 @@ class Item_func_udf_float :public Item_udf_func class Item_func_udf_int :public Item_udf_func { public: - Item_func_udf_int(udf_func *udf_arg) :Item_udf_func(udf_arg) {} - Item_func_udf_int(udf_func *udf_arg, List &list) - :Item_udf_func(udf_arg,list) {} + Item_func_udf_int(udf_func *udf_arg) + :Item_udf_func(udf_arg) {} + Item_func_udf_int(udf_func *udf_arg, + List &list) + :Item_udf_func(udf_arg, list) {} longlong val_int(); double val_real() { return (double) Item_func_udf_int::val_int(); } String *val_str(String *str); @@ -946,9 +951,10 @@ public: class Item_func_udf_decimal :public Item_udf_func { public: - Item_func_udf_decimal(udf_func *udf_arg) :Item_udf_func(udf_arg) {} + Item_func_udf_decimal(udf_func *udf_arg) + :Item_udf_func(udf_arg) {} Item_func_udf_decimal(udf_func *udf_arg, List &list) - :Item_udf_func(udf_arg,list) {} + :Item_udf_func(udf_arg, list) {} longlong val_int(); double val_real(); my_decimal *val_decimal(my_decimal *); @@ -961,9 +967,10 @@ public: class Item_func_udf_str :public Item_udf_func { public: - Item_func_udf_str(udf_func *udf_arg) :Item_udf_func(udf_arg) {} + Item_func_udf_str(udf_func *udf_arg) + :Item_udf_func(udf_arg) {} Item_func_udf_str(udf_func *udf_arg, List &list) - :Item_udf_func(udf_arg,list) {} + :Item_udf_func(udf_arg, list) {} String *val_str(String *); double val_real() { @@ -998,8 +1005,10 @@ public: class Item_func_udf_float :public Item_real_func { public: - Item_func_udf_float(udf_func *udf_arg) :Item_real_func() {} - Item_func_udf_float(udf_func *udf_arg, List &list) :Item_real_func(list) {} + Item_func_udf_float(udf_func *udf_arg) + :Item_real_func() {} + Item_func_udf_float(udf_func *udf_arg, List &list) + :Item_real_func(list) {} double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; } }; @@ -1007,8 +1016,10 @@ class Item_func_udf_float :public Item_real_func class Item_func_udf_int :public Item_int_func { public: - Item_func_udf_int(udf_func *udf_arg) :Item_int_func() {} - Item_func_udf_int(udf_func *udf_arg, List &list) :Item_int_func(list) {} + Item_func_udf_int(udf_func *udf_arg) + :Item_int_func() {} + Item_func_udf_int(udf_func *udf_arg, List &list) + :Item_int_func(list) {} longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; } }; @@ -1016,8 +1027,10 @@ public: class Item_func_udf_decimal :public Item_int_func { public: - Item_func_udf_decimal(udf_func *udf_arg) :Item_int_func() {} - Item_func_udf_decimal(udf_func *udf_arg, List &list) :Item_int_func(list) {} + Item_func_udf_decimal(udf_func *udf_arg) + :Item_int_func() {} + Item_func_udf_decimal(udf_func *udf_arg, List &list) + :Item_int_func(list) {} my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; } }; @@ -1025,8 +1038,10 @@ public: class Item_func_udf_str :public Item_func { public: - Item_func_udf_str(udf_func *udf_arg) :Item_func() {} - Item_func_udf_str(udf_func *udf_arg, List &list) :Item_func(list) {} + Item_func_udf_str(udf_func *udf_arg) + :Item_func() {} + Item_func_udf_str(udf_func *udf_arg, List &list) + :Item_func(list) {} String *val_str(String *) { DBUG_ASSERT(fixed == 1); null_value=1; return 0; } double val_real() { DBUG_ASSERT(fixed == 1); null_value= 1; return 0.0; } @@ -1116,7 +1131,7 @@ public: bool check(); bool update(); enum Item_result result_type () const { return cached_result_type; } - bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref); + bool fix_fields(THD *thd, Item **ref); void fix_length_and_dec(); void print(String *str); void print_as_stmt(String *str); @@ -1176,7 +1191,7 @@ public: String *val_str(String *str); my_decimal *val_decimal(my_decimal *decimal_buffer); /* fix_fields() binds variable name with its entry structure */ - bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref); + bool fix_fields(THD *thd, Item **ref); void print(String *str); void set_null_value(CHARSET_INFO* cs); void set_value(const char *str, uint length, CHARSET_INFO* cs); @@ -1230,7 +1245,7 @@ public: const char *func_name() const { return "match"; } void update_used_tables() {} table_map not_null_tables() const { return 0; } - bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); + bool fix_fields(THD *thd, Item **ref); bool eq(const Item *, bool binary_cmp) const; /* The following should be safe, even if we compare doubles */ longlong val_int() { DBUG_ASSERT(fixed == 1); return val_real() != 0.0; } @@ -1302,6 +1317,7 @@ class sp_name; class Item_func_sp :public Item_func { private: + Name_resolution_context *context; sp_name *m_name; mutable sp_head *m_sp; TABLE *dummy_table; @@ -1314,9 +1330,10 @@ private: public: - Item_func_sp(sp_name *name); + Item_func_sp(Name_resolution_context *context_arg, sp_name *name); - Item_func_sp(sp_name *name, List &list); + Item_func_sp(Name_resolution_context *context_arg, + sp_name *name, List &list); virtual ~Item_func_sp() {} @@ -1361,6 +1378,9 @@ public: return result_field->val_str(str); } + virtual bool change_context_processor(byte *cntx) + { context= (Name_resolution_context *)cntx; return FALSE; } + void fix_length_and_dec(); }; diff --git a/sql/item_row.cc b/sql/item_row.cc index 0c8baa332ca..9362518e6ef 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -53,7 +53,7 @@ void Item_row::illegal_method_call(const char *method) DBUG_VOID_RETURN; } -bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref) +bool Item_row::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); null_value= 0; @@ -61,7 +61,7 @@ bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref) Item **arg, **arg_end; for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++) { - if ((*arg)->fix_fields(thd, tabl, arg)) + if ((*arg)->fix_fields(thd, arg)) return TRUE; // we can't assign 'item' before, because fix_fields() can change arg Item *item= *arg; diff --git a/sql/item_row.h b/sql/item_row.h index e6b23eebb49..6fbe7436b72 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -61,7 +61,7 @@ public: illegal_method_call((const char*)"val_decimal"); return 0; }; - bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); + bool fix_fields(THD *thd, Item **ref); void split_sum_func(THD *thd, Item **ref_pointer_array, List &fields); table_map used_tables() const { return used_tables_cache; }; bool const_item() const { return const_item_cache; }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 06239de1f99..40c4c501222 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -461,7 +461,7 @@ String *Item_func_des_decrypt::val_str(String *str) struct st_des_keyblock keyblock; struct st_des_keyschedule keyschedule; String *res= args[0]->val_str(str); - uint length=res->length(),tail; + uint length= 0, tail; if ((null_value=args[0]->null_value)) goto error; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index c4beb3b08cb..b8696895047 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -415,12 +415,12 @@ class Item_func_make_set :public Item_str_func public: Item_func_make_set(Item *a,List &list) :Item_str_func(list),item(a) {} String *val_str(String *str); - bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) + bool fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); - return ((!item->fixed && item->fix_fields(thd, tlist, &item)) || + return ((!item->fixed && item->fix_fields(thd, &item)) || item->check_cols(1) || - Item_func::fix_fields(thd, tlist, ref)); + Item_func::fix_fields(thd, ref)); } void split_sum_func(THD *thd, Item **ref_pointer_array, List &fields); void fix_length_and_dec(); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index c7587686ecd..ad1c9977e5b 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -130,7 +130,7 @@ Item_subselect::select_transformer(JOIN *join) } -bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) +bool Item_subselect::fix_fields(THD *thd_param, Item **ref) { char const *save_where= thd_param->where; bool res; @@ -165,7 +165,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) substitution= 0; thd->where= "checking transformed subquery"; if (!(*ref)->fixed) - ret= (*ref)->fix_fields(thd, tables, ref); + ret= (*ref)->fix_fields(thd, ref); thd->where= save_where; return ret; } @@ -833,7 +833,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, reference, also Item_sum_(max|min) can't be fixed after creation, so we do not check item->fixed */ - if (item->fix_fields(thd, join->tables_list, 0)) + if (item->fix_fields(thd, 0)) DBUG_RETURN(RES_ERROR); /* we added aggregate function => we have to change statistic */ count_field_types(&join->tmp_table_param, join->all_fields, 0); @@ -862,7 +862,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, thd->lex->current_select= up= current->return_after_parsing(); //optimizer never use Item **ref => we can pass 0 as parameter - if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0)) + if (!optimizer || optimizer->fix_left(thd, 0)) { thd->lex->current_select= current; DBUG_RETURN(RES_ERROR); @@ -873,7 +873,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, As far as Item_ref_in_optimizer do not substitute itself on fix_fields we can use same item for all selects. */ - expr= new Item_direct_ref((Item**)optimizer->get_cache(), + expr= new Item_direct_ref(&select_lex->context, + (Item**)optimizer->get_cache(), (char *)"", (char *)in_left_expr_name); @@ -893,7 +894,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, { bool tmp; Item *item= func->create(expr, - new Item_ref_null_helper(this, + new Item_ref_null_helper(&select_lex->context, + this, select_lex-> ref_pointer_array, (char *)"", @@ -913,7 +915,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, we do not check join->having->fixed, because Item_and (from and_items) or comparison function (from func->create) can't be fixed after creation */ - tmp= join->having->fix_fields(thd, join->tables_list, 0); + tmp= join->having->fix_fields(thd, 0); select_lex->having_fix_field= 0; if (tmp) DBUG_RETURN(RES_ERROR); @@ -949,7 +951,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, and_items) or comparison function (from func->create) can't be fixed after creation */ - tmp= join->having->fix_fields(thd, join->tables_list, 0); + tmp= join->having->fix_fields(thd, 0); select_lex->having_fix_field= 0; if (tmp) DBUG_RETURN(RES_ERROR); @@ -971,7 +973,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, we do not check join->conds->fixed, because Item_and can't be fixed after creation */ - if (join->conds->fix_fields(thd, join->tables_list, 0)) + if (join->conds->fix_fields(thd, 0)) DBUG_RETURN(RES_ERROR); } else @@ -983,22 +985,23 @@ Item_in_subselect::single_value_transformer(JOIN *join, comparison functions can't be changed during fix_fields() we can assign select_lex->having here, and pass 0 as last argument (reference) to fix_fields() - */ - item= func->create(expr, - new Item_null_helper(this, item, - (char *)"", - (char *)"")); + */ + item= func->create(expr, + new Item_null_helper(&select_lex->context, + this, item, + (char *)"", + (char *)"")); #ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE if (!abort_on_null && left_expr->maybe_null) item= new Item_cond_or(new Item_func_isnull(left_expr), item); #endif - select_lex->having= join->having= item; + select_lex->having= join->having= item; select_lex->having_fix_field= 1; /* we do not check join->having->fixed, because comparison function (from func->create) can't be fixed after creation */ - tmp= join->having->fix_fields(thd, join->tables_list, 0); + tmp= join->having->fix_fields(thd, 0); select_lex->having_fix_field= 0; if (tmp) DBUG_RETURN(RES_ERROR); @@ -1048,7 +1051,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) SELECT_LEX *current= thd->lex->current_select, *up; thd->lex->current_select= up= current->return_after_parsing(); //optimizer never use Item **ref => we can pass 0 as parameter - if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0)) + if (!optimizer || optimizer->fix_left(thd, 0)) { thd->lex->current_select= current; DBUG_RETURN(RES_ERROR); @@ -1071,12 +1074,14 @@ Item_in_subselect::row_value_transformer(JOIN *join) if (select_lex->ref_pointer_array[i]-> check_cols(left_expr->el(i)->cols())) DBUG_RETURN(RES_ERROR); - Item *func= new Item_ref_null_helper(this, + Item *func= new Item_ref_null_helper(&select_lex->context, + this, select_lex->ref_pointer_array+i, (char *) "", (char *) ""); func= - eq_creator.create(new Item_direct_ref((*optimizer->get_cache())-> + eq_creator.create(new Item_direct_ref(&select_lex->context, + (*optimizer->get_cache())-> addr(i), (char *)"", (char *)in_left_expr_name), @@ -1099,7 +1104,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) join->having can't be fixed after creation, so we do not check join->having->fixed */ - if (join->having->fix_fields(thd, join->tables_list, 0)) + if (join->having->fix_fields(thd, 0)) { select_lex->having_fix_field= 0; DBUG_RETURN(RES_ERROR); @@ -1118,7 +1123,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) join->conds can't be fixed after creation, so we do not check join->conds->fixed */ - if (join->conds->fix_fields(thd, join->tables_list, 0)) + if (join->conds->fix_fields(thd, 0)) DBUG_RETURN(RES_ERROR); } @@ -1189,8 +1194,7 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func) thd->lex->current_select= up= current->return_after_parsing(); result= (!left_expr->fixed && - left_expr->fix_fields(thd, up->get_table_list(), - optimizer->arguments())); + left_expr->fix_fields(thd, optimizer->arguments())); /* fix_fields can change reference to left_expr, we need reassign it */ left_expr= optimizer->arguments()[0]; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 84935429353..e05db4a00cc 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -92,7 +92,7 @@ public: val_int(); return null_value; } - bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); + bool fix_fields(THD *thd, Item **ref); virtual bool exec(); virtual void fix_length_and_dec(); table_map used_tables() const; @@ -119,9 +119,9 @@ public: friend class select_subselect; friend class Item_in_optimizer; - friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **); - friend bool Item_ref::fix_fields(THD *, TABLE_LIST *, Item **); - friend bool Item_param::fix_fields(THD *, TABLE_LIST *, Item **); + friend bool Item_field::fix_fields(THD *, Item **); + friend bool Item_ref::fix_fields(THD *, Item **); + friend bool Item_param::fix_fields(THD *, Item **); friend void mark_select_range_as_dependent(THD*, st_select_lex*, st_select_lex*, Field*, Item*, Item_ident*); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 76f94801b49..d2f1016891b 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -193,7 +193,7 @@ my_decimal *Item_sum_int::val_decimal(my_decimal *decimal_value) bool -Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) +Item_sum_num::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); @@ -208,7 +208,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) maybe_null=0; for (uint i=0 ; i < arg_count ; i++) { - if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1)) + if (args[i]->fix_fields(thd, args + i) || args[i]->check_cols(1)) return TRUE; set_if_bigger(decimals, args[i]->decimals); maybe_null |= args[i]->maybe_null; @@ -253,7 +253,7 @@ Item_sum_hybrid::Item_sum_hybrid(THD *thd, Item_sum_hybrid *item) } bool -Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) +Item_sum_hybrid::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); @@ -268,7 +268,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) // 'item' can be changed during fix_fields if (!item->fixed && - item->fix_fields(thd, tables, args) || + item->fix_fields(thd, args) || (item= args[0])->check_cols(1)) return TRUE; decimals=item->decimals; @@ -2766,11 +2766,12 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)), */ Item_func_group_concat:: -Item_func_group_concat(bool distinct_arg, List *select_list, +Item_func_group_concat(Name_resolution_context *context_arg, + bool distinct_arg, List *select_list, SQL_LIST *order_list, String *separator_arg) :tmp_table_param(0), warning(0), separator(separator_arg), tree(0), table(0), - order(0), tables_list(0), + order(0), context(context_arg), arg_count_order(order_list ? order_list->elements : 0), arg_count_field(select_list->elements), count_cut_values(0), @@ -2826,7 +2827,7 @@ Item_func_group_concat::Item_func_group_concat(THD *thd, tree(item->tree), table(item->table), order(item->order), - tables_list(item->tables_list), + context(item->context), arg_count_order(item->arg_count_order), arg_count_field(item->arg_count_field), count_cut_values(item->count_cut_values), @@ -2946,7 +2947,7 @@ bool Item_func_group_concat::add() bool -Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) +Item_func_group_concat::fix_fields(THD *thd, Item **ref) { uint i; /* for loop variable */ DBUG_ASSERT(fixed == 0); @@ -2968,7 +2969,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) for (i=0 ; i < arg_count ; i++) { if ((!args[i]->fixed && - args[i]->fix_fields(thd, tables, args + i)) || + args[i]->fix_fields(thd, args + i)) || args[i]->check_cols(1)) return TRUE; if (i < arg_count_field) @@ -2979,7 +2980,6 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) null_value= 1; thd->allow_sum_func= 1; max_length= thd->variables.group_concat_max_len; - tables_list= tables; fixed= 1; return FALSE; } @@ -3029,7 +3029,7 @@ bool Item_func_group_concat::setup(THD *thd) tmp table columns. */ if (arg_count_order && - setup_order(thd, args, tables_list, list, all_fields, *order)) + setup_order(thd, args, context->table_list, list, all_fields, *order)) DBUG_RETURN(TRUE); count_field_types(tmp_table_param,all_fields,0); diff --git a/sql/item_sum.h b/sql/item_sum.h index b9a90ee5de5..b02d18e9a55 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -98,7 +98,7 @@ public: */ virtual const char *func_name() const= 0; virtual Item *result_item(Field *field) - { return new Item_field(field);} + { return new Item_field(field); } table_map used_tables() const { return ~(table_map) 0; } /* Not used */ bool const_item() const { return 0; } bool is_null() { return null_value; } @@ -124,7 +124,7 @@ public: Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {} Item_sum_num(List &list) :Item_sum(list) {} Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {} - bool fix_fields(THD *, TABLE_LIST *, Item **); + bool fix_fields(THD *, Item **); longlong val_int() { DBUG_ASSERT(fixed == 1); @@ -543,7 +543,7 @@ protected: was_values(TRUE) { collation.set(&my_charset_bin); } Item_sum_hybrid(THD *thd, Item_sum_hybrid *item); - bool fix_fields(THD *, TABLE_LIST *, Item **); + bool fix_fields(THD *, Item **); table_map used_tables() const { return used_table_cache; } bool const_item() const { return !used_table_cache; } @@ -660,18 +660,21 @@ protected: udf_handler udf; public: - Item_udf_sum(udf_func *udf_arg) :Item_sum(), udf(udf_arg) { quick_group=0;} - Item_udf_sum( udf_func *udf_arg, List &list ) - :Item_sum( list ), udf(udf_arg) + Item_udf_sum(udf_func *udf_arg) + :Item_sum(), udf(udf_arg) + { quick_group=0; } + Item_udf_sum(udf_func *udf_arg, List &list) + :Item_sum(list), udf(udf_arg) { quick_group=0;} Item_udf_sum(THD *thd, Item_udf_sum *item) - :Item_sum(thd, item), udf(item->udf) { udf.not_original= TRUE; } + :Item_sum(thd, item), udf(item->udf) + { udf.not_original= TRUE; } const char *func_name() const { return udf.name(); } - bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) + bool fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); fixed= 1; - return udf.fix_fields(thd,tables,this,this->arg_count,this->args); + return udf.fix_fields(thd, this, this->arg_count, this->args); } enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } virtual bool have_field_update(void) const { return 0; } @@ -688,9 +691,10 @@ public: class Item_sum_udf_float :public Item_udf_sum { public: - Item_sum_udf_float(udf_func *udf_arg) :Item_udf_sum(udf_arg) {} + Item_sum_udf_float(udf_func *udf_arg) + :Item_udf_sum(udf_arg) {} Item_sum_udf_float(udf_func *udf_arg, List &list) - :Item_udf_sum(udf_arg,list) {} + :Item_udf_sum(udf_arg, list) {} Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) :Item_udf_sum(thd, item) {} longlong val_int() @@ -709,9 +713,10 @@ class Item_sum_udf_float :public Item_udf_sum class Item_sum_udf_int :public Item_udf_sum { public: - Item_sum_udf_int(udf_func *udf_arg) :Item_udf_sum(udf_arg) {} + Item_sum_udf_int(udf_func *udf_arg) + :Item_udf_sum(udf_arg) {} Item_sum_udf_int(udf_func *udf_arg, List &list) - :Item_udf_sum(udf_arg,list) {} + :Item_udf_sum(udf_arg, list) {} Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) :Item_udf_sum(thd, item) {} longlong val_int(); @@ -728,7 +733,8 @@ public: class Item_sum_udf_str :public Item_udf_sum { public: - Item_sum_udf_str(udf_func *udf_arg) :Item_udf_sum(udf_arg) {} + Item_sum_udf_str(udf_func *udf_arg) + :Item_udf_sum(udf_arg) {} Item_sum_udf_str(udf_func *udf_arg, List &list) :Item_udf_sum(udf_arg,list) {} Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) @@ -766,9 +772,10 @@ public: class Item_sum_udf_decimal :public Item_udf_sum { public: - Item_sum_udf_decimal(udf_func *udf_arg) :Item_udf_sum(udf_arg) {} + Item_sum_udf_decimal(udf_func *udf_arg) + :Item_udf_sum(udf_arg) {} Item_sum_udf_decimal(udf_func *udf_arg, List &list) - :Item_udf_sum(udf_arg,list) {} + :Item_udf_sum(udf_arg, list) {} Item_sum_udf_decimal(THD *thd, Item_sum_udf_decimal *item) :Item_udf_sum(thd, item) {} String *val_str(String *); @@ -785,7 +792,8 @@ public: class Item_sum_udf_float :public Item_sum_num { public: - Item_sum_udf_float(udf_func *udf_arg) :Item_sum_num() {} + Item_sum_udf_float(udf_func *udf_arg) + :Item_sum_num() {} Item_sum_udf_float(udf_func *udf_arg, List &list) :Item_sum_num() {} Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) :Item_sum_num(thd, item) {} @@ -800,7 +808,8 @@ class Item_sum_udf_float :public Item_sum_num class Item_sum_udf_int :public Item_sum_num { public: - Item_sum_udf_int(udf_func *udf_arg) :Item_sum_num() {} + Item_sum_udf_int(udf_func *udf_arg) + :Item_sum_num() {} Item_sum_udf_int(udf_func *udf_arg, List &list) :Item_sum_num() {} Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) :Item_sum_num(thd, item) {} @@ -816,15 +825,17 @@ public: class Item_sum_udf_decimal :public Item_sum_num { public: - Item_sum_udf_decimal(udf_func *udf_arg) :Item_sum_num() {} - Item_sum_udf_decimal(udf_func *udf_arg, List &list) :Item_sum_num() {} + Item_sum_udf_decimal(udf_func *udf_arg) + :Item_sum_num() {} + Item_sum_udf_decimal(udf_func *udf_arg, List &list) + :Item_sum_num() {} Item_sum_udf_decimal(THD *thd, Item_sum_udf_float *item) :Item_sum_num(thd, item) {} enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; } my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; } void clear() {} - bool add() { return 0; } + bool add() { return 0; } void update_field() {} }; @@ -832,8 +843,10 @@ class Item_sum_udf_decimal :public Item_sum_num class Item_sum_udf_str :public Item_sum_num { public: - Item_sum_udf_str(udf_func *udf_arg) :Item_sum_num() {} - Item_sum_udf_str(udf_func *udf_arg, List &list) :Item_sum_num() {} + Item_sum_udf_str(udf_func *udf_arg) + :Item_sum_num() {} + Item_sum_udf_str(udf_func *udf_arg, List &list) + :Item_sum_num() {} Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) :Item_sum_num(thd, item) {} String *val_str(String *) @@ -862,7 +875,7 @@ class Item_func_group_concat : public Item_sum TREE *tree; TABLE *table; ORDER **order; - TABLE_LIST *tables_list; + Name_resolution_context *context; uint arg_count_order; // total count of ORDER BY items uint arg_count_field; // count of arguments uint count_cut_values; @@ -887,8 +900,9 @@ class Item_func_group_concat : public Item_sum Item_func_group_concat *group_concat_item); public: - Item_func_group_concat(bool is_distinct,List *is_select, - SQL_LIST *is_order,String *is_separator); + Item_func_group_concat(Name_resolution_context *context_arg, + bool is_distinct, List *is_select, + SQL_LIST *is_order, String *is_separator); Item_func_group_concat(THD *thd, Item_func_group_concat *item); ~Item_func_group_concat() {} @@ -901,7 +915,7 @@ public: bool add(); void reset_field() {} // not used void update_field() {} // not used - bool fix_fields(THD *, TABLE_LIST *, Item **); + bool fix_fields(THD *,Item **); bool setup(THD *thd); void make_unique(); double val_real() @@ -927,4 +941,6 @@ public: Item *copy_or_same(THD* thd); void no_rows_in_result() {} void print(String *str); + virtual bool change_context_processor(byte *cntx) + { context= (Name_resolution_context *)cntx; return FALSE; } }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 19386c15835..cac9613f1ad 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1753,10 +1753,10 @@ void Item_func_convert_tz::fix_length_and_dec() bool -Item_func_convert_tz::fix_fields(THD *thd_arg, TABLE_LIST *tables_arg, Item **ref) +Item_func_convert_tz::fix_fields(THD *thd_arg, Item **ref) { String str; - if (Item_date_func::fix_fields(thd_arg, tables_arg, ref)) + if (Item_date_func::fix_fields(thd_arg, ref)) return TRUE; tz_tables= thd_arg->lex->time_zone_tables_used; diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index a6dd9f7da91..107d12e6da2 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -561,7 +561,7 @@ class Item_func_convert_tz :public Item_date_func double val_real() { return (double) val_int(); } String *val_str(String *str); const char *func_name() const { return "convert_tz"; } - bool fix_fields(THD *, struct st_table_list *, Item **); + bool fix_fields(THD *, Item **); void fix_length_and_dec(); bool get_date(TIME *res, uint fuzzy_date); void cleanup(); diff --git a/sql/item_uniq.h b/sql/item_uniq.h index e95aa35101e..c884c454dac 100644 --- a/sql/item_uniq.h +++ b/sql/item_uniq.h @@ -47,7 +47,7 @@ public: bool add() { return 0; } void reset_field() {} void update_field() {} - bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) + bool fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); fixed= 1; diff --git a/sql/log_event.cc b/sql/log_event.cc index 8f109f00c5f..5a612791cdd 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2618,13 +2618,15 @@ void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_ev #ifndef MYSQL_CLIENT void Load_log_event::set_fields(const char* affected_db, - List &field_list) + List &field_list, + Name_resolution_context *context) { uint i; const char* field = fields; for (i= 0; i < num_fields; i++) { - field_list.push_back(new Item_field(affected_db, table_name, field)); + field_list.push_back(new Item_field(context, + affected_db, table_name, field)); field+= field_lens[i] + 1; } } @@ -2789,7 +2791,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, ex.skip_lines = skip_lines; List field_list; - set_fields(thd->db,field_list); + thd->main_lex.select_lex.context.resolve_in_table_list_only(&tables); + set_fields(thd->db, field_list, &thd->main_lex.select_lex.context); thd->variables.pseudo_thread_id= thread_id; List set_fields; if (net) @@ -3617,7 +3620,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) Item_func_set_user_var can't substitute something else on its place => 0 can be passed as last argument (reference on item) */ - e.fix_fields(thd, 0, 0); + e.fix_fields(thd, 0); /* A variable can just be considered as a table with a single record and with a single column. Thus, like diff --git a/sql/log_event.h b/sql/log_event.h index b163a37e7cc..9f4681ae2c5 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -877,7 +877,8 @@ public: const char* table_name_arg, List& fields_arg, enum enum_duplicates handle_dup, bool ignore, bool using_trans); - void set_fields(const char* db, List &fields_arg); + void set_fields(const char* db, List &fields_arg, + Name_resolution_context *context); const char* get_db() { return db; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 805af08b76a..ecd32ef35af 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -726,7 +726,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table,List &fields, List &values, List &update_fields, List &update_values, enum_duplicates flag, bool ignore); -int check_that_all_fields_are_given_values(THD *thd, TABLE *entry); +int check_that_all_fields_are_given_values(THD *thd, TABLE *entry, + TABLE_LIST *table_list); bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds); bool mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, SQL_LIST *order, ha_rows rows, ulong options); @@ -893,16 +894,29 @@ Item ** find_item_in_list(Item *item, List &items, uint *counter, bool *unaliased); bool get_key_map_from_key_list(key_map *map, TABLE *table, List *index_list); -bool insert_fields(THD *thd,TABLE_LIST *tables, +bool insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, const char *table_name, - List_iterator *it, bool any_privileges); -bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds, + List_iterator *it, bool any_privileges); +bool setup_tables(THD *thd, Name_resolution_context *context, + TABLE_LIST *tables, Item **conds, TABLE_LIST **leaves, bool select_insert); int setup_wild(THD *thd, TABLE_LIST *tables, List &fields, List *sum_func_list, uint wild_num); -bool setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables, +bool setup_fields(THD *thd, Item** ref_pointer_array, List &item, bool set_query_id, List *sum_func_list, bool allow_sum_func); +inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array, + List &item, bool set_query_id, + List *sum_func_list, + bool allow_sum_func) +{ + bool res; + thd->lex->select_lex.no_wrap_view_item= TRUE; + res= setup_fields(thd, ref_pointer_array, item, set_query_id, sum_func_list, + allow_sum_func); + thd->lex->select_lex.no_wrap_view_item= FALSE; + return res; +} int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds); int setup_ftfuncs(SELECT_LEX* select); diff --git a/sql/set_var.cc b/sql/set_var.cc index 1c0de702e4e..fbf3332a37a 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2983,7 +2983,7 @@ int set_var::check(THD *thd) } if ((!value->fixed && - value->fix_fields(thd, 0, &value)) || value->check_cols(1)) + value->fix_fields(thd, &value)) || value->check_cols(1)) return -1; if (var->check_update_type(value->result_type())) { @@ -3017,7 +3017,7 @@ int set_var::light_check(THD *thd) if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)) return 1; - if (value && ((!value->fixed && value->fix_fields(thd, 0, &value)) || + if (value && ((!value->fixed && value->fix_fields(thd, &value)) || value->check_cols(1))) return -1; return 0; @@ -3046,7 +3046,7 @@ int set_var_user::check(THD *thd) Item_func_set_user_var can't substitute something else on its place => 0 can be passed as last argument (reference on item) */ - return (user_var_item->fix_fields(thd, 0, (Item**) 0) || + return (user_var_item->fix_fields(thd, (Item**) 0) || user_var_item->check()) ? -1 : 0; } @@ -3069,7 +3069,7 @@ int set_var_user::light_check(THD *thd) Item_func_set_user_var can't substitute something else on its place => 0 can be passed as last argument (reference on item) */ - return (user_var_item->fix_fields(thd, 0, (Item**) 0)); + return (user_var_item->fix_fields(thd, (Item**) 0)); } diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 7ae5130764f..747e7031530 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5358,3 +5358,5 @@ ER_STMT_HAS_NO_OPEN_CURSOR eng "The statement (%lu) has no open cursor." ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG eng "Explicit or implicit commit is not allowed in stored function or trigger." +ER_NO_DEFAULT_FOR_VIEW_FIELD + eng "Field of view '%-.64s.%-.64s' underlying table doesn't have a default value" diff --git a/sql/sp.cc b/sql/sp.cc index 4f89d6ba6da..f376c9b5ed2 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -676,14 +676,18 @@ db_show_routine_status(THD *thd, int type, const char *wild) tables is not VIEW for sure => we can pass 0 as condition */ - setup_tables(thd, &tables, 0, &leaves, FALSE); + thd->lex->select_lex.context.resolve_in_table_list_only(&tables); + setup_tables(thd, &thd->lex->select_lex.context, + &tables, 0, &leaves, FALSE); for (used_field= &used_fields[0]; used_field->field_name; used_field++) { - Item_field *field= new Item_field("mysql", "proc", + Item_field *field= new Item_field(&thd->lex->select_lex.context, + "mysql", "proc", used_field->field_name); - if (!(used_field->field= find_field_in_tables(thd, field, &tables, + if (!field || + !(used_field->field= find_field_in_tables(thd, field, &tables, 0, REPORT_ALL_ERRORS, 1))) { res= SP_INTERNAL_ERROR; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index b2de24ca9b5..6be80568186 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -117,7 +117,7 @@ sp_prepare_func_item(THD* thd, Item **it_addr) DBUG_ENTER("sp_prepare_func_item"); it_addr= it->this_item_addr(thd, it_addr); - if (!it->fixed && (*it_addr)->fix_fields(thd, 0, it_addr)) + if (!it->fixed && (*it_addr)->fix_fields(thd, it_addr)) { DBUG_PRINT("info", ("fix_fields() failed")); DBUG_RETURN(NULL); @@ -962,7 +962,7 @@ sp_head::execute_procedure(THD *thd, List *args) we do not check suv->fixed, because it can't be fixed after creation */ - suv->fix_fields(thd, NULL, &item); + suv->fix_fields(thd, &item); suv->fix_length_and_dec(); suv->check(); suv->update(); @@ -1579,8 +1579,8 @@ sp_instr_set_trigger_field::execute(THD *thd, uint *nextp) DBUG_ENTER("sp_instr_set_trigger_field::execute"); /* QQ: Still unsure what should we return in case of error 1 or -1 ? */ - if (!value->fixed && value->fix_fields(thd, 0, &value) || - trigger_field->fix_fields(thd, 0, 0) || + if (!value->fixed && value->fix_fields(thd, &value) || + trigger_field->fix_fields(thd, 0) || (value->save_in_field(trigger_field->field, 0) < 0)) res= -1; *nextp= m_ip + 1; diff --git a/sql/sp_head.h b/sql/sp_head.h index aaef5a3d50e..08967bd9b4f 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -470,10 +470,11 @@ class sp_instr_set_trigger_field : public sp_instr public: - sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx, + sp_instr_set_trigger_field(Name_resolution_context *context_arg, + uint ip, sp_pcontext *ctx, Item_trigger_field *trg_fld, Item *val) : sp_instr(ip, ctx), - trigger_field(trg_fld), + trigger_field(context_arg, trg_fld), value(val) {} diff --git a/sql/sql_base.cc b/sql/sql_base.cc index d8bbb686ba2..7cc0c4fecf1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2439,21 +2439,19 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, table_list->alias, name, item_name, (ulong) ref)); if (table_list->field_translation) { - uint num; - if (table_list->schema_table_reformed) + Field_iterator_view field_it; + field_it.set(table_list); + DBUG_ASSERT(table_list->schema_table_reformed || + (ref != 0 && table_list->view != 0)); + for (; !field_it.end_of_fields(); field_it.next()) { - num= thd->lex->current_select->item_list.elements; - } - else - { - DBUG_ASSERT(ref != 0 && table_list->view != 0); - num= table_list->view->select_lex.item_list.elements; - } - Field_translator *trans= table_list->field_translation; - for (uint i= 0; i < num; i ++) - { - if (!my_strcasecmp(system_charset_info, trans[i].name, name)) + if (!my_strcasecmp(system_charset_info, field_it.name(), name)) { + Item *item= field_it.create_item(thd); + if (!item) + { + DBUG_RETURN(0); + } if (table_list->schema_table_reformed) { /* @@ -2462,7 +2460,7 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, So we can return ->field. It is used only for 'show & where' commands. */ - DBUG_RETURN(((Item_field*) (trans[i].item))->field); + DBUG_RETURN(((Item_field*) (field_it.item()))->field); } #ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_grants_view && @@ -2472,26 +2470,10 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, name, length)) DBUG_RETURN(WRONG_GRANT); #endif - if (thd->lex->current_select->no_wrap_view_item) - { - if (register_tree_change) - thd->change_item_tree(ref, trans[i].item); - else - *ref= trans[i].item; - } + if (register_tree_change) + thd->change_item_tree(ref, item); else - { - Item_ref *item_ref= new Item_ref(&trans[i].item, - table_list->view_name.str, - item_name); - /* as far as Item_ref have defined reference it do not need tables */ - if (register_tree_change && item_ref) - thd->change_item_tree(ref, item_ref); - else if (item_ref) - *ref= item_ref; - if (!(*ref)->fixed) - (*ref)->fix_fields(thd, 0, ref); - } + *ref= item; DBUG_RETURN((Field*) view_ref_found); } } @@ -3066,7 +3048,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List &fields, */ it.replace(new Item_int("Not_used", (longlong) 1, 21)); } - else if (insert_fields(thd,tables,((Item_field*) item)->db_name, + else if (insert_fields(thd, ((Item_field*) item)->context, + ((Item_field*) item)->db_name, ((Item_field*) item)->table_name, &it, any_privileges)) { @@ -3102,7 +3085,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List &fields, ** Check that all given fields exists and fill struct with current data ****************************************************************************/ -bool setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, +bool setup_fields(THD *thd, Item **ref_pointer_array, List &fields, bool set_query_id, List *sum_func_list, bool allow_sum_func) { @@ -3131,7 +3114,7 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, Item **ref= ref_pointer_array; while ((item= it++)) { - if (!item->fixed && item->fix_fields(thd, tables, it.ref()) || + if (!item->fixed && item->fix_fields(thd, it.ref()) || (item= *(it.ref()))->check_cols(1)) { DBUG_RETURN(TRUE); /* purecov: inspected */ @@ -3181,6 +3164,7 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables) SYNOPSIS setup_tables() thd Thread handler + context name resolution contest to setup table list there tables Table list conds Condition of current SELECT (can be changed by VIEW) leaves List of join table leaves list @@ -3200,11 +3184,15 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables) TRUE error */ -bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds, +bool setup_tables(THD *thd, Name_resolution_context *context, + TABLE_LIST *tables, Item **conds, TABLE_LIST **leaves, bool select_insert) { uint tablenr= 0; DBUG_ENTER("setup_tables"); + + context->table_list= tables; + /* this is used for INSERT ... SELECT. For select we setup tables except first (and its underlying tables) @@ -3259,10 +3247,21 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds, table_list; table_list= table_list->next_local) { - if (table_list->ancestor && - table_list->setup_ancestor(thd, conds, - table_list->effective_with_check)) - DBUG_RETURN(1); + if (table_list->ancestor) + { + DBUG_ASSERT(table_list->view); + Query_arena *arena= thd->current_arena, backup; + bool res; + if (arena->is_conventional()) + arena= 0; // For easier test + else + thd->set_n_backup_item_arena(arena, &backup); + res= table_list->setup_ancestor(thd); + if (arena) + thd->restore_backup_item_arena(arena, &backup); + if (res) + DBUG_RETURN(1); + } } DBUG_RETURN(0); } @@ -3314,7 +3313,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table, SYNOPSIS insert_fields() thd Thread handler - tables List of tables + context Context for name resolution db_name Database name in case of 'database_name.table_name.*' table_name Table name in case of 'table_name.*' it Pointer to '*' @@ -3328,7 +3327,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table, */ bool -insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, +insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, const char *table_name, List_iterator *it, bool any_privileges) { @@ -3352,7 +3351,9 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, } found= 0; - for (; tables; tables= tables->next_local) + for (TABLE_LIST *tables= context->table_list; + tables; + tables= tables->next_local) { Field_iterator *iterator; TABLE_LIST *natural_join_table; @@ -3361,7 +3362,6 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, TABLE_LIST *last; TABLE_LIST *embedding; TABLE *table= tables->table; - bool alias_used= 0; if (!table_name || (!my_strcasecmp(table_alias_charset, table_name, tables->alias) && @@ -3395,16 +3395,6 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, } } #endif - if (table) - thd->used_tables|= table->map; - else - { - view_iter.set(tables); - for (; !view_iter.end_of_fields(); view_iter.next()) - { - thd->used_tables|= view_iter.item(thd)->used_tables(); - } - } natural_join_table= 0; last= embedded= tables; @@ -3435,8 +3425,6 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, { iterator= &view_iter; view= 1; - alias_used= my_strcasecmp(table_alias_charset, - tables->table_name, tables->alias); } else { @@ -3445,6 +3433,10 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, } iterator->set(tables); + /* for view used tables will be collected in following loop */ + if (table) + thd->used_tables|= table->map; + for (; !iterator->end_of_fields(); iterator->next()) { Item *not_used_item; @@ -3457,16 +3449,10 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, strlen(field_name), ¬_used_item, 0, 0, 0, ¬_used_field_index, TRUE)) { - Item *item= iterator->item(thd); - if (view && !thd->lex->current_select->no_wrap_view_item) - { - /* - as far as we have view, then item point to view_iter, so we - can use it directly for this view specific operation - */ - item= new Item_ref(view_iter.item_ptr(), tables->view_name.str, - field_name); - } + Item *item= iterator->create_item(thd); + if (!item) + goto err; + thd->used_tables|= item->used_tables(); if (!found++) (void) it->replace(item); // Replace '*' else @@ -3537,9 +3523,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, my_message(ER_NO_TABLES_USED, ER(ER_NO_TABLES_USED), MYF(0)); else my_error(ER_BAD_TABLE_ERROR, MYF(0), table_name); -#ifndef NO_EMBEDDED_ACCESS_CHECKS err: -#endif DBUG_RETURN(1); } @@ -3550,16 +3534,25 @@ err: SYNOPSIS setup_conds() thd thread handler - tables list of tables for name resolving leaves list of leaves of join table tree */ -int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds) +int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, + COND **conds) { SELECT_LEX *select_lex= thd->lex->current_select; Query_arena *arena= thd->current_arena, backup; - bool save_wrapper= thd->lex->current_select->no_wrap_view_item; TABLE_LIST *table= NULL; // For HP compilers + /* + it_is_update set to TRUE when tables of primary SELECT_LEX (SELECT_LEX + which belong to LEX, i.e. most up SELECT) will be updated by + INSERT/UPDATE/LOAD + NOTE: using this condition helps to prevent call of prepare_check_option() + from subquery of VIEW, because tables of subquery belongs to VIEW + (see condition before prepare_check_option() call) + */ + bool it_is_update= (select_lex == &thd->lex->select_lex) && + thd->lex->which_check_option_applicable(); DBUG_ENTER("setup_conds"); if (select_lex->conds_processed_with_permanent_arena || @@ -3568,12 +3561,17 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds) thd->set_query_id=1; - thd->lex->current_select->no_wrap_view_item= 0; + for (table= tables; table; table= table->next_local) + { + if (table->prepare_where(thd, conds, FALSE)) + goto err_no_arena; + } + select_lex->cond_count= 0; if (*conds) { thd->where="where clause"; - if (!(*conds)->fixed && (*conds)->fix_fields(thd, tables, conds) || + if (!(*conds)->fixed && (*conds)->fix_fields(thd, conds) || (*conds)->check_cols(1)) goto err_no_arena; } @@ -3591,11 +3589,12 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds) /* Make a join an a expression */ thd->where="on clause"; if (!embedded->on_expr->fixed && - embedded->on_expr->fix_fields(thd, tables, &embedded->on_expr) || + embedded->on_expr->fix_fields(thd, &embedded->on_expr) || embedded->on_expr->check_cols(1)) goto err_no_arena; select_lex->cond_count++; } + if (embedded->natural_join) { /* Make a join of all fields wich have the same name */ @@ -3675,7 +3674,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds) { if (t2_field != view_ref_found) { - if (!(item_t2= new Item_field(thd, t2_field))) + if (!(item_t2= new Item_field(thd, &select_lex->context, + t2_field))) goto err; /* Mark field used for table cache */ t2_field->query_id= thd->query_id; @@ -3687,7 +3687,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds) t1_field->query_id= thd->query_id; t1->used_keys.intersect(t1_field->part_of_key); } - Item_func_eq *tmp= new Item_func_eq(iterator->item(thd), + Item_func_eq *tmp= new Item_func_eq(iterator->create_item(thd), item_t2); if (!tmp) goto err; @@ -3703,7 +3703,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds) { COND *on_expr= cond_and; if (!on_expr->fixed) - on_expr->fix_fields(thd, 0, &on_expr); + on_expr->fix_fields(thd, &on_expr); if (!embedded->outer_join) // Not left join { *conds= and_conds(*conds, cond_and); @@ -3712,7 +3712,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds) thd->restore_backup_item_arena(arena, &backup); if (*conds && !(*conds)->fixed) { - if ((*conds)->fix_fields(thd, tables, conds)) + if ((*conds)->fix_fields(thd, conds)) goto err_no_arena; } } @@ -3724,8 +3724,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds) thd->restore_backup_item_arena(arena, &backup); if (embedded->on_expr && !embedded->on_expr->fixed) { - if (embedded->on_expr->fix_fields(thd, tables, - &embedded->on_expr)) + if (embedded->on_expr->fix_fields(thd, &embedded->on_expr)) goto err_no_arena; } } @@ -3737,6 +3736,20 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds) } while (embedding && embedding->nested_join->join_list.head() == embedded); + + /* process CHECK OPTION */ + if (it_is_update) + { + TABLE_LIST *view= table->belong_to_view; + if (!view) + view= table; + if (view->effective_with_check) + { + if (view->prepare_check_option(thd)) + goto err_no_arena; + thd->change_item_tree(&table->check_option, view->check_option); + } + } } if (!thd->current_arena->is_conventional()) @@ -3750,14 +3763,12 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds) select_lex->where= *conds; select_lex->conds_processed_with_permanent_arena= 1; } - thd->lex->current_select->no_wrap_view_item= save_wrapper; DBUG_RETURN(test(thd->net.report_error)); err: if (arena) thd->restore_backup_item_arena(arena, &backup); err_no_arena: - thd->lex->current_select->no_wrap_view_item= save_wrapper; DBUG_RETURN(1); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 20f48da9283..f5d45ca53f4 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1451,17 +1451,16 @@ int select_dumpvar::prepare(List &list, SELECT_LEX_UNIT *u) (void)local_vars.push_back(new Item_splocal(mv->s, mv->offset)); else { - Item_func_set_user_var *xx = new Item_func_set_user_var(mv->s, item); + Item_func_set_user_var *var= new Item_func_set_user_var(mv->s, item); /* Item_func_set_user_var can't substitute something else on its place => 0 can be passed as last argument (reference on item) Item_func_set_user_var can't be fixed after creation, so we do not - check xx->fixed + check var->fixed */ - xx->fix_fields(thd, (TABLE_LIST*) thd->lex->select_lex.table_list.first, - 0); - xx->fix_length_and_dec(); - vars.push_back(xx); + var->fix_fields(thd, 0); + var->fix_length_and_dec(); + vars.push_back(var); } } return 0; @@ -1538,15 +1537,19 @@ void Statement::set_statement(Statement *stmt) void Statement::set_n_backup_statement(Statement *stmt, Statement *backup) { + DBUG_ENTER("Statement::set_n_backup_statement"); backup->set_statement(this); set_statement(stmt); + DBUG_VOID_RETURN; } void Statement::restore_backup_statement(Statement *stmt, Statement *backup) { + DBUG_ENTER("Statement::restore_backup_statement"); stmt->set_statement(this); set_statement(backup); + DBUG_VOID_RETURN; } @@ -1569,6 +1572,7 @@ void Query_arena::set_n_backup_item_arena(Query_arena *set, Query_arena *backup) { DBUG_ENTER("Query_arena::set_n_backup_item_arena"); DBUG_ASSERT(backup->is_backup_arena == FALSE); + backup->set_item_arena(this); set_item_arena(set); #ifndef DBUG_OFF diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 25fef8b0ad6..d83937098e2 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -300,7 +300,9 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) SELECT_LEX *select_lex= &thd->lex->select_lex; DBUG_ENTER("mysql_prepare_delete"); - if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables, FALSE) || + if (setup_tables(thd, &thd->lex->select_lex.context, + table_list, conds, &select_lex->leaf_tables, + FALSE) || setup_conds(thd, table_list, select_lex->leaf_tables, conds) || setup_ftfuncs(select_lex)) DBUG_RETURN(TRUE); @@ -356,7 +358,8 @@ bool mysql_multi_delete_prepare(THD *thd) lex->query_tables also point on local list of DELETE SELECT_LEX */ - if (setup_tables(thd, lex->query_tables, &lex->select_lex.where, + if (setup_tables(thd, &thd->lex->select_lex.context, + lex->query_tables, &lex->select_lex.where, &lex->select_lex.leaf_tables, FALSE)) DBUG_RETURN(TRUE); diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index e1d701936cf..fc9d15e94c4 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -114,6 +114,10 @@ int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) bool is_union= first_select->next_select() && first_select->next_select()->linkage == UNION_TYPE; + /* prevent name resolving out of derived table */ + for (SELECT_LEX *sl= first_select; sl; sl= sl->next_select()) + sl->context.outer_context= 0; + if (!(derived_result= new select_union(0))) DBUG_RETURN(1); // out of memory diff --git a/sql/sql_do.cc b/sql/sql_do.cc index e37f3e86dda..08388dee516 100644 --- a/sql/sql_do.cc +++ b/sql/sql_do.cc @@ -24,7 +24,7 @@ bool mysql_do(THD *thd, List &values) List_iterator li(values); Item *value; DBUG_ENTER("mysql_do"); - if (setup_fields(thd, 0, 0, values, 0, 0, 0)) + if (setup_fields(thd, 0, values, 0, 0, 0)) DBUG_RETURN(TRUE); while ((value = li++)) value->val_int(); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index e905f93b860..e109600bcd0 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -353,7 +353,9 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, LINT_INIT(key); LINT_INIT(key_len); - list.push_front(new Item_field(NULL,NULL,"*")); + thd->lex->select_lex.context.resolve_in_table_list_only(tables); + list.push_front(new Item_field(&thd->lex->select_lex.context, + NULL, NULL, "*")); List_iterator it(list); it++; @@ -410,7 +412,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, tables->table=table; if (cond && ((!cond->fixed && - cond->fix_fields(thd, tables, &cond)) || cond->check_cols(1))) + cond->fix_fields(thd, &cond)) || cond->check_cols(1))) goto err0; if (keyname) @@ -422,7 +424,8 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, } } - if (insert_fields(thd, tables, tables->db, tables->alias, &it, 0)) + if (insert_fields(thd, &thd->lex->select_lex.context, + tables->db, tables->alias, &it, 0)) goto err0; protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); @@ -505,7 +508,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, { // 'item' can be changed by fix_fields() call if ((!item->fixed && - item->fix_fields(thd, tables, it_ke.ref())) || + item->fix_fields(thd, it_ke.ref())) || (item= *it_ke.ref())->check_cols(1)) goto err; if (item->used_tables() & ~RAND_TABLE_BIT) diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 0cf8d1e93a7..3f151934e55 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -81,11 +81,14 @@ enum enum_used_fields static bool init_fields(THD *thd, TABLE_LIST *tables, struct st_find_field *find_fields, uint count) { + Name_resolution_context *context= &thd->lex->select_lex.context; DBUG_ENTER("init_fields"); + context->resolve_in_table_list_only(tables); for (; count-- ; find_fields++) { /* We have to use 'new' here as field will be re_linked on free */ - Item_field *field= new Item_field("mysql", find_fields->table_name, + Item_field *field= new Item_field(context, + "mysql", find_fields->table_name, find_fields->field_name); if (!(find_fields->field= find_field_in_tables(thd, field, tables, 0, REPORT_ALL_ERRORS, 1))) @@ -544,7 +547,6 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol, prepare_simple_select() thd Thread handler cond WHERE part of select - tables list of tables, used in WHERE table goal table error code of error (out) @@ -553,11 +555,11 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol, # created SQL_SELECT */ -SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables, +SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE *table, int *error) { if (!cond->fixed) - cond->fix_fields(thd, tables, &cond); // can never fail + cond->fix_fields(thd, &cond); // can never fail /* Assume that no indexes cover all required fields */ table->used_keys.clear_all(); @@ -599,7 +601,7 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen, new Item_string("\\",1,&my_charset_latin1)); if (thd->is_fatal_error) return 0; // OOM - return prepare_simple_select(thd,cond,tables,table,error); + return prepare_simple_select(thd, cond, table, error); } @@ -651,7 +653,8 @@ bool mysqld_help(THD *thd, const char *mask) tables do not contain VIEWs => we can pass 0 as conds */ - setup_tables(thd, tables, 0, &leaves, FALSE); + setup_tables(thd, &thd->lex->select_lex.context, + tables, 0, &leaves, FALSE); memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields)); if (init_fields(thd, tables, used_fields, array_elements(used_fields))) goto error; @@ -718,15 +721,15 @@ bool mysqld_help(THD *thd, const char *mask) Item *cond_cat_by_cat= new Item_func_equal(new Item_field(cat_cat_id), new Item_int((int32)category_id)); - if (!(select= prepare_simple_select(thd,cond_topic_by_cat, - tables,tables[0].table,&error))) + if (!(select= prepare_simple_select(thd, cond_topic_by_cat, + tables[0].table, &error))) goto error; get_all_items_for_category(thd,tables[0].table, used_fields[help_topic_name].field, select,&topics_list); delete select; - if (!(select= prepare_simple_select(thd,cond_cat_by_cat,tables, - tables[1].table,&error))) + if (!(select= prepare_simple_select(thd, cond_cat_by_cat, + tables[1].table, &error))) goto error; get_all_items_for_category(thd,tables[1].table, used_fields[help_category_name].field, diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 2ce81d8815e..53c47706734 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -31,7 +31,7 @@ static void end_delayed_insert(THD *thd); extern "C" pthread_handler_decl(handle_delayed_insert,arg); static void unlink_blobs(register TABLE *table); #endif -static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id); +static bool check_view_insertability(THD *thd, TABLE_LIST *view); /* Define to force use of my_malloc() if the allocated memory block is big */ @@ -106,7 +106,11 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, } else { // Part field list - TABLE_LIST *save_next; + Name_resolution_context *context= &thd->lex->select_lex.context; + TABLE_LIST *save_next= table_list->next_local, + *save_context= context->table_list; + bool save_resolve_in_select_list= + thd->lex->select_lex.context.resolve_in_select_list; int res; if (fields.elements != values.elements) { @@ -115,12 +119,15 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, } thd->dupp_field=0; - thd->lex->select_lex.no_wrap_view_item= 1; - save_next= table_list->next_local; // fields only from first table + thd->lex->select_lex.no_wrap_view_item= TRUE; + /* fields only from first table */ table_list->next_local= 0; - res= setup_fields(thd, 0, table_list, fields, 1, 0, 0); + context->resolve_in_table_list_only(table_list); + res= setup_fields(thd, 0, fields, 1, 0, 0); table_list->next_local= save_next; - thd->lex->select_lex.no_wrap_view_item= 0; + thd->lex->select_lex.no_wrap_view_item= FALSE; + context->table_list= save_context; + context->resolve_in_select_list= save_resolve_in_select_list; if (res) return -1; if (table_list->effective_algorithm == VIEW_ALGORITHM_MERGE) @@ -159,7 +166,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, if (check_key_in_view(thd, table_list) || (table_list->view && - check_view_insertability(table_list, thd->query_id))) + check_view_insertability(thd, table_list))) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT"); return -1; @@ -209,7 +216,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list, Check the fields we are going to modify. This will set the query_id of all used fields to the threads query_id. */ - if (setup_fields(thd, 0, insert_table_list, update_fields, 1, 0, 0)) + if (setup_fields(thd, 0, update_fields, 1, 0, 0)) return -1; if (table->timestamp_field) @@ -247,6 +254,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ulonglong id; COPY_INFO info; TABLE *table= 0; + TABLE_LIST *next_local; List_iterator_fast its(values_list); List_item *values; #ifndef EMBEDDED_LIBRARY @@ -327,7 +335,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, /* mysql_prepare_insert set table_list->table if it was not set */ table= table_list->table; - // is table which we are changing used somewhere in other parts of query + next_local= table_list->next_local; + table_list->next_local= 0; + thd->lex->select_lex.context.resolve_in_table_list_only(table_list); value_count= values->elements; while ((values= its++)) { @@ -337,10 +347,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); goto abort; } - if (setup_fields(thd, 0, table_list, *values, 0, 0, 0)) + if (setup_fields(thd, 0, *values, 0, 0, 0)) goto abort; } its.rewind (); + table_list->next_local= next_local; /* Fill in the given fields and dump it to the table file */ @@ -387,12 +398,16 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, MODE_STRICT_ALL_TABLES))); if ((fields.elements || !value_count) && - check_that_all_fields_are_given_values(thd, table)) + check_that_all_fields_are_given_values(thd, table, table_list)) { /* thd->net.report_error is now set, which will abort the next loop */ error= 1; } + if (table_list->prepare_where(thd, 0, TRUE) || + table_list->prepare_check_option(thd)) + error= 1; + while ((values= its++)) { if (fields.elements || !value_count) @@ -596,6 +611,7 @@ abort: SYNOPSIS check_view_insertability() + thd - thread handler view - reference on VIEW IMPLEMENTATION @@ -612,7 +628,7 @@ abort: TRUE - can't be used for insert */ -static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id) +static bool check_view_insertability(THD * thd, TABLE_LIST *view) { uint num= view->view->select_lex.item_list.elements; TABLE *table= view->table; @@ -620,15 +636,25 @@ static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id) *trans_end= trans_start + num; Field_translator *trans; Field **field_ptr= table->field; - query_id_t other_query_id= query_id - 1; + uint used_fields_buff_size= (table->s->fields + 7) / 8; + uchar *used_fields_buff= (uchar*)thd->alloc(used_fields_buff_size); + MY_BITMAP used_fields; DBUG_ENTER("check_key_in_view"); + if (!used_fields_buff) + DBUG_RETURN(TRUE); // EOM + DBUG_ASSERT(view->table != 0 && view->field_translation != 0); + bitmap_init(&used_fields, used_fields_buff, used_fields_buff_size * 8, 0); + bitmap_clear_all(&used_fields); + view->contain_auto_increment= 0; /* check simplicity and prepare unique test of view */ for (trans= trans_start; trans != trans_end; trans++) { + if (!trans->item->fixed && trans->item->fix_fields(thd, &trans->item)) + return TRUE; Item_field *field; /* simple SELECT list entry (field without expression) */ if (!(field= trans->item->filed_for_view_update())) @@ -636,7 +662,6 @@ static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id) if (field->field->unireg_check == Field::NEXT_NUMBER) view->contain_auto_increment= 1; /* prepare unique test */ - field->field->query_id= other_query_id; /* remove collation (or other transparent for update function) if we have it @@ -648,29 +673,12 @@ static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id) { /* Thanks to test above, we know that all columns are of type Item_field */ Item_field *field= (Item_field *)trans->item; - if (field->field->query_id == query_id) + /* check fields belong to table in which we are inserting */ + if (field->field->table == table && + bitmap_fast_test_and_set(&used_fields, field->field->field_index)) DBUG_RETURN(TRUE); - field->field->query_id= query_id; } - /* VIEW contain all fields without default value */ - for (; *field_ptr; field_ptr++) - { - Field *field= *field_ptr; - /* field have not default value */ - if ((field->type() == FIELD_TYPE_BLOB) && - (table->timestamp_field != field || - field->unireg_check == Field::TIMESTAMP_UN_FIELD)) - { - for (trans= trans_start; ; trans++) - { - if (trans == trans_end) - DBUG_RETURN(TRUE); // Field was not part of view - if (((Item_field *)trans->item)->field == *field_ptr) - break; // ok - } - } - } DBUG_RETURN(FALSE); } @@ -698,7 +706,8 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, bool insert_into_view= (table_list->view != 0); DBUG_ENTER("mysql_prepare_insert_check_table"); - if (setup_tables(thd, table_list, where, &thd->lex->select_lex.leaf_tables, + if (setup_tables(thd, &thd->lex->select_lex.context, + table_list, where, &thd->lex->select_lex.leaf_tables, select_insert)) DBUG_RETURN(TRUE); @@ -711,7 +720,7 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, table_list->view_db.str, table_list->view_name.str); DBUG_RETURN(TRUE); } - DBUG_RETURN(insert_view_fields(&fields, table_list)); + DBUG_RETURN(insert_view_fields(thd, &fields, table_list)); } DBUG_RETURN(FALSE); @@ -741,8 +750,10 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table, enum_duplicates duplic, COND **where, bool select_insert) { + TABLE_LIST *save_table_list= thd->lex->select_lex.context.table_list; bool insert_into_view= (table_list->view != 0); - /* TODO: use this condition for 'WITH CHECK OPTION' */ + bool save_resolve_in_select_list= + thd->lex->select_lex.context.resolve_in_select_list; bool res; TABLE_LIST *next_local; DBUG_ENTER("mysql_prepare_insert"); @@ -750,6 +761,26 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table, (ulong)table_list, (ulong)table, (int)insert_into_view)); + /* + For subqueries in VALUES() we should not see the table in which we are + inserting (for INSERT ... SELECT this is done by changing table_list, + because INSERT ... SELECT share SELECT_LEX it with SELECT. + */ + if (!select_insert) + { + for (SELECT_LEX_UNIT *un= thd->lex->select_lex.first_inner_unit(); + un; + un= un->next_unit()) + { + for (SELECT_LEX *sl= un->first_select(); + sl; + sl= sl->next_select()) + { + sl->context.outer_context= 0; + } + } + } + if (duplic == DUP_UPDATE) { /* it should be allocated before Item::fix_fields() */ @@ -763,29 +794,37 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table, next_local= table_list->next_local; table_list->next_local= 0; + thd->lex->select_lex.context.resolve_in_table_list_only(table_list); if ((values && check_insert_fields(thd, table_list, fields, *values, !insert_into_view)) || - (values && setup_fields(thd, 0, table_list, *values, 0, 0, 0)) || + (values && setup_fields(thd, 0, *values, 0, 0, 0)) || (duplic == DUP_UPDATE && - ((thd->lex->select_lex.no_wrap_view_item= 1, + ((thd->lex->select_lex.no_wrap_view_item= TRUE, (res= check_update_fields(thd, table_list, update_fields)), - thd->lex->select_lex.no_wrap_view_item= 0, + thd->lex->select_lex.no_wrap_view_item= FALSE, res) || - setup_fields(thd, 0, table_list, update_values, 1, 0, 0)))) + setup_fields(thd, 0, update_values, 1, 0, 0)))) DBUG_RETURN(TRUE); table_list->next_local= next_local; - + thd->lex->select_lex.context.table_list= save_table_list; + thd->lex->select_lex.context.resolve_in_select_list= + save_resolve_in_select_list; if (!table) table= table_list->table; - if (!select_insert && unique_table(table_list, table_list->next_global)) + if (!select_insert) { - my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name); - DBUG_RETURN(TRUE); + Item *fake_conds= 0; + if (unique_table(table_list, table_list->next_global)) + { + my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name); + DBUG_RETURN(TRUE); + } + thd->lex->select_lex.fix_prepare_information(thd, &fake_conds); + thd->lex->select_lex.first_execution= 0; } if (duplic == DUP_UPDATE || duplic == DUP_REPLACE) table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY); - thd->lex->select_lex.first_execution= 0; DBUG_RETURN(FALSE); } @@ -1038,7 +1077,8 @@ before_trg_err: Check that all fields with arn't null_fields are used ******************************************************************************/ -int check_that_all_fields_are_given_values(THD *thd, TABLE *entry) +int check_that_all_fields_are_given_values(THD *thd, TABLE *entry, + TABLE_LIST *table_list) { int err= 0; for (Field **field=entry->field ; *field ; field++) @@ -1047,10 +1087,29 @@ int check_that_all_fields_are_given_values(THD *thd, TABLE *entry) ((*field)->flags & NO_DEFAULT_VALUE_FLAG) && ((*field)->real_type() != FIELD_TYPE_ENUM)) { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_NO_DEFAULT_FOR_FIELD, - ER(ER_NO_DEFAULT_FOR_FIELD), - (*field)->field_name); + bool view= FALSE; + if (table_list) + { + table_list= (table_list->belong_to_view ? + table_list->belong_to_view : + table_list); + view= (table_list->view); + } + if (view) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_NO_DEFAULT_FOR_VIEW_FIELD, + ER(ER_NO_DEFAULT_FOR_VIEW_FIELD), + table_list->view_db.str, + table_list->view_name.str); + } + else + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_NO_DEFAULT_FOR_FIELD, + ER(ER_NO_DEFAULT_FOR_FIELD), + (*field)->field_name); + } err= 1; } } @@ -1938,7 +1997,6 @@ bool mysql_insert_select_prepare(THD *thd) SELECT_LEX do not belong to INSERT statement, so we can't add WHERE clause if table is VIEW */ - lex->query_tables->no_where_clause= 1; if (mysql_prepare_insert(thd, lex->query_tables, lex->query_tables->table, lex->field_list, 0, lex->update_list, lex->value_list, @@ -1988,8 +2046,8 @@ select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par, int select_insert::prepare(List &values, SELECT_LEX_UNIT *u) { - int res; LEX *lex= thd->lex; + int res; SELECT_LEX *lex_current_select_save= lex->current_select; DBUG_ENTER("select_insert::prepare"); @@ -2043,8 +2101,11 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))); - DBUG_RETURN(fields->elements && - check_that_all_fields_are_given_values(thd, table)); + res= ((fields->elements && + check_that_all_fields_are_given_values(thd, table, table_list)) || + table_list->prepare_where(thd, 0, TRUE) || + table_list->prepare_check_option(thd)); + DBUG_RETURN(res); } @@ -2290,7 +2351,8 @@ select_create::prepare(List &values, SELECT_LEX_UNIT *u) (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))); - DBUG_RETURN(check_that_all_fields_are_given_values(thd, table)); + DBUG_RETURN(check_that_all_fields_are_given_values(thd, table, + table_list)); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 08f0c3badf7..19578931d04 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1104,7 +1104,8 @@ void st_select_lex::init_query() having= where= prep_where= 0; olap= UNSPECIFIED_OLAP_TYPE; having_fix_field= 0; - resolve_mode= NOMATTER_MODE; + context.select_lex= this; + context.init(); cond_count= with_wild= 0; conds_processed_with_permanent_arena= 0; ref_pointer_array= 0; @@ -1703,8 +1704,7 @@ bool st_lex::can_not_use_merged() bool st_lex::only_view_structure() { - switch(sql_command) - { + switch (sql_command) { case SQLCOM_SHOW_CREATE: case SQLCOM_SHOW_TABLES: case SQLCOM_SHOW_FIELDS: @@ -1744,6 +1744,31 @@ bool st_lex::need_correct_ident() } } +/* + Get effective type of CHECK OPTION for given view + + SYNOPSIS + get_effective_with_check() + view given view + + NOTE + It have not sense to set CHECK OPTION for SELECT satement or subqueries, + so we do not. + + RETURN + VIEW_CHECK_NONE no need CHECK OPTION + VIEW_CHECK_LOCAL CHECK OPTION LOCAL + VIEW_CHECK_CASCADED CHECK OPTION CASCADED +*/ + +uint8 st_lex::get_effective_with_check(st_table_list *view) +{ + if (view->select_lex->master_unit() == &unit && + which_check_option_applicable()) + return (uint8)view->with_check; + return VIEW_CHECK_NONE; +} + /* initialize limit counters @@ -1804,7 +1829,8 @@ TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local) */ if ((*link_to_local= test(select_lex.table_list.first))) { - select_lex.table_list.first= (byte*) first->next_local; + select_lex.table_list.first= (byte*) (select_lex.context.table_list= + first->next_local); select_lex.table_list.elements--; //safety first->next_local= 0; /* @@ -1909,7 +1935,8 @@ void st_lex::link_first_table_back(TABLE_LIST *first, if (link_to_local) { first->next_local= (TABLE_LIST*) select_lex.table_list.first; - select_lex.table_list.first= (byte*) first; + select_lex.table_list.first= + (byte*) select_lex.context.table_list= first; select_lex.table_list.elements++; //safety } } @@ -1930,7 +1957,21 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds) if (!thd->current_arena->is_conventional() && first_execution) { first_execution= 0; - prep_where= where; + if (*conds) + { + prep_where= *conds; + *conds= where= prep_where->copy_andor_structure(thd); + } + for (TABLE_LIST *tbl= (TABLE_LIST *)table_list.first; + tbl; + tbl= tbl->next_local) + { + if (tbl->on_expr) + { + tbl->prep_on_expr= tbl->on_expr; + tbl->on_expr= tbl->on_expr->copy_andor_structure(thd); + } + } } } @@ -1945,3 +1986,4 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds) st_select_lex_unit::change_result are in sql_union.cc */ + diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 5cf0b66598f..8fde37b0126 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -470,6 +470,7 @@ typedef class st_select_lex_unit SELECT_LEX_UNIT; class st_select_lex: public st_select_lex_node { public: + Name_resolution_context context; char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */ Item *where, *having; /* WHERE & HAVING clauses */ Item *prep_where; /* saved WHERE clause for prepared statement processing */ @@ -549,27 +550,6 @@ public: /* exclude this select from check of unique_table() */ bool exclude_from_table_unique_test; - /* - SELECT for SELECT command st_select_lex. Used to privent scaning - item_list of non-SELECT st_select_lex (no sense find to finding - reference in it (all should be in tables, it is dangerouse due - to order of fix_fields calling for non-SELECTs commands (item list - can be not fix_fieldsd)). This value will be assigned for - primary select (sql_yac.yy) and for any subquery and - UNION SELECT (sql_parse.cc mysql_new_select()) - - - INSERT for primary st_select_lex structure of simple INSERT/REPLACE - (used for name resolution, see Item_fiels & Item_ref fix_fields, - FALSE for INSERT/REPLACE ... SELECT, because it's - st_select_lex->table_list will be preprocessed (first table removed) - before passing to handle_select) - - NOMATTER for other - */ - enum {NOMATTER_MODE, SELECT_MODE, INSERT_MODE} resolve_mode; - - void init_query(); void init_select(); st_select_lex_unit* master_unit(); @@ -903,7 +883,30 @@ typedef struct st_lex bool can_not_use_merged(); bool only_view_structure(); bool need_correct_ident(); + uint8 get_effective_with_check(st_table_list *view); + /* + Is this update command where 'WHITH CHECK OPTION' clause is important + SYNOPSIS + st_lex::which_check_option_applicable() + + RETURN + TRUE have to take 'WHITH CHECK OPTION' clause into account + FALSE 'WHITH CHECK OPTION' clause do not need + */ + inline bool which_check_option_applicable() + { + switch (sql_command) { + case SQLCOM_UPDATE: + case SQLCOM_UPDATE_MULTI: + case SQLCOM_INSERT: + case SQLCOM_INSERT_SELECT: + case SQLCOM_LOAD: + return TRUE; + default: + return FALSE; + } + } inline bool requires_prelocking() { return test(query_tables_own_last); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index cc25839bcc9..1ec209aba85 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -149,7 +149,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, } if (open_and_lock_tables(thd, table_list)) DBUG_RETURN(TRUE); - if (setup_tables(thd, table_list, &unused_conds, + if (setup_tables(thd, &thd->lex->select_lex.context, + table_list, &unused_conds, &thd->lex->select_lex.leaf_tables, FALSE)) DBUG_RETURN(-1); if (!table_list->table || // do not suport join view @@ -159,6 +160,11 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD"); DBUG_RETURN(TRUE); } + if (table_list->prepare_where(thd, 0, TRUE) || + table_list->prepare_check_option(thd)) + { + DBUG_RETURN(TRUE); + } /* Let us emit an error if we are loading data to table which is used in subselect in SET clause like we do it for INSERT. @@ -186,16 +192,16 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, Let us also prepare SET clause, altough it is probably empty in this case. */ - if (setup_fields(thd, 0, table_list, set_fields, 1, 0, 0) || - setup_fields(thd, 0, table_list, set_values, 1, 0, 0)) + if (setup_fields(thd, 0, set_fields, 1, 0, 0) || + setup_fields(thd, 0, set_values, 1, 0, 0)) DBUG_RETURN(TRUE); } else { // Part field list /* TODO: use this conds for 'WITH CHECK OPTIONS' */ - if (setup_fields(thd, 0, table_list, fields_vars, 1, 0, 0) || - setup_fields(thd, 0, table_list, set_fields, 1, 0, 0) || - check_that_all_fields_are_given_values(thd, table)) + if (setup_fields(thd, 0, fields_vars, 1, 0, 0) || + setup_fields(thd, 0, set_fields, 1, 0, 0) || + check_that_all_fields_are_given_values(thd, table, table_list)) DBUG_RETURN(TRUE); /* Check whenever TIMESTAMP field with auto-set feature specified @@ -209,7 +215,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, check_that_all_fields_are_given_values() and setting use_timestamp since it may update query_id for some fields. */ - if (setup_fields(thd, 0, table_list, set_values, 1, 0, 0)) + if (setup_fields(thd, 0, set_values, 1, 0, 0)) DBUG_RETURN(TRUE); } diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc index 831b15cf7ef..71e8fe4149f 100644 --- a/sql/sql_olap.cc +++ b/sql/sql_olap.cc @@ -77,7 +77,8 @@ static int make_new_olap_select(LEX *lex, SELECT_LEX *select_lex, List new { not_found= 0; ((Item_field*)new_item)->db_name=iif->db_name; - Item_field *new_one=new Item_field(iif->db_name, iif->table_name, iif->field_name); + Item_field *new_one=new Item_field(&select_lex->context, + iif->db_name, iif->table_name, iif->field_name); privlist.push_back(new_one); if (add_to_list(new_select->group_list,new_one,1)) return 1; @@ -152,12 +153,11 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex) List all_fields(select_lex->item_list); - if (setup_tables(lex->thd, (TABLE_LIST *)select_lex->table_list.first + if (setup_tables(lex->thd, &select_lex->context, + (TABLE_LIST *)select_lex->table_list.first &select_lex->where, &select_lex->leaf_tables, FALSE) || - setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first, - select_lex->item_list, 1, &all_fields,1) || - setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first, - item_list_copy, 1, &all_fields, 1)) + setup_fields(lex->thd, 0, select_lex->item_list, 1, &all_fields,1) || + setup_fields(lex->thd, 0, item_list_copy, 1, &all_fields, 1)) return -1; if (select_lex->olap == CUBE_TYPE) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d6a719e65f9..057d2f23ed3 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2289,6 +2289,10 @@ mysql_execute_command(THD *thd) lex->first_lists_tables_same(); /* should be assigned after making first tables same */ all_tables= lex->query_tables; + /* set context for commands which do not use setup_tables */ + select_lex-> + context.resolve_in_table_list_only((TABLE_LIST*)select_lex-> + table_list.first); /* Reset warning count for each query that uses tables @@ -2572,7 +2576,7 @@ mysql_execute_command(THD *thd) goto error; /* PURGE MASTER LOGS BEFORE 'data' */ it= (Item *)lex->value_list.head(); - if ((!it->fixed &&it->fix_fields(lex->thd, 0, &it)) || + if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1)) { my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE"); @@ -2881,9 +2885,7 @@ mysql_execute_command(THD *thd) CREATE from SELECT give its SELECT_LEX for SELECT, and item_list belong to SELECT */ - select_lex->resolve_mode= SELECT_LEX::SELECT_MODE; res= handle_select(thd, lex, result, 0); - select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE; delete result; } /* reset for PS */ @@ -3222,6 +3224,8 @@ end_with_restore_list: DBUG_ASSERT(first_table == all_tables && first_table != 0); if ((res= insert_precheck(thd, all_tables))) break; + /* Skip first table, which is the table we are inserting in */ + select_lex->context.table_list= first_table->next_local; res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values, lex->update_list, lex->value_list, lex->duplicates, lex->ignore); @@ -3252,18 +3256,17 @@ end_with_restore_list: select_lex->table_list.first= (byte*)first_table->next_local; res= mysql_insert_select_prepare(thd); + lex->select_lex.context.table_list= first_table->next_local; if (!res && (result= new select_insert(first_table, first_table->table, &lex->field_list, - &lex->update_list, &lex->value_list, + &lex->update_list, + &lex->value_list, lex->duplicates, lex->ignore))) { - /* - insert/replace from SELECT give its SELECT_LEX for SELECT, - and item_list belong to SELECT - */ - select_lex->resolve_mode= SELECT_LEX::SELECT_MODE; + /* Skip first table, which is the table we are inserting in */ + select_lex->context.table_list= first_table->next_local; + res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE); - select_lex->resolve_mode= SELECT_LEX::INSERT_MODE; delete result; } /* revert changes for SP */ @@ -3863,7 +3866,7 @@ end_with_restore_list: { Item *it= (Item *)lex->value_list.head(); - if ((!it->fixed && it->fix_fields(lex->thd, 0, &it)) || it->check_cols(1)) + if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1)) { my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), MYF(0)); @@ -5230,16 +5233,27 @@ mysql_new_select(LEX *lex, bool move_down) unit->link_prev= 0; unit->return_to= lex->current_select; select_lex->include_down(unit); - /* TODO: assign resolve_mode for fake subquery after merging with new tree */ + /* + By default we assume that it is usual subselect and we have outer name + resolution context, if no we will assign it to 0 later + */ + select_lex->context.outer_context= &select_lex->outer_select()->context; } else { + Name_resolution_context *outer_context; if (lex->current_select->order_list.first && !lex->current_select->braces) { my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY"); DBUG_RETURN(1); } select_lex->include_neighbour(lex->current_select); + /* + we are not sure that we have one level of SELECTs above, so we take + outer_context address from first select of unit + */ + outer_context= + select_lex->master_unit()->first_select()->context.outer_context; SELECT_LEX_UNIT *unit= select_lex->master_unit(); SELECT_LEX *fake= unit->fake_select_lex; if (!fake) @@ -5256,13 +5270,23 @@ mysql_new_select(LEX *lex, bool move_down) fake->make_empty_select(); fake->linkage= GLOBAL_OPTIONS_TYPE; fake->select_limit= 0; + + fake->context.outer_context= outer_context; + /* allow item list resolving in fake select for ORDER BY */ + fake->context.resolve_in_select_list= TRUE; + fake->context.select_lex= fake; } + select_lex->context.outer_context= outer_context; } select_lex->master_unit()->global_parameters= select_lex; select_lex->include_global((st_select_lex_node**)&lex->all_selects_list); lex->current_select= select_lex; - select_lex->resolve_mode= SELECT_LEX::SELECT_MODE; + /* + in subquery is SELECT query and we allow resolution of names in SELECT + list + */ + select_lex->context.resolve_in_select_list= TRUE; DBUG_RETURN(0); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index c97cb037f15..0ffd01356b4 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -963,7 +963,7 @@ static bool mysql_test_insert(Prepared_statement *stmt, my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); goto error; } - if (setup_fields(thd, 0, table_list, *values, 0, 0, 0)) + if (setup_fields(thd, 0, *values, 0, 0, 0)) goto error; } } @@ -1039,9 +1039,9 @@ static int mysql_test_update(Prepared_statement *stmt, table_list->grant.want_privilege= want_privilege; table_list->table->grant.want_privilege= want_privilege; #endif - thd->lex->select_lex.no_wrap_view_item= 1; - res= setup_fields(thd, 0, table_list, select->item_list, 1, 0, 0); - thd->lex->select_lex.no_wrap_view_item= 0; + thd->lex->select_lex.no_wrap_view_item= TRUE; + res= setup_fields(thd, 0, select->item_list, 1, 0, 0); + thd->lex->select_lex.no_wrap_view_item= FALSE; if (res) goto error; #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -1050,7 +1050,7 @@ static int mysql_test_update(Prepared_statement *stmt, table_list->table->grant.want_privilege= (SELECT_ACL & ~table_list->table->grant.privilege); #endif - if (setup_fields(thd, 0, table_list, stmt->lex->value_list, 0, 0, 0)) + if (setup_fields(thd, 0, stmt->lex->value_list, 0, 0, 0)) goto error; /* TODO: here we should send types of placeholders to the client. */ DBUG_RETURN(0); @@ -1119,6 +1119,8 @@ static bool mysql_test_select(Prepared_statement *stmt, SELECT_LEX_UNIT *unit= &lex->unit; DBUG_ENTER("mysql_test_select"); + lex->select_lex.context.resolve_in_select_list= TRUE; + #ifndef NO_EMBEDDED_ACCESS_CHECKS ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL; if (tables) @@ -1207,7 +1209,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt, if (open_and_lock_tables(thd, tables)) DBUG_RETURN(TRUE); - DBUG_RETURN(setup_fields(thd, 0, 0, *values, 0, 0, 0)); + DBUG_RETURN(setup_fields(thd, 0, *values, 0, 0, 0)); } @@ -1277,6 +1279,8 @@ static bool select_like_stmt_test(Prepared_statement *stmt, THD *thd= stmt->thd; LEX *lex= stmt->lex; + lex->select_lex.context.resolve_in_select_list= TRUE; + if (specific_prepare && (*specific_prepare)(thd)) DBUG_RETURN(TRUE); @@ -1354,9 +1358,8 @@ static bool mysql_test_create_table(Prepared_statement *stmt) if (select_lex->item_list.elements) { - select_lex->resolve_mode= SELECT_LEX::SELECT_MODE; + select_lex->context.resolve_in_select_list= TRUE; res= select_like_stmt_test_with_open_n_lock(stmt, tables, 0, 0); - select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE; } /* put tables back for PS rexecuting */ @@ -1446,16 +1449,21 @@ error: static bool mysql_insert_select_prepare_tester(THD *thd) { + TABLE_LIST *first; + bool res; SELECT_LEX *first_select= &thd->lex->select_lex; /* Skip first table, which is the table we are inserting in */ - first_select->table_list.first= (byte*)((TABLE_LIST*)first_select-> - table_list.first)->next_local; + first_select->table_list.first= (byte*)(first= + ((TABLE_LIST*)first_select-> + table_list.first)->next_local); + res= mysql_insert_select_prepare(thd); /* insert/replace from SELECT give its SELECT_LEX for SELECT, and item_list belong to SELECT */ - first_select->resolve_mode= SELECT_LEX::SELECT_MODE; - return mysql_insert_select_prepare(thd); + thd->lex->select_lex.context.resolve_in_select_list= TRUE; + thd->lex->select_lex.context.table_list= first; + return res; } @@ -1493,12 +1501,12 @@ static int mysql_test_insert_select(Prepared_statement *stmt, first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first; DBUG_ASSERT(first_local_table != 0); - res= select_like_stmt_test_with_open_n_lock(stmt, tables, - &mysql_insert_select_prepare_tester, - OPTION_SETUP_TABLES_DONE); + res= + select_like_stmt_test_with_open_n_lock(stmt, tables, + &mysql_insert_select_prepare_tester, + OPTION_SETUP_TABLES_DONE); /* revert changes made by mysql_insert_select_prepare_tester */ lex->select_lex.table_list.first= (byte*) first_local_table; - lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; return res; } @@ -1538,6 +1546,10 @@ static bool check_prepared_statement(Prepared_statement *stmt, lex->first_lists_tables_same(); tables= lex->query_tables; + /* set context for commands which do not use setup_tables */ + lex->select_lex.context.resolve_in_table_list_only(select_lex-> + get_table_list()); + switch (sql_command) { case SQLCOM_REPLACE: case SQLCOM_INSERT: @@ -1813,18 +1825,9 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, void init_stmt_after_parse(THD *thd, LEX *lex) { SELECT_LEX *sl= lex->all_selects_list; - /* - Save WHERE clause pointers, because they may be changed during query - optimisation. - */ - for (; sl; sl= sl->next_select_in_list()) - { - sl->prep_where= sl->where; - sl->uncacheable&= ~UNCACHEABLE_PREPARE; - } - for (TABLE_LIST *table= lex->query_tables; table; table= table->next_global) - table->prep_on_expr= table->on_expr; + for (; sl; sl= sl->next_select_in_list()) + sl->uncacheable&= ~UNCACHEABLE_PREPARE; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cf8d7b1b83c..195d34cbbe2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -182,8 +182,8 @@ static void reset_cache_read(JOIN_CACHE *cache); static void reset_cache_write(JOIN_CACHE *cache); static void read_cached_record(JOIN_TAB *tab); static bool cmp_buffer_with_ref(JOIN_TAB *tab); -static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List &fields, - List &all_fields,ORDER *new_order); +static bool setup_new_fields(THD *thd, List &fields, + List &all_fields, ORDER *new_order); static ORDER *create_distinct_group(THD *thd, ORDER *order, List &fields, bool *all_order_by_fields_used); @@ -283,6 +283,7 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array, save_allow_sum_func= thd->allow_sum_func; thd->allow_sum_func= 0; res= setup_conds(thd, tables, leaves, conds); + thd->allow_sum_func= save_allow_sum_func; res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields, order); @@ -339,11 +340,12 @@ JOIN::prepare(Item ***rref_pointer_array, /* Check that all tables, fields, conds and order are ok */ if ((!(select_options & OPTION_SETUP_TABLES_DONE) && - setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables, + setup_tables(thd, &select_lex->context, + tables_list, &conds, &select_lex->leaf_tables, FALSE)) || setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || select_lex->setup_ref_array(thd, og_num) || - setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1, + setup_fields(thd, (*rref_pointer_array), fields_list, 1, &all_fields, 1) || setup_without_group(thd, (*rref_pointer_array), tables_list, select_lex->leaf_tables, fields_list, @@ -359,7 +361,7 @@ JOIN::prepare(Item ***rref_pointer_array, thd->allow_sum_func=1; select_lex->having_fix_field= 1; bool having_fix_rc= (!having->fixed && - (having->fix_fields(thd, tables_list, &having) || + (having->fix_fields(thd, &having) || having->check_cols(1))); select_lex->having_fix_field= 0; if (having_fix_rc || thd->net.report_error) @@ -432,7 +434,7 @@ JOIN::prepare(Item ***rref_pointer_array, goto err; /* purecov: inspected */ if (procedure) { - if (setup_new_fields(thd, tables_list, fields_list, all_fields, + if (setup_new_fields(thd, fields_list, all_fields, procedure->param_fields)) goto err; /* purecov: inspected */ if (procedure->group) @@ -566,7 +568,7 @@ JOIN::optimize() Item_cond_and can't be fixed after creation, so we do not check conds->fixed */ - conds->fix_fields(thd, tables_list, &conds); + conds->fix_fields(thd, &conds); conds->change_ref_to_fields(thd, tables_list); conds->top_level_item(); having= 0; @@ -1117,7 +1119,6 @@ int JOIN::reinit() { DBUG_ENTER("JOIN::reinit"); - first_record= 0; if (exec_tmp_table1) @@ -1977,6 +1978,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, bool free_join= 1; DBUG_ENTER("mysql_select"); + select_lex->context.resolve_in_select_list= TRUE; JOIN *join; if (select_lex->join != 0) { @@ -7445,7 +7447,7 @@ simplify_joins(JOIN *join, List *join_list, COND *conds, bool top) conds->top_level_item(); /* conds is always a new item as both cond and on_expr existed */ DBUG_ASSERT(!conds->fixed); - conds->fix_fields(join->thd, 0, &conds); + conds->fix_fields(join->thd, &conds); } else conds= table->on_expr; @@ -7666,7 +7668,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) cond->fixed, also it do not need tables so we use 0 as second argument. */ - cond->fix_fields(thd, 0, &cond); + cond->fix_fields(thd, &cond); } thd->insert_id(0); // Clear for next request } @@ -7685,7 +7687,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) cond->fixed, also it do not need tables so we use 0 as second argument. */ - cond->fix_fields(thd, 0, &cond); + cond->fix_fields(thd, &cond); } } } @@ -8208,6 +8210,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, *blob_field++= (uint) (reg_field - table->field); blob_count++; } + new_field->field_index= (uint) (reg_field - table->field); *(reg_field++)= new_field; if (new_field->real_type() == MYSQL_TYPE_STRING || new_field->real_type() == MYSQL_TYPE_VARCHAR) @@ -8273,6 +8276,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, new_field->flags|= GROUP_FLAG; } new_field->query_id= thd->query_id; + new_field->field_index= (uint) (reg_field - table->field); *(reg_field++) =new_field; } if (!--hidden_field_count) @@ -11181,8 +11185,7 @@ static bool fix_having(JOIN *join, Item **having) else // This should never happen if (!(table->select->cond= new Item_cond_and(table->select->cond, sort_table_cond)) || - table->select->cond->fix_fields(join->thd, join->tables_list, - &table->select->cond)) + table->select->cond->fix_fields(join->thd, &table->select->cond)) return 1; table->select_cond=table->select->cond; table->select_cond->top_level_item(); @@ -11873,8 +11876,8 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, original field name, we should additionaly check if we have conflict for this name (in case if we would perform lookup in all tables). */ - if (unaliased && !order_item->fixed && order_item->fix_fields(thd, tables, - order->item)) + if (unaliased && !order_item->fixed && + order_item->fix_fields(thd, order->item)) return TRUE; /* Lookup the current GROUP field in the FROM clause. */ @@ -11941,7 +11944,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, arguments for which fix_fields already was called. */ if (!order_item->fixed && - (order_item->fix_fields(thd, tables, order->item) || + (order_item->fix_fields(thd, order->item) || (order_item= *order->item)->check_cols(1) || thd->is_fatal_error)) return TRUE; /* Wrong field. */ @@ -12053,7 +12056,7 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, */ static bool -setup_new_fields(THD *thd,TABLE_LIST *tables,List &fields, +setup_new_fields(THD *thd, List &fields, List &all_fields, ORDER *new_field) { Item **item; @@ -12070,7 +12073,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List &fields, else { thd->where="procedure list"; - if ((*new_field->item)->fix_fields(thd, tables, new_field->item)) + if ((*new_field->item)->fix_fields(thd, new_field->item)) DBUG_RETURN(1); /* purecov: inspected */ all_fields.push_front(*new_field->item); new_field->item=all_fields.head_ref(); @@ -12868,7 +12871,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) DBUG_RETURN(TRUE); if (!cond->fixed) - cond->fix_fields(thd,(TABLE_LIST *) 0, (Item**)&cond); + cond->fix_fields(thd, (Item**)&cond); if (join_tab->select) { error=(int) cond->add(join_tab->select->cond); @@ -12910,8 +12913,8 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select) thd reference to the context expr expression to make replacement group_list list of references to group by items - changed out: returns 1 if item contains a replaced field item - + changed out: returns 1 if item contains a replaced field item + DESCRIPTION The function replaces occurrences of group by fields in expr by ref objects for these fields unless they are under aggregate @@ -12940,6 +12943,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list, { if (expr->arg_count) { + Name_resolution_context *context= &thd->lex->current_select->context; Item **arg,**arg_end; for (arg= expr->arguments(), arg_end= expr->arguments()+expr->arg_count; @@ -12953,8 +12957,9 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list, { if (item->eq(*group_tmp->item,0)) { - Item *new_item; - if(!(new_item= new Item_ref(group_tmp->item, 0, item->name))) + Item *new_item; + if(!(new_item= new Item_ref(context, group_tmp->item, 0, + item->name))) return 1; // fatal_error is set thd->change_item_tree(arg, new_item); *changed= TRUE; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 12025c82da6..72092db400d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3240,11 +3240,13 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) { ST_FIELD_INFO *field_info= schema_table->fields_info; + Name_resolution_context *context= &thd->lex->select_lex.context; for ( ; field_info->field_name; field_info++) { if (field_info->old_name) { - Item_field *field= new Item_field(NullS, NullS, field_info->field_name); + Item_field *field= new Item_field(context, + NullS, NullS, field_info->field_name); if (field) { field->set_name(field_info->old_name, @@ -3264,12 +3266,14 @@ int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) char tmp[128]; LEX *lex= thd->lex; SELECT_LEX *sel= lex->current_select; + Name_resolution_context *context= &sel->context; if (!sel->item_list.elements) { ST_FIELD_INFO *field_info= &schema_table->fields_info[1]; String buffer(tmp,sizeof(tmp), system_charset_info); - Item_field *field= new Item_field(NullS, NullS, field_info->field_name); + Item_field *field= new Item_field(context, + NullS, NullS, field_info->field_name); if (!field || add_item_to_list(thd, field)) return 1; buffer.length(0); @@ -3291,6 +3295,7 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) char tmp[128]; String buffer(tmp,sizeof(tmp), thd->charset()); LEX *lex= thd->lex; + Name_resolution_context *context= &lex->select_lex.context; ST_FIELD_INFO *field_info= &schema_table->fields_info[2]; buffer.length(0); @@ -3302,7 +3307,8 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) buffer.append(lex->wild->ptr()); buffer.append(")"); } - Item_field *field= new Item_field(NullS, NullS, field_info->field_name); + Item_field *field= new Item_field(context, + NullS, NullS, field_info->field_name); if (add_item_to_list(thd, field)) return 1; field->set_name(buffer.ptr(), buffer.length(), system_charset_info); @@ -3310,7 +3316,7 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) { field->set_name(buffer.ptr(), buffer.length(), system_charset_info); field_info= &schema_table->fields_info[3]; - field= new Item_field(NullS, NullS, field_info->field_name); + field= new Item_field(context, NullS, NullS, field_info->field_name); if (add_item_to_list(thd, field)) return 1; field->set_name(field_info->old_name, strlen(field_info->old_name), @@ -3325,6 +3331,8 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) int fields_arr[]= {3, 14, 13, 6, 15, 5, 16, 17, 18, -1}; int *field_num= fields_arr; ST_FIELD_INFO *field_info; + Name_resolution_context *context= &thd->lex->select_lex.context; + for (; *field_num >= 0; field_num++) { field_info= &schema_table->fields_info[*field_num]; @@ -3332,7 +3340,8 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) *field_num == 17 || *field_num == 18)) continue; - Item_field *field= new Item_field(NullS, NullS, field_info->field_name); + Item_field *field= new Item_field(context, + NullS, NullS, field_info->field_name); if (field) { field->set_name(field_info->old_name, @@ -3351,10 +3360,13 @@ int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) int fields_arr[]= {0, 2, 1, 3, -1}; int *field_num= fields_arr; ST_FIELD_INFO *field_info; + Name_resolution_context *context= &thd->lex->select_lex.context; + for (; *field_num >= 0; field_num++) { field_info= &schema_table->fields_info[*field_num]; - Item_field *field= new Item_field(NullS, NullS, field_info->field_name); + Item_field *field= new Item_field(context, + NullS, NullS, field_info->field_name); if (field) { field->set_name(field_info->old_name, @@ -3373,10 +3385,13 @@ int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) int fields_arr[]= {2, 3, 4, 19, 16, 15, 14, 18, -1}; int *field_num= fields_arr; ST_FIELD_INFO *field_info; + Name_resolution_context *context= &thd->lex->select_lex.context; + for (; *field_num >= 0; field_num++) { field_info= &schema_table->fields_info[*field_num]; - Item_field *field= new Item_field(NullS, NullS, field_info->field_name); + Item_field *field= new Item_field(context, + NullS, NullS, field_info->field_name); if (field) { field->set_name(field_info->old_name, @@ -3442,12 +3457,11 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) if (table_list->field_translation) { - Field_translator *end= table_list->field_translation + - sel->item_list.elements; + Field_translator *end= table_list->field_translation_end; for (transl= table_list->field_translation; transl < end; transl++) { if (!transl->item->fixed && - transl->item->fix_fields(thd, table_list, &transl->item)) + transl->item->fix_fields(thd, &transl->item)) DBUG_RETURN(1); } DBUG_RETURN(0); @@ -3464,11 +3478,12 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) { char *name= item->name; transl[i].item= item; - if (!item->fixed && item->fix_fields(thd, table_list, &transl[i].item)) + if (!item->fixed && item->fix_fields(thd, &transl[i].item)) DBUG_RETURN(1); transl[i++].name= name; } table_list->field_translation= transl; + table_list->field_translation_end= transl + sel->item_list.elements; } DBUG_RETURN(0); @@ -3495,7 +3510,7 @@ int make_schema_select(THD *thd, SELECT_LEX *sel, ST_SCHEMA_TABLE *schema_table= get_schema_table(schema_table_idx); LEX_STRING db, table; DBUG_ENTER("mysql_schema_select"); - /* + /* We have to make non const db_name & table_name because of lower_case_table_names */ @@ -3503,7 +3518,7 @@ int make_schema_select(THD *thd, SELECT_LEX *sel, information_schema_name.length, 0); make_lex_string(thd, &table, schema_table->table_name, strlen(schema_table->table_name), 0); - if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */ + if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */ !sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0), 0, 0, TL_READ, (List *) 0, (List *) 0)) diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 95524a6dfbf..1272d38f729 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -201,7 +201,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables) { trg_field->setup_field(thd, table); if (!trg_field->fixed && - trg_field->fix_fields(thd, (TABLE_LIST *)0, (Item **)0)) + trg_field->fix_fields(thd, (Item **)0)) return 1; } diff --git a/sql/sql_udf.h b/sql/sql_udf.h index 4df3fe0949d..d588572a762 100644 --- a/sql/sql_udf.h +++ b/sql/sql_udf.h @@ -65,8 +65,8 @@ class udf_handler :public Sql_alloc Item_result result_type () const { return u_d ? u_d->returns : STRING_RESULT;} bool get_arguments(); - bool fix_fields(THD *thd,struct st_table_list *tlist,Item_result_field *item, - uint arg_count,Item **args); + bool fix_fields(THD *thd, Item_result_field *item, + uint arg_count, Item **args); void cleanup(); double val(my_bool *null_value) { diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 6e307dda5be..c32c557a45e 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -124,6 +124,13 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd) fake_select_lex->table_list.link_in_list((byte *)&result_table_list, (byte **) &result_table_list.next_local); + for (ORDER *order= (ORDER *)global_parameters->order_list.first; + order; + order=order->next) + { + (*order->item)->walk(&Item::change_context_processor, + (byte *) &fake_select_lex->context); + } } @@ -187,6 +194,8 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, else tmp_result= sel_result; + sl->context.resolve_in_select_list= TRUE; + for (;sl; sl= sl->next_select()) { bool can_skip_order_by; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 6b9a8ddfcb6..ce4a7d6394e 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -67,6 +67,8 @@ static bool check_fields(THD *thd, List &items) List_iterator it(items); Item *item; Item_field *field; + Name_resolution_context *context= &thd->lex->select_lex.context; + while ((item= it++)) { if (!(field= item->filed_for_view_update())) @@ -185,14 +187,8 @@ int mysql_update(THD *thd, #ifndef NO_EMBEDDED_ACCESS_CHECKS table_list->grant.want_privilege= table->grant.want_privilege= want_privilege; #endif - { - bool res; - select_lex->no_wrap_view_item= 1; - res= setup_fields(thd, 0, table_list, fields, 1, 0, 0); - select_lex->no_wrap_view_item= 0; - if (res) - DBUG_RETURN(1); /* purecov: inspected */ - } + if (setup_fields_with_no_wrap(thd, 0, fields, 1, 0, 0)) + DBUG_RETURN(1); /* purecov: inspected */ if (table_list->view && check_fields(thd, fields)) { DBUG_RETURN(1); @@ -216,7 +212,7 @@ int mysql_update(THD *thd, table_list->grant.want_privilege= table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); #endif - if (setup_fields(thd, 0, table_list, values, 1, 0, 0)) + if (setup_fields(thd, 0, values, 1, 0, 0)) { free_underlaid_joins(thd, select_lex); DBUG_RETURN(1); /* purecov: inspected */ @@ -557,7 +553,9 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, tables.table= table; tables.alias= table_list->alias; - if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables, FALSE) || + if (setup_tables(thd, &select_lex->context, + table_list, conds, &select_lex->leaf_tables, + FALSE) || setup_conds(thd, table_list, select_lex->leaf_tables, conds) || select_lex->setup_ref_array(thd, order_num) || setup_order(thd, select_lex->ref_pointer_array, @@ -617,7 +615,6 @@ bool mysql_multi_update_prepare(THD *thd) TABLE_LIST *tl, *leaves; List *fields= &lex->select_lex.item_list; table_map tables_for_update; - int res; bool update_view= 0; /* if this multi-update was converted from usual update, here is table @@ -642,15 +639,12 @@ bool mysql_multi_update_prepare(THD *thd) call in setup_tables()). */ - if (setup_tables(thd, table_list, &lex->select_lex.where, + if (setup_tables(thd, &lex->select_lex.context, + table_list, &lex->select_lex.where, &lex->select_lex.leaf_tables, FALSE)) DBUG_RETURN(TRUE); - leaves= lex->select_lex.leaf_tables; - if ((lex->select_lex.no_wrap_view_item= 1, - res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0), - lex->select_lex.no_wrap_view_item= 0, - res)) + if (setup_fields_with_no_wrap(thd, 0, *fields, 1, 0, 0)) DBUG_RETURN(TRUE); for (tl= table_list; tl ; tl= tl->next_local) @@ -672,6 +666,7 @@ bool mysql_multi_update_prepare(THD *thd) /* Setup timestamp handling and locking mode */ + leaves= lex->select_lex.leaf_tables; for (tl= leaves; tl; tl= tl->next_leaf) { TABLE *table= tl->table; @@ -762,12 +757,10 @@ bool mysql_multi_update_prepare(THD *thd) for (TABLE_LIST *tbl= table_list; tbl; tbl= tbl->next_global) tbl->cleanup_items(); - if (setup_tables(thd, table_list, &lex->select_lex.where, + if (setup_tables(thd, &lex->select_lex.context, + table_list, &lex->select_lex.where, &lex->select_lex.leaf_tables, FALSE) || - (lex->select_lex.no_wrap_view_item= 1, - res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0), - lex->select_lex.no_wrap_view_item= 0, - res)) + setup_fields_with_no_wrap(thd, 0, *fields, 1, 0, 0)) DBUG_RETURN(TRUE); } @@ -897,7 +890,7 @@ int multi_update::prepare(List ¬_used_values, reference tables */ - if (setup_fields(thd, 0, all_tables, *values, 1, 0, 0)) + if (setup_fields(thd, 0, *values, 1, 0, 0)) DBUG_RETURN(1); /* diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 0b351407c13..b7b1335b107 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -828,10 +828,23 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) table->effective_algorithm= VIEW_ALGORITHM_MERGE; DBUG_PRINT("info", ("algorithm: MERGE")); table->updatable= (table->updatable_view != 0); - table->effective_with_check= (uint8)table->with_check; - - table->ancestor= view_tables; + table->effective_with_check= + old_lex->get_effective_with_check(table); + /* prepare view context */ + lex->select_lex.context.resolve_in_table_list_only(table->ancestor= + view_tables); + lex->select_lex.context.outer_context= 0; + lex->select_lex.context.select_lex= table->select_lex; + /* do not check privileges & hide errors for view underlyings */ + for (SELECT_LEX *sl= lex->all_selects_list; + sl; + sl= sl->next_select_in_list()) + { + sl->context.check_privileges= FALSE; + sl->context.error_processor= &view_error_processor; + sl->context.error_processor_data= (void *)table; + } /* Tables of the main select of the view should be marked as belonging to the same select as original view (again we can use LEX::select_lex @@ -866,13 +879,12 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) table->where= view_select->where; /* Add subqueries units to SELECT into which we merging current view. - unit(->next)* chain starts with subqueries that are used by this view and continues with subqueries that are used by other views. We must not add any subquery twice (otherwise we'll form a loop), - to do this we remember in end_unit the first subquery that has + to do this we remember in end_unit the first subquery that has been already added. - + NOTE: we do not support UNION here, so we take only one select */ SELECT_LEX_NODE *end_unit= table->select_lex->slave; @@ -1058,9 +1070,9 @@ frm_type_enum mysql_frm_type(char *path) bool check_key_in_view(THD *thd, TABLE_LIST *view) { TABLE *table; - Field_translator *trans; + Field_translator *trans, *end_of_trans; KEY *key_info, *key_info_end; - uint i, elements_in_view; + uint i; DBUG_ENTER("check_key_in_view"); /* @@ -1077,9 +1089,24 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) trans= view->field_translation; key_info_end= (key_info= table->key_info)+ table->s->keys; - elements_in_view= view->view->select_lex.item_list.elements; + end_of_trans= view->field_translation_end; DBUG_ASSERT(table != 0 && view->field_translation != 0); + { + /* + We should be sure that all fields are ready to get keys from them, but + this operation should not have influence on Field::query_id, to avoid + marking as used fields which are not used + */ + bool save_set_query_id= thd->set_query_id; + thd->set_query_id= 0; + for (Field_translator *fld= trans; fld < end_of_trans; fld++) + { + if (!fld->item->fixed && fld->item->fix_fields(thd, &fld->item)) + return TRUE; + } + thd->set_query_id= save_set_query_id; + } /* Loop over all keys to see if a unique-not-null key is used */ for (;key_info != key_info_end ; key_info++) { @@ -1091,15 +1118,15 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) /* check that all key parts are used */ for (;;) { - uint k; - for (k= 0; k < elements_in_view; k++) + Field_translator *k; + for (k= trans; k < end_of_trans; k++) { Item_field *field; - if ((field= trans[k].item->filed_for_view_update()) && + if ((field= k->item->filed_for_view_update()) && field->field == key_part->field) break; } - if (k == elements_in_view) + if (k == end_of_trans) break; // Key is not possible if (++key_part == key_part_end) DBUG_RETURN(FALSE); // Found usable key @@ -1111,19 +1138,20 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) /* check all fields presence */ { Field **field_ptr; + Field_translator *fld; for (field_ptr= table->field; *field_ptr; field_ptr++) { - for (i= 0; i < elements_in_view; i++) + for (fld= trans; fld < end_of_trans; fld++) { Item_field *field; - if ((field= trans[i].item->filed_for_view_update()) && + if ((field= fld->item->filed_for_view_update()) && field->field == *field_ptr) break; } - if (i == elements_in_view) // If field didn't exists + if (fld == end_of_trans) // If field didn't exists { /* - Keys or all fields of underlying tables are not foud => we have + Keys or all fields of underlying tables are not found => we have to check variable updatable_views_with_limit to decide should we issue an error or just a warning */ @@ -1148,6 +1176,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) SYNOPSIS insert_view_fields() + thd thread handler list list for insertion view view for processing @@ -1156,19 +1185,22 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) TRUE error (is not sent to cliet) */ -bool insert_view_fields(List *list, TABLE_LIST *view) +bool insert_view_fields(THD *thd, List *list, TABLE_LIST *view) { - uint elements_in_view= view->view->select_lex.item_list.elements; + Field_translator *trans_end; Field_translator *trans; DBUG_ENTER("insert_view_fields"); if (!(trans= view->field_translation)) DBUG_RETURN(FALSE); + trans_end= view->field_translation_end; - for (uint i= 0; i < elements_in_view; i++) + for (Field_translator *entry= trans; entry < trans_end; entry++) { Item_field *fld; - if ((fld= trans[i].item->filed_for_view_update())) + if (!entry->item->fixed && entry->item->fix_fields(thd, &entry->item)) + DBUG_RETURN(TRUE); + if ((fld= entry->item->filed_for_view_update())) list->push_back(fld); else { diff --git a/sql/sql_view.h b/sql/sql_view.h index 4e6aaf7f477..3246dbae383 100644 --- a/sql/sql_view.h +++ b/sql/sql_view.h @@ -25,7 +25,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode); bool check_key_in_view(THD *thd, TABLE_LIST * view); -bool insert_view_fields(List *list, TABLE_LIST *view); +bool insert_view_fields(THD *thd, List *list, TABLE_LIST *view); frm_type_enum mysql_frm_type(char *path); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 360bc421965..c06bf8f7bf0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1259,7 +1259,6 @@ create: THD *thd= YYTHD; LEX *lex= thd->lex; lex->sql_command= SQLCOM_CREATE_VIEW; - lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE; /* first table in list is target VIEW name */ if (!lex->select_lex.add_table_to_list(thd, $5, NULL, 0)) YYABORT; @@ -3383,7 +3382,6 @@ alter: LEX *lex= thd->lex; lex->sql_command= SQLCOM_CREATE_VIEW; lex->create_view_mode= VIEW_ALTER; - lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE; /* first table in list is target VIEW name */ lex->select_lex.add_table_to_list(thd, $4, NULL, 0); } @@ -3941,7 +3939,6 @@ select: { LEX *lex= Lex; lex->sql_command= SQLCOM_SELECT; - lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE; } ; @@ -4095,7 +4092,10 @@ select_item_list: | '*' { THD *thd= YYTHD; - if (add_item_to_list(thd, new Item_field(NULL, NULL, "*"))) + if (add_item_to_list(thd, + new Item_field(&thd->lex->current_select-> + context, + NULL, NULL, "*"))) YYABORT; (thd->lex->current_select->with_wild)++; }; @@ -4393,10 +4393,10 @@ simple_expr: my_error(ER_WRONG_COLUMN_NAME, MYF(0), name->str); YYABORT; } - $$= new Item_default_value($3); + $$= new Item_default_value(&Select->context, $3); } | VALUES '(' simple_ident ')' - { $$= new Item_insert_value($3); } + { $$= new Item_insert_value(&Select->context, $3); } | FUNC_ARG0 '(' ')' { if (!$1.symbol->create_func) @@ -4687,15 +4687,16 @@ simple_expr: name->init_qname(YYTHD); sp_add_to_hash(&lex->spfuns, name); if ($5) - $$= new Item_func_sp(name, *$5); + $$= new Item_func_sp(&lex->current_select->context, name, *$5); else - $$= new Item_func_sp(name); + $$= new Item_func_sp(&lex->current_select->context, name); lex->safe_to_cache_query=0; } | IDENT_sys '(' udf_expr_list ')' { #ifdef HAVE_DLOPEN udf_func *udf; + SELECT_LEX *sel= Select; if (using_udf_functions && (udf=find_udf($1.str, $1.length))) { @@ -4776,9 +4777,9 @@ simple_expr: sp_add_to_hash(&lex->spfuns, name); if ($3) - $$= new Item_func_sp(name, *$3); + $$= new Item_func_sp(&lex->current_select->context, name, *$3); else - $$= new Item_func_sp(name); + $$= new Item_func_sp(&lex->current_select->context, name); lex->safe_to_cache_query=0; } } @@ -4980,8 +4981,10 @@ sum_expr: opt_gconcat_separator ')' { - Select->in_sum_expr--; - $$=new Item_func_group_concat($3,$5,Select->gorder_list,$7); + SELECT_LEX *sel= Select; + sel->in_sum_expr--; + $$=new Item_func_group_concat(&sel->context, $3, $5, + sel->gorder_list, $7); $5->empty(); }; @@ -5400,16 +5403,30 @@ using_list: ident { SELECT_LEX *sel= Select; - if (!($$= new Item_func_eq(new Item_field(sel->db1, sel->table1, + if (!($$= new Item_func_eq(new Item_field(&sel->context, + sel->db1, sel->table1, $1.str), - new Item_field(sel->db2, sel->table2, + new Item_field(&sel->context, + sel->db2, sel->table2, $1.str)))) YYABORT; } | using_list ',' ident { SELECT_LEX *sel= Select; - if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(sel->db1,sel->table1,$3.str), new Item_field(sel->db2,sel->table2,$3.str)), $1))) + if (!($$= + new Item_cond_and(new + Item_func_eq(new + Item_field(&sel->context, + sel->db1, + sel->table1, + $3.str), + new + Item_field(&sel->context, + sel->db2, + sel->table2, + $3.str)), + $1))) YYABORT; }; @@ -5675,7 +5692,10 @@ procedure_clause: lex->proc_list.elements=0; lex->proc_list.first=0; lex->proc_list.next= (byte**) &lex->proc_list.first; - if (add_proc_to_list(lex->thd, new Item_field(NULL,NULL,$2.str))) + if (add_proc_to_list(lex->thd, new Item_field(&lex-> + current_select-> + context, + NULL,NULL,$2.str))) YYABORT; Lex->uncacheable(UNCACHEABLE_SIDEEFFECT); } @@ -5922,7 +5942,6 @@ insert: mysql_init_select(lex); /* for subselects */ lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; - lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; } insert_lock_option opt_ignore insert2 { @@ -5940,7 +5959,6 @@ replace: lex->sql_command = SQLCOM_REPLACE; lex->duplicates= DUP_REPLACE; mysql_init_select(lex); - lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; } replace_lock_option insert2 { @@ -6058,7 +6076,7 @@ values: expr_or_default: expr { $$= $1;} - | DEFAULT {$$= new Item_default_value(); } + | DEFAULT {$$= new Item_default_value(&Select->context); } ; opt_insert_update: @@ -7027,15 +7045,17 @@ insert_ident: table_wild: ident '.' '*' { - $$ = new Item_field(NullS,$1.str,"*"); - Lex->current_select->with_wild++; + SELECT_LEX *sel= Select; + $$ = new Item_field(&sel->context, NullS, $1.str, "*"); + sel->with_wild++; } | ident '.' ident '.' '*' { - $$ = new Item_field((YYTHD->client_capabilities & + SELECT_LEX *sel= Select; + $$ = new Item_field(&sel->context, (YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str), $3.str,"*"); - Lex->current_select->with_wild++; + sel->with_wild++; } ; @@ -7060,8 +7080,8 @@ simple_ident: SELECT_LEX *sel=Select; $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? - (Item*) new Item_field(NullS,NullS,$1.str) : - (Item*) new Item_ref(NullS,NullS,$1.str); + (Item*) new Item_field(&sel->context, NullS, NullS, $1.str) : + (Item*) new Item_ref(&sel->context, NullS, NullS, $1.str); } } | simple_ident_q { $$= $1; } @@ -7073,8 +7093,8 @@ simple_ident_nospvar: SELECT_LEX *sel=Select; $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? - (Item*) new Item_field(NullS,NullS,$1.str) : - (Item*) new Item_ref(NullS,NullS,$1.str); + (Item*) new Item_field(&sel->context, NullS, NullS, $1.str) : + (Item*) new Item_ref(&sel->context, NullS, NullS, $1.str); } | simple_ident_q { $$= $1; } ; @@ -7111,7 +7131,8 @@ simple_ident_q: YYABORT; } - if (!(trg_fld= new Item_trigger_field(new_row ? + if (!(trg_fld= new Item_trigger_field(&lex->current_select->context, + new_row ? Item_trigger_field::NEW_ROW: Item_trigger_field::OLD_ROW, $3.str))) @@ -7136,8 +7157,8 @@ simple_ident_q: } $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? - (Item*) new Item_field(NullS,$1.str,$3.str) : - (Item*) new Item_ref(NullS,$1.str,$3.str); + (Item*) new Item_field(&sel->context, NullS, $1.str, $3.str) : + (Item*) new Item_ref(&sel->context, NullS, $1.str, $3.str); } } | '.' ident '.' ident @@ -7152,8 +7173,8 @@ simple_ident_q: } $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? - (Item*) new Item_field(NullS,$2.str,$4.str) : - (Item*) new Item_ref(NullS, $2.str, $4.str); + (Item*) new Item_field(&sel->context, NullS, $2.str, $4.str) : + (Item*) new Item_ref(&sel->context, NullS, $2.str, $4.str); } | ident '.' ident '.' ident { @@ -7167,10 +7188,12 @@ simple_ident_q: } $$= (sel->parsing_place != IN_HAVING || sel->get_in_sum_expr() > 0) ? - (Item*) new Item_field((YYTHD->client_capabilities & + (Item*) new Item_field(&sel->context, + (YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str), $3.str, $5.str) : - (Item*) new Item_ref((YYTHD->client_capabilities & + (Item*) new Item_ref(&sel->context, + (YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str), $3.str, $5.str); }; @@ -7720,9 +7743,11 @@ sys_option_value: it= new Item_null(); } - if (!(trg_fld= new Item_trigger_field(Item_trigger_field::NEW_ROW, + if (!(trg_fld= new Item_trigger_field(&lex->current_select->context, + Item_trigger_field::NEW_ROW, $2.base_name.str)) || !(i= new sp_instr_set_trigger_field( + &lex->current_select->context, lex->sphead->instructions(), lex->spcont, trg_fld, it))) YYABORT; diff --git a/sql/table.cc b/sql/table.cc index 6677453969b..fec74c570f3 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -594,6 +594,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, goto err; /* purecov: inspected */ } + reg_field->field_index= i; reg_field->comment=comment; if (field_type == FIELD_TYPE_BIT && !f_bit_as_char(pack_flag)) { @@ -1713,8 +1714,6 @@ void st_table_list::set_ancestor() } if (tbl->multitable_view) multitable_view= TRUE; - if (tbl->table) - tbl->table->grant= grant; } while ((tbl= tbl->next_local)); if (!multitable_view) @@ -1726,69 +1725,19 @@ void st_table_list::set_ancestor() } -/* - Save old want_privilege and clear want_privilege - - SYNOPSIS - save_and_clear_want_privilege() -*/ - -void st_table_list::save_and_clear_want_privilege() -{ - for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) - { - if (tbl->table) - { - privilege_backup= tbl->table->grant.want_privilege; - tbl->table->grant.want_privilege= 0; - } - else - { - tbl->save_and_clear_want_privilege(); - } - } -} - - -/* - restore want_privilege saved by save_and_clear_want_privilege - - SYNOPSIS - restore_want_privilege() -*/ - -void st_table_list::restore_want_privilege() -{ - for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) - { - if (tbl->table) - tbl->table->grant.want_privilege= privilege_backup; - else - { - tbl->restore_want_privilege(); - } - } -} - - /* setup fields of placeholder of merged VIEW SYNOPSIS st_table_list::setup_ancestor() thd - thread handler - conds - condition of this JOIN - check_opt_type - WHITH CHECK OPTION type (VIEW_CHECK_NONE, - VIEW_CHECK_LOCAL, VIEW_CHECK_CASCADED) + NOTES ancestor is list of tables and views used by view (underlying tables/views) DESCRIPTION It is: - - preparing translation table for view columns (fix_fields() for every - call and creation for first call) - - preparing WHERE, ON and CHECK OPTION condition (fix_fields() for every - call and merging for first call). + - preparing translation table for view columns If there are underlying view(s) procedure first will be called for them. RETURN @@ -1796,163 +1745,114 @@ void st_table_list::restore_want_privilege() TRUE - error */ -bool st_table_list::setup_ancestor(THD *thd, Item **conds, - uint8 check_opt_type) +bool st_table_list::setup_ancestor(THD *thd) { - Field_translator *transl; - SELECT_LEX *select= &view->select_lex; - SELECT_LEX *current_select_save= thd->lex->current_select; - byte *main_table_list_save= select_lex->table_list.first; - Item *item; - TABLE_LIST *tbl; - List_iterator_fast it(select->item_list); - uint i= 0; - enum sub_select_type linkage_save= - select_lex->master_unit()->first_select()->linkage; - bool save_set_query_id= thd->set_query_id; - bool save_wrapper= select_lex->no_wrap_view_item; - bool save_allow_sum_func= thd->allow_sum_func; - bool res= FALSE; DBUG_ENTER("st_table_list::setup_ancestor"); - - if (check_stack_overrun(thd, STACK_MIN_SIZE, (char *)&res)) - return TRUE; - - for (tbl= ancestor; tbl; tbl= tbl->next_local) + if (!field_translation) { - if (tbl->ancestor && - tbl->setup_ancestor(thd, conds, - (check_opt_type == VIEW_CHECK_CASCADED ? - VIEW_CHECK_CASCADED : - VIEW_CHECK_NONE))) - DBUG_RETURN(TRUE); - } + Field_translator *transl; + SELECT_LEX *select= &view->select_lex; + Item *item; + TABLE_LIST *tbl; + List_iterator_fast it(select->item_list); + uint field_count= 0; - /* - We have to ensure that inside the view we are not referring to any - table outside of the view. We do it by changing the pointers used - by fix_fields to look up tables so that only tables and views in - view are seen. We also set linkage to DERIVED_TABLE_TYPE as a barrier - so that we stop resolving fields as this level. - */ - thd->lex->current_select= select_lex; - select_lex->table_list.first= (byte *)ancestor; - select_lex->master_unit()->first_select()->linkage= DERIVED_TABLE_TYPE; - - if (field_translation) - { - DBUG_PRINT("info", ("there are already translation table")); - - select_lex->no_wrap_view_item= 1; - - thd->set_query_id= 1; - /* this view was prepared already on previous PS/SP execution */ - Field_translator *end= field_translation + select->item_list.elements; - /* real rights will be checked in VIEW field */ - save_and_clear_want_privilege(); - /* aggregate function are allowed */ - thd->allow_sum_func= 1; - for (transl= field_translation; transl < end; transl++) + if (check_stack_overrun(thd, STACK_MIN_SIZE, (char *)&field_count)) { - if (!transl->item->fixed && - transl->item->fix_fields(thd, ancestor, &transl->item)) - goto err; + DBUG_RETURN(TRUE); } + for (tbl= ancestor; tbl; tbl= tbl->next_local) { - if (tbl->on_expr && !tbl->on_expr->fixed && - tbl->on_expr->fix_fields(thd, ancestor, &tbl->on_expr)) - goto err; - } - if (where && !where->fixed && where->fix_fields(thd, ancestor, &where)) - goto err; - if (check_option && !check_option->fixed && - check_option->fix_fields(thd, ancestor, &check_option)) - goto err; - restore_want_privilege(); - - /* WHERE/ON resolved => we can rename fields */ - for (transl= field_translation; transl < end; transl++) - { - transl->item->rename((char *)transl->name); - } - goto ok; - } - - /* Create view fields translation table */ - - if (!(transl= - (Field_translator*)(thd->current_arena-> - alloc(select->item_list.elements * - sizeof(Field_translator))))) - { - res= TRUE; - goto ok; // Restore thd - } - - select_lex->no_wrap_view_item= 1; - - /* - Resolve all view items against ancestor table. - - TODO: do it only for real used fields "on demand" to mark really - used fields correctly. - */ - thd->set_query_id= 1; - /* real rights will be checked in VIEW field */ - save_and_clear_want_privilege(); - /* aggregate function are allowed */ - thd->allow_sum_func= 1; - while ((item= it++)) - { - /* save original name of view column */ - char *name= item->name; - transl[i].item= item; - if (!item->fixed && item->fix_fields(thd, ancestor, &transl[i].item)) - goto err; - /* set new item get in fix fields and original column name */ - transl[i++].name= name; - } - field_translation= transl; - /* TODO: sort this list? Use hash for big number of fields */ - - for (tbl= ancestor; tbl; tbl= tbl->next_local) - { - if (tbl->on_expr && !tbl->on_expr->fixed && - tbl->on_expr->fix_fields(thd, ancestor, &tbl->on_expr)) - goto err; - } - if (where || - (check_opt_type == VIEW_CHECK_CASCADED && - ancestor->check_option)) - { - Query_arena *arena= thd->current_arena, backup; - TABLE_LIST *tbl= this; - if (arena->is_conventional()) - arena= 0; // For easier test - - if (where && !where->fixed && where->fix_fields(thd, ancestor, &where)) - goto err; - - if (arena) - thd->set_n_backup_item_arena(arena, &backup); - - if (check_opt_type) - { - if (where) - check_option= where->copy_andor_structure(thd); - if (check_opt_type == VIEW_CHECK_CASCADED) + if (tbl->ancestor && + tbl->setup_ancestor(thd)) { - check_option= and_conds(check_option, ancestor->check_option); + DBUG_RETURN(TRUE); } } + /* Create view fields translation table */ + + if (!(transl= + (Field_translator*)(thd->current_arena-> + alloc(select->item_list.elements * + sizeof(Field_translator))))) + { + DBUG_RETURN(TRUE); + } + + while ((item= it++)) + { + transl[field_count].name= item->name; + transl[field_count++].item= item; + } + field_translation= transl; + field_translation_end= transl + field_count; + /* TODO: use hash for big number of fields */ + + /* full text function moving to current select */ + if (view->select_lex.ftfunc_list->elements) + { + Item_func_match *ifm; + SELECT_LEX *current_select= thd->lex->current_select; + List_iterator_fast + li(*(view->select_lex.ftfunc_list)); + while ((ifm= li++)) + current_select->ftfunc_list->push_front(ifm); + } + } + DBUG_RETURN(FALSE); +} + + +/* + Prepare where expression of view + + SYNOPSIS + st_table_list::prep_where() + thd - thread handler + conds - condition of this JOIN + no_where_clause - do not build WHERE or ON outer qwery do not need it + (it is INSERT), we do not need conds if this flag is set + + NOTE: have to be called befor CHECK OPTION preparation, because it makes + fix_fields for view WHERE clause + + RETURN + FALSE - OK + TRUE - error +*/ + +bool st_table_list::prep_where(THD *thd, Item **conds, + bool no_where_clause) +{ + DBUG_ENTER("st_table_list::prep_where"); + + for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) + { + if (tbl->view && tbl->prep_where(thd, conds, no_where_clause)) + { + DBUG_RETURN(TRUE); + } + } + + if (where) + { + if (!where->fixed && where->fix_fields(thd, &where)) + { + DBUG_RETURN(TRUE); + } + /* check that it is not VIEW in which we insert with INSERT SELECT (in this case we can't add view WHERE condition to main SELECT_LEX) */ - if (where && !no_where_clause) + if (!no_where_clause && !where_processed) { + TABLE_LIST *tbl= this; + Query_arena *arena= thd->current_arena, backup; + arena= thd->change_arena_if_needed(&backup); // For easier test + /* Go up to join tree and try to find left join */ for (; tbl; tbl= tbl->embedding) { @@ -1969,72 +1869,107 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds, } } if (tbl == 0) + *conds= and_conds(*conds, where); + if (arena) + thd->restore_backup_item_arena(arena, &backup); + where_processed= TRUE; + } + } + + DBUG_RETURN(FALSE); +} + + +/* + Prepare check option expression of table + + SYNOPSIS + st_table_list::prep_check_option() + thd - thread handler + check_opt_type - WITH CHECK OPTION type (VIEW_CHECK_NONE, + VIEW_CHECK_LOCAL, VIEW_CHECK_CASCADED) + we use this parameter instead of direct check of + effective_with_check to change type of underlying + views to VIEW_CHECK_CASCADED if outer view have + such option and prevent processing of underlying + view check options if outer view have just + VIEW_CHECK_LOCAL option. + + NOTE + This method build check options for every call + (usual execution or every SP/PS call) + This method have to be called after WHERE preparation + (st_table_list::prep_where) + + RETURN + FALSE - OK + TRUE - error +*/ + +bool st_table_list::prep_check_option(THD *thd, uint8 check_opt_type) +{ + DBUG_ENTER("st_table_list::prep_check_option"); + + for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) + { + /* see comment of check_opt_type parameter */ + if (tbl->view && + tbl->prep_check_option(thd, + ((check_opt_type == VIEW_CHECK_CASCADED) ? + VIEW_CHECK_CASCADED : + VIEW_CHECK_NONE))) + { + DBUG_RETURN(TRUE); + } + } + + if (check_opt_type) + { + Item *item= 0; + if (where) + { + DBUG_ASSERT(where->fixed); + item= where->copy_andor_structure(thd); + } + if (check_opt_type == VIEW_CHECK_CASCADED) + { + for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) { - if (outer_join) - { - /* - Store WHERE condition to ON expression for outer join, because - we can't use WHERE to correctly execute left joins on VIEWs and - this expression will not be moved to WHERE condition (i.e. will - be clean correctly for PS/SP) - */ - on_expr= and_conds(on_expr, where); - } - else - { - /* - It is conds of JOIN, but it will be stored in - st_select_lex::prep_where for next reexecution - */ - *conds= and_conds(*conds, where); - } + if (tbl->check_option) + item= and_conds(item, tbl->check_option); } } - - if (arena) - thd->restore_backup_item_arena(arena, &backup); + if (item) + thd->change_item_tree(&check_option, item); } - restore_want_privilege(); - /* - fix_fields do not need tables, because new are only AND operation and we - just need recollect statistics - */ - if (check_option && !check_option->fixed && - check_option->fix_fields(thd, 0, &check_option)) - goto err; - - /* WHERE/ON resolved => we can rename fields */ + if (check_option) { - Field_translator *end= field_translation + select->item_list.elements; - for (transl= field_translation; transl < end; transl++) + const char *save_where= thd->where; + thd->where= "check option"; + if (!check_option->fixed && + check_option->fix_fields(thd, &check_option) || + check_option->check_cols(1)) { - transl->item->rename((char *)transl->name); + DBUG_RETURN(TRUE); } + thd->where= save_where; } + DBUG_RETURN(FALSE); +} - /* full text function moving to current select */ - if (view->select_lex.ftfunc_list->elements) - { - Query_arena *arena= thd->current_arena, backup; - if (arena->is_conventional()) - arena= 0; // For easier test - else - thd->set_n_backup_item_arena(arena, &backup); - Item_func_match *ifm; - List_iterator_fast - li(*(view->select_lex.ftfunc_list)); - while ((ifm= li++)) - current_select_save->ftfunc_list->push_front(ifm); - if (arena) - thd->restore_backup_item_arena(arena, &backup); - } +/* + Hide errors which show view underlying table information - goto ok; + SYNOPSIS + st_table_list::hide_view_error() + thd thread handler -err: - res= TRUE; +*/ + +void st_table_list::hide_view_error(THD *thd) +{ /* Hide "Unknown column" or "Unknown function" error */ if (thd->net.last_errno == ER_BAD_FIELD_ERROR || thd->net.last_errno == ER_SP_DOES_NOT_EXIST) @@ -2042,15 +1977,12 @@ err: thd->clear_error(); my_error(ER_VIEW_INVALID, MYF(0), view_db.str, view_name.str); } - -ok: - select_lex->no_wrap_view_item= save_wrapper; - thd->lex->current_select= current_select_save; - select_lex->table_list.first= main_table_list_save; - select_lex->master_unit()->first_select()->linkage= linkage_save; - thd->set_query_id= save_set_query_id; - thd->allow_sum_func= save_allow_sum_func; - DBUG_RETURN(res); + else if (thd->net.last_errno == ER_NO_DEFAULT_FOR_FIELD) + { + thd->clear_error(); + // TODO: make correct error message + my_error(ER_NO_DEFAULT_FOR_VIEW_FIELD, MYF(0), view_db.str, view_name.str); + } } @@ -2094,9 +2026,9 @@ void st_table_list::cleanup_items() if (!field_translation) return; - Field_translator *end= (field_translation + - view->select_lex.item_list.elements); - for (Field_translator *transl= field_translation; transl < end; transl++) + for (Field_translator *transl= field_translation; + transl < field_translation_end; + transl++) transl->item->walk(&Item::cleanup_processor, 0); } @@ -2209,8 +2141,9 @@ bool st_table_list::set_insert_values(MEM_ROOT *mem_root) void Field_iterator_view::set(TABLE_LIST *table) { + view= table; ptr= table->field_translation; - array_end= ptr + table->view->select_lex.item_list.elements; + array_end= table->field_translation_end; } @@ -2220,9 +2153,9 @@ const char *Field_iterator_table::name() } -Item *Field_iterator_table::item(THD *thd) +Item *Field_iterator_table::create_item(THD *thd) { - return new Item_field(thd, *ptr); + return new Item_field(thd, &thd->lex->current_select->context, *ptr); } @@ -2232,6 +2165,51 @@ const char *Field_iterator_view::name() } +Item *Field_iterator_view::create_item(THD *thd) +{ + return create_view_field(thd, view, &ptr->item, ptr->name); +} + +Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref, + const char *name) +{ + bool save_wrapper= thd->lex->select_lex.no_wrap_view_item; + Item *field= *field_ref; + DBUG_ENTER("create_view_field"); + + if (view->schema_table_reformed) + { + /* + In case of SHOW command (schema_table_reformed set) all items are + fixed + */ + DBUG_ASSERT(field && field->fixed); + DBUG_RETURN(field); + } + + DBUG_ASSERT(field); + thd->lex->current_select->no_wrap_view_item= TRUE; + if (!field->fixed) + { + if (field->fix_fields(thd, field_ref)) + { + thd->lex->current_select->no_wrap_view_item= save_wrapper; + DBUG_RETURN(0); + } + field= *field_ref; + } + thd->lex->current_select->no_wrap_view_item= save_wrapper; + if (thd->lex->current_select->no_wrap_view_item) + { + DBUG_RETURN(field); + } + Item *item= new Item_direct_view_ref(&view->view->select_lex.context, + field_ref, view->view_name.str, + name); + DBUG_RETURN(item); +} + + /***************************************************************************** ** Instansiate templates *****************************************************************************/ diff --git a/sql/table.h b/sql/table.h index 8bc4e01852f..d0c998c4c10 100644 --- a/sql/table.h +++ b/sql/table.h @@ -314,9 +314,9 @@ typedef struct st_schema_table #define JOIN_TYPE_LEFT 1 #define JOIN_TYPE_RIGHT 2 -#define VIEW_ALGORITHM_UNDEFINED 0 -#define VIEW_ALGORITHM_TMPTABLE 1 -#define VIEW_ALGORITHM_MERGE 2 +#define VIEW_ALGORITHM_UNDEFINED 0 +#define VIEW_ALGORITHM_TMPTABLE 1 +#define VIEW_ALGORITHM_MERGE 2 /* view WITH CHECK OPTION parameter options */ #define VIEW_CHECK_NONE 0 @@ -329,9 +329,13 @@ typedef struct st_schema_table #define VIEW_CHECK_SKIP 2 struct st_lex; +struct st_table_list; class select_union; class TMP_TABLE_PARAM; +Item *create_view_field(THD *thd, st_table_list *view, Item **field_ref, + const char *name); + struct Field_translator { Item *item; @@ -384,6 +388,8 @@ typedef struct st_table_list st_select_lex *select_lex; st_lex *view; /* link on VIEW lex for merging */ Field_translator *field_translation; /* array of VIEW fields */ + /* pointer to element after last one in translation table above */ + Field_translator *field_translation_end; /* list of ancestor(s) of this table (underlying table(s)/view(s) */ st_table_list *ancestor; /* most upper view this table belongs to */ @@ -408,8 +414,7 @@ typedef struct st_table_list algorithm) */ uint8 effective_with_check; - uint effective_algorithm; /* which algorithm was really used */ - uint privilege_backup; /* place for saving privileges */ + uint8 effective_algorithm; /* which algorithm was really used */ GRANT_INFO grant; /* data need by some engines in query cache*/ ulonglong engine_data; @@ -424,7 +429,6 @@ typedef struct st_table_list bool updating; /* for replicate-do/ignore table */ bool force_index; /* prefer index over table scan */ bool ignore_leaves; /* preload only non-leaf nodes */ - bool no_where_clause; /* do not attach WHERE to SELECT */ table_map dep_tables; /* tables the table depends on */ table_map on_expr_dep_tables; /* tables on expression depends on */ struct st_nested_join *nested_join; /* if the element is a nested join */ @@ -437,6 +441,8 @@ typedef struct st_table_list /* TRUE if this merged view contain auto_increment field */ bool contain_auto_increment; bool multitable_view; /* TRUE iff this is multitable view */ + /* view where processed */ + bool where_processed; /* FRMTYPE_ERROR if any type is acceptable */ enum frm_type_enum required_type; char timestamp_buffer[20]; /* buffer for timestamp (19+1) */ @@ -449,16 +455,32 @@ typedef struct st_table_list void calc_md5(char *buffer); void set_ancestor(); int view_check_option(THD *thd, bool ignore_failure); - bool setup_ancestor(THD *thd, Item **conds, uint8 check_option); + bool setup_ancestor(THD *thd); void cleanup_items(); bool placeholder() {return derived || view; } void print(THD *thd, String *str); - void save_and_clear_want_privilege(); - void restore_want_privilege(); bool check_single_table(st_table_list **table, table_map map, st_table_list *view); bool set_insert_values(MEM_ROOT *mem_root); + void hide_view_error(THD *thd); st_table_list *find_underlying_table(TABLE *table); + inline bool prepare_check_option(THD *thd) + { + bool res= FALSE; + if (effective_with_check) + res= prep_check_option(thd, effective_with_check); + return res; + } + inline bool prepare_where(THD *thd, Item **conds, + bool no_where_clause) + { + if (effective_algorithm == VIEW_ALGORITHM_MERGE) + return prep_where(thd, conds, no_where_clause); + return FALSE; + } +private: + bool prep_check_option(THD *thd, uint8 check_opt_type); + bool prep_where(THD *thd, Item **conds, bool no_where_clause); } TABLE_LIST; class Item; @@ -471,7 +493,7 @@ public: virtual void next()= 0; virtual bool end_of_fields()= 0; /* Return 1 at end of list */ virtual const char *name()= 0; - virtual Item *item(THD *)= 0; + virtual Item *create_item(THD *)= 0; virtual Field *field()= 0; }; @@ -486,7 +508,7 @@ public: void next() { ptr++; } bool end_of_fields() { return *ptr == 0; } const char *name(); - Item *item(THD *thd); + Item *create_item(THD *thd); Field *field() { return *ptr; } }; @@ -494,15 +516,18 @@ public: class Field_iterator_view: public Field_iterator { Field_translator *ptr, *array_end; + TABLE_LIST *view; public: Field_iterator_view() :ptr(0), array_end(0) {} void set(TABLE_LIST *table); void next() { ptr++; } bool end_of_fields() { return ptr == array_end; } const char *name(); - Item *item(THD *thd) { return ptr->item; } + Item *create_item(THD *thd); Item **item_ptr() {return &ptr->item; } Field *field() { return 0; } + + inline Item *item() { return ptr->item; } }; From df7852f20d25f9f298a3a65133cb192d4f08983e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 09:40:05 +0300 Subject: [PATCH 119/216] Optimization during review Add extra check to delete [] to ensure we are not deleting not allocated data sql/sql_select.cc: Optimization Add extra check to delete [] to ensure we are not deleting not allocated data --- sql/sql_select.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 044dc60e4b6..fcc10ae466a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8222,12 +8222,10 @@ cp_buffer_from_ref(THD *thd, TABLE_REF *ref) thd->count_cuted_fields= CHECK_FIELD_IGNORE; for (store_key **copy=ref->key_copy ; *copy ; copy++) { - int res; - if ((res= (*copy)->copy())) + if ((*copy)->copy() & 1) { thd->count_cuted_fields= save_count_cuted_fields; - if ((res= res & 1)) - return res; // Something went wrong + return 1; // Something went wrong } } thd->count_cuted_fields= save_count_cuted_fields; @@ -8818,7 +8816,8 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, DBUG_RETURN(0); err: - delete [] param->copy_field; // This is never 0 + if (copy) + delete [] param->copy_field; param->copy_field=0; err2: DBUG_RETURN(TRUE); From 0f64a495068bc8898c7269b495c76cb28624b50d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 13:01:46 +0400 Subject: [PATCH 120/216] "Fix" for bug #11394 "Recursion in SP crash server" and bug #11600 "Stored procedures: crash with function calling itself". Disallow recursive stored routines until we either make Item's and LEX reentrant safe or will use spearate sp_head instances (and thus separate LEX objects and Item trees) for each routine invocation. mysql-test/r/sp-error.result: Added tests for bug #11394 "Recursion in SP crash server" and bug #11600 "Stored procedures: crash with function calling itself". (We simply disallow recursion for stored routines). mysql-test/r/sp.result: Disabled test cases containing recursive stored routines until we will support for them. mysql-test/t/sp-error.test: Added tests for bug #11394 "Recursion in SP crash server" and bug #11600 "Stored procedures: crash with function calling itself". (We simply disallow recursion for stored routines). mysql-test/t/sp.test: Disabled test cases containing recursive stored routines until we will support for them. sql/share/errmsg.txt: Added error message saying that recursive stored routines are disallowed. sql/sp_head.cc: sp_head::execute(): Since many Item's and LEX members can't be used in reentrant fashion we have to disable recursion for stored routines. So let us track routine invocations using sp_head::m_is_invoked member and raise error when one attempts to call routine recursively. sql/sp_head.h: sp_head: Added m_is_invoked member for tracking of routine invocations and preventing recursion. --- mysql-test/r/sp-error.result | 40 +++++++++++ mysql-test/r/sp.result | 68 ------------------ mysql-test/t/sp-error.test | 55 ++++++++++++++ mysql-test/t/sp.test | 136 ++++++++++++++++++----------------- sql/share/errmsg.txt | 2 + sql/sp_head.cc | 26 ++++++- sql/sp_head.h | 3 + 7 files changed, 195 insertions(+), 135 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index b6ba737a8ba..814abe4f56d 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -686,3 +686,43 @@ ERROR 0A000: EXECUTE is not allowed in stored procedures create function f() returns int begin execute stmt; ERROR 0A000: EXECUTE is not allowed in stored procedures deallocate prepare stmt; +drop function if exists bug11394| +drop function if exists bug11394_1| +drop function if exists bug11394_2| +drop procedure if exists bug11394| +create function bug11394(i int) returns int +begin +if i <= 0 then +return 0; +else +return (i in (100, 200, bug11394(i-1), 400)); +end if; +end| +select bug11394(2)| +ERROR HY000: Recursive stored routines are not allowed. +drop function bug11394| +create function bug11394_1(i int) returns int +begin +if i <= 0 then +return 0; +else +return (select bug11394_1(i-1)); +end if; +end| +select bug11394_1(2)| +ERROR HY000: Recursive stored routines are not allowed. +drop function bug11394_1| +create function bug11394_2(i int) returns int return i| +select bug11394_2(bug11394_2(10))| +bug11394_2(bug11394_2(10)) +10 +drop function bug11394_2| +create procedure bug11394(i int, j int) +begin +if i > 0 then +call bug11394(i - 1,(select 1)); +end if; +end| +call bug11394(2, 1)| +ERROR HY000: Recursive stored routines are not allowed. +drop procedure bug11394| diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index ed858ba27ee..2840e82829c 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1396,60 +1396,6 @@ drop procedure opp| drop procedure ip| show procedure status like '%p%'| Db Name Type Definer Modified Created Security_type Comment -drop table if exists fib| -create table fib ( f bigint unsigned not null )| -drop procedure if exists fib| -create procedure fib(n int unsigned) -begin -if n > 1 then -begin -declare x, y bigint unsigned; -declare c cursor for select f from fib order by f desc limit 2; -open c; -fetch c into y; -fetch c into x; -close c; -insert into fib values (x+y); -call fib(n-1); -end; -end if; -end| -insert into fib values (0), (1)| -call fib(3)| -select * from fib order by f asc| -f -0 -1 -1 -2 -delete from fib| -insert into fib values (0), (1)| -call fib(20)| -select * from fib order by f asc| -f -0 -1 -1 -2 -3 -5 -8 -13 -21 -34 -55 -89 -144 -233 -377 -610 -987 -1597 -2584 -4181 -6765 -drop table fib| -drop procedure fib| drop procedure if exists bar| create procedure bar(x char(16), y int) comment "111111111111" sql security invoker @@ -2506,20 +2452,6 @@ s1 1 drop procedure bug4905| drop table t3| -drop function if exists bug6022| -drop function if exists bug6022| -create function bug6022(x int) returns int -begin -if x < 0 then -return 0; -else -return bug6022(x-1); -end if; -end| -select bug6022(5)| -bug6022(5) -0 -drop function bug6022| drop procedure if exists bug6029| drop procedure if exists bug6029| create procedure bug6029() diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index faf6d8b4de3..ea49aff8bbe 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -986,3 +986,58 @@ create procedure p() execute stmt; create function f() returns int begin execute stmt; deallocate prepare stmt; +# +# Bug #11394 "Recursion in SP crash server" and bug #11600 "Stored +# procedures: crash with function calling itself". +# We have to disable recursion since in many cases LEX and many +# Item's can't be used in reentrant way nowdays. +delimiter |; +--disable_warnings +drop function if exists bug11394| +drop function if exists bug11394_1| +drop function if exists bug11394_2| +drop procedure if exists bug11394| +--enable_warnings +create function bug11394(i int) returns int +begin + if i <= 0 then + return 0; + else + return (i in (100, 200, bug11394(i-1), 400)); + end if; +end| +# If we allow recursive functions without additional modifications +# this will crash server since Item for "IN" is not reenterable. +--error 1423 +select bug11394(2)| +drop function bug11394| +create function bug11394_1(i int) returns int +begin + if i <= 0 then + return 0; + else + return (select bug11394_1(i-1)); + end if; +end| +# The following statement will crash because some LEX members responsible +# for selects cannot be used in reentrant fashion. +--error 1423 +select bug11394_1(2)| +drop function bug11394_1| +# Note that the following should be allowed since it does not contains +# recursion +create function bug11394_2(i int) returns int return i| +select bug11394_2(bug11394_2(10))| +drop function bug11394_2| +create procedure bug11394(i int, j int) +begin + if i > 0 then + call bug11394(i - 1,(select 1)); + end if; +end| +# Again if we allow recursion for stored procedures (without +# additional efforts) the following statement will crash the server. +--error 1423 +call bug11394(2, 1)| +drop procedure bug11394| +delimiter |; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index e7ee4b134ba..4d22f1d4b90 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1630,54 +1630,56 @@ show procedure status like '%p%'| # Fibonacci, for recursion test. (Yet Another Numerical series :) - ---disable_warnings -drop table if exists fib| ---enable_warnings -create table fib ( f bigint unsigned not null )| - -# We deliberately do it the awkward way, fetching the last two -# values from the table, in order to exercise various statements -# and table accesses at each turn. ---disable_warnings -drop procedure if exists fib| ---enable_warnings -create procedure fib(n int unsigned) -begin - if n > 1 then - begin - declare x, y bigint unsigned; - declare c cursor for select f from fib order by f desc limit 2; - - open c; - fetch c into y; - fetch c into x; - close c; - insert into fib values (x+y); - call fib(n-1); - end; - end if; -end| - -# Minimum test: recursion of 3 levels - -insert into fib values (0), (1)| - -call fib(3)| - -select * from fib order by f asc| - -delete from fib| - -# Original test: 20 levels (may run into memory limits!) - -insert into fib values (0), (1)| - -call fib(20)| - -select * from fib order by f asc| -drop table fib| -drop procedure fib| +# +# This part of test is disabled until we implement support for +# recursive stored procedures. +#--disable_warnings +#drop table if exists fib| +#--enable_warnings +#create table fib ( f bigint unsigned not null )| +# +## We deliberately do it the awkward way, fetching the last two +## values from the table, in order to exercise various statements +## and table accesses at each turn. +#--disable_warnings +#drop procedure if exists fib| +#--enable_warnings +#create procedure fib(n int unsigned) +#begin +# if n > 1 then +# begin +# declare x, y bigint unsigned; +# declare c cursor for select f from fib order by f desc limit 2; +# +# open c; +# fetch c into y; +# fetch c into x; +# close c; +# insert into fib values (x+y); +# call fib(n-1); +# end; +# end if; +#end| +# +## Minimum test: recursion of 3 levels +# +#insert into fib values (0), (1)| +# +#call fib(3)| +# +#select * from fib order by f asc| +# +#delete from fib| +# +## Original test: 20 levels (may run into memory limits!) +# +#insert into fib values (0), (1)| +# +#call fib(20)| +# +#select * from fib order by f asc| +#drop table fib| +#drop procedure fib| # @@ -3011,24 +3013,26 @@ drop table t3| # # BUG#6022: Stored procedure shutdown problem with self-calling function. # ---disable_warnings -drop function if exists bug6022| ---enable_warnings - ---disable_warnings -drop function if exists bug6022| ---enable_warnings -create function bug6022(x int) returns int -begin - if x < 0 then - return 0; - else - return bug6022(x-1); - end if; -end| - -select bug6022(5)| -drop function bug6022| +# This part of test is disabled until we implement support for +# recursive stored functions. +#--disable_warnings +#drop function if exists bug6022| +#--enable_warnings +# +#--disable_warnings +#drop function if exists bug6022| +#--enable_warnings +#create function bug6022(x int) returns int +#begin +# if x < 0 then +# return 0; +# else +# return bug6022(x-1); +# end if; +#end| +# +#select bug6022(5)| +#drop function bug6022| # # BUG#6029: Stored procedure specific handlers should have priority diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 7ae5130764f..8230443da48 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5358,3 +5358,5 @@ ER_STMT_HAS_NO_OPEN_CURSOR eng "The statement (%lu) has no open cursor." ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG eng "Explicit or implicit commit is not allowed in stored function or trigger." +ER_SP_NO_RECURSION + eng "Recursive stored routines are not allowed." diff --git a/sql/sp_head.cc b/sql/sp_head.cc index e4dc64c993d..3d5525015c6 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -312,7 +312,8 @@ sp_head::operator delete(void *ptr, size_t size) sp_head::sp_head() :Query_arena(&main_mem_root, INITIALIZED_FOR_SP), m_returns_cs(NULL), m_has_return(FALSE), - m_simple_case(FALSE), m_multi_results(FALSE), m_in_handler(FALSE) + m_simple_case(FALSE), m_multi_results(FALSE), m_in_handler(FALSE), + m_is_invoked(FALSE) { extern byte * sp_table_key(const byte *ptr, uint *plen, my_bool first); @@ -587,6 +588,28 @@ sp_head::execute(THD *thd) DBUG_RETURN(-1); } + if (m_is_invoked) + { + /* + We have to disable recursion for stored routines since in + many cases LEX structure and many Item's can't be used in + reentrant way now. + + TODO: We can circumvent this problem by using separate + sp_head instances for each recursive invocation. + + NOTE: Theoretically arguments of procedure can be evaluated + before its invocation so there should be no problem with + recursion. But since we perform cleanup for CALL statement + as for any other statement only after its execution, its LEX + structure is not reusable for recursive calls. Thus we have + to prohibit recursion for stored procedures too. + */ + my_error(ER_SP_NO_RECURSION, MYF(0)); + DBUG_RETURN(-1); + } + m_is_invoked= TRUE; + dbchanged= FALSE; if (m_db.length && (ret= sp_use_new_db(thd, m_db.str, olddb, sizeof(olddb), 0, &dbchanged))) @@ -704,6 +727,7 @@ sp_head::execute(THD *thd) if (! thd->killed) ret= sp_change_db(thd, olddb, 0); } + m_is_invoked= FALSE; DBUG_RETURN(ret); } diff --git a/sql/sp_head.h b/sql/sp_head.h index aaef5a3d50e..39b0c1394fe 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -259,6 +259,9 @@ private: */ HASH m_sptabs; + /* Used for tracking of routine invocations and preventing recursion. */ + bool m_is_invoked; + int execute(THD *thd); From f20c899892d8b8a453a3d54c5b29c93235804a01 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 12:01:00 +0200 Subject: [PATCH 121/216] BUG#11678: mysqldump --master-data should fail if master binlog disabled client/mysqldump.c: Add error message in case master does not have binlogging enabled --- client/mysqldump.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/client/mysqldump.c b/client/mysqldump.c index fb5270c3222..4d340cb4051 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2356,6 +2356,7 @@ static int do_show_master_status(MYSQL *mysql_con) row = mysql_fetch_row(master); if (row && row[0] && row[1]) { + /* SHOW MASTER STATUS reports file and position */ if (opt_comments) fprintf(md_result_file, "\n--\n-- Position to start replication or point-in-time " @@ -2365,6 +2366,14 @@ static int do_show_master_status(MYSQL *mysql_con) comment_prefix, row[0], row[1]); check_io(md_result_file); } + else if (!ignore_errors) + { + /* SHOW MASTER STATUS reports nothing and --force is not enabled */ + my_printf_error(0, "Error: Binlogging on server not active", + MYF(0), mysql_error(mysql_con)); + mysql_free_result(master); + return 1; + } mysql_free_result(master); } return 0; From 0e6a93ece30a2c5d145e51d5b8c3d0edb0066337 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 15:07:06 +0500 Subject: [PATCH 122/216] sql_table.cc: Bug#11657 Creation of secondary index fails: If TINYBLOB key part length is 255, it is equal to field length. For BLOB, unlike for CHAR/VARCHAR, we should keep a non-zero key part length, otherwise "BLOB/TEXT column used in key specification without a key length" error is produced afterwards. type_blob.result, type_blob.test: fixing tests accordinly sql/sql_table.cc: Bug#11657 Creation of secondary index fails For TINYBLOB key part length can be equal to field length. We should still keep a non-zero key part length, mysql-test/t/type_blob.test: fixing tests accordinly mysql-test/r/type_blob.result: fixing tests accordinly --- mysql-test/r/type_blob.result | 15 +++++++++++++++ mysql-test/t/type_blob.test | 9 ++++++++- sql/sql_table.cc | 3 ++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index 67a011231be..193ed298339 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -703,3 +703,18 @@ select max(i) from t1 where c = ''; max(i) 4 drop table t1; +create table t1 (a int, b int, c tinyblob, d int, e int); +alter table t1 add primary key (a,b,c(255),d); +alter table t1 add key (a,b,d,e); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL default '0', + `b` int(11) NOT NULL default '0', + `c` tinyblob NOT NULL, + `d` int(11) NOT NULL default '0', + `e` int(11) default NULL, + PRIMARY KEY (`a`,`b`,`c`(255),`d`), + KEY `a` (`a`,`b`,`d`,`e`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test index c33ea3f435d..80aabf6c5e0 100644 --- a/mysql-test/t/type_blob.test +++ b/mysql-test/t/type_blob.test @@ -394,4 +394,11 @@ INSERT t1 (i, c) VALUES (1,''),(2,''),(3,'asdfh'),(4,''); select max(i) from t1 where c = ''; drop table t1; - +# +# Bug#11657: Creation of secondary index fails +# +create table t1 (a int, b int, c tinyblob, d int, e int); +alter table t1 add primary key (a,b,c(255),d); +alter table t1 add key (a,b,d,e); +show create table t1; +drop table t1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 553a853bede..5903576947d 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3400,7 +3400,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, */ if (!Field::type_can_have_key_part(cfield->field->type()) || !Field::type_can_have_key_part(cfield->sql_type) || - cfield->field->field_length == key_part_length || + (cfield->field->field_length == key_part_length && + !f_is_blob(key_part->key_type)) || (cfield->length && (cfield->length < key_part_length / key_part->field->charset()->mbmaxlen))) key_part_length= 0; // Use whole field From da83833964d877cacdb4e432522d171b3260e06a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 13:20:16 +0300 Subject: [PATCH 123/216] InnoDB: Optimize [and clarify] a condition in build_template() sql/ha_innodb.cc: build_template(): Optimize (and make more readable) the conditions for skipping or including a field. --- sql/ha_innodb.cc | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index db354066849..162e3184713 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2955,21 +2955,44 @@ build_template( templ = prebuilt->mysql_template + n_requested_fields; field = table->field[i]; - ibool index_contains_field= - dict_index_contains_col_or_prefix(index, i); + if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) { + /* Decide which columns we should fetch + and which we can skip. */ + register const ibool index_contains_field = + dict_index_contains_col_or_prefix(index, i); - if (templ_type == ROW_MYSQL_REC_FIELDS && - ((prebuilt->read_just_key && !index_contains_field) || - (!(fetch_all_in_key && index_contains_field) && - !(fetch_primary_key_cols && - dict_table_col_in_clustered_key(index->table, i)) && - thd->query_id != field->query_id))) { + if (!index_contains_field && prebuilt->read_just_key) { + /* If this is a 'key read', we do not need + columns that are not in the key */ + + goto skip_field; + } + + if (index_contains_field && fetch_all_in_key) { + /* This field is needed in the query */ + + goto include_field; + } + + if (thd->query_id == field->query_id) { + /* This field is needed in the query */ + + goto include_field; + } + + if (fetch_primary_key_cols + && dict_table_col_in_clustered_key(index->table, + i)) { + /* This field is needed in the query */ + + goto include_field; + } /* This field is not needed in the query, skip it */ goto skip_field; } - +include_field: n_requested_fields++; templ->col_no = i; From 497b88652bf1529e62ae31c6c7151f5966435504 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 13:27:23 +0300 Subject: [PATCH 124/216] fix bugs found by gcc 3.4 compiler sql/sp_head.h: removed unused parameter sql/sql_lex.cc: make correct operation order sql/sql_yacc.yy: removed unused parameter --- sql/sp_head.h | 5 ++--- sql/sql_lex.cc | 2 +- sql/sql_yacc.yy | 10 +++++----- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/sql/sp_head.h b/sql/sp_head.h index 08967bd9b4f..aaef5a3d50e 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -470,11 +470,10 @@ class sp_instr_set_trigger_field : public sp_instr public: - sp_instr_set_trigger_field(Name_resolution_context *context_arg, - uint ip, sp_pcontext *ctx, + sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx, Item_trigger_field *trg_fld, Item *val) : sp_instr(ip, ctx), - trigger_field(context_arg, trg_fld), + trigger_field(trg_fld), value(val) {} diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 19578931d04..fe79b6dd035 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1936,7 +1936,7 @@ void st_lex::link_first_table_back(TABLE_LIST *first, { first->next_local= (TABLE_LIST*) select_lex.table_list.first; select_lex.table_list.first= - (byte*) select_lex.context.table_list= first; + (byte*) (select_lex.context.table_list= first); select_lex.table_list.elements++; //safety } } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c06bf8f7bf0..7a789cba035 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7743,13 +7743,13 @@ sys_option_value: it= new Item_null(); } - if (!(trg_fld= new Item_trigger_field(&lex->current_select->context, + if (!(trg_fld= new Item_trigger_field(&lex->current_select-> + context, Item_trigger_field::NEW_ROW, $2.base_name.str)) || - !(i= new sp_instr_set_trigger_field( - &lex->current_select->context, - lex->sphead->instructions(), lex->spcont, - trg_fld, it))) + !(i= new sp_instr_set_trigger_field(lex->sphead-> + instructions(), + lex->spcont, trg_fld, it))) YYABORT; /* From 66b4354a84800dd55c385d331884b16e9e5aa74b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 03:46:08 -0700 Subject: [PATCH 125/216] view.result: Fixed the results of a test for group_concat. After the fix foor bug #11639 the results became correct. olap.result, olap.test: Added a test case for bug #11639. sql_select.cc: Fixed bug #11639: a wrong result set when using a view instead of the underlying table in a rollup query executed through filesort. The old code did not take into account that we always use an Item_ref object when referring to a view column. item.h: Fixed bug #11639. Now if two Item_ref items ref1 and ref2 refer to the same field then ref1->eq(ref2) returns 1. sql/item.h: Fixed bug #11639. Now if two Item_ref items ref1 and ref2 refer to the same field then ref1->eq(ref2) returns 1. sql/sql_select.cc: Fixed bug #11639: a wrong result set when using a view instead of the underlying table in a rollup query executed through filesort. The old code did not take into account that we always use an Item_ref object when referring to a view column. mysql-test/t/olap.test: Added a test case for bug #11639. mysql-test/r/olap.result: Added a test case for bug #11639. mysql-test/r/view.result: Fixed the results of a test for group_concat. After the fix foor bug #11639 the results became correct. --- mysql-test/r/olap.result | 22 ++++++++++++++++++++++ mysql-test/r/view.result | 2 +- mysql-test/t/olap.test | 16 ++++++++++++++++ sql/item.h | 5 ++++- sql/sql_select.cc | 7 ++++--- 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index c37a42d3fa7..a19734d55b5 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -555,3 +555,25 @@ IFNULL(a, 'TEST') COALESCE(b, 'TEST') 4 TEST TEST TEST DROP TABLE t1,t2; +CREATE TABLE t1(id int, type char(1)); +INSERT INTO t1 VALUES +(1,"A"),(2,"C"),(3,"A"),(4,"A"),(5,"B"), +(6,"B"),(7,"A"),(8,"C"),(9,"A"),(10,"C"); +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT type FROM t1 GROUP BY type WITH ROLLUP; +type +A +B +C +NULL +SELECT type FROM v1 GROUP BY type WITH ROLLUP; +type +A +B +C +NULL +EXPLAIN SELECT type FROM v1 GROUP BY type WITH ROLLUP; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using filesort +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 4c1db618b4b..674073968d4 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1561,7 +1561,7 @@ one 1025,2025,3025 two 1050,1050 select col1,group_concat(col2,col3) from v1 group by col1; col1 group_concat(col2,col3) -two 1025,2025,3025 +one 1025,2025,3025 two 1050,1050 drop view v1; drop table t1; diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test index c75cad0b051..26fcc7463d6 100644 --- a/mysql-test/t/olap.test +++ b/mysql-test/t/olap.test @@ -250,3 +250,19 @@ SELECT IFNULL(a, 'TEST'), COALESCE(b, 'TEST') FROM t2 DROP TABLE t1,t2; +# +# Tests for bug #11639: ROLLUP over view executed through filesort +# + +CREATE TABLE t1(id int, type char(1)); +INSERT INTO t1 VALUES + (1,"A"),(2,"C"),(3,"A"),(4,"A"),(5,"B"), + (6,"B"),(7,"A"),(8,"C"),(9,"A"),(10,"C"); +CREATE VIEW v1 AS SELECT * FROM t1; + +SELECT type FROM t1 GROUP BY type WITH ROLLUP; +SELECT type FROM v1 GROUP BY type WITH ROLLUP; +EXPLAIN SELECT type FROM v1 GROUP BY type WITH ROLLUP; + +DROP VIEW v1; +DROP TABLE t1; diff --git a/sql/item.h b/sql/item.h index c8180b4932a..f2eedb57ed3 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1340,7 +1340,10 @@ public: Item_ref(THD *thd, Item_ref *item) :Item_ident(thd, item), result_field(item->result_field), ref(item->ref) {} enum Type type() const { return REF_ITEM; } bool eq(const Item *item, bool binary_cmp) const - { return ref && (*ref)->eq(item, binary_cmp); } + { + Item *it= ((Item *) item)->real_item(); + return ref && (*ref)->eq(it, binary_cmp); + } double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal *); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cf8d7b1b83c..d360bf55d59 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12150,7 +12150,7 @@ count_field_types(TMP_TABLE_PARAM *param, List &fields, param->quick_group=1; while ((field=li++)) { - Item::Type type=field->type(); + Item::Type type=field->real_item()->type(); if (type == Item::FIELD_ITEM) param->field_count++; else if (type == Item::SUM_FUNC_ITEM) @@ -12164,7 +12164,7 @@ count_field_types(TMP_TABLE_PARAM *param, List &fields, for (uint i=0 ; i < sum_item->arg_count ; i++) { - if (sum_item->args[0]->type() == Item::FIELD_ITEM) + if (sum_item->args[0]->real_item()->type() == Item::FIELD_ITEM) param->field_count++; else param->func_count++; @@ -12411,9 +12411,10 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, param->copy_funcs.empty(); for (i= 0; (pos= li++); i++) { - if (pos->type() == Item::FIELD_ITEM) + if (pos->real_item()->type() == Item::FIELD_ITEM) { Item_field *item; + pos= pos->real_item(); if (!(item= new Item_field(thd, ((Item_field*) pos)))) goto err; pos= item; From d36c14f7488af415258b03b61e1e7dad74e1cdcb Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 15:47:45 +0400 Subject: [PATCH 126/216] A fix and a test case for Bug#11172 "mysql_stmt_attr_set CURSOR_TYPE_READ_ONLY date/datetime filter server crash". The fix adds support for Item_change_list in cursors (proper rollback of the modified item tree). sql/sql_class.cc: No need to call fatal_error() twice. sql/sql_prepare.cc: - implement proper cleanup of the prepared statement in mysql_stmt_reset if there is a cursor. - take into account thd->change_list when fetching data through a cursor. sql/sql_select.cc: - take into account thd->change_list when fetching data from a cursor: grab it when we open a cursor, and rollback the changes to the parsed tree when we close it. sql/sql_select.h: - Cursor::change_list added tests/mysql_client_test.c: - a test case for Bug#11172 "mysql_stmt_attr_set CURSOR_TYPE_READ_ONLY date/datetime filter server crash" --- sql/sql_class.cc | 5 ++- sql/sql_prepare.cc | 30 ++++++++++++----- sql/sql_select.cc | 26 ++++++++------- sql/sql_select.h | 4 ++- tests/mysql_client_test.c | 69 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 113 insertions(+), 21 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 20f48da9283..0eac72b8fdc 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -784,7 +784,10 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value, void *change_mem= alloc_root(runtime_memroot, sizeof(*change)); if (change_mem == 0) { - fatal_error(); + /* + OOM, thd->fatal_error() is called by the error handler of the + memroot. Just return. + */ return; } change= new (change_mem) Item_change_record; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index c97cb037f15..7c9e0bc8a08 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2203,13 +2203,15 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) ulong num_rows= uint4korr(packet+4); Prepared_statement *stmt; Statement stmt_backup; + Cursor *cursor; DBUG_ENTER("mysql_stmt_fetch"); statistic_increment(thd->status_var.com_stmt_fetch, &LOCK_status); if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch"))) DBUG_VOID_RETURN; - if (!stmt->cursor || !stmt->cursor->is_open()) + cursor= stmt->cursor; + if (!cursor || !cursor->is_open()) { my_error(ER_STMT_HAS_NO_OPEN_CURSOR, MYF(0), stmt_id); DBUG_VOID_RETURN; @@ -2222,22 +2224,27 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) my_pthread_setprio(pthread_self(), QUERY_PRIOR); thd->protocol= &thd->protocol_prep; // Switch to binary protocol - stmt->cursor->fetch(num_rows); + cursor->fetch(num_rows); thd->protocol= &thd->protocol_simple; // Use normal protocol if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(), WAIT_PRIOR); - thd->restore_backup_statement(stmt, &stmt_backup); - thd->current_arena= thd; - - if (!stmt->cursor->is_open()) + if (!cursor->is_open()) { /* We're done with the fetch: reset PS for next execution */ cleanup_stmt_and_thd_after_use(stmt, thd); reset_stmt_params(stmt); + /* + Must be the last, as some momory is still needed for + the previous calls. + */ + free_root(cursor->mem_root, MYF(0)); } + thd->restore_backup_statement(stmt, &stmt_backup); + thd->current_arena= thd; + DBUG_VOID_RETURN; } @@ -2264,14 +2271,21 @@ void mysql_stmt_reset(THD *thd, char *packet) /* There is always space for 4 bytes in buffer */ ulong stmt_id= uint4korr(packet); Prepared_statement *stmt; + Cursor *cursor; DBUG_ENTER("mysql_stmt_reset"); statistic_increment(thd->status_var.com_stmt_reset, &LOCK_status); if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset"))) DBUG_VOID_RETURN; - if (stmt->cursor && stmt->cursor->is_open()) - stmt->cursor->close(); + cursor= stmt->cursor; + if (cursor && cursor->is_open()) + { + thd->change_list= cursor->change_list; + cursor->close(FALSE); + cleanup_stmt_and_thd_after_use(stmt, thd); + free_root(cursor->mem_root, MYF(0)); + } stmt->state= Query_arena::PREPARED; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cf8d7b1b83c..42b21a94794 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1737,6 +1737,7 @@ Cursor::init_from_thd(THD *thd) lock= thd->lock; query_id= thd->query_id; free_list= thd->free_list; + change_list= thd->change_list; reset_thd(thd); /* XXX: thd->locked_tables is not changed. @@ -1753,6 +1754,7 @@ Cursor::reset_thd(THD *thd) thd->open_tables= 0; thd->lock= 0; thd->free_list= 0; + thd->change_list.empty(); } @@ -1826,6 +1828,7 @@ Cursor::fetch(ulong num_rows) thd->open_tables= open_tables; thd->lock= lock; thd->query_id= query_id; + thd->change_list= change_list; /* save references to memory, allocated during fetch */ thd->set_n_backup_item_arena(this, &backup_arena); @@ -1842,10 +1845,8 @@ Cursor::fetch(ulong num_rows) #ifdef USING_TRANSACTIONS ha_release_temporary_latches(thd); #endif - + /* Grab free_list here to correctly free it in close */ thd->restore_backup_item_arena(this, &backup_arena); - DBUG_ASSERT(thd->free_list == 0); - reset_thd(thd); if (error == NESTED_LOOP_CURSOR_LIMIT) { @@ -1853,10 +1854,12 @@ Cursor::fetch(ulong num_rows) thd->server_status|= SERVER_STATUS_CURSOR_EXISTS; ::send_eof(thd); thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS; + change_list= thd->change_list; + reset_thd(thd); } else { - close(); + close(TRUE); if (error == NESTED_LOOP_OK) { thd->server_status|= SERVER_STATUS_LAST_ROW_SENT; @@ -1871,7 +1874,7 @@ Cursor::fetch(ulong num_rows) void -Cursor::close() +Cursor::close(bool is_active) { THD *thd= join->thd; DBUG_ENTER("Cursor::close"); @@ -1884,6 +1887,10 @@ Cursor::close() (void) unit->cleanup(); else (void) join->select_lex->cleanup(); + + if (is_active) + close_thread_tables(thd); + else { /* XXX: Another hack: closing tables used in the cursor */ DBUG_ASSERT(lock || open_tables || derived_tables); @@ -1903,11 +1910,7 @@ Cursor::close() join= 0; unit= 0; free_items(); - /* - Must be last, as some memory might be allocated for free purposes, - like in free_tmp_table() (TODO: fix this issue) - */ - free_root(mem_root, MYF(0)); + change_list.empty(); DBUG_VOID_RETURN; } @@ -1915,7 +1918,8 @@ Cursor::close() Cursor::~Cursor() { if (is_open()) - close(); + close(FALSE); + free_root(mem_root, MYF(0)); } /*********************************************************************/ diff --git a/sql/sql_select.h b/sql/sql_select.h index 6d33ae2f978..ac3e8898cc6 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -390,6 +390,7 @@ class Cursor: public Sql_alloc, public Query_arena /* List of items created during execution */ query_id_t query_id; public: + Item_change_list change_list; select_send result; /* Temporary implementation as now we replace THD state by value */ @@ -402,7 +403,8 @@ public: void fetch(ulong num_rows); void reset() { join= 0; } bool is_open() const { return join != 0; } - void close(); + + void close(bool is_active); void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; } Cursor(THD *thd); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index fa70168d0ef..e57d00e5a91 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13477,6 +13477,74 @@ static void test_bug10794() } +/* Bug#11172: cursors, crash on a fetch from a datetime column */ + +static void test_bug11172() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind_in[1], bind_out[2]; + MYSQL_TIME hired; + int rc; + const char *stmt_text; + int i= 0, id; + ulong type; + + myheader("test_bug11172"); + + mysql_query(mysql, "drop table if exists t1"); + mysql_query(mysql, "create table t1 (id integer not null primary key," + "hired date not null)"); + rc= mysql_query(mysql, + "insert into t1 (id, hired) values (1, '1933-08-24'), " + "(2, '1965-01-01'), (3, '1949-08-17'), (4, '1945-07-07'), " + "(5, '1941-05-15'), (6, '1978-09-15'), (7, '1936-03-28')"); + myquery(rc); + stmt= mysql_stmt_init(mysql); + stmt_text= "SELECT id, hired FROM t1 WHERE hired=?"; + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + check_execute(stmt, rc); + + type= (ulong) CURSOR_TYPE_READ_ONLY; + mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type); + + bzero(bind_in, sizeof(bind_in)); + bzero(bind_out, sizeof(bind_out)); + bzero(&hired, sizeof(hired)); + hired.year= 1965; + hired.month= 1; + hired.day= 1; + bind_in[0].buffer_type= MYSQL_TYPE_DATE; + bind_in[0].buffer= (void*) &hired; + bind_in[0].buffer_length= sizeof(hired); + bind_out[0].buffer_type= MYSQL_TYPE_LONG; + bind_out[0].buffer= (void*) &id; + bind_out[1]= bind_in[0]; + + for (i= 0; i < 3; i++) + { + rc= mysql_stmt_bind_param(stmt, bind_in); + check_execute(stmt, rc); + rc= mysql_stmt_bind_result(stmt, bind_out); + check_execute(stmt, rc); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + while ((rc= mysql_stmt_fetch(stmt)) == 0) + { + if (!opt_silent) + printf("fetched data %d:%d-%d-%d\n", id, + hired.year, hired.month, hired.day); + } + DIE_UNLESS(rc == MYSQL_NO_DATA); + mysql_stmt_free_result(stmt) || mysql_stmt_reset(stmt); + } + mysql_stmt_close(stmt); + mysql_rollback(mysql); + mysql_rollback(mysql); + + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -13714,6 +13782,7 @@ static struct my_tests_st my_tests[]= { { "test_bug9992", test_bug9992 }, { "test_bug10736", test_bug10736 }, { "test_bug10794", test_bug10794 }, + { "test_bug11172", test_bug11172 }, { 0, 0 } }; From 6c8d397588722dece2803370409d4776d5ffb461 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 16:23:05 +0400 Subject: [PATCH 127/216] - fix -ansi -pedantic error --- sql/item.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item.cc b/sql/item.cc index 00b93cfa270..d62ac38e943 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4410,7 +4410,7 @@ void Item_ref::make_field(Send_field *field) field->table_name= table_name; if (db_name) field->db_name= db_name; -}; +} void Item_ref_null_helper::print(String *str) From eb4cb6eba3147b271d893354465e9b2b44addd20 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 17:11:39 +0400 Subject: [PATCH 128/216] tests/mysql_client_test.c Add a test case for Bug#11656 "Server crash with mysql_stmt_fetch (cursors)", the bug itself is no longer present. tests/mysql_client_test.c: Add a test case for Bug#11656 "Server crash with mysql_stmt_fetch (cursors)", the bug itself is no longer present. --- tests/mysql_client_test.c | 56 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index e57d00e5a91..a80d5e1d1be 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13545,6 +13545,61 @@ static void test_bug11172() myquery(rc); } + +/* Bug#11656: cursors, crash on a fetch from a query with distinct. */ + +static void test_bug11656() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[2]; + int rc; + const char *stmt_text; + char buf[2][20]; + int i= 0; + ulong type; + + myheader("test_bug11656"); + + mysql_query(mysql, "drop table if exists t1"); + + rc= mysql_query(mysql, "create table t1 (" + "server varchar(40) not null, " + "test_kind varchar(1) not null, " + "test_id varchar(30) not null , " + "primary key (server,test_kind,test_id))"); + myquery(rc); + + stmt_text= "select distinct test_kind, test_id from t1 " + "where server in (?, ?)"; + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + check_execute(stmt, rc); + type= (ulong) CURSOR_TYPE_READ_ONLY; + mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type); + + bzero(bind, sizeof(bind)); + strcpy(buf[0], "pcint502_MY2"); + strcpy(buf[1], "*"); + for (i=0; i < 2; i++) + { + bind[i].buffer_type= MYSQL_TYPE_STRING; + bind[i].buffer= (gptr *)&buf[i]; + bind[i].buffer_length= strlen(buf[i]); + } + mysql_stmt_bind_param(stmt, bind); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_fetch(stmt); + DIE_UNLESS(rc == MYSQL_NO_DATA); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -13783,6 +13838,7 @@ static struct my_tests_st my_tests[]= { { "test_bug10736", test_bug10736 }, { "test_bug10794", test_bug10794 }, { "test_bug11172", test_bug11172 }, + { "test_bug11656", test_bug11656 }, { 0, 0 } }; From 1ff4a0ebf17959d242b7822ecc0438b7078a4acd Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 15:25:51 +0200 Subject: [PATCH 129/216] Disabled the GOTO feature. (It's non-standard and undocumented.) We want to have the defacto standard syntax for labels ("L:" instead of "label L;"), and fix some known bugs, before we enable this again. The code is left intact (#ifdef'ed SP_GOTO) and the test cases are kept in sp-goto.test, for the future... mysql-test/r/sp-error.result: Moved all goto tests to sp-goto.test. mysql-test/r/sp.result: Moved all goto tests to sp-goto.test. mysql-test/t/disabled.def: Disabled GOTO/LABEL (until the label syntax and some bugs can be fixed). We keep the tests in sp-goto.test for the future, but disable for now. mysql-test/t/sp-error.test: Moved all goto tests to sp-goto.test. mysql-test/t/sp.test: Moved all goto tests to sp-goto.test. sql/lex.h: Disabled GOTO/LABEL (until the label syntax and some bugs can be fixed). sql/sql_yacc.yy: Disabled GOTO/LABEL (until the label syntax and some bugs can be fixed). --- mysql-test/r/sp-error.result | 51 -------- mysql-test/r/sp-goto.result | 205 ++++++++++++++++++++++++++++++ mysql-test/r/sp.result | 148 ---------------------- mysql-test/t/disabled.def | 1 + mysql-test/t/sp-error.test | 55 +------- mysql-test/t/sp-goto.test | 238 +++++++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 150 +--------------------- sql/lex.h | 5 + sql/sql_yacc.yy | 11 +- 9 files changed, 461 insertions(+), 403 deletions(-) create mode 100644 mysql-test/r/sp-goto.result create mode 100644 mysql-test/t/sp-goto.test diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index b6ba737a8ba..bfbfb87ac43 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -65,47 +65,6 @@ iterate foo; end| ERROR 42000: ITERATE with no matching label: foo create procedure foo() -begin -goto foo; -end| -ERROR 42000: GOTO with no matching label: foo -create procedure foo() -begin -begin -label foo; -end; -goto foo; -end| -ERROR 42000: GOTO with no matching label: foo -create procedure foo() -begin -goto foo; -begin -label foo; -end; -end| -ERROR 42000: GOTO with no matching label: foo -create procedure foo() -begin -begin -goto foo; -end; -begin -label foo; -end; -end| -ERROR 42000: GOTO with no matching label: foo -create procedure foo() -begin -begin -label foo; -end; -begin -goto foo; -end; -end| -ERROR 42000: GOTO with no matching label: foo -create procedure foo() foo: loop foo: loop set @x=2; @@ -308,16 +267,6 @@ declare continue handler for sqlstate '42S99' set x = 1; declare c cursor for select * from t1; end| ERROR 42000: Cursor declaration after handler declaration -create procedure p() -begin -declare continue handler for sqlexception -begin -goto L1; -end; -select field from t1; -label L1; -end| -ERROR HY000: GOTO is not allowed in a stored procedure handler drop procedure if exists p| create procedure p(in x int, inout y int, out z int) begin diff --git a/mysql-test/r/sp-goto.result b/mysql-test/r/sp-goto.result new file mode 100644 index 00000000000..ca560f62318 --- /dev/null +++ b/mysql-test/r/sp-goto.result @@ -0,0 +1,205 @@ +drop table if exists t1; +create table t1 ( +id char(16) not null default '', +data int not null +); +drop procedure if exists goto1// +create procedure goto1() +begin +declare y int; +label a; +select * from t1; +select count(*) into y from t1; +if y > 2 then +goto b; +end if; +insert into t1 values ("j", y); +goto a; +label b; +end// +call goto1()// +id data +id data +j 0 +id data +j 0 +j 1 +id data +j 0 +j 1 +j 2 +drop procedure goto1// +drop procedure if exists goto2// +create procedure goto2(a int) +begin +declare x int default 0; +declare continue handler for sqlstate '42S98' set x = 1; +label a; +select * from t1; +b: +while x < 2 do +begin +declare continue handler for sqlstate '42S99' set x = 2; +if a = 0 then +set x = x + 1; +iterate b; +elseif a = 1 then +leave b; +elseif a = 2 then +set a = 1; +goto a; +end if; +end; +end while b; +select * from t1; +end// +call goto2(0)// +id data +j 0 +j 1 +j 2 +id data +j 0 +j 1 +j 2 +call goto2(1)// +id data +j 0 +j 1 +j 2 +id data +j 0 +j 1 +j 2 +call goto2(2)// +id data +j 0 +j 1 +j 2 +id data +j 0 +j 1 +j 2 +id data +j 0 +j 1 +j 2 +drop procedure goto2// +delete from t1// +drop procedure if exists goto3// +create procedure goto3() +begin +label L1; +begin +end; +goto L1; +end// +drop procedure goto3// +drop procedure if exists goto4// +create procedure goto4() +begin +begin +label lab1; +begin +goto lab1; +end; +end; +end// +drop procedure goto4// +drop procedure if exists goto5// +create procedure goto5() +begin +begin +begin +goto lab1; +end; +label lab1; +end; +end// +drop procedure goto5// +drop procedure if exists goto6// +create procedure goto6() +begin +label L1; +goto L5; +begin +label L2; +goto L1; +goto L5; +begin +label L3; +goto L1; +goto L2; +goto L3; +goto L4; +goto L5; +end; +goto L2; +goto L4; +label L4; +end; +label L5; +goto L1; +end// +drop procedure goto6// +create procedure foo() +begin +goto foo; +end// +ERROR 42000: GOTO with no matching label: foo +create procedure foo() +begin +begin +label foo; +end; +goto foo; +end// +ERROR 42000: GOTO with no matching label: foo +create procedure foo() +begin +goto foo; +begin +label foo; +end; +end// +ERROR 42000: GOTO with no matching label: foo +create procedure foo() +begin +begin +goto foo; +end; +begin +label foo; +end; +end// +ERROR 42000: GOTO with no matching label: foo +create procedure foo() +begin +begin +label foo; +end; +begin +goto foo; +end; +end// +ERROR 42000: GOTO with no matching label: foo +create procedure p() +begin +declare continue handler for sqlexception +begin +goto L1; +end; +select field from t1; +label L1; +end// +ERROR HY000: GOTO is not allowed in a stored procedure handler +drop procedure if exists bug6898// +create procedure bug6898() +begin +goto label1; +label label1; +begin end; +goto label1; +end// +drop procedure bug6898// +drop table t1; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 69ae64475d2..7b99a3bacd0 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -438,145 +438,6 @@ id data i 3 delete from t1| drop procedure i| -drop procedure if exists goto1| -create procedure goto1() -begin -declare y int; -label a; -select * from t1; -select count(*) into y from t1; -if y > 2 then -goto b; -end if; -insert into t1 values ("j", y); -goto a; -label b; -end| -call goto1()| -id data -id data -j 0 -id data -j 0 -j 1 -id data -j 0 -j 1 -j 2 -drop procedure goto1| -drop procedure if exists goto2| -create procedure goto2(a int) -begin -declare x int default 0; -declare continue handler for sqlstate '42S98' set x = 1; -label a; -select * from t1; -b: -while x < 2 do -begin -declare continue handler for sqlstate '42S99' set x = 2; -if a = 0 then -set x = x + 1; -iterate b; -elseif a = 1 then -leave b; -elseif a = 2 then -set a = 1; -goto a; -end if; -end; -end while b; -select * from t1; -end| -call goto2(0)| -id data -j 0 -j 1 -j 2 -id data -j 0 -j 1 -j 2 -call goto2(1)| -id data -j 0 -j 1 -j 2 -id data -j 0 -j 1 -j 2 -call goto2(2)| -id data -j 0 -j 1 -j 2 -id data -j 0 -j 1 -j 2 -id data -j 0 -j 1 -j 2 -drop procedure goto2| -delete from t1| -drop procedure if exists goto3| -create procedure goto3() -begin -label L1; -begin -end; -goto L1; -end| -drop procedure goto3| -drop procedure if exists goto4| -create procedure goto4() -begin -begin -label lab1; -begin -goto lab1; -end; -end; -end| -drop procedure goto4| -drop procedure if exists goto5| -create procedure goto5() -begin -begin -begin -goto lab1; -end; -label lab1; -end; -end| -drop procedure goto5| -drop procedure if exists goto6| -create procedure goto6() -begin -label L1; -goto L5; -begin -label L2; -goto L1; -goto L5; -begin -label L3; -goto L1; -goto L2; -goto L3; -goto L4; -goto L5; -end; -goto L2; -goto L4; -label L4; -end; -label L5; -goto L1; -end| -drop procedure goto6| insert into t1 values ("foo", 3), ("bar", 19)| insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)| drop procedure if exists sel1| @@ -2971,15 +2832,6 @@ select @x| set global query_cache_size = @qcs1| delete from t1| drop function bug9902| -drop procedure if exists bug6898| -create procedure bug6898() -begin -goto label1; -label label1; -begin end; -goto label1; -end| -drop procedure bug6898| drop function if exists bug9102| create function bug9102() returns blob return 'a'| select bug9102()| diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 9bfe9567d83..c5f96ec4201 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -10,3 +10,4 @@ # ############################################################################## +sp-goto:GOTO is currently is disabled - will be fixed in the future diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index faf6d8b4de3..f5a9e53e710 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -84,7 +84,7 @@ show create procedure foo| --error 1305 show create function foo| -# LEAVE/ITERATE/GOTO with no match +# LEAVE/ITERATE with no match --error 1308 create procedure foo() foo: loop @@ -100,47 +100,6 @@ create procedure foo() foo: begin iterate foo; end| ---error 1308 -create procedure foo() -begin - goto foo; -end| ---error 1308 -create procedure foo() -begin - begin - label foo; - end; - goto foo; -end| ---error 1308 -create procedure foo() -begin - goto foo; - begin - label foo; - end; -end| ---error 1308 -create procedure foo() -begin - begin - goto foo; - end; - begin - label foo; - end; -end| ---error 1308 -create procedure foo() -begin - begin - label foo; - end; - begin - goto foo; - end; -end| # Redefining label --error 1309 @@ -398,18 +357,6 @@ begin declare c cursor for select * from t1; end| ---error 1358 -create procedure p() -begin - declare continue handler for sqlexception - begin - goto L1; - end; - - select field from t1; - label L1; -end| - # Check in and inout arguments. --disable_warnings drop procedure if exists p| diff --git a/mysql-test/t/sp-goto.test b/mysql-test/t/sp-goto.test new file mode 100644 index 00000000000..e770dd285ff --- /dev/null +++ b/mysql-test/t/sp-goto.test @@ -0,0 +1,238 @@ +# +# The non-standard GOTO, for compatibility +# +# QQQ The "label" syntax is temporary, it will (hopefully) +# change to the more common "L:" syntax soon. +# For the time being, this feature is disabled, until +# the syntax (and some other known bugs) can be fixed. +# +# Test cases for bugs are added at the end. See template there. +# + +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 ( + id char(16) not null default '', + data int not null +); + +delimiter //; + +--disable_warnings +drop procedure if exists goto1// +--enable_warnings +create procedure goto1() +begin + declare y int; + +label a; + select * from t1; + select count(*) into y from t1; + if y > 2 then + goto b; + end if; + insert into t1 values ("j", y); + goto a; +label b; +end// + +call goto1()// +drop procedure goto1// + +# With dummy handlers, just to test restore of contexts with jumps +--disable_warnings +drop procedure if exists goto2// +--enable_warnings +create procedure goto2(a int) +begin + declare x int default 0; + declare continue handler for sqlstate '42S98' set x = 1; + +label a; + select * from t1; +b: + while x < 2 do + begin + declare continue handler for sqlstate '42S99' set x = 2; + + if a = 0 then + set x = x + 1; + iterate b; + elseif a = 1 then + leave b; + elseif a = 2 then + set a = 1; + goto a; + end if; + end; + end while b; + + select * from t1; +end// + +call goto2(0)// +call goto2(1)// +call goto2(2)// + +drop procedure goto2// +delete from t1// + +# Check label visibility for some more cases. We don't call these. +--disable_warnings +drop procedure if exists goto3// +--enable_warnings +create procedure goto3() +begin + label L1; + begin + end; + goto L1; +end// +drop procedure goto3// + +--disable_warnings +drop procedure if exists goto4// +--enable_warnings +create procedure goto4() +begin + begin + label lab1; + begin + goto lab1; + end; + end; +end// +drop procedure goto4// + +--disable_warnings +drop procedure if exists goto5// +--enable_warnings +create procedure goto5() +begin + begin + begin + goto lab1; + end; + label lab1; + end; +end// +drop procedure goto5// + +--disable_warnings +drop procedure if exists goto6// +--enable_warnings +create procedure goto6() +begin + label L1; + goto L5; + begin + label L2; + goto L1; + goto L5; + begin + label L3; + goto L1; + goto L2; + goto L3; + goto L4; + goto L5; + end; + goto L2; + goto L4; + label L4; + end; + label L5; + goto L1; +end// +drop procedure goto6// + +# Mismatching labels +--error 1308 +create procedure foo() +begin + goto foo; +end// +--error 1308 +create procedure foo() +begin + begin + label foo; + end; + goto foo; +end// +--error 1308 +create procedure foo() +begin + goto foo; + begin + label foo; + end; +end// +--error 1308 +create procedure foo() +begin + begin + goto foo; + end; + begin + label foo; + end; +end// +--error 1308 +create procedure foo() +begin + begin + label foo; + end; + begin + goto foo; + end; +end// + +# No goto in a handler +--error 1358 +create procedure p() +begin + declare continue handler for sqlexception + begin + goto L1; + end; + + select field from t1; + label L1; +end// + + +# +# Test cases for old bugs +# + +# +# BUG#6898: Stored procedure crash if GOTO statements exist +# +--disable_warnings +drop procedure if exists bug6898// +--enable_warnings +create procedure bug6898() +begin + goto label1; + label label1; + begin end; + goto label1; +end// +drop procedure bug6898// + +# +# BUG#NNNN: New bug synopsis +# +#--disable_warnings +#drop procedure if exists bugNNNN// +#--enable_warnings +#create procedure bugNNNN... + + +# Add bugs above this line. Use existing tables t1 and t2 when +# practical, or create table t3, t4 etc temporarily (and drop them). +delimiter ;// +drop table t1; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 314ed58b5a9..7455bc139dc 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -12,6 +12,7 @@ # Tests that check privilege and security issues go to sp-security.test. # Tests that require multiple connections, except security/privilege tests, # go to sp-thread. +# Tests that uses 'goto' to into sp-goto.test (currently disabled) use test; @@ -585,139 +586,6 @@ delete from t1| drop procedure i| -# The non-standard GOTO, for compatibility -# -# QQQ The "label" syntax is temporary, it will (hopefully) -# change to the more common "L:" syntax soon. -# ---disable_warnings -drop procedure if exists goto1| ---enable_warnings -create procedure goto1() -begin - declare y int; - -label a; - select * from t1; - select count(*) into y from t1; - if y > 2 then - goto b; - end if; - insert into t1 values ("j", y); - goto a; -label b; -end| - -call goto1()| -drop procedure goto1| - -# With dummy handlers, just to test restore of contexts with jumps ---disable_warnings -drop procedure if exists goto2| ---enable_warnings -create procedure goto2(a int) -begin - declare x int default 0; - declare continue handler for sqlstate '42S98' set x = 1; - -label a; - select * from t1; -b: - while x < 2 do - begin - declare continue handler for sqlstate '42S99' set x = 2; - - if a = 0 then - set x = x + 1; - iterate b; - elseif a = 1 then - leave b; - elseif a = 2 then - set a = 1; - goto a; - end if; - end; - end while b; - - select * from t1; -end| - -call goto2(0)| -call goto2(1)| -call goto2(2)| - -drop procedure goto2| -delete from t1| - -# Check label visibility for some more cases. We don't call these. ---disable_warnings -drop procedure if exists goto3| ---enable_warnings -create procedure goto3() -begin - label L1; - begin - end; - goto L1; -end| -drop procedure goto3| - ---disable_warnings -drop procedure if exists goto4| ---enable_warnings -create procedure goto4() -begin - begin - label lab1; - begin - goto lab1; - end; - end; -end| -drop procedure goto4| - ---disable_warnings -drop procedure if exists goto5| ---enable_warnings -create procedure goto5() -begin - begin - begin - goto lab1; - end; - label lab1; - end; -end| -drop procedure goto5| - ---disable_warnings -drop procedure if exists goto6| ---enable_warnings -create procedure goto6() -begin - label L1; - goto L5; - begin - label L2; - goto L1; - goto L5; - begin - label L3; - goto L1; - goto L2; - goto L3; - goto L4; - goto L5; - end; - goto L2; - goto L4; - label L4; - end; - label L5; - goto L1; -end| -drop procedure goto6| - # SELECT with one of more result set sent back to the clinet insert into t1 values ("foo", 3), ("bar", 19)| insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)| @@ -3634,22 +3502,6 @@ delete from t1| drop function bug9902| -# -# BUG#6898: Stored procedure crash if GOTO statements exist -# ---disable_warnings -drop procedure if exists bug6898| ---enable_warnings -create procedure bug6898() -begin - goto label1; - label label1; - begin end; - goto label1; -end| -drop procedure bug6898| - - # # BUG#9102: Stored proccedures: function which returns blob causes crash # diff --git a/sql/lex.h b/sql/lex.h index d0dc287775e..aa10328ced0 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -214,7 +214,9 @@ static SYMBOL symbols[] = { { "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)}, { "GET_FORMAT", SYM(GET_FORMAT)}, { "GLOBAL", SYM(GLOBAL_SYM)}, +#ifdef SP_GOTO { "GOTO", SYM(GOTO_SYM)}, +#endif { "GRANT", SYM(GRANT)}, { "GRANTS", SYM(GRANTS)}, { "GROUP", SYM(GROUP)}, @@ -262,7 +264,10 @@ static SYMBOL symbols[] = { { "KEY", SYM(KEY_SYM)}, { "KEYS", SYM(KEYS)}, { "KILL", SYM(KILL_SYM)}, +#ifdef SP_GOTO + /* QQ This will go away when the GOTO label syntax is fixed */ { "LABEL", SYM(LABEL_SYM)}, +#endif { "LANGUAGE", SYM(LANGUAGE_SYM)}, { "LAST", SYM(LAST_SYM)}, { "LEADING", SYM(LEADING)}, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 7a789cba035..b1438f1c571 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2113,6 +2113,7 @@ sp_proc_stmt: } | LABEL_SYM IDENT { +#ifdef SP_GOTO LEX *lex= Lex; sp_head *sp= lex->sphead; sp_pcontext *ctx= lex->spcont; @@ -2130,9 +2131,14 @@ sp_proc_stmt: lab->ctx= ctx; sp->backpatch(lab); } +#else + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; +#endif } | GOTO_SYM IDENT { +#ifdef SP_GOTO LEX *lex= Lex; sp_head *sp= lex->sphead; sp_pcontext *ctx= lex->spcont; @@ -2185,6 +2191,10 @@ sp_proc_stmt: i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */ sp->add_instr(i); } +#else + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; +#endif } | OPEN_SYM ident { @@ -7437,7 +7447,6 @@ keyword: | INNOBASE_SYM {} | INSERT_METHOD {} | RELAY_THREAD {} - | LABEL_SYM {} | LANGUAGE_SYM {} | LAST_SYM {} | LEAVES {} From d305f6d3ce4e1e09b9e7e02836f20da3faa9dfe1 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 15:39:36 +0200 Subject: [PATCH 130/216] Win port fixes client/mysqltest.c: Check for HAVE_SYS_WAIT_H Define WEXITSTATUS if not defined --- client/mysqltest.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/mysqltest.c b/client/mysqltest.c index fd8f19332ec..d3e0014aa80 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -60,7 +60,12 @@ #include #include #include /* Our own version of lib */ +#ifdef HAVE_SYS_WAIT_H #include +#endif +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif #define MAX_QUERY 131072 #define MAX_VAR_NAME 256 #define MAX_COLUMNS 256 From b32d2ac276357828b5f814df4e6eade4d37d7d1f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 17:51:04 +0400 Subject: [PATCH 131/216] Fix a valgrind warning. sql/sql_prepare.cc: A small fix for the previous patch: we should first free the prepared statement items, and then free the runtime memory root, as some memory used for cleanup is allocated in that mem root. sql/sql_select.cc: - ever free the cursor mem root in close() (it's too early). --- sql/sql_prepare.cc | 1 + sql/sql_select.cc | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index d5cf671abcd..2bf2f165a66 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2447,6 +2447,7 @@ Prepared_statement::~Prepared_statement() if (cursor) cursor->Cursor::~Cursor(); free_items(); + free_root(cursor->mem_root, MYF(0)); delete lex->result; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c6a9bd54f9c..f5c1c784ece 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1920,7 +1920,6 @@ Cursor::~Cursor() { if (is_open()) close(FALSE); - free_root(mem_root, MYF(0)); } /*********************************************************************/ From 672dffcaf24332626cd3abe8f4366c7c66382d43 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 20:00:59 +0500 Subject: [PATCH 132/216] WL#2286 - Compile MySQL w/YASSL support Merge with latest yaSSL. It includes fix for bigendian/littleendian problem (fixes func_encrypt test failure). Our trees are in sync now. extra/yassl/include/yassl_types.hpp: Merge with latest yaSSL. extra/yassl/src/Makefile.am: Merge with latest yaSSL. extra/yassl/src/buffer.cpp: Merge with latest yaSSL. extra/yassl/src/cert_wrapper.cpp: Merge with latest yaSSL. extra/yassl/src/lock.cpp: Merge with latest yaSSL. extra/yassl/src/log.cpp: Merge with latest yaSSL. extra/yassl/src/socket_wrapper.cpp: Merge with latest yaSSL. extra/yassl/src/template_instnt.cpp: Merge with latest yaSSL. extra/yassl/src/timer.cpp: Merge with latest yaSSL. extra/yassl/src/yassl_error.cpp: Merge with latest yaSSL. extra/yassl/src/yassl_int.cpp: Merge with latest yaSSL. extra/yassl/taocrypt/include/types.hpp: Merge with latest yaSSL. extra/yassl/taocrypt/src/Makefile.am: Merge with latest yaSSL. extra/yassl/taocrypt/src/aestables.cpp: Merge with latest yaSSL. extra/yassl/taocrypt/src/algebra.cpp: Merge with latest yaSSL. extra/yassl/taocrypt/src/arc4.cpp: Merge with latest yaSSL. extra/yassl/taocrypt/src/coding.cpp: Merge with latest yaSSL. extra/yassl/taocrypt/src/file.cpp: Merge with latest yaSSL. extra/yassl/taocrypt/src/integer.cpp: Merge with latest yaSSL. extra/yassl/taocrypt/src/misc.cpp: Merge with latest yaSSL. extra/yassl/taocrypt/src/random.cpp: Merge with latest yaSSL. extra/yassl/taocrypt/src/template_instnt.cpp: Merge with latest yaSSL. --- extra/yassl/include/yassl_types.hpp | 3 +- extra/yassl/src/Makefile.am | 1 + extra/yassl/src/buffer.cpp | 1 + extra/yassl/src/cert_wrapper.cpp | 1 + extra/yassl/src/lock.cpp | 1 + extra/yassl/src/log.cpp | 2 + extra/yassl/src/socket_wrapper.cpp | 1 + extra/yassl/src/template_instnt.cpp | 32 +++++++++++++++- extra/yassl/src/timer.cpp | 1 + extra/yassl/src/yassl_error.cpp | 1 + extra/yassl/src/yassl_int.cpp | 34 +++++++++++------ extra/yassl/taocrypt/include/types.hpp | 40 ++++++++------------ extra/yassl/taocrypt/src/Makefile.am | 1 + extra/yassl/taocrypt/src/aestables.cpp | 1 + extra/yassl/taocrypt/src/algebra.cpp | 2 + extra/yassl/taocrypt/src/arc4.cpp | 1 + extra/yassl/taocrypt/src/coding.cpp | 1 + extra/yassl/taocrypt/src/file.cpp | 1 + extra/yassl/taocrypt/src/integer.cpp | 6 ++- extra/yassl/taocrypt/src/misc.cpp | 27 ++++++++----- extra/yassl/taocrypt/src/random.cpp | 1 + extra/yassl/taocrypt/src/template_instnt.cpp | 30 +++++++++++++++ 22 files changed, 140 insertions(+), 49 deletions(-) diff --git a/extra/yassl/include/yassl_types.hpp b/extra/yassl/include/yassl_types.hpp index 01b82d95039..ec9e6fb7ceb 100644 --- a/extra/yassl/include/yassl_types.hpp +++ b/extra/yassl/include/yassl_types.hpp @@ -445,7 +445,7 @@ const opaque master_label[MASTER_LABEL_SZ + 1] = "master secret"; const opaque key_label [KEY_LABEL_SZ + 1] = "key expansion"; -} // namespace +} // naemspace #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 /* @@ -456,4 +456,5 @@ const opaque key_label [KEY_LABEL_SZ + 1] = "key expansion"; using yaSSL::byte; #endif + #endif // yaSSL_TYPES_HPP diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am index 1f5f1ee7a4e..4ebb9a2d862 100644 --- a/extra/yassl/src/Makefile.am +++ b/extra/yassl/src/Makefile.am @@ -5,3 +5,4 @@ libyassl_a_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \ handshake.cpp lock.cpp log.cpp socket_wrapper.cpp ssl.cpp \ template_instnt.cpp timer.cpp yassl_imp.cpp yassl_error.cpp yassl_int.cpp EXTRA_DIST = ../include/*.hpp ../include/openssl/*.h +AM_CXXFLAGS = -DYASSL_PURE_C diff --git a/extra/yassl/src/buffer.cpp b/extra/yassl/src/buffer.cpp index 1da0827ac4e..56d355bea80 100644 --- a/extra/yassl/src/buffer.cpp +++ b/extra/yassl/src/buffer.cpp @@ -25,6 +25,7 @@ */ #include // memcpy +#include "runtime.hpp" #include "buffer.hpp" #include "yassl_types.hpp" diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp index 7a8c7dfe253..a775c366a92 100644 --- a/extra/yassl/src/cert_wrapper.cpp +++ b/extra/yassl/src/cert_wrapper.cpp @@ -24,6 +24,7 @@ * */ +#include "runtime.hpp" #include "cert_wrapper.hpp" #include "yassl_int.hpp" diff --git a/extra/yassl/src/lock.cpp b/extra/yassl/src/lock.cpp index 8a0b66ead42..4827d396e81 100644 --- a/extra/yassl/src/lock.cpp +++ b/extra/yassl/src/lock.cpp @@ -22,6 +22,7 @@ /* Locking functions */ +#include "runtime.hpp" #include "lock.hpp" diff --git a/extra/yassl/src/log.cpp b/extra/yassl/src/log.cpp index 38633cd1210..8ab351ee2b1 100644 --- a/extra/yassl/src/log.cpp +++ b/extra/yassl/src/log.cpp @@ -22,6 +22,8 @@ /* Debug logging functions */ + +#include "runtime.hpp" #include "log.hpp" #ifdef YASSL_LOG diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp index 00f9c8d170c..2252dfafdc5 100644 --- a/extra/yassl/src/socket_wrapper.cpp +++ b/extra/yassl/src/socket_wrapper.cpp @@ -26,6 +26,7 @@ */ +#include "runtime.hpp" #include "socket_wrapper.hpp" #ifndef _WIN32 diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp index 5cf4f8c39f8..5ee57e76aed 100644 --- a/extra/yassl/src/template_instnt.cpp +++ b/extra/yassl/src/template_instnt.cpp @@ -1,3 +1,29 @@ +/* template_instnt.cpp + * + * Copyright (C) 2003 Sawtooth Consulting Ltd. + * + * This file is part of yaSSL. + * + * yaSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * yaSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/* Explicit template instantiation requests + */ + + #include "runtime.hpp" #include "handshake.hpp" #include "yassl_int.hpp" @@ -15,7 +41,7 @@ template class HMAC; template class HMAC; template class HMAC; } -#endif +#endif // USE_CRYPTOPP_LIB namespace mySTL { template class list; @@ -64,4 +90,6 @@ template void ysDelete(Message*); template void ysArrayDelete(unsigned char*); template void ysArrayDelete(char*); } -#endif + +#endif // HAVE_EXPLICIT_TEMPLATE_INSTANTIATION + diff --git a/extra/yassl/src/timer.cpp b/extra/yassl/src/timer.cpp index cfa1319ae80..4fe0d3aa4f9 100644 --- a/extra/yassl/src/timer.cpp +++ b/extra/yassl/src/timer.cpp @@ -23,6 +23,7 @@ * */ +#include "runtime.hpp" #include "timer.hpp" namespace yaSSL { diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp index 6ae5a9f6663..c53aef2068d 100644 --- a/extra/yassl/src/yassl_error.cpp +++ b/extra/yassl/src/yassl_error.cpp @@ -23,6 +23,7 @@ /* yaSSL error implements and an exception class */ +#include "runtime.hpp" #include "yassl_error.hpp" namespace yaSSL { diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp index e9c1ed53816..740618ce701 100644 --- a/extra/yassl/src/yassl_int.cpp +++ b/extra/yassl/src/yassl_int.cpp @@ -33,28 +33,36 @@ void* operator new(size_t sz, yaSSL::new_t) { +#ifdef YASSL_PURE_C void* ptr = malloc(sz ? sz : 1); if (!ptr) abort(); return ptr; +#else + return ::operator new(sz); +#endif } -void* operator new[](size_t sz, yaSSL::new_t) -{ - void* ptr = malloc(sz ? sz : 1); - if (!ptr) abort(); - - return ptr; -} void operator delete(void* ptr, yaSSL::new_t) { +#ifdef YASSL_PURE_C if (ptr) free(ptr); +#else + ::operator delete(ptr); +#endif } -void operator delete[](void* ptr, yaSSL::new_t) + +void* operator new[](size_t sz, yaSSL::new_t nt) { - if (ptr) free(ptr); + return ::operator new(sz, nt); +} + + +void operator delete[](void* ptr, yaSSL::new_t nt) +{ + ::operator delete(ptr, nt); } @@ -923,7 +931,7 @@ void SSL::setKeys() // local functors -namespace yassl_int_cpp_local1 { +namespace yassl_int_cpp_local1 { // for explicit templates struct SumData { uint total_; @@ -1385,7 +1393,8 @@ Sessions::~Sessions() } -namespace yassl_int_cpp_local2 { // locals +// locals +namespace yassl_int_cpp_local2 { // for explicit templates typedef mySTL::list::iterator iterator; @@ -1974,6 +1983,8 @@ X509_NAME* X509::GetSubject() return &subject_; } + + } // namespace #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION @@ -1983,3 +1994,4 @@ template yaSSL::yassl_int_cpp_local1::SumBuffer for_each::iterator find_if::iterator, yaSSL::yassl_int_cpp_local2::sess_match>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::yassl_int_cpp_local2::sess_match); } #endif + diff --git a/extra/yassl/taocrypt/include/types.hpp b/extra/yassl/taocrypt/include/types.hpp index 18961cf4d6f..92164eaaab4 100644 --- a/extra/yassl/taocrypt/include/types.hpp +++ b/extra/yassl/taocrypt/include/types.hpp @@ -31,10 +31,8 @@ namespace TaoCrypt { -// define this if running on a big-endian CPU -#if !defined(LITTLE_ENDIAN_ORDER) && (defined(__BIG_ENDIAN__) || \ - defined(__sparc) || defined(__sparc__) || defined(__hppa__) || \ - defined(__mips__) || (defined(__MWERKS__) && !defined(__INTEL__))) + +#if defined(WORDS_BIGENDIAN) || (defined(__MWERKS__) && !defined(__INTEL__)) #define BIG_ENDIAN_ORDER #endif @@ -47,34 +45,28 @@ typedef unsigned char byte; typedef unsigned short word16; typedef unsigned int word32; -#if defined(__GNUC__) || defined(__MWERKS__) || defined(_LONGLONG_TYPE) - #define WORD64_AVAILABLE - #define WORD64_IS_DISTINCT_TYPE - typedef unsigned long long word64; - #define W64LIT(x) x##LL -#elif defined(_MSC_VER) || defined(__BCPLUSPLUS__) +#if defined(_MSC_VER) || defined(__BCPLUSPLUS__) #define WORD64_AVAILABLE #define WORD64_IS_DISTINCT_TYPE typedef unsigned __int64 word64; - #define W64LIT(x) x##ui64 -#elif defined(__DECCXX) +#elif SIZEOF_LONG == 8 #define WORD64_AVAILABLE typedef unsigned long word64; -#endif - -// define largest word type -#ifdef WORD64_AVAILABLE - typedef word64 lword; -#else - typedef word32 lword; +#elif SIZEOF_LONG_LONG == 8 + #define WORD64_AVAILABLE + #define WORD64_IS_DISTINCT_TYPE + typedef unsigned long long word64; #endif -// TODO: FIXME, add asm multiply for x86_64 on Solaris and remove !__sun +// compilers we've found 64-bit multiply insructions for +#if defined(__GNUC__) || defined(_MSC_VER) || defined(__DECCXX) + #define HAVE_64_MULTIPLY +#endif + -#if defined(__alpha__) || (defined(__ia64__) && !defined(__INTEL_COMPILER)) || \ - defined(_ARCH_PPC64) || defined(__mips64) || \ - (defined(__x86_64__) && !defined(__sun)) +#if defined(HAVE_64_MULTIPLY) && (defined(__alpha__) || defined(__ia64__) \ + || defined(_ARCH_PPC64) || defined(__mips64) || defined(__x86_64__)) // These platforms have 64-bit CPU registers. Unfortunately most C++ compilers // don't allow any way to access the 64-bit by 64-bit multiply instruction // without using assembly, so in order to use word64 as word, the assembly @@ -84,7 +76,7 @@ typedef unsigned int word32; #else #define TAOCRYPT_NATIVE_DWORD_AVAILABLE #ifdef WORD64_AVAILABLE - #define TAOCRYPT_SLOW_WORD64 + #define TAOCRYPT_SLOW_WORD64 typedef word16 hword; typedef word32 word; typedef word64 dword; diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am index 4005be94fb2..5bf45074a98 100644 --- a/extra/yassl/taocrypt/src/Makefile.am +++ b/extra/yassl/taocrypt/src/Makefile.am @@ -6,3 +6,4 @@ libtaocrypt_a_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp asn.cpp \ md2.cpp md5.cpp misc.cpp random.cpp ripemd.cpp rsa.cpp sha.cpp \ template_instnt.cpp EXTRA_DIST = ../include/*.hpp +AM_CXXFLAGS = -DYASSL_PURE_C diff --git a/extra/yassl/taocrypt/src/aestables.cpp b/extra/yassl/taocrypt/src/aestables.cpp index 5a125dfd44d..7ba25bc9ffb 100644 --- a/extra/yassl/taocrypt/src/aestables.cpp +++ b/extra/yassl/taocrypt/src/aestables.cpp @@ -21,6 +21,7 @@ /* based on Wei Dai's aestables.cpp from CryptoPP */ +#include "runtime.hpp" #include "aes.hpp" diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp index e0472f2fc76..45bbcfa662a 100644 --- a/extra/yassl/taocrypt/src/algebra.cpp +++ b/extra/yassl/taocrypt/src/algebra.cpp @@ -319,9 +319,11 @@ void AbstractRing::SimultaneousExponentiate(Integer *results, } // namespace + #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION namespace mySTL { template TaoCrypt::WindowSlider* uninit_copy(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*); template void destroy(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*); } #endif + diff --git a/extra/yassl/taocrypt/src/arc4.cpp b/extra/yassl/taocrypt/src/arc4.cpp index bbd77cd822c..1e521b48f0c 100644 --- a/extra/yassl/taocrypt/src/arc4.cpp +++ b/extra/yassl/taocrypt/src/arc4.cpp @@ -21,6 +21,7 @@ /* based on Wei Dai's arc4.cpp from CryptoPP */ +#include "runtime.hpp" #include "arc4.hpp" diff --git a/extra/yassl/taocrypt/src/coding.cpp b/extra/yassl/taocrypt/src/coding.cpp index 6514ed4d46d..944a47c288e 100644 --- a/extra/yassl/taocrypt/src/coding.cpp +++ b/extra/yassl/taocrypt/src/coding.cpp @@ -22,6 +22,7 @@ /* coding.cpp implements hex and base64 encoding/decoing */ +#include "runtime.hpp" #include "coding.hpp" #include "file.hpp" diff --git a/extra/yassl/taocrypt/src/file.cpp b/extra/yassl/taocrypt/src/file.cpp index 75df80608ae..4d48b9e7bca 100644 --- a/extra/yassl/taocrypt/src/file.cpp +++ b/extra/yassl/taocrypt/src/file.cpp @@ -22,6 +22,7 @@ /* file.cpp implements File Sources and Sinks */ +#include "runtime.hpp" #include "file.hpp" diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index 460b2d31426..71324b04b92 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -35,8 +35,9 @@ #endif -#if defined(_MSC_VER) && defined(_WIN64) && \ - !defined(__INTEL_COMPILER) // 64 bit X overflow intrinsic +// 64bit multiply overflow intrinsic +#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER) && \ + !defined(TAOCRYPT_NATIVE_DWORD_AVAILABLE) #ifdef __ia64__ #define myUMULH __UMULH #elif __x86_64__ @@ -3957,6 +3958,7 @@ Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, return p * (u * (xq-xp) % q) + xp; } + #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION #ifndef TAOCRYPT_NATIVE_DWORD_AVAILABLE template hword DivideThreeWordsByTwo(hword*, hword, hword, Word*); diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp index 6a801a9995a..ef051332098 100644 --- a/extra/yassl/taocrypt/src/misc.cpp +++ b/extra/yassl/taocrypt/src/misc.cpp @@ -22,34 +22,43 @@ /* based on Wei Dai's misc.cpp from CryptoPP */ +#include "runtime.hpp" #include "misc.hpp" #include // for NewHandler void* operator new(size_t sz, TaoCrypt::new_t) { +#ifdef YASSL_PURE_C void* ptr = malloc(sz ? sz : 1); if (!ptr) abort(); return ptr; +#else + return ::operator new(sz); +#endif } -void* operator new[](size_t sz, TaoCrypt::new_t) -{ - void* ptr = malloc(sz ? sz : 1); - if (!ptr) abort(); - - return ptr; -} void operator delete(void* ptr, TaoCrypt::new_t) { +#ifdef YASSL_PURE_C if (ptr) free(ptr); +#else + ::operator delete(ptr); +#endif } -void operator delete[](void* ptr, TaoCrypt::new_t) + +void* operator new[](size_t sz, TaoCrypt::new_t nt) { - if (ptr) free(ptr); + return ::operator new(sz, nt); +} + + +void operator delete[](void* ptr, TaoCrypt::new_t nt) +{ + ::operator delete(ptr, nt); } diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp index 69fb180720a..e1e6416eb00 100644 --- a/extra/yassl/taocrypt/src/random.cpp +++ b/extra/yassl/taocrypt/src/random.cpp @@ -24,6 +24,7 @@ specific seed, switch to /dev/random for more security but may block */ +#include "runtime.hpp" #include "random.hpp" #if defined(_WIN32) diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp index 28994282669..9a3c12badfc 100644 --- a/extra/yassl/taocrypt/src/template_instnt.cpp +++ b/extra/yassl/taocrypt/src/template_instnt.cpp @@ -1,3 +1,29 @@ +/* template_instnt.cpp + * + * Copyright (C) 2003 Sawtooth Consulting Ltd. + * + * This file is part of yaSSL. + * + * yaSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * yaSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/* Explicit template instantiation requests + */ + + #include "integer.hpp" #include "rsa.hpp" #include "algebra.hpp" @@ -6,9 +32,11 @@ #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION namespace TaoCrypt { + #if defined(SSE2_INTRINSICS_AVAILABLE) template AlignedAllocator::pointer StdReallocate >(AlignedAllocator&, unsigned int*, AlignedAllocator::size_type, AlignedAllocator::size_type, bool); #endif + template class RSA_Decryptor; template class RSA_Encryptor; template class RSA_Encryptor; @@ -17,10 +45,12 @@ template void tcArrayDelete(byte*); template AllocatorWithCleanup::pointer StdReallocate >(AllocatorWithCleanup&, byte*, AllocatorWithCleanup::size_type, AllocatorWithCleanup::size_type, bool); template void tcArrayDelete(word*); template AllocatorWithCleanup::pointer StdReallocate >(AllocatorWithCleanup&, word*, AllocatorWithCleanup::size_type, AllocatorWithCleanup::size_type, bool); + #ifndef TAOCRYPT_SLOW_WORD64 // defined when word != word32 template void tcArrayDelete(word32*); template AllocatorWithCleanup::pointer StdReallocate >(AllocatorWithCleanup&, word32*, AllocatorWithCleanup::size_type, AllocatorWithCleanup::size_type, bool); #endif + template void tcArrayDelete(char*); } From d0df504b834604556f2dfb4349fb3a4722d08b6e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 19:01:02 +0400 Subject: [PATCH 133/216] Fix a crash I introduced by the last push. --- sql/sql_prepare.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 2bf2f165a66..136854a4eaf 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2447,7 +2447,8 @@ Prepared_statement::~Prepared_statement() if (cursor) cursor->Cursor::~Cursor(); free_items(); - free_root(cursor->mem_root, MYF(0)); + if (cursor) + free_root(cursor->mem_root, MYF(0)); delete lex->result; } From 534ab53c17a0b3656a81cb6fbbc69b3d56fcf8c4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 20:13:07 +0300 Subject: [PATCH 134/216] fixed create_distinct_group() to make references via ref_pointer_array --- sql/sql_select.cc | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 044dc60e4b6..ba14c880b65 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -134,8 +134,8 @@ static void read_cached_record(JOIN_TAB *tab); static bool cmp_buffer_with_ref(JOIN_TAB *tab); static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List &fields, List &all_fields,ORDER *new_order); -static ORDER *create_distinct_group(THD *thd, ORDER *order, - List &fields, +static ORDER *create_distinct_group(THD *thd, Item **ref_pointer_array, + ORDER *order, List &fields, bool *all_order_by_fields_used); static bool test_if_subpart(ORDER *a,ORDER *b); static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables); @@ -642,7 +642,8 @@ JOIN::optimize() bool all_order_fields_used; if (order) skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1); - if ((group_list=create_distinct_group(thd, order, fields_list, + if ((group_list=create_distinct_group(thd, select_lex->ref_pointer_array, + order, fields_list, &all_order_fields_used))) { bool skip_group= (skip_sort_order && @@ -8440,12 +8441,14 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List &fields, */ static ORDER * -create_distinct_group(THD *thd, ORDER *order_list, List &fields, +create_distinct_group(THD *thd, Item **ref_pointer_array, + ORDER *order_list, List &fields, bool *all_order_by_fields_used) { List_iterator li(fields); Item *item; ORDER *order,*group,**prev; + uint index= 0; *all_order_by_fields_used= 1; while ((item=li++)) @@ -8477,11 +8480,17 @@ create_distinct_group(THD *thd, ORDER *order_list, List &fields, ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER)); if (!ord) return 0; - ord->item=li.ref(); + /* + We have here only field_list (not all_field_list), so we can use + simple indexing of ref_pointer_array (order in the array and in the + list are same) + */ + ord->item= ref_pointer_array + index; ord->asc=1; *prev=ord; prev= &ord->next; } + index++; } *prev=0; return group; From 8561600a5a876750c7de6154db3d2280ce62e13c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 20:44:35 +0300 Subject: [PATCH 135/216] Many files: Fix Bug #3300 : if innodb_locks_unsafe_for_binlog is set, release locks on rows that we do not UPDATE or DELETE sql/ha_innodb.cc: Fix Bug #3300 : if innodb_locks_unsafe_for_binlog is set, release locks on rows that we do not UPDATE or DELETE innobase/row/row0mysql.c: Fix Bug #3300 : if innodb_locks_unsafe_for_binlog is set, release locks on rows that we do not UPDATE or DELETE innobase/row/row0sel.c: Fix Bug #3300 : if innodb_locks_unsafe_for_binlog is set, release locks on rows that we do not UPDATE or DELETE innobase/include/trx0trx.ic: Fix Bug #3300 : if innodb_locks_unsafe_for_binlog is set, release locks on rows that we do not UPDATE or DELETE innobase/include/row0mysql.h: Fix Bug #3300 : if innodb_locks_unsafe_for_binlog is set, release locks on rows that we do not UPDATE or DELETE innobase/include/trx0trx.h: Fix Bug #3300 : if innodb_locks_unsafe_for_binlog is set, release locks on rows that we do not UPDATE or DELETE innobase/lock/lock0lock.c: Fix Bug #3300 : if innodb_locks_unsafe_for_binlog is set, release locks on rows that we do not UPDATE or DELETE innobase/trx/trx0trx.c: Fix Bug #3300 : if innodb_locks_unsafe_for_binlog is set, release locks on rows that we do not UPDATE or DELETE --- innobase/include/row0mysql.h | 18 ++++-- innobase/include/trx0trx.h | 43 +++++++++++++- innobase/include/trx0trx.ic | 48 ++++++++++++++++ innobase/lock/lock0lock.c | 60 +++++++++++--------- innobase/row/row0mysql.c | 107 ++++++++++++++++++++++++++--------- innobase/row/row0sel.c | 81 ++++++++++++++++++++++---- innobase/trx/trx0trx.c | 2 + sql/ha_innodb.cc | 10 +++- 8 files changed, 296 insertions(+), 73 deletions(-) diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 4bb9fa63cd1..4e6ff73b0f8 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -243,17 +243,27 @@ row_update_for_mysql( the MySQL format */ row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL handle */ - /************************************************************************* -Does an unlock of a row for MySQL. */ +This can only be used when srv_locks_unsafe_for_binlog is TRUE. Before +calling this function we must use trx_reset_new_rec_lock_info() and +trx_register_new_rec_lock() to store the information which new record locks +really were set. This function removes a newly set lock under prebuilt->pcur, +and also under prebuilt->clust_pcur. Currently, this is only used and tested +in the case of an UPDATE or a DELETE statement, where the row lock is of the +LOCK_X type. +Thus, this implements a 'mini-rollback' that releases the latest record +locks we set. */ int row_unlock_for_mysql( /*=================*/ /* out: error code or DB_SUCCESS */ - row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL + row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL handle */ - + ibool has_latches_on_recs);/* TRUE if called so that we have + the latches on the records under pcur + and clust_pcur, and we do not need to + reposition the cursors. */ /************************************************************************* Creates an query graph node of 'update' type to be used in the MySQL interface. */ diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index 8df50d6703d..1b118a86467 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -16,10 +16,39 @@ Created 3/26/1996 Heikki Tuuri #include "que0types.h" #include "mem0mem.h" #include "read0types.h" +#include "dict0types.h" #include "trx0xa.h" extern ulint trx_n_mysql_transactions; +/***************************************************************** +Resets the new record lock info in a transaction struct. */ +UNIV_INLINE +void +trx_reset_new_rec_lock_info( +/*========================*/ + trx_t* trx); /* in: transaction struct */ +/***************************************************************** +Registers that we have set a new record lock on an index. This can only be +called twice after calling trx_reset_new_rec_lock_info(), since we only have +space to store 2 indexes! */ +UNIV_INLINE +void +trx_register_new_rec_lock( +/*======================*/ + trx_t* trx, /* in: transaction struct */ + dict_index_t* index); /* in: trx sets a new record lock on this + index*/ +/***************************************************************** +Checks if trx has set a new record lock on an index. */ +UNIV_INLINE +ibool +trx_new_rec_locks_contain( +/*======================*/ + /* out: TRUE if trx has set a new record lock + on index */ + trx_t* trx, /* in: transaction struct */ + dict_index_t* index); /* in: index */ /************************************************************************ Releases the search latch if trx has reserved it. */ @@ -495,8 +524,18 @@ struct trx_struct{ lock_t* auto_inc_lock; /* possible auto-inc lock reserved by the transaction; note that it is also in the lock list trx_locks */ - ibool trx_create_lock;/* this is TRUE if we have created a - new lock for a record accessed */ + dict_index_t* new_rec_locks[2];/* these are normally NULL; if + srv_locks_unsafe_for_binlog is TRUE, + in a cursor search, if we set a new + record lock on an index, this is set + to point to the index; this is + used in releasing the locks under the + cursors if we are performing an UPDATE + and we determine after retrieving + the row that it does not need to be + locked; thus, these can be used to + implement a 'mini-rollback' that + releases the latest record locks */ UT_LIST_NODE_T(trx_t) trx_list; /* list of transactions */ UT_LIST_NODE_T(trx_t) diff --git a/innobase/include/trx0trx.ic b/innobase/include/trx0trx.ic index 78e5acda148..d23165b74e8 100644 --- a/innobase/include/trx0trx.ic +++ b/innobase/include/trx0trx.ic @@ -39,4 +39,52 @@ trx_start_if_not_started_low( } } +/***************************************************************** +Resets the new record lock info in a transaction struct. */ +UNIV_INLINE +void +trx_reset_new_rec_lock_info( +/*========================*/ + trx_t* trx) /* in: transaction struct */ +{ + trx->new_rec_locks[0] = NULL; + trx->new_rec_locks[1] = NULL; +} +/***************************************************************** +Registers that we have set a new record lock on an index. This can only be +called twice after calling trx_reset_new_rec_lock_info(), since we only have +space to store 2 indexes! */ +UNIV_INLINE +void +trx_register_new_rec_lock( +/*======================*/ + trx_t* trx, /* in: transaction struct */ + dict_index_t* index) /* in: trx sets a new record lock on this + index*/ +{ + if (trx->new_rec_locks[0] == NULL) { + trx->new_rec_locks[0] = index; + + return; + } + + ut_a(trx->new_rec_locks[1] == NULL); + + trx->new_rec_locks[1] = index; +} + +/***************************************************************** +Checks if trx has set a new record lock on an index. */ +UNIV_INLINE +ibool +trx_new_rec_locks_contain( +/*======================*/ + /* out: TRUE if trx has set a new record lock + on index */ + trx_t* trx, /* in: transaction struct */ + dict_index_t* index) /* in: index */ +{ + return(trx->new_rec_locks[0] == index + || trx->new_rec_locks[1] == index); +} diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index 48db7ced0cb..280c4871ee9 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -956,7 +956,7 @@ lock_rec_has_to_wait( cause waits */ if ((lock_is_on_supremum || (type_mode & LOCK_GAP)) - && !(type_mode & LOCK_INSERT_INTENTION)) { + && !(type_mode & LOCK_INSERT_INTENTION)) { /* Gap type locks without LOCK_INSERT_INTENTION flag do not need to wait for anything. This is because @@ -1765,10 +1765,7 @@ lock_rec_create( lock_rec_set_nth_bit(lock, heap_no); HASH_INSERT(lock_t, hash, lock_sys->rec_hash, - lock_rec_fold(space, page_no), lock); - /* Note that we have create a new lock */ - trx->trx_create_lock = TRUE; - + lock_rec_fold(space, page_no), lock); if (type_mode & LOCK_WAIT) { lock_set_lock_and_trx_wait(lock, trx); @@ -1945,15 +1942,6 @@ lock_rec_add_to_queue( if (similar_lock && !somebody_waits && !(type_mode & LOCK_WAIT)) { - /* If the nth bit of a record lock is already set then we - do not set a new lock bit, otherwice we set */ - - if (lock_rec_get_nth_bit(similar_lock, heap_no)) { - trx->trx_create_lock = FALSE; - } else { - trx->trx_create_lock = TRUE; - } - lock_rec_set_nth_bit(similar_lock, heap_no); return(similar_lock); @@ -2005,11 +1993,14 @@ lock_rec_lock_fast( lock = lock_rec_get_first_on_page(rec); trx = thr_get_trx(thr); - trx->trx_create_lock = FALSE; if (lock == NULL) { if (!impl) { lock_rec_create(mode, rec, index, trx); + + if (srv_locks_unsafe_for_binlog) { + trx_register_new_rec_lock(trx, index); + } } return(TRUE); @@ -2021,23 +2012,22 @@ lock_rec_lock_fast( } if (lock->trx != trx - || lock->type_mode != (mode | LOCK_REC) - || lock_rec_get_n_bits(lock) <= heap_no) { + || lock->type_mode != (mode | LOCK_REC) + || lock_rec_get_n_bits(lock) <= heap_no) { + return(FALSE); } if (!impl) { + /* If the nth bit of the record lock is already set then we + do not set a new lock bit, otherwise we do set */ - /* If the nth bit of a record lock is already set then we - do not set a new lock bit, otherwice we set */ - - if (lock_rec_get_nth_bit(lock, heap_no)) { - trx->trx_create_lock = FALSE; - } else { - trx->trx_create_lock = TRUE; + if (!lock_rec_get_nth_bit(lock, heap_no)) { + lock_rec_set_nth_bit(lock, heap_no); + if (srv_locks_unsafe_for_binlog) { + trx_register_new_rec_lock(trx, index); + } } - - lock_rec_set_nth_bit(lock, heap_no); } return(TRUE); @@ -2093,12 +2083,19 @@ lock_rec_lock_slow( enough already granted on the record, we have to wait. */ err = lock_rec_enqueue_waiting(mode, rec, index, thr); + + if (srv_locks_unsafe_for_binlog) { + trx_register_new_rec_lock(trx, index); + } } else { if (!impl) { /* Set the requested lock on the record */ lock_rec_add_to_queue(LOCK_REC | mode, rec, index, trx); + if (srv_locks_unsafe_for_binlog) { + trx_register_new_rec_lock(trx, index); + } } err = DB_SUCCESS; @@ -2436,8 +2433,15 @@ lock_rec_inherit_to_gap( lock = lock_rec_get_first(rec); + /* If srv_locks_unsafe_for_binlog is TRUE, we do not want locks set + by an UPDATE or a DELETE to be inherited as gap type locks. But we + DO want S-locks set by a consistency constraint to be inherited also + then. */ + while (lock != NULL) { - if (!lock_rec_get_insert_intention(lock)) { + if (!lock_rec_get_insert_intention(lock) + && !(srv_locks_unsafe_for_binlog + && lock_get_mode(lock) == LOCK_X)) { lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock) | LOCK_GAP, @@ -3069,7 +3073,7 @@ lock_update_insert( lock_rec_inherit_to_gap_if_gap_lock(rec, page_rec_get_next(rec)); lock_mutex_exit_kernel(); -} +} /***************************************************************** Updates the lock table when a record is removed. */ diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index eb50b83a4d5..354b7be3e77 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1429,51 +1429,106 @@ run_again: } /************************************************************************* -Does an unlock of a row for MySQL. */ +This can only be used when srv_locks_unsafe_for_binlog is TRUE. Before +calling this function we must use trx_reset_new_rec_lock_info() and +trx_register_new_rec_lock() to store the information which new record locks +really were set. This function removes a newly set lock under prebuilt->pcur, +and also under prebuilt->clust_pcur. Currently, this is only used and tested +in the case of an UPDATE or a DELETE statement, where the row lock is of the +LOCK_X type. +Thus, this implements a 'mini-rollback' that releases the latest record +locks we set. */ int row_unlock_for_mysql( /*=================*/ /* out: error code or DB_SUCCESS */ - row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL + row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL handle */ + ibool has_latches_on_recs)/* TRUE if called so that we have + the latches on the records under pcur + and clust_pcur, and we do not need to + reposition the cursors. */ { - rec_t* rec; - btr_pcur_t* cur = prebuilt->pcur; + dict_index_t* index; + btr_pcur_t* pcur = prebuilt->pcur; + btr_pcur_t* clust_pcur = prebuilt->clust_pcur; trx_t* trx = prebuilt->trx; + rec_t* rec; mtr_t mtr; ut_ad(prebuilt && trx); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - - trx->op_info = "unlock_row"; - - if (srv_locks_unsafe_for_binlog) { - if (trx->trx_create_lock == TRUE) { - - mtr_start(&mtr); - /* Restore a cursor position and find a record */ - btr_pcur_restore_position(BTR_SEARCH_LEAF, cur, &mtr); - rec = btr_pcur_get_rec(cur); + if (!srv_locks_unsafe_for_binlog) { - if (rec) { + fprintf(stderr, +"InnoDB: Error: calling row_unlock_for_mysql though\n" +"InnoDB: srv_locks_unsafe_for_binlog is FALSE.\n"); - lock_rec_reset_and_release_wait(rec); - } else { - fputs("InnoDB: Error: " - "Record for the lock not found\n", - stderr); - mem_analyze_corruption((byte*) trx); - ut_error; - } + return(DB_SUCCESS); + } - trx->trx_create_lock = FALSE; - mtr_commit(&mtr); - } + trx->op_info = "unlock_row"; + + index = btr_pcur_get_btr_cur(pcur)->index; + + if (index != NULL && trx_new_rec_locks_contain(trx, index)) { + + mtr_start(&mtr); + + /* Restore the cursor position and find the record */ + if (!has_latches_on_recs) { + btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, &mtr); + } + + rec = btr_pcur_get_rec(pcur); + + mutex_enter(&kernel_mutex); + + lock_rec_reset_and_release_wait(rec); + + mutex_exit(&kernel_mutex); + + mtr_commit(&mtr); + + /* If the search was done through the clustered index, then + we have not used clust_pcur at all, and we must NOT try to + reset locks on clust_pcur. The values in clust_pcur may be + garbage! */ + + if (index->type & DICT_CLUSTERED) { + + goto func_exit; + } + } + + index = btr_pcur_get_btr_cur(clust_pcur)->index; + + if (index != NULL && trx_new_rec_locks_contain(trx, index)) { + + mtr_start(&mtr); + + /* Restore the cursor position and find the record */ + + if (!has_latches_on_recs) { + btr_pcur_restore_position(BTR_SEARCH_LEAF, clust_pcur, + &mtr); + } + + rec = btr_pcur_get_rec(pcur); + + mutex_enter(&kernel_mutex); + + lock_rec_reset_and_release_wait(rec); + + mutex_exit(&kernel_mutex); + + mtr_commit(&mtr); } +func_exit: trx->op_info = ""; return(DB_SUCCESS); diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index c7a548fe448..44372f4eb87 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2784,6 +2784,10 @@ sel_restore_position_for_mysql( process the record the cursor is now positioned on (i.e. we should not go to the next record yet) */ + ibool* same_user_rec, /* out: TRUE if we were able to restore + the cursor on a user record with the + same ordering prefix in in the + B-tree index */ ulint latch_mode, /* in: latch mode wished in restoration */ btr_pcur_t* pcur, /* in: cursor whose position @@ -2800,6 +2804,8 @@ sel_restore_position_for_mysql( success = btr_pcur_restore_position(latch_mode, pcur, mtr); + *same_user_rec = success; + if (relative_position == BTR_PCUR_ON) { if (success) { return(FALSE); @@ -3064,10 +3070,12 @@ row_search_for_mysql( ulint cnt = 0; #endif /* UNIV_SEARCH_DEBUG */ ulint next_offs; + ibool same_user_rec; mtr_t mtr; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; + *offsets_ = (sizeof offsets_) / sizeof *offsets_; ut_ad(index && pcur && search_tuple); @@ -3138,6 +3146,14 @@ row_search_for_mysql( trx->search_latch_timeout = BTR_SEA_TIMEOUT; } + /* Reset the new record lock info if we srv_locks_unsafe_for_binlog + is set. Then we are able to remove the record locks set here on an + individual row. */ + + if (srv_locks_unsafe_for_binlog) { + trx_reset_new_rec_lock_info(trx); + } + /*-------------------------------------------------------------*/ /* PHASE 1: Try to pop the row from the prefetch cache */ @@ -3396,8 +3412,9 @@ shortcut_fails_too_big_rec: clust_index = dict_table_get_first_index(index->table); if (UNIV_LIKELY(direction != 0)) { - if (!sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur, - moves_up, &mtr)) { + if (!sel_restore_position_for_mysql(&same_user_rec, + BTR_SEARCH_LEAF, + pcur, moves_up, &mtr)) { goto next_rec; } @@ -3659,7 +3676,7 @@ rec_loop: goto normal_return; } } - + /* We are ready to look at a possible new index entry in the result set: the cursor is now placed on a user record */ @@ -3679,6 +3696,7 @@ rec_loop: || srv_locks_unsafe_for_binlog || (unique_search && !UNIV_UNLIKELY(rec_get_deleted_flag( rec, page_rec_is_comp(rec))))) { + goto no_gap_lock; } else { lock_type = LOCK_ORDINARY; @@ -3701,7 +3719,7 @@ rec_loop: && dtuple_get_n_fields_cmp(search_tuple) == dict_index_get_n_unique(index) && 0 == cmp_dtuple_rec(search_tuple, rec, offsets)) { - no_gap_lock: +no_gap_lock: lock_type = LOCK_REC_NOT_GAP; } @@ -3764,6 +3782,7 @@ rec_loop: /* Get the clustered index record if needed */ index_rec = rec; ut_ad(index != clust_index); + goto requires_clust_rec; } } @@ -3773,6 +3792,15 @@ rec_loop: /* The record is delete-marked: we can skip it if this is not a consistent read which might see an earlier version of a non-clustered index record */ + + if (srv_locks_unsafe_for_binlog) { + /* No need to keep a lock on a delete-marked record + if we do not want to use next-key locking. */ + + row_unlock_for_mysql(prebuilt, TRUE); + + trx_reset_new_rec_lock_info(trx); + } goto next_rec; } @@ -3783,7 +3811,8 @@ rec_loop: index_rec = rec; if (index != clust_index && prebuilt->need_to_access_clustered) { - requires_clust_rec: + +requires_clust_rec: /* Before and after this "if" block, "offsets" will be related to "rec", which may be in a secondary index "index" or the clustered index ("clust_index"). However, after this @@ -3816,6 +3845,16 @@ rec_loop: /* The record is delete marked: we can skip it */ + if (srv_locks_unsafe_for_binlog) { + /* No need to keep a lock on a delete-marked + record if we do not want to use next-key + locking. */ + + row_unlock_for_mysql(prebuilt, TRUE); + + trx_reset_new_rec_lock_info(trx); + } + goto next_rec; } @@ -3908,7 +3947,7 @@ got_row: next_rec: /*-------------------------------------------------------------*/ /* PHASE 5: Move the cursor to the next index record */ - + if (UNIV_UNLIKELY(mtr_has_extra_clust_latch)) { /* We must commit mtr if we are moving to the next non-clustered index record, because we could break the @@ -3921,8 +3960,9 @@ next_rec: mtr_has_extra_clust_latch = FALSE; mtr_start(&mtr); - if (sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur, - moves_up, &mtr)) { + if (sel_restore_position_for_mysql(&same_user_rec, + BTR_SEARCH_LEAF, + pcur, moves_up, &mtr)) { #ifdef UNIV_SEARCH_DEBUG cnt++; #endif /* UNIV_SEARCH_DEBUG */ @@ -3976,8 +4016,29 @@ lock_wait_or_error: thr->lock_state = QUE_THR_LOCK_NOLOCK; mtr_start(&mtr); - sel_restore_position_for_mysql(BTR_SEARCH_LEAF, pcur, - moves_up, &mtr); + sel_restore_position_for_mysql(&same_user_rec, + BTR_SEARCH_LEAF, pcur, + moves_up, &mtr); + if (srv_locks_unsafe_for_binlog && !same_user_rec) { + /* Since we were not able to restore the cursor + on the same user record, we cannot use + row_unlock_for_mysql() to unlock any records, and + we must thus reset the new rec lock info. Since + in lock0lock.c we have blocked the inheriting of gap + X-locks, we actually do not have any new record locks + set in this case. + + Note that if we were able to restore on the 'same' + user record, it is still possible that we were actually + waiting on a delete-marked record, and meanwhile + it was removed by purge and inserted again by some + other user. But that is no problem, because in + rec_loop we will again try to set a lock, and + new_rec_lock_info in trx will be right at the end. */ + + trx_reset_new_rec_lock_info(trx); + } + mode = pcur->search_mode; goto rec_loop; diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index 9e155ee1de0..10fbf3468c0 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -166,6 +166,8 @@ trx_create( memset(&trx->xid, 0, sizeof(trx->xid)); trx->xid.formatID = -1; + trx_reset_new_rec_lock_info(trx); + return(trx); } diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index f4c53f2b3da..8b12b43d3d9 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3538,7 +3538,9 @@ ha_innobase::delete_row( } /************************************************************************** -Deletes a lock set to a row */ +Removes a new lock set on a row. This can be called after a row has been read +in the processing of an UPDATE or a DELETE query, if the option +innodb_locks_unsafe_for_binlog is set. */ void ha_innobase::unlock_row(void) @@ -3556,8 +3558,10 @@ ha_innobase::unlock_row(void) mem_analyze_corruption((byte *) prebuilt->trx); ut_error; } - - row_unlock_for_mysql(prebuilt); + + if (srv_locks_unsafe_for_binlog) { + row_unlock_for_mysql(prebuilt, FALSE); + } } /********************************************************************** From 5bcbe404c011bcbd88e88597578b15b6648a5178 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 21:06:23 +0300 Subject: [PATCH 136/216] trx0trx.ic, trx0trx.h: Fix bug in the Bug #3300 bug fix innobase/include/trx0trx.h: Fix bug in the Bug #3300 bug fix innobase/include/trx0trx.ic: Fix bug in the Bug #3300 bug fix --- innobase/include/trx0trx.h | 8 ++++---- innobase/include/trx0trx.ic | 18 +++++++++++++----- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index 1b118a86467..c45024c3d59 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -29,16 +29,16 @@ trx_reset_new_rec_lock_info( /*========================*/ trx_t* trx); /* in: transaction struct */ /***************************************************************** -Registers that we have set a new record lock on an index. This can only be -called twice after calling trx_reset_new_rec_lock_info(), since we only have -space to store 2 indexes! */ +Registers that we have set a new record lock on an index. We only have +space to store 2 indexes! If this is called more than twice after +trx_reset_new_rec_lock_info(), then this function does nothing. */ UNIV_INLINE void trx_register_new_rec_lock( /*======================*/ trx_t* trx, /* in: transaction struct */ dict_index_t* index); /* in: trx sets a new record lock on this - index*/ + index */ /***************************************************************** Checks if trx has set a new record lock on an index. */ UNIV_INLINE diff --git a/innobase/include/trx0trx.ic b/innobase/include/trx0trx.ic index d23165b74e8..0404104aafe 100644 --- a/innobase/include/trx0trx.ic +++ b/innobase/include/trx0trx.ic @@ -52,16 +52,16 @@ trx_reset_new_rec_lock_info( } /***************************************************************** -Registers that we have set a new record lock on an index. This can only be -called twice after calling trx_reset_new_rec_lock_info(), since we only have -space to store 2 indexes! */ +Registers that we have set a new record lock on an index. We only have +space to store 2 indexes! If this is called more than twice after +trx_reset_new_rec_lock_info(), then this function does nothing. */ UNIV_INLINE void trx_register_new_rec_lock( /*======================*/ trx_t* trx, /* in: transaction struct */ dict_index_t* index) /* in: trx sets a new record lock on this - index*/ + index */ { if (trx->new_rec_locks[0] == NULL) { trx->new_rec_locks[0] = index; @@ -69,7 +69,15 @@ trx_register_new_rec_lock( return; } - ut_a(trx->new_rec_locks[1] == NULL); + if (trx->new_rec_locks[0] == index) { + + return; + } + + if (trx->new_rec_locks[1] != NULL) { + + return; + } trx->new_rec_locks[1] = index; } From c2323bae9ab53711c36784df6f80429cae0b0f7c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Jul 2005 22:53:08 +0300 Subject: [PATCH 137/216] trx0trx.h, trx0trx.ic, row0mysql.c: Fix another bug in the fix of Bug #3300 innobase/row/row0mysql.c: Fix another bug in the fix of Bug #3300 innobase/include/trx0trx.ic: Fix another bug in the fix of Bug #3300 innobase/include/trx0trx.h: Fix another bug in the fix of Bug #3300 --- innobase/include/trx0trx.h | 4 ++-- innobase/include/trx0trx.ic | 4 ++-- innobase/row/row0mysql.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index c45024c3d59..146730d46f8 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -29,8 +29,8 @@ trx_reset_new_rec_lock_info( /*========================*/ trx_t* trx); /* in: transaction struct */ /***************************************************************** -Registers that we have set a new record lock on an index. We only have -space to store 2 indexes! If this is called more than twice after +Registers that we have set a new record lock on an index. We only have space +to store 2 indexes! If this is called to store more than 2 indexes after trx_reset_new_rec_lock_info(), then this function does nothing. */ UNIV_INLINE void diff --git a/innobase/include/trx0trx.ic b/innobase/include/trx0trx.ic index 0404104aafe..54cf2ff331f 100644 --- a/innobase/include/trx0trx.ic +++ b/innobase/include/trx0trx.ic @@ -52,8 +52,8 @@ trx_reset_new_rec_lock_info( } /***************************************************************** -Registers that we have set a new record lock on an index. We only have -space to store 2 indexes! If this is called more than twice after +Registers that we have set a new record lock on an index. We only have space +to store 2 indexes! If this is called to store more than 2 indexes after trx_reset_new_rec_lock_info(), then this function does nothing. */ UNIV_INLINE void diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 354b7be3e77..2ac0824b331 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1517,7 +1517,7 @@ row_unlock_for_mysql( &mtr); } - rec = btr_pcur_get_rec(pcur); + rec = btr_pcur_get_rec(clust_pcur); mutex_enter(&kernel_mutex); From c75eae35782787856a5450ad0534a2e86bdc8f15 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 2 Jul 2005 00:39:47 +0300 Subject: [PATCH 138/216] row0sel.c: Optimize speed: no need to keep track of set new rec locks in a consistent read innobase/row/row0sel.c: Optimize speed: no need to keep track of set new rec locks in a consistent read --- innobase/row/row0sel.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 44372f4eb87..15439bed7e7 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -3150,7 +3150,9 @@ row_search_for_mysql( is set. Then we are able to remove the record locks set here on an individual row. */ - if (srv_locks_unsafe_for_binlog) { + if (srv_locks_unsafe_for_binlog + && prebuilt->select_lock_type != LOCK_NONE) { + trx_reset_new_rec_lock_info(trx); } @@ -3793,7 +3795,9 @@ no_gap_lock: not a consistent read which might see an earlier version of a non-clustered index record */ - if (srv_locks_unsafe_for_binlog) { + if (srv_locks_unsafe_for_binlog + && prebuilt->select_lock_type != LOCK_NONE) { + /* No need to keep a lock on a delete-marked record if we do not want to use next-key locking. */ @@ -3845,7 +3849,9 @@ requires_clust_rec: /* The record is delete marked: we can skip it */ - if (srv_locks_unsafe_for_binlog) { + if (srv_locks_unsafe_for_binlog + && prebuilt->select_lock_type != LOCK_NONE) { + /* No need to keep a lock on a delete-marked record if we do not want to use next-key locking. */ @@ -4013,6 +4019,8 @@ lock_wait_or_error: thr->lock_state = QUE_THR_LOCK_ROW; if (row_mysql_handle_errors(&err, trx, thr, NULL)) { + /* It was a lock wait, and it ended */ + thr->lock_state = QUE_THR_LOCK_NOLOCK; mtr_start(&mtr); From 2fec2ba4c910d3db4059b8ffc77169021a39e04a Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 2 Jul 2005 02:00:56 +0200 Subject: [PATCH 139/216] configure.in: Enable build with CXX=gcc and gcc version 4 configure.in: Enable build with CXX=gcc and gcc version 4 --- configure.in | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index b291200c114..5af41d29c21 100644 --- a/configure.in +++ b/configure.in @@ -370,9 +370,14 @@ then if echo $CXX | grep gcc > /dev/null 2>&1 then - if $CXX -v 2>&1 | grep 'version 3' > /dev/null 2>&1 + AC_MSG_CHECKING([if CXX is gcc 3 or 4]) + if $CXX -v 2>&1 | grep 'version [[34]]' > /dev/null 2>&1 then + AC_MSG_RESULT([yes]) + AC_MSG_NOTICE([using MySQL tricks to avoid linking C++ code with C++ libraries]) CXXFLAGS="$CXXFLAGS -DUSE_MYSYS_NEW -DDEFINE_CXA_PURE_VIRTUAL" + else + AC_MSG_RESULT([no]) fi fi fi From 7e8c38656f84211615ba7127abf67a7375e23cb9 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 2 Jul 2005 13:16:30 +0300 Subject: [PATCH 140/216] fixed difference between ps-protocol and usual execution mysql-test/r/view.result: removed wrong warning sql/sql_view.cc: fix_fields have to be (and will be) made later --- mysql-test/r/view.result | 2 -- sql/sql_view.cc | 2 -- 2 files changed, 4 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f3c45d77637..cad86dc94b8 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -754,8 +754,6 @@ create view v1 as select * from t1; create view v2 as select * from t2; insert into v1 values (1); insert into v2 values (1); -Warnings: -Warning 1423 Field of view 'test.v2' underlying table doesn't have a default value create view v3 (a,b) as select v1.col1 as a, v2.col1 as b from v1, v2 where v1.col1 = v2.col1; select * from v3; a b diff --git a/sql/sql_view.cc b/sql/sql_view.cc index b7b1335b107..0a4d26c3a95 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1198,8 +1198,6 @@ bool insert_view_fields(THD *thd, List *list, TABLE_LIST *view) for (Field_translator *entry= trans; entry < trans_end; entry++) { Item_field *fld; - if (!entry->item->fixed && entry->item->fix_fields(thd, &entry->item)) - DBUG_RETURN(TRUE); if ((fld= entry->item->filed_for_view_update())) list->push_back(fld); else From be515e075cf9f08d2249c2d3c4d6048bf7befe29 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 2 Jul 2005 16:12:32 +0300 Subject: [PATCH 141/216] fixed var_samp printing (BUG#10651) mysql-test/r/view.result: Using var_samp with view (BUG#10651) mysql-test/t/view.test: Using var_samp with view (BUG#10651) sql/item_sum.h: fixed var_samp printing --- mysql-test/r/view.result | 7 +++++++ mysql-test/t/view.test | 10 ++++++++++ sql/item_sum.h | 3 ++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 4c1db618b4b..e69d0f35226 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1850,3 +1850,10 @@ SELECT * FROM v1; SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1) dkjhgd drop view v1; +create table t1 (s1 int); +create view v1 as select var_samp(s1) from t1; +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select var_samp(`test`.`t1`.`s1`) AS `var_samp(s1)` from `test`.`t1` +drop view v1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 06b523b3610..504a30bb8b7 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1696,3 +1696,13 @@ drop view v1; CREATE VIEW v1 AS SELECT SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1); SELECT * FROM v1; drop view v1; + +# +# Using var_samp with view (BUG#10651) +# +create table t1 (s1 int); +create view v1 as select var_samp(s1) from t1; +show create view v1; +drop view v1; +drop table t1; + diff --git a/sql/item_sum.h b/sql/item_sum.h index b9a90ee5de5..58cc14c2d31 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -479,7 +479,8 @@ public: Item *result_item(Field *field) { return new Item_variance_field(this); } void no_rows_in_result() {} - const char *func_name() const { return "variance("; } + const char *func_name() const + { return sample ? "var_samp(" : "variance("; } Item *copy_or_same(THD* thd); Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); enum Item_result result_type () const { return hybrid_type; } From 6d9bc9c8b71acd82aa79ae580271e7dc4012e5a4 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 3 Jul 2005 00:51:02 +0300 Subject: [PATCH 142/216] do not register changes of stack variable sql/item.cc: new argument of find_field_in_tables() sql/mysql_priv.h: new argument of find_field_in_tables() sql/sp.cc: new argument of find_field_in_tables() sql/sql_base.cc: new argument of find_field_in_tables() sql/sql_help.cc: new argument of find_field_in_tables() --- sql/item.cc | 11 +++++++---- sql/mysql_priv.h | 3 ++- sql/sp.cc | 5 +++-- sql/sql_base.cc | 36 +++++++++++++++++++----------------- sql/sql_help.cc | 3 ++- sql/sql_select.cc | 3 ++- 6 files changed, 35 insertions(+), 26 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index d62ac38e943..766d40f209e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2837,7 +2837,8 @@ bool Item_field::fix_fields(THD *thd, Item **reference) reference, IGNORE_EXCEPT_NON_UNIQUE, !any_privileges && - context->check_privileges)) == + context->check_privileges, + TRUE)) == not_found_field) { /* @@ -2880,7 +2881,8 @@ bool Item_field::fix_fields(THD *thd, Item **reference) reference, IGNORE_EXCEPT_NON_UNIQUE, outer_context-> - check_privileges)) != + check_privileges, + TRUE)) != not_found_field) { if (from_field) @@ -2953,7 +2955,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference) find_field_in_tables(thd, this, context->table_list, reference, REPORT_ALL_ERRORS, !any_privileges && - context->check_privileges); + context->check_privileges, TRUE); } goto error; } @@ -4102,7 +4104,8 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) outer_context->table_list, reference, IGNORE_EXCEPT_NON_UNIQUE, - outer_context->check_privileges); + outer_context->check_privileges, + TRUE); if (! from_field) goto error; if (from_field == view_ref_found) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index ecd32ef35af..9a3684c3865 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -758,7 +758,8 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND, Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, Item **ref, find_item_error_report_type report_error, - bool check_privileges); + bool check_privileges, + bool register_tree_change); Field * find_field_in_table(THD *thd, TABLE_LIST *table_list, const char *name, const char *item_name, diff --git a/sql/sp.cc b/sql/sp.cc index f376c9b5ed2..456248db66b 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -687,8 +687,9 @@ db_show_routine_status(THD *thd, int type, const char *wild) "mysql", "proc", used_field->field_name); if (!field || - !(used_field->field= find_field_in_tables(thd, field, &tables, - 0, REPORT_ALL_ERRORS, 1))) + !(used_field->field= find_field_in_tables(thd, field, &tables, + 0, REPORT_ALL_ERRORS, 1, + TRUE))) { res= SP_INTERNAL_ERROR; goto err_case1; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7cc0c4fecf1..ef3ccf794b0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2581,19 +2581,21 @@ Field *find_field_in_real_table(THD *thd, TABLE *table, SYNOPSIS find_field_in_tables() - thd Pointer to current thread structure - item Field item that should be found - tables Tables to be searched for item - ref If 'item' is resolved to a view field, ref is set to - point to the found view field - report_error Degree of error reporting: - - IGNORE_ERRORS then do not report any error - - IGNORE_EXCEPT_NON_UNIQUE report only non-unique - fields, suppress all other errors - - REPORT_EXCEPT_NON_UNIQUE report all other errors - except when non-unique fields were found - - REPORT_ALL_ERRORS - check_privileges need to check privileges + thd Pointer to current thread structure + item Field item that should be found + tables Tables to be searched for item + ref If 'item' is resolved to a view field, ref is set to + point to the found view field + report_error Degree of error reporting: + - IGNORE_ERRORS then do not report any error + - IGNORE_EXCEPT_NON_UNIQUE report only non-unique + fields, suppress all other errors + - REPORT_EXCEPT_NON_UNIQUE report all other errors + except when non-unique fields were found + - REPORT_ALL_ERRORS + check_privileges need to check privileges + register_tree_change TRUE if ref is not stack variable and we + need register changes in item tree RETURN VALUES 0 If error: the found field is not unique, or there are @@ -2609,7 +2611,7 @@ Field *find_field_in_real_table(THD *thd, TABLE *table, Field * find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, Item **ref, find_item_error_report_type report_error, - bool check_privileges) + bool check_privileges, bool register_tree_change) { Field *found=0; const char *db=item->db_name; @@ -2651,7 +2653,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, (test(table->grant.want_privilege) && check_privileges), 1, &(item->cached_field_index), - TRUE); + register_tree_change); } if (found) { @@ -2707,7 +2709,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, (test(tables->grant.want_privilege) && check_privileges), 1, &(item->cached_field_index), - TRUE); + register_tree_change); if (find) { item->cached_table= tables; @@ -2775,7 +2777,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, check_privileges), allow_rowid, &(item->cached_field_index), - TRUE); + register_tree_change); if (field) { if (field == WRONG_GRANT) diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 3f151934e55..6780beec258 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -91,7 +91,8 @@ static bool init_fields(THD *thd, TABLE_LIST *tables, "mysql", find_fields->table_name, find_fields->field_name); if (!(find_fields->field= find_field_in_tables(thd, field, tables, - 0, REPORT_ALL_ERRORS, 1))) + 0, REPORT_ALL_ERRORS, 1, + TRUE))) DBUG_RETURN(1); } DBUG_RETURN(0); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d41b503575f..d7ef692e8c3 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11890,7 +11890,8 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, order_item_type == Item::REF_ITEM) { from_field= find_field_in_tables(thd, (Item_ident*) order_item, tables, - &view_ref, IGNORE_ERRORS, TRUE); + &view_ref, IGNORE_ERRORS, TRUE, + FALSE); if(!from_field) from_field= (Field*) not_found_field; } From 428830c50024475e85e12f6b188879c2de536529 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Jul 2005 03:24:25 +0300 Subject: [PATCH 143/216] After merge fixes Better fix for ON DUPLICATE KEY UPDATE mysql-test/r/group_by.result: After merge fixes mysql-test/r/select.result: Reorder test to match 4.1 tests (will make future merges easier) mysql-test/t/group_by.test: Added --disable_ps_protocol to avoid extra warning mysql-test/t/select.test: Reorder test to match 4.1 tests (will make future merges easier) sql/mysql_priv.h: Better fix for ON DUPLICATE KEY UPDATE sql/sql_base.cc: After merge fixes sql/sql_insert.cc: Better fix for ON DUPLICATE KEY UPDATE (old solution gave problem with item->cached_table) sql/sql_prepare.cc: Better fix for ON DUPLICATE KEY UPDATE --- mysql-test/r/group_by.result | 6 +- mysql-test/r/select.result | 236 ++++++++++++++++---------------- mysql-test/t/group_by.test | 4 +- mysql-test/t/select.test | 251 +++++++++++++++++------------------ sql/mysql_priv.h | 3 +- sql/sql_base.cc | 3 +- sql/sql_insert.cc | 51 +++---- sql/sql_prepare.cc | 18 +-- 8 files changed, 283 insertions(+), 289 deletions(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 85b923bf15a..28fa101f45f 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -721,13 +721,15 @@ SELECT hostname, COUNT(DISTINCT user_id) as no FROM t1 WHERE hostname LIKE '%aol%' GROUP BY hostname; hostname no +cache-dtc-af05.proxy.aol.com 1 +DROP TABLE t1; CREATE TABLE t1 (n int); INSERT INTO t1 VALUES (1); SELECT n+1 AS n FROM t1 GROUP BY n; n 2 -DROP TABLE t1; -cache-dtc-af05.proxy.aol.com 1 +Warnings: +Warning 1052 Column 'n' in group statement is ambiguous DROP TABLE t1; CREATE TABLE t1 (a int, b int); INSERT INTO t1 VALUES (1,2), (1,3); diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 4381220eacc..d02c28a0a97 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2423,12 +2423,130 @@ ERROR HY000: Incorrect usage of ALL and DISTINCT select distinct all * from t1; ERROR HY000: Incorrect usage of ALL and DISTINCT drop table t1; +CREATE TABLE t1 ( +kunde_intern_id int(10) unsigned NOT NULL default '0', +kunde_id int(10) unsigned NOT NULL default '0', +FK_firma_id int(10) unsigned NOT NULL default '0', +aktuell enum('Ja','Nein') NOT NULL default 'Ja', +vorname varchar(128) NOT NULL default '', +nachname varchar(128) NOT NULL default '', +geloescht enum('Ja','Nein') NOT NULL default 'Nein', +firma varchar(128) NOT NULL default '' +); +INSERT INTO t1 VALUES +(3964,3051,1,'Ja','Vorname1','1Nachname','Nein','Print Schau XXXX'), +(3965,3051111,1,'Ja','Vorname1111','1111Nachname','Nein','Print Schau XXXX'); +SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, geloescht FROM t1 +WHERE +( +( +( '' != '' AND firma LIKE CONCAT('%', '', '%')) +OR +(vorname LIKE CONCAT('%', 'Vorname1', '%') AND +nachname LIKE CONCAT('%', '1Nachname', '%') AND +'Vorname1' != '' AND 'xxxx' != '') +) +AND +( +aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2 +) +) +; +kunde_id FK_firma_id aktuell vorname nachname geloescht +SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, +geloescht FROM t1 +WHERE +( +( +aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2 +) +AND +( +( '' != '' AND firma LIKE CONCAT('%', '', '%') ) +OR +( vorname LIKE CONCAT('%', 'Vorname1', '%') AND +nachname LIKE CONCAT('%', '1Nachname', '%') AND 'Vorname1' != '' AND +'xxxx' != '') +) +) +; +kunde_id FK_firma_id aktuell vorname nachname geloescht +SELECT COUNT(*) FROM t1 WHERE +( 0 OR (vorname LIKE '%Vorname1%' AND nachname LIKE '%1Nachname%' AND 1)) +AND FK_firma_id = 2; +COUNT(*) +0 +drop table t1; CREATE TABLE t1 (b BIGINT(20) UNSIGNED NOT NULL, PRIMARY KEY (b)); INSERT INTO t1 VALUES (0x8000000000000000); SELECT b FROM t1 WHERE b=0x8000000000000000; b 9223372036854775808 DROP TABLE t1; +CREATE TABLE `t1` ( `gid` int(11) default NULL, `uid` int(11) default NULL); +CREATE TABLE `t2` ( `ident` int(11) default NULL, `level` char(16) default NULL); +INSERT INTO `t2` VALUES (0,'READ'); +CREATE TABLE `t3` ( `id` int(11) default NULL, `name` char(16) default NULL); +INSERT INTO `t3` VALUES (1,'fs'); +select * from t3 left join t1 on t3.id = t1.uid, t2 where t2.ident in (0, t1.gid, t3.id, 0); +id name gid uid ident level +1 fs NULL NULL 0 READ +drop table t1,t2,t3; +CREATE TABLE t1 ( city char(30) ); +INSERT INTO t1 VALUES ('London'); +INSERT INTO t1 VALUES ('Paris'); +SELECT * FROM t1 WHERE city='London'; +city +London +SELECT * FROM t1 WHERE city='london'; +city +London +EXPLAIN SELECT * FROM t1 WHERE city='London' AND city='london'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where +SELECT * FROM t1 WHERE city='London' AND city='london'; +city +London +EXPLAIN SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where +SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London'; +city +London +DROP TABLE t1; +create table t1 (a int(11) unsigned, b int(11) unsigned); +insert into t1 values (1,0), (1,1), (1,2); +select a-b from t1 order by 1; +a-b +0 +1 +18446744073709551615 +select a-b , (a-b < 0) from t1 order by 1; +a-b (a-b < 0) +0 0 +1 0 +18446744073709551615 0 +select a-b as d, (a-b >= 0), b from t1 group by b having d >= 0; +d (a-b >= 0) b +1 1 0 +0 1 1 +18446744073709551615 1 2 +select cast((a - b) as unsigned) from t1 order by 1; +cast((a - b) as unsigned) +0 +1 +18446744073709551615 +drop table t1; +create table t1 (a int(11)); +select all all * from t1; +a +select distinct distinct * from t1; +a +select all distinct * from t1; +ERROR HY000: Incorrect usage of ALL and DISTINCT +select distinct all * from t1; +ERROR HY000: Incorrect usage of ALL and DISTINCT +drop table t1; CREATE TABLE t1 ( K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '', K4N4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '0000', @@ -2573,124 +2691,6 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 5 1 SIMPLE t2 ref a a 23 test.t1.a 2 DROP TABLE t1, t2; -CREATE TABLE t1 ( city char(30) ); -INSERT INTO t1 VALUES ('London'); -INSERT INTO t1 VALUES ('Paris'); -SELECT * FROM t1 WHERE city='London'; -city -London -SELECT * FROM t1 WHERE city='london'; -city -London -EXPLAIN SELECT * FROM t1 WHERE city='London' AND city='london'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where -SELECT * FROM t1 WHERE city='London' AND city='london'; -city -London -EXPLAIN SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London'; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where -SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London'; -city -London -DROP TABLE t1; -create table t1 (a int(11) unsigned, b int(11) unsigned); -insert into t1 values (1,0), (1,1), (1,2); -select a-b from t1 order by 1; -a-b -0 -1 -18446744073709551615 -select a-b , (a-b < 0) from t1 order by 1; -a-b (a-b < 0) -0 0 -1 0 -18446744073709551615 0 -select a-b as d, (a-b >= 0), b from t1 group by b having d >= 0; -d (a-b >= 0) b -1 1 0 -0 1 1 -18446744073709551615 1 2 -select cast((a - b) as unsigned) from t1 order by 1; -cast((a - b) as unsigned) -0 -1 -18446744073709551615 -drop table t1; -create table t1 (a int(11)); -select all all * from t1; -a -select distinct distinct * from t1; -a -select all distinct * from t1; -ERROR HY000: Incorrect usage of ALL and DISTINCT -select distinct all * from t1; -ERROR HY000: Incorrect usage of ALL and DISTINCT -drop table t1; -CREATE TABLE t1 ( -kunde_intern_id int(10) unsigned NOT NULL default '0', -kunde_id int(10) unsigned NOT NULL default '0', -FK_firma_id int(10) unsigned NOT NULL default '0', -aktuell enum('Ja','Nein') NOT NULL default 'Ja', -vorname varchar(128) NOT NULL default '', -nachname varchar(128) NOT NULL default '', -geloescht enum('Ja','Nein') NOT NULL default 'Nein', -firma varchar(128) NOT NULL default '' -); -INSERT INTO t1 VALUES -(3964,3051,1,'Ja','Vorname1','1Nachname','Nein','Print Schau XXXX'), -(3965,3051111,1,'Ja','Vorname1111','1111Nachname','Nein','Print Schau XXXX'); -SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, geloescht FROM t1 -WHERE -( -( -( '' != '' AND firma LIKE CONCAT('%', '', '%')) -OR -(vorname LIKE CONCAT('%', 'Vorname1', '%') AND -nachname LIKE CONCAT('%', '1Nachname', '%') AND -'Vorname1' != '' AND 'xxxx' != '') -) -AND -( -aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2 -) -) -; -kunde_id FK_firma_id aktuell vorname nachname geloescht -SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, -geloescht FROM t1 -WHERE -( -( -aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2 -) -AND -( -( '' != '' AND firma LIKE CONCAT('%', '', '%') ) -OR -( vorname LIKE CONCAT('%', 'Vorname1', '%') AND -nachname LIKE CONCAT('%', '1Nachname', '%') AND 'Vorname1' != '' AND -'xxxx' != '') -) -) -; -kunde_id FK_firma_id aktuell vorname nachname geloescht -SELECT COUNT(*) FROM t1 WHERE -( 0 OR (vorname LIKE '%Vorname1%' AND nachname LIKE '%1Nachname%' AND 1)) -AND FK_firma_id = 2; -COUNT(*) -0 -CREATE TABLE `t1` ( `gid` int(11) default NULL, `uid` int(11) default NULL); -CREATE TABLE `t2` ( `ident` int(11) default NULL, `level` char(16) default NULL); -INSERT INTO `t2` VALUES (0,'READ'); -CREATE TABLE `t3` ( `id` int(11) default NULL, `name` char(16) default NULL); -INSERT INTO `t3` VALUES (1,'fs'); -select * from t3 left join t1 on t3.id = t1.uid, t2 where t2.ident in (0, t1.gid, t3.id, 0); -id name gid uid ident level -1 fs NULL NULL 0 READ -drop table t1,t2,t3; -drop table t1; CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); INSERT INTO t1 VALUES (1), (2), (3), (4), (5); diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index aa7ea9bb6cb..6845f310843 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -550,9 +550,9 @@ DROP TABLE t1; CREATE TABLE t1 (n int); INSERT INTO t1 VALUES (1); - +--disable_ps_protocol SELECT n+1 AS n FROM t1 GROUP BY n; - +--enable_ps_protocol DROP TABLE t1; # Test for bug #8614: GROUP BY 'const' with DISTINCT diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index da08c7253a4..2e4bb3e13ad 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -1954,6 +1954,131 @@ EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a; DROP TABLE t1, t2; +# +# Test case for bug 7098: substitution of a constant for a string field +# + +CREATE TABLE t1 ( city char(30) ); +INSERT INTO t1 VALUES ('London'); +INSERT INTO t1 VALUES ('Paris'); + +SELECT * FROM t1 WHERE city='London'; +SELECT * FROM t1 WHERE city='london'; +EXPLAIN SELECT * FROM t1 WHERE city='London' AND city='london'; +SELECT * FROM t1 WHERE city='London' AND city='london'; +EXPLAIN SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London'; +SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London'; + +DROP TABLE t1; + +# +# Bug#7425 inconsistent sort order on unsigned columns result of substraction +# + +create table t1 (a int(11) unsigned, b int(11) unsigned); +insert into t1 values (1,0), (1,1), (1,2); +select a-b from t1 order by 1; +select a-b , (a-b < 0) from t1 order by 1; +select a-b as d, (a-b >= 0), b from t1 group by b having d >= 0; +select cast((a - b) as unsigned) from t1 order by 1; +drop table t1; + + +# +# Bug#8733 server accepts malformed query (multiply mentioned distinct) +# +create table t1 (a int(11)); +select all all * from t1; +select distinct distinct * from t1; +--error 1221 +select all distinct * from t1; +--error 1221 +select distinct all * from t1; +drop table t1; + +# +# Test for BUG#10095 +# +CREATE TABLE t1 ( + kunde_intern_id int(10) unsigned NOT NULL default '0', + kunde_id int(10) unsigned NOT NULL default '0', + FK_firma_id int(10) unsigned NOT NULL default '0', + aktuell enum('Ja','Nein') NOT NULL default 'Ja', + vorname varchar(128) NOT NULL default '', + nachname varchar(128) NOT NULL default '', + geloescht enum('Ja','Nein') NOT NULL default 'Nein', + firma varchar(128) NOT NULL default '' +); + +INSERT INTO t1 VALUES + (3964,3051,1,'Ja','Vorname1','1Nachname','Nein','Print Schau XXXX'), + (3965,3051111,1,'Ja','Vorname1111','1111Nachname','Nein','Print Schau XXXX'); + + +SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, geloescht FROM t1 + WHERE + ( + ( + ( '' != '' AND firma LIKE CONCAT('%', '', '%')) + OR + (vorname LIKE CONCAT('%', 'Vorname1', '%') AND + nachname LIKE CONCAT('%', '1Nachname', '%') AND + 'Vorname1' != '' AND 'xxxx' != '') + ) + AND + ( + aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2 + ) + ) + ; + +SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, +geloescht FROM t1 + WHERE + ( + ( + aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2 + ) + AND + ( + ( '' != '' AND firma LIKE CONCAT('%', '', '%') ) + OR + ( vorname LIKE CONCAT('%', 'Vorname1', '%') AND +nachname LIKE CONCAT('%', '1Nachname', '%') AND 'Vorname1' != '' AND +'xxxx' != '') + ) + ) + ; + +SELECT COUNT(*) FROM t1 WHERE +( 0 OR (vorname LIKE '%Vorname1%' AND nachname LIKE '%1Nachname%' AND 1)) +AND FK_firma_id = 2; + +drop table t1; + +# +# Test for Bug#8009, SELECT failed on bigint unsigned when using HEX +# + +CREATE TABLE t1 (b BIGINT(20) UNSIGNED NOT NULL, PRIMARY KEY (b)); +INSERT INTO t1 VALUES (0x8000000000000000); +SELECT b FROM t1 WHERE b=0x8000000000000000; +DROP TABLE t1; + +# +# IN with outer join condition (BUG#9393) +# +CREATE TABLE `t1` ( `gid` int(11) default NULL, `uid` int(11) default NULL); + +CREATE TABLE `t2` ( `ident` int(11) default NULL, `level` char(16) default NULL); +INSERT INTO `t2` VALUES (0,'READ'); + +CREATE TABLE `t3` ( `id` int(11) default NULL, `name` char(16) default NULL); +INSERT INTO `t3` VALUES (1,'fs'); + +select * from t3 left join t1 on t3.id = t1.uid, t2 where t2.ident in (0, t1.gid, t3.id, 0); + +drop table t1,t2,t3; # # Test case for bug 7098: substitution of a constant for a string field @@ -1998,30 +2123,6 @@ select distinct all * from t1; drop table t1; # - -# -# Test for Bug#8009, SELECT failed on bigint unsigned when using HEX -# - -CREATE TABLE t1 (b BIGINT(20) UNSIGNED NOT NULL, PRIMARY KEY (b)); -INSERT INTO t1 VALUES (0x8000000000000000); -SELECT b FROM t1 WHERE b=0x8000000000000000; -DROP TABLE t1; - -# -# IN with outer join condition (BUG#9393) -# -CREATE TABLE `t1` ( `gid` int(11) default NULL, `uid` int(11) default NULL); - -CREATE TABLE `t2` ( `ident` int(11) default NULL, `level` char(16) default NULL); -INSERT INTO `t2` VALUES (0,'READ'); - -CREATE TABLE `t3` ( `id` int(11) default NULL, `name` char(16) default NULL); -INSERT INTO `t3` VALUES (1,'fs'); - -select * from t3 left join t1 on t3.id = t1.uid, t2 where t2.ident in (0, t1.gid, t3.id, 0); - -drop table t1,t2,t3; # Test for bug #6474 # @@ -2168,108 +2269,6 @@ EXPLAIN SELECT * FROM t1 LEFT JOIN t2 FORCE INDEX (a) ON t1.a=t2.a; DROP TABLE t1, t2; -# -# Test case for bug 7098: substitution of a constant for a string field -# - -CREATE TABLE t1 ( city char(30) ); -INSERT INTO t1 VALUES ('London'); -INSERT INTO t1 VALUES ('Paris'); - -SELECT * FROM t1 WHERE city='London'; -SELECT * FROM t1 WHERE city='london'; -EXPLAIN SELECT * FROM t1 WHERE city='London' AND city='london'; -SELECT * FROM t1 WHERE city='London' AND city='london'; -EXPLAIN SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London'; -SELECT * FROM t1 WHERE city LIKE '%london%' AND city='London'; - -DROP TABLE t1; - -# -# Bug#7425 inconsistent sort order on unsigned columns result of substraction -# - -create table t1 (a int(11) unsigned, b int(11) unsigned); -insert into t1 values (1,0), (1,1), (1,2); -select a-b from t1 order by 1; -select a-b , (a-b < 0) from t1 order by 1; -select a-b as d, (a-b >= 0), b from t1 group by b having d >= 0; -select cast((a - b) as unsigned) from t1 order by 1; -drop table t1; - - -# -# Bug#8733 server accepts malformed query (multiply mentioned distinct) -# -create table t1 (a int(11)); -select all all * from t1; -select distinct distinct * from t1; ---error 1221 -select all distinct * from t1; ---error 1221 -select distinct all * from t1; -drop table t1; - -# -# Test for BUG#10095 -# -CREATE TABLE t1 ( - kunde_intern_id int(10) unsigned NOT NULL default '0', - kunde_id int(10) unsigned NOT NULL default '0', - FK_firma_id int(10) unsigned NOT NULL default '0', - aktuell enum('Ja','Nein') NOT NULL default 'Ja', - vorname varchar(128) NOT NULL default '', - nachname varchar(128) NOT NULL default '', - geloescht enum('Ja','Nein') NOT NULL default 'Nein', - firma varchar(128) NOT NULL default '' -); - -INSERT INTO t1 VALUES - (3964,3051,1,'Ja','Vorname1','1Nachname','Nein','Print Schau XXXX'), - (3965,3051111,1,'Ja','Vorname1111','1111Nachname','Nein','Print Schau XXXX'); - - -SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, geloescht FROM t1 - WHERE - ( - ( - ( '' != '' AND firma LIKE CONCAT('%', '', '%')) - OR - (vorname LIKE CONCAT('%', 'Vorname1', '%') AND - nachname LIKE CONCAT('%', '1Nachname', '%') AND - 'Vorname1' != '' AND 'xxxx' != '') - ) - AND - ( - aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2 - ) - ) - ; - -SELECT kunde_id ,FK_firma_id ,aktuell, vorname, nachname, -geloescht FROM t1 - WHERE - ( - ( - aktuell = 'Ja' AND geloescht = 'Nein' AND FK_firma_id = 2 - ) - AND - ( - ( '' != '' AND firma LIKE CONCAT('%', '', '%') ) - OR - ( vorname LIKE CONCAT('%', 'Vorname1', '%') AND -nachname LIKE CONCAT('%', '1Nachname', '%') AND 'Vorname1' != '' AND -'xxxx' != '') - ) - ) - ; - -SELECT COUNT(*) FROM t1 WHERE -( 0 OR (vorname LIKE '%Vorname1%' AND nachname LIKE '%1Nachname%' AND 1)) -AND FK_firma_id = 2; - -drop table t1; - # # Test for bug #10084: STRAIGHT_JOIN with ON expression # diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index daa3618808b..9a3684c3865 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -717,8 +717,7 @@ bool mysql_multi_update(THD *thd, TABLE_LIST *table_list, COND *conds, ulong options, enum enum_duplicates handle_duplicates, bool ignore, SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex); -bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, - TABLE_LIST *dup_table_list, TABLE *table, +bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table, List &fields, List_item *values, List &update_fields, List &update_values, enum_duplicates duplic, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 0d19a45c438..383adcadc6a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2620,6 +2620,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, uint length=(uint) strlen(name); char name_buff[NAME_LEN+1]; bool allow_rowid; + if (item->cached_table) { /* @@ -2689,7 +2690,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, if (table_name && table_name[0]) { /* Qualified field */ bool found_table= 0; - for (; tables; tables= tables->next_local), + for (; tables; tables= tables->next_local) { /* TODO; Ensure that db and tables->db always points to something ! */ if (!my_strcasecmp(table_alias_charset, tables->alias, table_name) && diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index adb1eb01292..576866cb17d 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -327,7 +327,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, thd->used_tables=0; values= its++; - if (mysql_prepare_insert(thd, table_list, table_list, table, fields, values, + if (mysql_prepare_insert(thd, table_list, table, fields, values, update_fields, update_values, duplic, &unused_conds, FALSE)) goto abort; @@ -734,10 +734,6 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, mysql_prepare_insert() thd Thread handler table_list Global/local table list - dup_table_list Tables to be used in ON DUPLICATE KEY - It's either all global tables or only the table we - insert into, depending on if we are using GROUP BY - in the SELECT clause). table Table to insert into (can be NULL if table should be taken from table_list->table) where Where clause (for insert ... select) @@ -759,18 +755,17 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, */ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, - TABLE_LIST *dup_table_list, TABLE *table, - List &fields, List_item *values, + TABLE *table, List &fields, List_item *values, List &update_fields, List &update_values, enum_duplicates duplic, COND **where, bool select_insert) { - SELECT_LEX= &thd->lex->select_lex; + SELECT_LEX *select_lex= &thd->lex->select_lex; TABLE_LIST *save_table_list; TABLE_LIST *save_next_local; bool insert_into_view= (table_list->view != 0); bool save_resolve_in_select_list; - bool res; + bool res= 0; DBUG_ENTER("mysql_prepare_insert"); DBUG_PRINT("enter", ("table_list 0x%lx, table 0x%lx, view %d", (ulong)table_list, (ulong)table, @@ -815,15 +810,23 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, select_lex->context.resolve_in_table_list_only(table_list); if ((values && check_insert_fields(thd, table_list, fields, *values, !insert_into_view)) || - (values && setup_fields(thd, 0, *values, 0, 0, 0)) || - setup_fields(thd, 0, update_values, 1, 0, 0)) + (values && setup_fields(thd, 0, *values, 0, 0, 0))) res= TRUE; else if (duplic == DUP_UPDATE) { - select_lex->context.resolve_in_table_list_only(dup_table_list); select_lex->no_wrap_view_item= TRUE; res= check_update_fields(thd, table_list, update_fields); select_lex->no_wrap_view_item= FALSE; + if (select_lex->group_list.elements == 0) + { + /* + When we are not using GROUP BY we can refer to other tables in the + ON DUPLICATE KEY part + */ + table_list->next_local= save_next_local; + } + if (!res) + res= setup_fields(thd, 0, update_values, 1, 0, 0); } table_list->next_local= save_next_local; select_lex->context.table_list= save_table_list; @@ -2013,8 +2016,8 @@ bool delayed_insert::handle_inserts(void) bool mysql_insert_select_prepare(THD *thd) { LEX *lex= thd->lex; + SELECT_LEX *select_lex= &lex->select_lex; TABLE_LIST *first_select_leaf_table; - TABLE_LIST dup_tables; DBUG_ENTER("mysql_insert_select_prepare"); /* @@ -2022,38 +2025,28 @@ bool mysql_insert_select_prepare(THD *thd) clause if table is VIEW */ - dup_tables= *lex->query_tables; - if (lex->select_lex->group_list.elements != 0) - { - /* - When we are using GROUP BY we can't refere to other tables in the - ON DUPLICATE KEY part - */ - dup_tables.local_next= 0; - } - - if (mysql_prepare_insert(thd, lex->query_tables, &dup_tables + if (mysql_prepare_insert(thd, lex->query_tables, lex->query_tables->table, lex->field_list, 0, lex->update_list, lex->value_list, lex->duplicates, - &lex->select_lex.where, TRUE)) + &select_lex->where, TRUE)) DBUG_RETURN(TRUE); /* exclude first table from leaf tables list, because it belong to INSERT */ - DBUG_ASSERT(lex->select_lex.leaf_tables != 0); - lex->leaf_tables_insert= lex->select_lex.leaf_tables; + DBUG_ASSERT(select_lex->leaf_tables != 0); + lex->leaf_tables_insert= select_lex->leaf_tables; /* skip all leaf tables belonged to view where we are insert */ - for (first_select_leaf_table= lex->select_lex.leaf_tables->next_leaf; + for (first_select_leaf_table= select_lex->leaf_tables->next_leaf; first_select_leaf_table && first_select_leaf_table->belong_to_view && first_select_leaf_table->belong_to_view == lex->leaf_tables_insert->belong_to_view; first_select_leaf_table= first_select_leaf_table->next_leaf) {} - lex->select_lex.leaf_tables= first_select_leaf_table; + select_lex->leaf_tables= first_select_leaf_table; DBUG_RETURN(FALSE); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 61f9ab9e00d..53f706bd0f6 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -917,12 +917,12 @@ static bool mysql_test_insert(Prepared_statement *stmt, goto error; /* - open temporary memory pool for temporary data allocated by derived - tables & preparation procedure - Note that this is done without locks (should not be needed as we will not - access any data here) - If we would use locks, then we have to ensure we are not using - TL_WRITE_DELAYED as having two such locks can cause table corruption. + open temporary memory pool for temporary data allocated by derived + tables & preparation procedure + Note that this is done without locks (should not be needed as we will not + access any data here) + If we would use locks, then we have to ensure we are not using + TL_WRITE_DELAYED as having two such locks can cause table corruption. */ if (open_normal_and_derived_tables(thd, table_list)) goto error; @@ -939,9 +939,9 @@ static bool mysql_test_insert(Prepared_statement *stmt, table_list->table->insert_values=(byte *)1; } - if (mysql_prepare_insert(thd, table_list, table_list, table_list->table, fields, - values, update_fields, update_values, duplic, - &unused_conds, FALSE)) + if (mysql_prepare_insert(thd, table_list, table_list->table, + fields, values, update_fields, update_values, + duplic, &unused_conds, FALSE)) goto error; value_count= values->elements; From 306ebf7b1c1b26b45e93fbcbbf248b3479142c41 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Jul 2005 03:42:33 +0300 Subject: [PATCH 144/216] Fixes during review of new code - Mostly indentation fixes - Added missing test - Ensure that Item_func_case() checks for stack overruns - Use real_item() instead of (Item_ref*) item - Fixed wrong error handling myisam/mi_unique.c: Improved comments myisam/myisampack.c: Updated version number mysql-test/r/group_by.result: Added test that was lost during earlier merge mysql-test/r/information_schema.result: Safety fix: Drop procedures before used mysql-test/t/group_by.test: Added test that was lost during earlier merge mysql-test/t/information_schema.test: Safety fix: Drop procedures before used mysys/hash.c: Updated comment sql/field.cc: false -> FALSE sql/ha_ndbcluster.cc: Fix some style issues - No () around argument to 'case' - Space before ( in switch and if - Removed 'goto' - Added {} - Added () to make expressions easier to read - my_snprintf -> strmov sql/handler.cc: if( -> if ( sql/item.cc: Indentation changes sql/item.h: false -> FALSE sql/item_cmpfunc.cc: Ensure that Item_func_case() check for stack overrun properly sql/item_cmpfunc.h: Ensure that Item_func_case() check for stack overrun properly sql/item_func.cc: Indentation fixes Fixed wrong goto label sql/mysqld.cc: Remove test for opt_disable_networking as this flag can never be set here sql/opt_range.cc: Simplify code sql/sql_class.h: Move define out from middle of class definition sql/sql_parse.cc: Remove extra empty lines sql/sql_select.cc: use real_item() instead of (Item_ref*) item Modifed function comment to be align with others Simple optimization sql/sql_union.cc: Portability fix: Don't use 'bool_variable|=...' sql/sql_view.cc: Move List_iterator_fast out from loops (rewind is faster than creating a new itearator) strings/ctype-utf8.c: if( -> if ( strings/ctype.c: Remove disabled code strings/decimal.c: Indentation fixes strings/xml.c: Indentation fixes --- myisam/mi_unique.c | 21 +- myisam/myisampack.c | 2 +- mysql-test/r/group_by.result | 21 ++ mysql-test/r/information_schema.result | 5 + mysql-test/t/group_by.test | 23 ++ mysql-test/t/information_schema.test | 11 + mysys/hash.c | 3 +- sql/field.cc | 2 +- sql/ha_ndbcluster.cc | 379 ++++++++++++++----------- sql/handler.cc | 2 +- sql/item.cc | 15 +- sql/item.h | 2 +- sql/item_cmpfunc.cc | 17 +- sql/item_cmpfunc.h | 1 + sql/item_func.cc | 23 +- sql/mysqld.cc | 11 +- sql/opt_range.cc | 15 +- sql/sql_class.h | 12 +- sql/sql_parse.cc | 4 - sql/sql_select.cc | 67 +++-- sql/sql_union.cc | 4 +- sql/sql_view.cc | 23 +- strings/ctype-utf8.c | 2 +- strings/ctype.c | 8 - strings/decimal.c | 16 +- strings/xml.c | 67 ++--- 26 files changed, 443 insertions(+), 313 deletions(-) diff --git a/myisam/mi_unique.c b/myisam/mi_unique.c index f2d5f01be25..34f5f595f30 100644 --- a/myisam/mi_unique.c +++ b/myisam/mi_unique.c @@ -64,7 +64,12 @@ my_bool mi_check_unique(MI_INFO *info, MI_UNIQUEDEF *def, byte *record, } -/* Calculate a hash for a row */ +/* + Calculate a hash for a row + + TODO + Add support for bit fields +*/ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record) { @@ -126,9 +131,17 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record) return crc; } - /* - Returns 0 if both rows have equal unique value - */ + +/* + compare unique key for two rows + + TODO + Add support for bit fields + + RETURN + 0 if both rows have equal unique value + # Rows are different +*/ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b, my_bool null_are_equal) diff --git a/myisam/myisampack.c b/myisam/myisampack.c index 70a32902da6..daf2bbdf85c 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -288,7 +288,7 @@ static struct my_option my_long_options[] = static void print_version(void) { - VOID(printf("%s Ver 1.22 for %s on %s\n", + VOID(printf("%s Ver 1.23 for %s on %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE)); NETWARE_SET_SCREEN_MODE(1); } diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index a56cfd4492a..7cbd8c7d095 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -723,6 +723,27 @@ WHERE hostname LIKE '%aol%' hostname no cache-dtc-af05.proxy.aol.com 1 DROP TABLE t1; +create table t1 (c1 char(3), c2 char(3)); +create table t2 (c3 char(3), c4 char(3)); +insert into t1 values ('aaa', 'bb1'), ('aaa', 'bb2'); +insert into t2 values ('aaa', 'bb1'), ('aaa', 'bb2'); +select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4 +group by c2; +c2 +aaa +aaa +Warnings: +Warning 1052 Column 'c2' in group statement is ambiguous +show warnings; +Level Code Message +Warning 1052 Column 'c2' in group statement is ambiguous +select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4 +group by t1.c1; +c2 +aaa +show warnings; +Level Code Message +drop table t1, t2; CREATE TABLE t1 (a int, b int); INSERT INTO t1 VALUES (1,2), (1,3); SELECT a, b FROM t1 GROUP BY 'const'; diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index c6090bc663d..908082afd65 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -227,6 +227,9 @@ latin1_bin latin1 latin1_general_ci latin1 latin1_general_cs latin1 latin1_spanish_ci latin1 +drop procedure if exists sel2; +drop function if exists sub1; +drop function if exists sub2; create function sub1(i int) returns int return i+1; create procedure sel2() @@ -823,6 +826,8 @@ GRANT SELECT ON *.* TO 'user4'@'localhost' drop user user1@localhost, user2@localhost, user3@localhost, user4@localhost; use test; drop database mysqltest; +drop procedure if exists p1; +drop procedure if exists p2; create procedure p1 () modifies sql data set @a = 5; create procedure p2 () set @a = 5; select sql_data_access from information_schema.routines diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 9f920a1dd83..5d84098a84a 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -542,6 +542,29 @@ SELECT hostname, COUNT(DISTINCT user_id) as no FROM t1 DROP TABLE t1; +# +# Bug#11211: Ambiguous column reference in GROUP BY. +# + +create table t1 (c1 char(3), c2 char(3)); +create table t2 (c3 char(3), c4 char(3)); +insert into t1 values ('aaa', 'bb1'), ('aaa', 'bb2'); +insert into t2 values ('aaa', 'bb1'), ('aaa', 'bb2'); + +# query with ambiguous column reference 'c2' +--disable_ps_protocol +select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4 +group by c2; +show warnings; +--enable_ps_protocol + +# this query has no ambiguity +select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4 +group by t1.c1; + +show warnings; +drop table t1, t2; + # # Test for bug #8614: GROUP BY 'const' with DISTINCT # diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index e03bea5899a..15785a067df 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -101,6 +101,12 @@ where COLLATION_NAME like 'latin1%'; # Test for information_schema.ROUTINES & # +--disable_warnings +drop procedure if exists sel2; +drop function if exists sub1; +drop function if exists sub2; +--enable_warnings + create function sub1(i int) returns int return i+1; delimiter |; @@ -546,6 +552,11 @@ drop database mysqltest; # # Bug #11055 information_schema: routines.sql_data_access has wrong value # +--disable_warnings +drop procedure if exists p1; +drop procedure if exists p2; +--enable_warnings + create procedure p1 () modifies sql data set @a = 5; create procedure p2 () set @a = 5; select sql_data_access from information_schema.routines diff --git a/mysys/hash.c b/mysys/hash.c index 28f8797288c..45cf7d5ff1d 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -277,9 +277,8 @@ static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink) record being compared against. RETURN - < 0 key of record < key = 0 key of record == key - > 0 key of record > key + != 0 key of record != key */ static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length) diff --git a/sql/field.cc b/sql/field.cc index 2cfd162899c..2ce3228be0a 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2479,7 +2479,7 @@ int Field_new_decimal::store(longlong nr) int err; if ((err= int2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, - nr, false, &decimal_value))) + nr, FALSE, &decimal_value))) { if (check_overflow(err)) set_value_on_overflow(&decimal_value, decimal_value.sign()); diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 00623251c29..976a3eeead0 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -341,7 +341,7 @@ void ha_ndbcluster::records_update() { Ndb *ndb= get_ndb(); struct Ndb_statistics stat; - if(ndb_get_table_statistics(ndb, m_tabname, &stat) == 0){ + if (ndb_get_table_statistics(ndb, m_tabname, &stat) == 0){ mean_rec_length= stat.row_size; data_file_length= stat.fragment_memory; info->records= stat.row_count; @@ -448,27 +448,27 @@ void ha_ndbcluster::invalidate_dictionary_cache(bool global) NDBINDEX *unique_index = (NDBINDEX *) m_index[i].unique_index; NDB_INDEX_TYPE idx_type= m_index[i].type; - switch(idx_type) { - case(PRIMARY_KEY_ORDERED_INDEX): - case(ORDERED_INDEX): + switch (idx_type) { + case PRIMARY_KEY_ORDERED_INDEX: + case ORDERED_INDEX: if (global) dict->invalidateIndex(index->getName(), m_tabname); else dict->removeCachedIndex(index->getName(), m_tabname); break; - case(UNIQUE_ORDERED_INDEX): + case UNIQUE_ORDERED_INDEX: if (global) dict->invalidateIndex(index->getName(), m_tabname); else dict->removeCachedIndex(index->getName(), m_tabname); - case(UNIQUE_INDEX): + case UNIQUE_INDEX: if (global) dict->invalidateIndex(unique_index->getName(), m_tabname); else dict->removeCachedIndex(unique_index->getName(), m_tabname); break; - case(PRIMARY_KEY_INDEX): - case(UNDEFINED_INDEX): + case PRIMARY_KEY_INDEX: + case UNDEFINED_INDEX: break; } } @@ -515,8 +515,10 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans) if (m_rows_to_insert == 1) m_dupkey= table->s->primary_key; else + { // We are batching inserts, offending key is not available m_dupkey= (uint) -1; + } } DBUG_RETURN(res); } @@ -1385,7 +1387,7 @@ int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf) return res; } - if((res= define_read_attrs(buf, op))) + if ((res= define_read_attrs(buf, op))) DBUG_RETURN(res); if (execute_no_commit_ie(this,trans) != 0) @@ -1515,10 +1517,10 @@ int ha_ndbcluster::unique_index_read(const byte *key, ERR_RETURN(trans->getNdbError()); // Set secondary index key(s) - if((res= set_index_key(op, table->key_info + active_index, key))) + if ((res= set_index_key(op, table->key_info + active_index, key))) DBUG_RETURN(res); - if((res= define_read_attrs(buf, op))) + if ((res= define_read_attrs(buf, op))) DBUG_RETURN(res); if (execute_no_commit_ie(this,trans) != 0) @@ -1578,7 +1580,7 @@ inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor) { if (execute_commit(this,trans) != 0) DBUG_RETURN(-1); - if(trans->restart() != 0) + if (trans->restart() != 0) { DBUG_ASSERT(0); DBUG_RETURN(-1); @@ -1616,7 +1618,7 @@ inline int ha_ndbcluster::next_result(byte *buf) if (!m_active_cursor) DBUG_RETURN(HA_ERR_END_OF_FILE); - if((res= fetch_next(m_active_cursor)) == 0) + if ((res= fetch_next(m_active_cursor)) == 0) { DBUG_PRINT("info", ("One more record found")); @@ -1624,7 +1626,7 @@ inline int ha_ndbcluster::next_result(byte *buf) table->status= 0; DBUG_RETURN(0); } - else if(res == 1) + else if (res == 1) { // No more records table->status= STATUS_NOT_FOUND; @@ -1855,7 +1857,7 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key, DBUG_ASSERT(op->getSorted() == sorted); DBUG_ASSERT(op->getLockMode() == (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type)); - if(op->reset_bounds(m_force_send)) + if (op->reset_bounds(m_force_send)) DBUG_RETURN(ndb_err(m_active_trans)); } @@ -1901,7 +1903,7 @@ int ha_ndbcluster::full_table_scan(byte *buf) m_active_cursor= op; if (generate_scan_filter(m_cond_stack, op)) DBUG_RETURN(ndb_err(trans)); - if((res= define_read_attrs(buf, op))) + if ((res= define_read_attrs(buf, op))) DBUG_RETURN(res); if (execute_no_commit(this,trans) != 0) @@ -2039,7 +2041,7 @@ int ha_ndbcluster::write_row(byte *record) no_uncommitted_rows_execute_failure(); DBUG_RETURN(ndb_err(trans)); } - if(trans->restart() != 0) + if (trans->restart() != 0) { DBUG_ASSERT(0); DBUG_RETURN(-1); @@ -2418,7 +2420,7 @@ void ha_ndbcluster::print_results() field= table->field[f]; if (!(value= m_value[f]).ptr) { - my_snprintf(buf, sizeof(buf), "not read"); + strmov(buf, "not read"); goto print_value; } @@ -2428,7 +2430,7 @@ void ha_ndbcluster::print_results() { if (value.rec->isNULL()) { - my_snprintf(buf, sizeof(buf), "NULL"); + strmov(buf, "NULL"); goto print_value; } type.length(0); @@ -2442,10 +2444,8 @@ void ha_ndbcluster::print_results() NdbBlob *ndb_blob= value.blob; bool isNull= TRUE; ndb_blob->getNull(isNull); - if (isNull) { - my_snprintf(buf, sizeof(buf), "NULL"); - goto print_value; - } + if (isNull) + strmov(buf, "NULL"); } print_value: @@ -2485,7 +2485,7 @@ check_null_in_key(const KEY* key_info, const byte *key, uint key_len) for (; curr_part != end_part && key < end_ptr; curr_part++) { - if(curr_part->null_bit && *key) + if (curr_part->null_bit && *key) return 1; key += curr_part->store_length; @@ -2509,7 +2509,7 @@ int ha_ndbcluster::index_read(byte *buf, case PRIMARY_KEY_INDEX: if (find_flag == HA_READ_KEY_EXACT && key_info->key_length == key_len) { - if(m_active_cursor && (error= close_scan())) + if (m_active_cursor && (error= close_scan())) DBUG_RETURN(error); DBUG_RETURN(pk_read(key, key_len, buf)); } @@ -2523,7 +2523,7 @@ int ha_ndbcluster::index_read(byte *buf, if (find_flag == HA_READ_KEY_EXACT && key_info->key_length == key_len && !check_null_in_key(key_info, key, key_len)) { - if(m_active_cursor && (error= close_scan())) + if (m_active_cursor && (error= close_scan())) DBUG_RETURN(error); DBUG_RETURN(unique_index_read(key, key_len, buf)); } @@ -2635,7 +2635,7 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key, start_key->length == key_info->key_length && start_key->flag == HA_READ_KEY_EXACT) { - if(m_active_cursor && (error= close_scan())) + if (m_active_cursor && (error= close_scan())) DBUG_RETURN(error); error= pk_read(start_key->key, start_key->length, buf); DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error); @@ -2648,7 +2648,7 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key, start_key->flag == HA_READ_KEY_EXACT && !check_null_in_key(key_info, start_key->key, start_key->length)) { - if(m_active_cursor && (error= close_scan())) + if (m_active_cursor && (error= close_scan())) DBUG_RETURN(error); error= unique_index_read(start_key->key, start_key->length, buf); DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error); @@ -2695,7 +2695,7 @@ int ha_ndbcluster::rnd_init(bool scan) { if (!scan) DBUG_RETURN(1); - if(cursor->restart(m_force_send) != 0) + if (cursor->restart(m_force_send) != 0) { DBUG_ASSERT(0); DBUG_RETURN(-1); @@ -3465,7 +3465,7 @@ int ndbcluster_commit(THD *thd, bool all) } ndb->closeTransaction(trans); - if(all) + if (all) thd_ndb->all= NULL; else thd_ndb->stmt= NULL; @@ -3515,7 +3515,7 @@ int ndbcluster_rollback(THD *thd, bool all) } ndb->closeTransaction(trans); - if(all) + if (all) thd_ndb->all= NULL; else thd_ndb->stmt= NULL; @@ -3771,7 +3771,8 @@ static int create_ndb_column(NDBCOL &col, col.setType(NDBCOL::Char); col.setLength(field->pack_length()); break; - case MYSQL_TYPE_BIT: { + case MYSQL_TYPE_BIT: + { int no_of_bits= field->field_length*8 + ((Field_bit *) field)->bit_len; col.setType(NDBCOL::Bit); if (!no_of_bits) @@ -3906,7 +3907,7 @@ int ha_ndbcluster::create(const char *name, if ((my_errno= create_ndb_column(col, field, info))) DBUG_RETURN(my_errno); tab.addColumn(col); - if(col.getPrimaryKey()) + if (col.getPrimaryKey()) pk_length += (field->pack_length() + 3) / 4; } @@ -3939,7 +3940,7 @@ int ha_ndbcluster::create(const char *name, { NdbDictionary::Column * col= tab.getColumn(i); int size= pk_length + (col->getPartSize()+3)/4 + 7; - if(size > NDB_MAX_TUPLE_SIZE_IN_WORDS && + if (size > NDB_MAX_TUPLE_SIZE_IN_WORDS && (pk_length+7) < NDB_MAX_TUPLE_SIZE_IN_WORDS) { size= NDB_MAX_TUPLE_SIZE_IN_WORDS - pk_length - 7; @@ -4167,12 +4168,10 @@ ulonglong ha_ndbcluster::get_auto_increment() m_rows_to_insert+= m_autoincrement_prefetch; } cache_size= - (int) - (m_rows_to_insert - m_rows_inserted < m_autoincrement_prefetch) ? - m_rows_to_insert - m_rows_inserted - : (m_rows_to_insert > m_autoincrement_prefetch) ? - m_rows_to_insert - : m_autoincrement_prefetch; + (int) ((m_rows_to_insert - m_rows_inserted < m_autoincrement_prefetch) ? + m_rows_to_insert - m_rows_inserted : + ((m_rows_to_insert > m_autoincrement_prefetch) ? + m_rows_to_insert : m_autoincrement_prefetch)); auto_value= NDB_FAILED_AUTO_INCREMENT; uint retries= NDB_AUTO_INCREMENT_RETRIES; do { @@ -4776,7 +4775,7 @@ ndbcluster_init() g_ndb_cluster_connection->get_connected_port())); g_ndb_cluster_connection->wait_until_ready(10,3); } - else if(res == 1) + else if (res == 1) { if (g_ndb_cluster_connection->start_connect_thread(connect_callback)) { @@ -4824,7 +4823,7 @@ ndbcluster_init() DBUG_RETURN(&ndbcluster_hton); ndbcluster_init_error: - if(g_ndb) + if (g_ndb) delete g_ndb; g_ndb= NULL; if (g_ndb_cluster_connection) @@ -4853,7 +4852,7 @@ bool ndbcluster_end() (void) pthread_cond_signal(&COND_ndb_util_thread); (void) pthread_mutex_unlock(&LOCK_ndb_util_thread); - if(g_ndb) + if (g_ndb) delete g_ndb; g_ndb= NULL; if (g_ndb_cluster_connection) @@ -5103,7 +5102,7 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, } pthread_mutex_lock(&share->mutex); - if(share->commit_count_lock == lock) + if (share->commit_count_lock == lock) { DBUG_PRINT("info", ("Setting commit_count to %llu", stat.commit_count)); share->commit_count= stat.commit_count; @@ -5594,9 +5593,13 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, for (; multi_range_currstart_key.length == key_info->key_length && + multi_range_curr->start_key.flag == HA_READ_KEY_EXACT)) + goto range; + /* fall through */ case PRIMARY_KEY_INDEX: - pk: { multi_range_curr->range_flag |= UNIQUE_RANGE; if ((op= m_active_trans->getNdbOperation(tab)) && @@ -5610,8 +5613,14 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, break; } break; + case UNIQUE_ORDERED_INDEX: + if (!(multi_range_curr->start_key.length == key_info->key_length && + multi_range_curr->start_key.flag == HA_READ_KEY_EXACT && + !check_null_in_key(key_info, multi_range_curr->start_key.key, + multi_range_curr->start_key.length))) + goto range; + /* fall through */ case UNIQUE_INDEX: - sk: { multi_range_curr->range_flag |= UNIQUE_RANGE; if ((op= m_active_trans->getNdbIndexOperation(unique_idx, tab)) && @@ -5624,19 +5633,8 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, ERR_RETURN(op ? op->getNdbError() : m_active_trans->getNdbError()); break; } - case PRIMARY_KEY_ORDERED_INDEX: - if (multi_range_curr->start_key.length == key_info->key_length && - multi_range_curr->start_key.flag == HA_READ_KEY_EXACT) - goto pk; - goto range; - case UNIQUE_ORDERED_INDEX: - if (multi_range_curr->start_key.length == key_info->key_length && - multi_range_curr->start_key.flag == HA_READ_KEY_EXACT && - !check_null_in_key(key_info, multi_range_curr->start_key.key, - multi_range_curr->start_key.length)) - goto sk; - goto range; - case ORDERED_INDEX: { + case ORDERED_INDEX: + { range: multi_range_curr->range_flag &= ~(uint)UNIQUE_RANGE; if (scanOp == 0) @@ -5647,7 +5645,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, DBUG_ASSERT(scanOp->getSorted() == sorted); DBUG_ASSERT(scanOp->getLockMode() == (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type)); - if(scanOp->reset_bounds(m_force_send)) + if (scanOp->reset_bounds(m_force_send)) DBUG_RETURN(ndb_err(m_active_trans)); end_of_buffer -= reclength; @@ -5673,7 +5671,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, DBUG_RETURN(res); break; } - case(UNDEFINED_INDEX): + case UNDEFINED_INDEX: DBUG_ASSERT(FALSE); DBUG_RETURN(1); break; @@ -5782,7 +5780,7 @@ ha_ndbcluster::read_multi_range_next(KEY_MULTI_RANGE ** multi_range_found_p) DBUG_MULTI_RANGE(6); // First fetch from cursor DBUG_ASSERT(range_no == -1); - if((res= m_multi_cursor->nextResult(true))) + if ((res= m_multi_cursor->nextResult(true))) { goto close_scan; } @@ -5885,7 +5883,7 @@ ha_ndbcluster::update_table_comment( const char* comment)/* in: table comment defined by user */ { uint length= strlen(comment); - if(length > 64000 - 3) + if (length > 64000 - 3) { return((char*)comment); /* string too long */ } @@ -5912,9 +5910,9 @@ ha_ndbcluster::update_table_comment( return (char*)comment; } - snprintf(str,fmt_len_plus_extra,fmt,comment, - length > 0 ? " ":"", - tab->getReplicaCount()); + my_snprintf(str,fmt_len_plus_extra,fmt,comment, + length > 0 ? " ":"", + tab->getReplicaCount()); return str; } @@ -6013,7 +6011,7 @@ extern "C" pthread_handler_decl(ndb_util_thread_func, lock= share->commit_count_lock; pthread_mutex_unlock(&share->mutex); - if(ndb_get_table_statistics(ndb, tabname, &stat) == 0) + if (ndb_get_table_statistics(ndb, tabname, &stat) == 0) { DBUG_PRINT("ndb_util_thread", ("Table: %s, commit_count: %llu, rows: %llu", @@ -6048,7 +6046,7 @@ extern "C" pthread_handler_decl(ndb_util_thread_func, abstime.tv_sec= tick_time.tv_sec; abstime.tv_nsec= tick_time.tv_usec * 1000; - if(msecs >= 1000){ + if (msecs >= 1000){ secs= msecs / 1000; msecs= msecs % 1000; } @@ -6157,17 +6155,18 @@ void ndb_serialize_cond(const Item *item, void *arg) { DBUG_PRINT("info", ("Skiping argument %d", context->skip)); context->skip--; - switch(item->type()) { - case (Item::FUNC_ITEM): { + switch (item->type()) { + case Item::FUNC_ITEM: + { Item_func *func_item= (Item_func *) item; context->skip+= func_item->argument_count(); break; } - case(Item::INT_ITEM): - case(Item::REAL_ITEM): - case(Item::STRING_ITEM): - case(Item::VARBIN_ITEM): - case(Item::DECIMAL_ITEM): + case Item::INT_ITEM: + case Item::REAL_ITEM: + case Item::STRING_ITEM: + case Item::VARBIN_ITEM: + case Item::DECIMAL_ITEM: break; default: context->supported= FALSE; @@ -6186,8 +6185,8 @@ void ndb_serialize_cond(const Item *item, void *arg) (func_item= rewrite_context->func_item) && rewrite_context->count++ == 0) { - switch(func_item->functype()) { - case(Item_func::BETWEEN): + switch (func_item->functype()) { + case Item_func::BETWEEN: /* Rewrite | BETWEEN | AND | @@ -6197,7 +6196,8 @@ void ndb_serialize_cond(const Item *item, void *arg) BEGIN(AND) GT(|, |), LT(|, |), END() */ - case(Item_func::IN_FUNC): { + case Item_func::IN_FUNC: + { /* Rewrite | IN(|, |,..) to | = | OR @@ -6262,17 +6262,18 @@ void ndb_serialize_cond(const Item *item, void *arg) { Ndb_rewrite_context *rewrite_context= context->rewrite_stack; const Item_func *func_item= rewrite_context->func_item; - switch(func_item->functype()) { - case(Item_func::BETWEEN): { - /* - Rewrite - | BETWEEN | AND | - to | > | AND - | < | - or actually in prefix format - BEGIN(AND) GT(|, |), - LT(|, |), END() - */ + switch (func_item->functype()) { + case Item_func::BETWEEN: + { + /* + Rewrite + | BETWEEN | AND | + to | > | AND + | < | + or actually in prefix format + BEGIN(AND) GT(|, |), + LT(|, |), END() + */ if (rewrite_context->count == 2) { // Lower limit of BETWEEN @@ -6294,7 +6295,8 @@ void ndb_serialize_cond(const Item *item, void *arg) } break; } - case(Item_func::IN_FUNC): { + case Item_func::IN_FUNC: + { /* Rewrite | IN(|, |,..) to | = | OR @@ -6343,8 +6345,10 @@ void ndb_serialize_cond(const Item *item, void *arg) curr_cond->ndb_item= new Ndb_item(NDB_END_COND); } else - switch(item->type()) { - case(Item::FIELD_ITEM): { + { + switch (item->type()) { + case Item::FIELD_ITEM: + { Item_field *field_item= (Item_field *) item; Field *field= field_item->field; enum_field_types type= field->type(); @@ -6390,23 +6394,23 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect(Item::INT_ITEM); } else - switch(field->result_type()) { - case(STRING_RESULT): + switch (field->result_type()) { + case STRING_RESULT: // Expect char string or binary string context->expect_only(Item::STRING_ITEM); context->expect(Item::VARBIN_ITEM); context->expect_collation(field_item->collation.collation); break; - case(REAL_RESULT): + case REAL_RESULT: context->expect_only(Item::REAL_ITEM); context->expect(Item::DECIMAL_ITEM); context->expect(Item::INT_ITEM); break; - case(INT_RESULT): + case INT_RESULT: context->expect_only(Item::INT_ITEM); context->expect(Item::VARBIN_ITEM); break; - case(DECIMAL_RESULT): + case DECIMAL_RESULT: context->expect_only(Item::DECIMAL_ITEM); context->expect(Item::REAL_ITEM); context->expect(Item::INT_ITEM); @@ -6451,7 +6455,8 @@ void ndb_serialize_cond(const Item *item, void *arg) } break; } - case(Item::FUNC_ITEM): { + case Item::FUNC_ITEM: + { Item_func *func_item= (Item_func *) item; // Check that we expect a function or functional expression here if (context->expecting(Item::FUNC_ITEM) || @@ -6464,8 +6469,9 @@ void ndb_serialize_cond(const Item *item, void *arg) break; } - switch(func_item->functype()) { - case(Item_func::EQ_FUNC): { + switch (func_item->functype()) { + case Item_func::EQ_FUNC: + { DBUG_PRINT("info", ("EQ_FUNC")); curr_cond->ndb_item= new Ndb_item(func_item->functype(), func_item); @@ -6481,7 +6487,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect_field_result(DECIMAL_RESULT); break; } - case(Item_func::NE_FUNC): { + case Item_func::NE_FUNC: + { DBUG_PRINT("info", ("NE_FUNC")); curr_cond->ndb_item= new Ndb_item(func_item->functype(), func_item); @@ -6497,7 +6504,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect_field_result(DECIMAL_RESULT); break; } - case(Item_func::LT_FUNC): { + case Item_func::LT_FUNC: + { DBUG_PRINT("info", ("LT_FUNC")); curr_cond->ndb_item= new Ndb_item(func_item->functype(), func_item); @@ -6513,7 +6521,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect_field_result(DECIMAL_RESULT); break; } - case(Item_func::LE_FUNC): { + case Item_func::LE_FUNC: + { DBUG_PRINT("info", ("LE_FUNC")); curr_cond->ndb_item= new Ndb_item(func_item->functype(), func_item); @@ -6529,7 +6538,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect_field_result(DECIMAL_RESULT); break; } - case(Item_func::GE_FUNC): { + case Item_func::GE_FUNC: + { DBUG_PRINT("info", ("GE_FUNC")); curr_cond->ndb_item= new Ndb_item(func_item->functype(), func_item); @@ -6545,7 +6555,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect_field_result(DECIMAL_RESULT); break; } - case(Item_func::GT_FUNC): { + case Item_func::GT_FUNC: + { DBUG_PRINT("info", ("GT_FUNC")); curr_cond->ndb_item= new Ndb_item(func_item->functype(), func_item); @@ -6561,7 +6572,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect_field_result(DECIMAL_RESULT); break; } - case(Item_func::LIKE_FUNC): { + case Item_func::LIKE_FUNC: + { DBUG_PRINT("info", ("LIKE_FUNC")); curr_cond->ndb_item= new Ndb_item(func_item->functype(), func_item); @@ -6571,7 +6583,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect(Item::FUNC_ITEM); break; } - case(Item_func::NOTLIKE_FUNC): { + case Item_func::NOTLIKE_FUNC: + { DBUG_PRINT("info", ("NOTLIKE_FUNC")); curr_cond->ndb_item= new Ndb_item(func_item->functype(), func_item); @@ -6581,7 +6594,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect(Item::FUNC_ITEM); break; } - case(Item_func::ISNULL_FUNC): { + case Item_func::ISNULL_FUNC: + { DBUG_PRINT("info", ("ISNULL_FUNC")); curr_cond->ndb_item= new Ndb_item(func_item->functype(), func_item); @@ -6592,7 +6606,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect_field_result(DECIMAL_RESULT); break; } - case(Item_func::ISNOTNULL_FUNC): { + case Item_func::ISNOTNULL_FUNC: + { DBUG_PRINT("info", ("ISNOTNULL_FUNC")); curr_cond->ndb_item= new Ndb_item(func_item->functype(), func_item); @@ -6603,7 +6618,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect_field_result(DECIMAL_RESULT); break; } - case(Item_func::NOT_FUNC): { + case Item_func::NOT_FUNC: + { DBUG_PRINT("info", ("NOT_FUNC")); curr_cond->ndb_item= new Ndb_item(func_item->functype(), func_item); @@ -6611,7 +6627,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect(Item::COND_ITEM); break; } - case(Item_func::BETWEEN) : { + case Item_func::BETWEEN: + { DBUG_PRINT("info", ("BETWEEN, rewriting using AND")); Ndb_rewrite_context *rewrite_context= new Ndb_rewrite_context(func_item); @@ -6627,7 +6644,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect(Item::FUNC_ITEM); break; } - case(Item_func::IN_FUNC) : { + case Item_func::IN_FUNC: + { DBUG_PRINT("info", ("IN_FUNC, rewriting using OR")); Ndb_rewrite_context *rewrite_context= new Ndb_rewrite_context(func_item); @@ -6643,13 +6661,16 @@ void ndb_serialize_cond(const Item *item, void *arg) context->expect(Item::FUNC_ITEM); break; } - case(Item_func::UNKNOWN_FUNC): { + case Item_func::UNKNOWN_FUNC: + { DBUG_PRINT("info", ("UNKNOWN_FUNC %s", func_item->const_item()?"const":"")); DBUG_PRINT("info", ("result type %d", func_item->result_type())); if (func_item->const_item()) - switch(func_item->result_type()) { - case(STRING_RESULT): { + { + switch (func_item->result_type()) { + case STRING_RESULT: + { NDB_ITEM_QUALIFICATION q; q.value_type= Item::STRING_ITEM; curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); @@ -6678,7 +6699,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->skip= func_item->argument_count(); break; } - case(REAL_RESULT): { + case REAL_RESULT: + { NDB_ITEM_QUALIFICATION q; q.value_type= Item::REAL_ITEM; curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); @@ -6700,7 +6722,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->skip= func_item->argument_count(); break; } - case(INT_RESULT): { + case INT_RESULT: + { NDB_ITEM_QUALIFICATION q; q.value_type= Item::INT_ITEM; curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); @@ -6722,7 +6745,8 @@ void ndb_serialize_cond(const Item *item, void *arg) context->skip= func_item->argument_count(); break; } - case(DECIMAL_RESULT): { + case DECIMAL_RESULT: + { NDB_ITEM_QUALIFICATION q; q.value_type= Item::DECIMAL_ITEM; curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); @@ -6746,12 +6770,14 @@ void ndb_serialize_cond(const Item *item, void *arg) default: break; } + } else // Function does not return constant expression context->supported= FALSE; break; } - default: { + default: + { DBUG_PRINT("info", ("Found func_item of type %d", func_item->functype())); context->supported= FALSE; @@ -6759,7 +6785,7 @@ void ndb_serialize_cond(const Item *item, void *arg) } break; } - case(Item::STRING_ITEM): + case Item::STRING_ITEM: DBUG_PRINT("info", ("STRING_ITEM")); if (context->expecting(Item::STRING_ITEM)) { @@ -6798,7 +6824,7 @@ void ndb_serialize_cond(const Item *item, void *arg) else context->supported= FALSE; break; - case(Item::INT_ITEM): + case Item::INT_ITEM: DBUG_PRINT("info", ("INT_ITEM")); if (context->expecting(Item::INT_ITEM)) { @@ -6825,7 +6851,7 @@ void ndb_serialize_cond(const Item *item, void *arg) else context->supported= FALSE; break; - case(Item::REAL_ITEM): + case Item::REAL_ITEM: DBUG_PRINT("info", ("REAL_ITEM %s")); if (context->expecting(Item::REAL_ITEM)) { @@ -6850,7 +6876,7 @@ void ndb_serialize_cond(const Item *item, void *arg) else context->supported= FALSE; break; - case(Item::VARBIN_ITEM): + case Item::VARBIN_ITEM: DBUG_PRINT("info", ("VARBIN_ITEM")); if (context->expecting(Item::VARBIN_ITEM)) { @@ -6873,7 +6899,7 @@ void ndb_serialize_cond(const Item *item, void *arg) else context->supported= FALSE; break; - case(Item::DECIMAL_ITEM): + case Item::DECIMAL_ITEM: DBUG_PRINT("info", ("DECIMAL_ITEM %s")); if (context->expecting(Item::DECIMAL_ITEM)) { @@ -6899,17 +6925,19 @@ void ndb_serialize_cond(const Item *item, void *arg) else context->supported= FALSE; break; - case(Item::COND_ITEM): { + case Item::COND_ITEM: + { Item_cond *cond_item= (Item_cond *) item; if (context->expecting(Item::COND_ITEM)) - switch(cond_item->functype()) { - case(Item_func::COND_AND_FUNC): + { + switch (cond_item->functype()) { + case Item_func::COND_AND_FUNC: DBUG_PRINT("info", ("COND_AND_FUNC")); curr_cond->ndb_item= new Ndb_item(cond_item->functype(), cond_item); break; - case(Item_func::COND_OR_FUNC): + case Item_func::COND_OR_FUNC: DBUG_PRINT("info", ("COND_OR_FUNC")); curr_cond->ndb_item= new Ndb_item(cond_item->functype(), cond_item); @@ -6919,17 +6947,21 @@ void ndb_serialize_cond(const Item *item, void *arg) context->supported= FALSE; break; } + } else - // Did not expect condition + { + /* Did not expect condition */ context->supported= FALSE; + } break; } - default: { + default: + { DBUG_PRINT("info", ("Found item of type %d", item->type())); context->supported= FALSE; } } - + } if (context->supported && context->rewrite_stack) { Ndb_rewrite_context *rewrite_context= context->rewrite_stack; @@ -6973,18 +7005,19 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, bool negated) { DBUG_ENTER("build_scan_filter_predicate"); - switch(cond->ndb_item->type) { - case(NDB_FUNCTION): { + switch (cond->ndb_item->type) { + case NDB_FUNCTION: + { if (!cond->next) break; Ndb_item *a= cond->next->ndb_item; Ndb_item *b, *field, *value= NULL; - switch(cond->ndb_item->argument_count()) { - case(1): + switch (cond->ndb_item->argument_count()) { + case 1: field= (a->type == NDB_FIELD)? a : NULL; break; - case(2): + case 2: if (!cond->next->next) break; b= cond->next->next->ndb_item; @@ -7000,11 +7033,11 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, default: break; } - switch((negated) ? - Ndb_item::negate(cond->ndb_item->qualification.function_type) - : cond->ndb_item->qualification.function_type) + switch ((negated) ? + Ndb_item::negate(cond->ndb_item->qualification.function_type) + : cond->ndb_item->qualification.function_type) { + case Item_func::EQ_FUNC: { - case(Item_func::EQ_FUNC): { if (!value || !field) break; // Save value in right format for the field type value->save_in_field(field); @@ -7017,7 +7050,8 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, cond= cond->next->next->next; DBUG_RETURN(0); } - case(Item_func::NE_FUNC): { + case Item_func::NE_FUNC: + { if (!value || !field) break; // Save value in right format for the field type value->save_in_field(field); @@ -7030,7 +7064,8 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, cond= cond->next->next->next; DBUG_RETURN(0); } - case(Item_func::LT_FUNC): { + case Item_func::LT_FUNC: + { if (!value || !field) break; // Save value in right format for the field type value->save_in_field(field); @@ -7055,7 +7090,8 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, cond= cond->next->next->next; DBUG_RETURN(0); } - case(Item_func::LE_FUNC): { + case Item_func::LE_FUNC: + { if (!value || !field) break; // Save value in right format for the field type value->save_in_field(field); @@ -7080,7 +7116,8 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, cond= cond->next->next->next; DBUG_RETURN(0); } - case(Item_func::GE_FUNC): { + case Item_func::GE_FUNC: + { if (!value || !field) break; // Save value in right format for the field type value->save_in_field(field); @@ -7105,7 +7142,8 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, cond= cond->next->next->next; DBUG_RETURN(0); } - case(Item_func::GT_FUNC): { + case Item_func::GT_FUNC: + { if (!value || !field) break; // Save value in right format for the field type value->save_in_field(field); @@ -7130,7 +7168,8 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, cond= cond->next->next->next; DBUG_RETURN(0); } - case(Item_func::LIKE_FUNC): { + case Item_func::LIKE_FUNC: + { if (!value || !field) break; if ((value->qualification.value_type != Item::STRING_ITEM) && (value->qualification.value_type != Item::VARBIN_ITEM)) @@ -7148,7 +7187,8 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, cond= cond->next->next->next; DBUG_RETURN(0); } - case(Item_func::NOTLIKE_FUNC): { + case Item_func::NOTLIKE_FUNC: + { if (!value || !field) break; if ((value->qualification.value_type != Item::STRING_ITEM) && (value->qualification.value_type != Item::VARBIN_ITEM)) @@ -7166,7 +7206,7 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, cond= cond->next->next->next; DBUG_RETURN(0); } - case(Item_func::ISNULL_FUNC): + case Item_func::ISNULL_FUNC: if (!field) break; DBUG_PRINT("info", ("Generating ISNULL filter")); @@ -7174,7 +7214,8 @@ ha_ndbcluster::build_scan_filter_predicate(Ndb_cond * &cond, DBUG_RETURN(1); cond= cond->next->next; DBUG_RETURN(0); - case(Item_func::ISNOTNULL_FUNC): { + case Item_func::ISNOTNULL_FUNC: + { if (!field) break; DBUG_PRINT("info", ("Generating ISNOTNULL filter")); @@ -7200,15 +7241,18 @@ ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter) { uint level=0; bool negated= FALSE; - DBUG_ENTER("build_scan_filter_group"); + do { - if (!cond) DBUG_RETURN(1); - switch(cond->ndb_item->type) { - case(NDB_FUNCTION): - switch(cond->ndb_item->qualification.function_type) { - case(Item_func::COND_AND_FUNC): { + if (!cond) + DBUG_RETURN(1); + switch (cond->ndb_item->type) { + case NDB_FUNCTION: + { + switch (cond->ndb_item->qualification.function_type) { + case Item_func::COND_AND_FUNC: + { level++; DBUG_PRINT("info", ("Generating %s group %u", (negated)?"NAND":"AND", level)); @@ -7219,7 +7263,8 @@ ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter) cond= cond->next; break; } - case(Item_func::COND_OR_FUNC): { + case Item_func::COND_OR_FUNC: + { level++; DBUG_PRINT("info", ("Generating %s group %u", (negated)?"NOR":"OR", level)); @@ -7230,11 +7275,11 @@ ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter) cond= cond->next; break; } - case(Item_func::NOT_FUNC): { + case Item_func::NOT_FUNC: + { DBUG_PRINT("info", ("Generating negated query")); cond= cond->next; negated= TRUE; - break; } default: @@ -7244,7 +7289,8 @@ ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter) break; } break; - case(NDB_END_COND): + } + case NDB_END_COND: DBUG_PRINT("info", ("End of group %u", level)); level--; if (cond) cond= cond->next; @@ -7253,7 +7299,8 @@ ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter) if (!negated) break; // else fall through (NOT END is an illegal condition) - default: { + default: + { DBUG_PRINT("info", ("Illegal scan filter")); } } @@ -7268,11 +7315,11 @@ ha_ndbcluster::build_scan_filter(Ndb_cond * &cond, NdbScanFilter *filter) bool simple_cond= TRUE; DBUG_ENTER("build_scan_filter"); - switch(cond->ndb_item->type) { - case(NDB_FUNCTION): - switch(cond->ndb_item->qualification.function_type) { - case(Item_func::COND_AND_FUNC): - case(Item_func::COND_OR_FUNC): + switch (cond->ndb_item->type) { + case NDB_FUNCTION: + switch (cond->ndb_item->qualification.function_type) { + case Item_func::COND_AND_FUNC: + case Item_func::COND_OR_FUNC: simple_cond= FALSE; break; default: diff --git a/sql/handler.cc b/sql/handler.cc index 46a80770024..4480dbf3777 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1954,7 +1954,7 @@ int ha_create_table_from_engine(THD* thd, bzero((char*) &create_info,sizeof(create_info)); - if(error= ha_discover(thd, db, name, &frmblob, &frmlen)) + if ((error= ha_discover(thd, db, name, &frmblob, &frmlen))) { // Table could not be discovered and thus not created DBUG_RETURN(error); diff --git a/sql/item.cc b/sql/item.cc index d3888cef9d5..deab704fa24 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4366,18 +4366,16 @@ my_decimal *Item_ref::val_decimal(my_decimal *decimal_value) int Item_ref::save_in_field(Field *to, bool no_conversions) { int res; - if(result_field){ + if (result_field) + { if (result_field->is_null()) { null_value= 1; return set_field_to_null_with_conversions(to, no_conversions); } - else - { - to->set_notnull(); - field_conv(to, result_field); - null_value= 0; - } + to->set_notnull(); + field_conv(to, result_field); + null_value= 0; return 0; } res= (*ref)->save_in_field(to, no_conversions); @@ -5153,8 +5151,7 @@ enum_field_types Item_type_holder::get_real_type(Item *item) acceptable information for client in send_field, so we make field type from expression type. */ - switch (item->result_type()) - { + switch (item->result_type()) { case STRING_RESULT: return MYSQL_TYPE_VAR_STRING; case INT_RESULT: diff --git a/sql/item.h b/sql/item.h index c8180b4932a..bd843add4ef 100644 --- a/sql/item.h +++ b/sql/item.h @@ -593,7 +593,7 @@ public: virtual bool set_flags_processor(byte *args) { this->item_flags|= *((uint8*)args); - return false; + return FALSE; } virtual bool is_splocal() { return 0; } /* Needed for error checking */ diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 58a7f3316d7..a3be5ec6cd1 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -275,7 +275,7 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) owner= item; func= comparator_matrix[type] [test(owner->functype() == Item_func::EQUAL_FUNC)]; - switch(type) { + switch (type) { case ROW_RESULT: { uint n= (*a)->cols(); @@ -1581,6 +1581,21 @@ my_decimal *Item_func_case::val_decimal(my_decimal *decimal_value) } +bool Item_func_case::fix_fields(THD *thd, struct st_table_list *tables, + Item **ref) +{ + /* + buff should match stack usage from + Item_func_case::val_int() -> Item_func_case::find_item() + */ + char buff[MAX_FIELD_WIDTH*2+sizeof(String)*2+sizeof(String*)*2+sizeof(double)*2+sizeof(longlong)*2]; + if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) + return TRUE; // Fatal error flag is set! + return Item_func::fix_fields(thd, tables, ref); +} + + + void Item_func_case::fix_length_and_dec() { Item **agg; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 7a22e76b217..33c9e518860 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -566,6 +566,7 @@ public: longlong val_int(); String *val_str(String *); my_decimal *val_decimal(my_decimal *); + bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref); void fix_length_and_dec(); uint decimal_precision() const; table_map not_null_tables() const { return 0; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 1dbf28b67cb..c347cd2913b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1882,8 +1882,7 @@ void Item_func_round::fix_length_and_dec() return; } - switch (args[0]->result_type()) - { + switch (args[0]->result_type()) { case REAL_RESULT: case STRING_RESULT: hybrid_type= REAL_RESULT; @@ -1891,16 +1890,17 @@ void Item_func_round::fix_length_and_dec() max_length= float_length(decimals); break; case INT_RESULT: - if ((decimals_to_set==0) && + if (!decimals_to_set && (truncate || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))) { + int length_can_increase= test(!truncate && (args[1]->val_int() < 0)); + max_length= args[0]->max_length + length_can_increase; /* Here we can keep INT_RESULT */ hybrid_type= INT_RESULT; - int length_can_increase= !truncate && (args[1]->val_int() < 0); - max_length= args[0]->max_length + length_can_increase; decimals= 0; break; } + /* fall through */ case DECIMAL_RESULT: { hybrid_type= DECIMAL_RESULT; @@ -4451,7 +4451,8 @@ err: bool Item_func_match::eq(const Item *item, bool binary_cmp) const { - if (item->type() != FUNC_ITEM || ((Item_func*)item)->functype() != FT_FUNC || + if (item->type() != FUNC_ITEM || + ((Item_func*)item)->functype() != FT_FUNC || flags != ((Item_func_match*)item)->flags) return 0; @@ -4809,7 +4810,7 @@ Item_func_sp::execute(Item **itp) ulong old_client_capabilites; int res= -1; bool save_in_sub_stmt= thd->transaction.in_sub_stmt; - my_bool nsok; + my_bool save_no_send_ok; #ifndef NO_EMBEDDED_ACCESS_CHECKS st_sp_security_context save_ctx; #endif @@ -4824,7 +4825,7 @@ Item_func_sp::execute(Item **itp) thd->client_capabilities &= ~CLIENT_MULTI_RESULTS; #ifndef EMBEDDED_LIBRARY - nsok= thd->net.no_send_ok; + save_no_send_ok= thd->net.no_send_ok; thd->net.no_send_ok= TRUE; #endif @@ -4836,7 +4837,7 @@ Item_func_sp::execute(Item **itp) if (save_ctx.changed && check_routine_access(thd, EXECUTE_ACL, m_sp->m_db.str, m_sp->m_name.str, 0, 0)) - goto error_check; + goto error_check_ctx; #endif /* Like for SPs, we don't binlog the substatements. If the statement which @@ -4859,8 +4860,8 @@ Item_func_sp::execute(Item **itp) ER_FAILED_ROUTINE_BREAK_BINLOG, ER(ER_FAILED_ROUTINE_BREAK_BINLOG)); -error_check_ctx: #ifndef NO_EMBEDDED_ACCESS_CHECKS +error_check_ctx: sp_restore_security_context(thd, m_sp, &save_ctx); #endif @@ -4868,7 +4869,7 @@ error_check_ctx: error_check: #ifndef EMBEDDED_LIBRARY - thd->net.no_send_ok= nsok; + thd->net.no_send_ok= save_no_send_ok; #endif thd->client_capabilities|= old_client_capabilites & CLIENT_MULTI_RESULTS; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 2dbc8fdac96..915668aa7b1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2991,9 +2991,7 @@ int win_main(int argc, char **argv) int main(int argc, char **argv) #endif { - DEBUGGER_OFF; - MY_INIT(argv[0]); // init my_sys library & pthreads #ifdef _CUSTOMSTARTUPCONFIG_ @@ -3005,14 +3003,15 @@ int main(int argc, char **argv) #endif #ifdef __WIN__ -/* Before performing any socket operation (like retrieving hostname */ -/* in init_common_variables we have to call WSAStartup */ - if (!opt_disable_networking) + /* + Before performing any socket operation (like retrieving hostname + in init_common_variables we have to call WSAStartup + */ { WSADATA WsaData; if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData)) { - /* errors are not read yet, so we use test here */ + /* errors are not read yet, so we use english text here */ my_message(ER_WSAS_FAILED, "WSAStartup Failed", MYF(0)); unireg_abort(1); } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 05028c4e2a5..65db1a290f6 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3528,15 +3528,12 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) { /* Optimize NOT BETWEEN and NOT IN */ Item *arg= cond_func->arguments()[0]; - if (arg->type() == Item::FUNC_ITEM) - { - cond_func= (Item_func*) arg; - if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE) - DBUG_RETURN(0); - inv= TRUE; - } - else + if (arg->type() != Item::FUNC_ITEM) DBUG_RETURN(0); + cond_func= (Item_func*) arg; + if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE) + DBUG_RETURN(0); + inv= TRUE; } else if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE) DBUG_RETURN(0); @@ -8153,7 +8150,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next() (have_max && have_min && (max_res == 0))); } /* - If this is a just a GROUP BY or DISTINCT without MIN or MAX and there + If this is just a GROUP BY or DISTINCT without MIN or MAX and there are equality predicates for the key parts after the group, find the first sub-group with the extended prefix. */ diff --git a/sql/sql_class.h b/sql/sql_class.h index 1f232b9ca21..5642fa0d6af 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -653,6 +653,14 @@ typedef struct system_status_var void free_tmp_table(THD *thd, TABLE *entry); +/* The following macro is to make init of Query_arena simpler */ +#ifndef DBUG_OFF +#define INIT_ARENA_DBUG_INFO is_backup_arena= 0 +#else +#define INIT_ARENA_DBUG_INFO +#endif + + class Query_arena { public: @@ -664,9 +672,6 @@ public: MEM_ROOT *mem_root; // Pointer to current memroot #ifndef DBUG_OFF bool is_backup_arena; /* True if this arena is used for backup. */ -#define INIT_ARENA_DBUG_INFO is_backup_arena= 0 -#else -#define INIT_ARENA_DBUG_INFO #endif enum enum_state { @@ -691,7 +696,6 @@ public: */ Query_arena() { INIT_ARENA_DBUG_INFO; } -#undef INIT_ARENA_DBUG_INFO virtual Type type() const; virtual ~Query_arena() {}; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d6a719e65f9..6b65f24e289 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2351,10 +2351,6 @@ mysql_execute_command(THD *thd) } #endif /* !HAVE_REPLICATION */ - - - - /* When option readonly is set deny operations which change tables. Except for the replication thread and the 'super' users. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 13c5c7cd716..a31e4203a93 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7978,9 +7978,11 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, convert_blob_length); } case Item::REF_ITEM: - if ( item->real_item()->type() == Item::FIELD_ITEM) + { + Item *tmp_item; + if ((tmp_item= item->real_item())->type() == Item::FIELD_ITEM) { - Item_field *field= (Item_field*) *((Item_ref*)item)->ref; + Item_field *field= (Item_field*) tmp_item; Field *new_field= create_tmp_field_from_field(thd, (*from_field= field->field), item->name, table, @@ -7990,6 +7992,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, item->set_result_field(new_field); return new_field; } + } case Item::FUNC_ITEM: case Item::COND_ITEM: case Item::FIELD_AVG_ITEM: @@ -11791,14 +11794,13 @@ cp_buffer_from_ref(THD *thd, TABLE_REF *ref) SYNOPSIS find_order_in_list() - thd [in] Pointer to current thread structure - ref_pointer_array [in/out] All select, group and order by fields - tables [in] List of tables to search in (usually FROM clause) - order [in] Column reference to be resolved - fields [in] List of fields to search in (usually SELECT list) - all_fields [in/out] All select, group and order by fields - is_group_field [in] True if order is a GROUP field, false if - ORDER by field + thd Pointer to current thread structure + ref_pointer_array All select, group and order by fields + tables List of tables to search in (usually FROM clause) + order Column reference to be resolved + fields List of fields to search in (usually SELECT list) + all_fields All select, group and order by fields + is_group_field True if order is a GROUP field, false if ORDER by field DESCRIPTION Given a column reference (represented by 'order') from a GROUP BY or ORDER @@ -11815,6 +11817,8 @@ cp_buffer_from_ref(THD *thd, TABLE_REF *ref) RETURN FALSE if OK TRUE if error occurred + + ref_pointer_array and all_fields are updated */ static bool @@ -11866,20 +11870,18 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, /* Lookup the current GROUP field in the FROM clause. */ order_item_type= order_item->type(); + from_field= (Field*) not_found_field; if (is_group_field && order_item_type == Item::FIELD_ITEM || order_item_type == Item::REF_ITEM) { from_field= find_field_in_tables(thd, (Item_ident*) order_item, tables, &view_ref, IGNORE_ERRORS, TRUE); - if(!from_field) - from_field= (Field*) not_found_field; + if (!from_field) + from_field= (Field*) not_found_field; } - else - from_field= (Field*) not_found_field; if (from_field == not_found_field || - from_field && (from_field != view_ref_found ? /* it is field of base table => check that fields are same */ ((*select_item)->type() == Item::FIELD_ITEM && @@ -11892,37 +11894,40 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, view_ref->type() == Item::REF_ITEM && ((Item_ref *) (*select_item))->ref == ((Item_ref *) view_ref)->ref))) - /* - If there is no such field in the FROM clause, or it is the same field as - the one found in the SELECT clause, then use the Item created for the - SELECT field. As a result if there was a derived field that 'shadowed' - a table field with the same name, the table field will be chosen over - the derived field. - */ { + /* + If there is no such field in the FROM clause, or it is the same field + as the one found in the SELECT clause, then use the Item created for + the SELECT field. As a result if there was a derived field that + 'shadowed' a table field with the same name, the table field will be + chosen over the derived field. + */ order->item= ref_pointer_array + counter; order->in_field_list=1; return FALSE; } else + { /* - There is a field with the same name in the FROM clause. This is the field - that will be chosen. In this case we issue a warning so the user knows - that the field from the FROM clause overshadows the column reference from - the SELECT list. + There is a field with the same name in the FROM clause. This + is the field that will be chosen. In this case we issue a + warning so the user knows that the field from the FROM clause + overshadows the column reference from the SELECT list. */ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR, ER(ER_NON_UNIQ_ERROR), from_field->field_name, current_thd->where); + } } order->in_field_list=0; /* - The call to order_item->fix_fields() means that here we resolve 'order_item' - to a column from a table in the list 'tables', or to a column in some outer - query. Exactly because of the second case we come to this point even if - (select_item == not_found_item), inspite of that fix_fields() calls - find_item_in_list() one more time. + The call to order_item->fix_fields() means that here we resolve + 'order_item' to a column from a table in the list 'tables', or to + a column in some outer query. Exactly because of the second case + we come to this point even if (select_item == not_found_item), + inspite of that fix_fields() calls find_item_in_list() one more + time. We check order_item->fixed because Item_func_group_concat can put arguments for which fix_fields already was called. diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 87b67a5127a..bf657ce5396 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -646,14 +646,14 @@ bool st_select_lex::cleanup() if (join) { - error|= join->destroy(); + error= join->destroy(); delete join; join= 0; } for (SELECT_LEX_UNIT *lex_unit= first_inner_unit(); lex_unit ; lex_unit= lex_unit->next_unit()) { - error|= lex_unit->cleanup(); + error= (bool) ((uint) error | (uint) lex_unit->cleanup()); } DBUG_RETURN(error); } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 0b351407c13..25610f8749b 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -58,13 +58,13 @@ static void make_unique_view_field_name(Item *target, char *name= (target->orig_name ? target->orig_name : target->name); - uint name_len; - uint attempt= 0; + uint name_len, attempt; char buff[NAME_LEN+1]; - for (;; attempt++) + List_iterator_fast itc(item_list); + + for (attempt= 0;; attempt++) { Item *check; - List_iterator_fast itc(item_list); bool ok= TRUE; if (attempt) @@ -84,6 +84,7 @@ static void make_unique_view_field_name(Item *target, } while (check != last_element); if (ok) break; + itc.rewind(); } target->orig_name= target->name; @@ -305,13 +306,14 @@ bool mysql_create_view(THD *thd, { Item *item; List_iterator_fast it(select_lex->item_list); + List_iterator_fast itc(select_lex->item_list); while ((item= it++)) { Item *check; - List_iterator_fast itc(select_lex->item_list); /* treat underlying fields like set by user names */ if (item->real_item()->type() == Item::FIELD_ITEM) item->is_autogenerated_name= FALSE; + itc.rewind(); while ((check= itc++) && check != item) { if (my_strcasecmp(system_charset_info, item->name, check->name) == 0) @@ -822,6 +824,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) old_lex->can_use_merged()) && !old_lex->can_not_use_merged()) { + List_iterator_fast ti(view_select->top_join_list); /* lex should contain at least one table */ DBUG_ASSERT(view_tables != 0); @@ -852,13 +855,11 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) nested_join->join_list= view_select->top_join_list; /* re-nest tables of VIEW */ + ti.rewind(); + while ((tbl= ti++)) { - List_iterator_fast ti(nested_join->join_list); - while ((tbl= ti++)) - { - tbl->join_list= &nested_join->join_list; - tbl->embedding= table; - } + tbl->join_list= &nested_join->join_list; + tbl->embedding= table; } } diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 53197972dab..c991953f206 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2790,7 +2790,7 @@ static void test_mb(CHARSET_INFO *cs, uchar *s) { while(*s) { - if(my_ismbhead_utf8(cs,*s)) + if (my_ismbhead_utf8(cs,*s)) { int len=my_mbcharlen_utf8(cs,*s); while(len--) diff --git a/strings/ctype.c b/strings/ctype.c index ba6dbaeb887..91fa1413259 100644 --- a/strings/ctype.c +++ b/strings/ctype.c @@ -218,14 +218,6 @@ static int cs_value(MY_XML_PARSER *st,const char *attr, uint len) struct my_cs_file_section_st *s; int state= (int)((s=cs_file_sec(st->attr, (int) strlen(st->attr))) ? s->state : 0); -#ifndef DBUG_OFF - if(0){ - char str[1024]; - mstr(str,attr,len,sizeof(str)-1); - printf("VALUE %d %s='%s'\n",state,st->attr,str); - } -#endif - switch (state) { case _CS_ID: i->cs.number= strtol(attr,(char**)NULL,10); diff --git a/strings/decimal.c b/strings/decimal.c index 18f920badd3..be403c5e3fb 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1492,17 +1492,18 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, { int do_inc= FALSE; DBUG_ASSERT(frac0+intg0 >= 0); - switch (round_digit) - { + switch (round_digit) { case 0: { dec1 *p0= buf0 + (frac1-frac0); for (; p0 > buf0; p0--) + { if (*p0) { do_inc= TRUE; break; - }; + } + } break; } case 5: @@ -1511,9 +1512,10 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, do_inc= (x>5) || ((x == 5) && (mode == HALF_UP || (frac0+intg0 > 0 && *buf0 & 1))); break; - }; - default:; - }; + } + default: + break; + } if (do_inc) { if (frac0+intg0>0) @@ -1567,9 +1569,9 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, *buf1=1; to->intg++; } - /* Here we check 999.9 -> 1000 case when we need to increase intg */ else { + /* Here we check 999.9 -> 1000 case when we need to increase intg */ int first_dig= to->intg % DIG_PER_DEC1; /* first_dig==0 should be handled above in the 'if' */ if (first_dig && (*buf1 >= powers10[first_dig])) diff --git a/strings/xml.c b/strings/xml.c index 17f1b400957..02ca3932c39 100644 --- a/strings/xml.c +++ b/strings/xml.c @@ -96,13 +96,13 @@ static int my_xml_scan(MY_XML_PARSER *p,MY_XML_ATTR *a) a->end=p->cur; lex=a->beg[0]; } - else if ( (p->cur[0]=='"') || (p->cur[0]=='\'') ) + else if ( (p->cur[0] == '"') || (p->cur[0] == '\'') ) { p->cur++; for( ; ( p->cur < p->end ) && (p->cur[0] != a->beg[0]); p->cur++) {} a->end=p->cur; - if (a->beg[0]==p->cur[0])p->cur++; + if (a->beg[0] == p->cur[0])p->cur++; a->beg++; my_xml_norm_text(a); lex=MY_XML_STRING; @@ -169,8 +169,8 @@ static int my_xml_leave(MY_XML_PARSER *p, const char *str, uint slen) int rc; /* Find previous '.' or beginning */ - for( e=p->attrend; (e>p->attr) && (e[0]!='.') ; e--); - glen = (uint) ((e[0]=='.') ? (p->attrend-e-1) : p->attrend-e); + for( e=p->attrend; (e>p->attr) && (e[0] != '.') ; e--); + glen = (uint) ((e[0] == '.') ? (p->attrend-e-1) : p->attrend-e); if (str && (slen != glen)) { @@ -199,7 +199,7 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len) while ( p->cur < p->end ) { MY_XML_ATTR a; - if(p->cur[0]=='<') + if (p->cur[0] == '<') { int lex; int question=0; @@ -207,40 +207,40 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len) lex=my_xml_scan(p,&a); - if (MY_XML_COMMENT==lex) + if (MY_XML_COMMENT == lex) { continue; } lex=my_xml_scan(p,&a); - if (MY_XML_SLASH==lex) + if (MY_XML_SLASH == lex) { - if(MY_XML_IDENT!=(lex=my_xml_scan(p,&a))) + if (MY_XML_IDENT != (lex=my_xml_scan(p,&a))) { sprintf(p->errstr,"1: %s unexpected (ident wanted)",lex2str(lex)); return MY_XML_ERROR; } - if(MY_XML_OK!=my_xml_leave(p,a.beg,(uint) (a.end-a.beg))) + if (MY_XML_OK != my_xml_leave(p,a.beg,(uint) (a.end-a.beg))) return MY_XML_ERROR; lex=my_xml_scan(p,&a); goto gt; } - if (MY_XML_EXCLAM==lex) + if (MY_XML_EXCLAM == lex) { lex=my_xml_scan(p,&a); exclam=1; } - else if (MY_XML_QUESTION==lex) + else if (MY_XML_QUESTION == lex) { lex=my_xml_scan(p,&a); question=1; } - if (MY_XML_IDENT==lex) + if (MY_XML_IDENT == lex) { - if(MY_XML_OK!=my_xml_enter(p,a.beg,(uint) (a.end-a.beg))) + if (MY_XML_OK != my_xml_enter(p,a.beg,(uint) (a.end-a.beg))) return MY_XML_ERROR; } else @@ -250,17 +250,18 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len) return MY_XML_ERROR; } - while ((MY_XML_IDENT==(lex=my_xml_scan(p,&a))) || (MY_XML_STRING==lex)) + while ((MY_XML_IDENT == (lex=my_xml_scan(p,&a))) || + (MY_XML_STRING == lex)) { MY_XML_ATTR b; - if(MY_XML_EQ==(lex=my_xml_scan(p,&b))) + if (MY_XML_EQ == (lex=my_xml_scan(p,&b))) { lex=my_xml_scan(p,&b); - if ( (lex==MY_XML_IDENT) || (lex==MY_XML_STRING) ) + if ( (lex == MY_XML_IDENT) || (lex == MY_XML_STRING) ) { - if((MY_XML_OK!=my_xml_enter(p,a.beg,(uint) (a.end-a.beg))) || - (MY_XML_OK!=my_xml_value(p,b.beg,(uint) (b.end-b.beg))) || - (MY_XML_OK!=my_xml_leave(p,a.beg,(uint) (a.end-a.beg)))) + if ((MY_XML_OK != my_xml_enter(p,a.beg,(uint) (a.end-a.beg))) || + (MY_XML_OK != my_xml_value(p,b.beg,(uint) (b.end-b.beg))) || + (MY_XML_OK != my_xml_leave(p,a.beg,(uint) (a.end-a.beg)))) return MY_XML_ERROR; } else @@ -270,19 +271,19 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len) return MY_XML_ERROR; } } - else if ( (MY_XML_STRING==lex) || (MY_XML_IDENT==lex) ) + else if ((MY_XML_STRING == lex) || (MY_XML_IDENT == lex)) { - if((MY_XML_OK!=my_xml_enter(p,a.beg,(uint) (a.end-a.beg))) || - (MY_XML_OK!=my_xml_leave(p,a.beg,(uint) (a.end-a.beg)))) + if ((MY_XML_OK != my_xml_enter(p,a.beg,(uint) (a.end-a.beg))) || + (MY_XML_OK != my_xml_leave(p,a.beg,(uint) (a.end-a.beg)))) return MY_XML_ERROR; } else break; } - if (lex==MY_XML_SLASH) + if (lex == MY_XML_SLASH) { - if(MY_XML_OK!=my_xml_leave(p,NULL,0)) + if (MY_XML_OK != my_xml_leave(p,NULL,0)) return MY_XML_ERROR; lex=my_xml_scan(p,&a); } @@ -290,23 +291,23 @@ int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len) gt: if (question) { - if (lex!=MY_XML_QUESTION) + if (lex != MY_XML_QUESTION) { sprintf(p->errstr,"6: %s unexpected ('?' wanted)",lex2str(lex)); return MY_XML_ERROR; } - if(MY_XML_OK!=my_xml_leave(p,NULL,0)) + if (MY_XML_OK != my_xml_leave(p,NULL,0)) return MY_XML_ERROR; lex=my_xml_scan(p,&a); } if (exclam) { - if(MY_XML_OK!=my_xml_leave(p,NULL,0)) + if (MY_XML_OK != my_xml_leave(p,NULL,0)) return MY_XML_ERROR; } - if (lex!=MY_XML_GT) + if (lex != MY_XML_GT) { sprintf(p->errstr,"5: %s unexpected ('>' wanted)",lex2str(lex)); return MY_XML_ERROR; @@ -315,11 +316,11 @@ gt: else { a.beg=p->cur; - for ( ; (p->cur < p->end) && (p->cur[0]!='<') ; p->cur++); + for ( ; (p->cur < p->end) && (p->cur[0] != '<') ; p->cur++); a.end=p->cur; my_xml_norm_text(&a); - if (a.beg!=a.end) + if (a.beg != a.end) { my_xml_value(p,a.beg,(uint) (a.end-a.beg)); } @@ -381,7 +382,7 @@ uint my_xml_error_pos(MY_XML_PARSER *p) const char *s; for ( s=p->beg ; scur; s++) { - if (s[0]=='\n') + if (s[0] == '\n') beg=s; } return (uint) (p->cur-beg); @@ -391,9 +392,9 @@ uint my_xml_error_lineno(MY_XML_PARSER *p) { uint res=0; const char *s; - for ( s=p->beg ; scur; s++) + for (s=p->beg ; scur; s++) { - if (s[0]=='\n') + if (s[0] == '\n') res++; } return res; From ece95b3d4b5c283d60f6d18cb7ef91841b78eb69 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Jul 2005 12:58:53 +0200 Subject: [PATCH 145/216] - bumped up version number in configure.in to 4.0.26 configure.in: - bumped up version number to 4.0.26 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 5af41d29c21..83685009ee6 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! -AM_INIT_AUTOMAKE(mysql, 4.0.25) +AM_INIT_AUTOMAKE(mysql, 4.0.26) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 From 5d82b41e3adccc566b68542bf5be097ed45f5390 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Jul 2005 16:01:04 +0300 Subject: [PATCH 146/216] After merge fixes mysql-test/r/group_by.result: After merge fix (Put test in same order as in 4.1) mysql-test/t/group_by.test: After merge fix (Put test in same order as in 4.1) sql/item_cmpfunc.cc: After merge fix (+ simple fix to not allow compiler to do tail optimization) sql/item_cmpfunc.h: After merge fix --- mysql-test/r/group_by.result | 56 ++++++++++++++--------------- mysql-test/t/group_by.test | 68 +++++++++++++++++++----------------- sql/item_cmpfunc.cc | 10 ++++-- sql/item_cmpfunc.h | 2 +- 4 files changed, 71 insertions(+), 65 deletions(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 34a9cc4221f..64446e63e6f 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -723,6 +723,34 @@ WHERE hostname LIKE '%aol%' hostname no cache-dtc-af05.proxy.aol.com 1 DROP TABLE t1; +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (1,2), (1,3); +SELECT a, b FROM t1 GROUP BY 'const'; +a b +1 2 +SELECT DISTINCT a, b FROM t1 GROUP BY 'const'; +a b +1 2 +DROP TABLE t1; +CREATE TABLE t1 (id INT, dt DATETIME); +INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); +INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); +INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); +INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); +SELECT dt DIV 1 AS f, id FROM t1 GROUP BY f; +f id +20050501123000 1 +DROP TABLE t1; +CREATE TABLE t1 (id varchar(20) NOT NULL); +INSERT INTO t1 VALUES ('trans1'), ('trans2'); +CREATE TABLE t2 (id varchar(20) NOT NULL, err_comment blob NOT NULL); +INSERT INTO t2 VALUES ('trans1', 'a problem'); +SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS comment +FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY comment; +COUNT(DISTINCT(t1.id)) comment +1 NULL +1 a problem +DROP TABLE t1, t2; CREATE TABLE t1 (n int); INSERT INTO t1 VALUES (1); SELECT n+1 AS n FROM t1 GROUP BY n; @@ -752,31 +780,3 @@ aaa show warnings; Level Code Message drop table t1, t2; -CREATE TABLE t1 (a int, b int); -INSERT INTO t1 VALUES (1,2), (1,3); -SELECT a, b FROM t1 GROUP BY 'const'; -a b -1 2 -SELECT DISTINCT a, b FROM t1 GROUP BY 'const'; -a b -1 2 -DROP TABLE t1; -CREATE TABLE t1 (id INT, dt DATETIME); -INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); -INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); -INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); -INSERT INTO t1 VALUES ( 1, '2005-05-01 12:30:00' ); -SELECT dt DIV 1 AS f, id FROM t1 GROUP BY f; -f id -20050501123000 1 -DROP TABLE t1; -CREATE TABLE t1 (id varchar(20) NOT NULL); -INSERT INTO t1 VALUES ('trans1'), ('trans2'); -CREATE TABLE t2 (id varchar(20) NOT NULL, err_comment blob NOT NULL); -INSERT INTO t2 VALUES ('trans1', 'a problem'); -SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS comment -FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY comment; -COUNT(DISTINCT(t1.id)) comment -1 NULL -1 a problem -DROP TABLE t1, t2; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 2defb480deb..6f1880ae8fb 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -543,39 +543,6 @@ SELECT hostname, COUNT(DISTINCT user_id) as no FROM t1 DROP TABLE t1; # -# Bug#11211: Ambiguous column reference in GROUP BY. -# - -create table t1 (c1 char(3), c2 char(3)); -create table t2 (c3 char(3), c4 char(3)); -insert into t1 values ('aaa', 'bb1'), ('aaa', 'bb2'); -insert into t2 values ('aaa', 'bb1'), ('aaa', 'bb2'); - -# query with ambiguous column reference 'c2' ---disable_ps_protocol -select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4 -group by c2; -show warnings; ---enable_ps_protocol - -# this query has no ambiguity -select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4 -group by t1.c1; - -show warnings; -drop table t1, t2; - -# -# Test for bug #11414: crash on Windows for a simple GROUP BY query -# - -CREATE TABLE t1 (n int); -INSERT INTO t1 VALUES (1); ---disable_ps_protocol -SELECT n+1 AS n FROM t1 GROUP BY n; ---enable_ps_protocol -DROP TABLE t1; - # Test for bug #8614: GROUP BY 'const' with DISTINCT # @@ -613,3 +580,38 @@ SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS comment FROM t1 LEFT JOIN t2 ON t1.id=t2.id GROUP BY comment; DROP TABLE t1, t2; + +# +# Test for bug #11414: crash on Windows for a simple GROUP BY query +# + +CREATE TABLE t1 (n int); +INSERT INTO t1 VALUES (1); +--disable_ps_protocol +SELECT n+1 AS n FROM t1 GROUP BY n; +--enable_ps_protocol +DROP TABLE t1; + +# +# Bug#11211: Ambiguous column reference in GROUP BY. +# + +create table t1 (c1 char(3), c2 char(3)); +create table t2 (c3 char(3), c4 char(3)); +insert into t1 values ('aaa', 'bb1'), ('aaa', 'bb2'); +insert into t2 values ('aaa', 'bb1'), ('aaa', 'bb2'); + +# query with ambiguous column reference 'c2' +--disable_ps_protocol +select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4 +group by c2; +show warnings; +--enable_ps_protocol + +# this query has no ambiguity +select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4 +group by t1.c1; + +show warnings; +drop table t1, t2; + diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index bce6a58330f..5ed857319be 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1578,17 +1578,21 @@ my_decimal *Item_func_case::val_decimal(my_decimal *decimal_value) } -bool Item_func_case::fix_fields(THD *thd, struct st_table_list *tables, - Item **ref) +bool Item_func_case::fix_fields(THD *thd, Item **ref) { /* buff should match stack usage from Item_func_case::val_int() -> Item_func_case::find_item() */ char buff[MAX_FIELD_WIDTH*2+sizeof(String)*2+sizeof(String*)*2+sizeof(double)*2+sizeof(longlong)*2]; + bool res= Item_func::fix_fields(thd, ref); + /* + Call check_stack_overrun after fix_fields to be sure that stack variable + is not optimized away + */ if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) return TRUE; // Fatal error flag is set! - return Item_func::fix_fields(thd, tables, ref); + return res; } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index c21e9ba4925..75c8411b844 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -566,7 +566,7 @@ public: longlong val_int(); String *val_str(String *); my_decimal *val_decimal(my_decimal *); - bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref); + bool fix_fields(THD *thd, Item **ref); void fix_length_and_dec(); uint decimal_precision() const; table_map not_null_tables() const { return 0; } From e9ac18c204c0600e651986ad90dd1fffe915d879 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Jul 2005 20:36:38 +0200 Subject: [PATCH 147/216] Fixed indentation --- sql/ha_ndbcluster.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 462670df64c..4f35bf07cc1 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1222,9 +1222,9 @@ int ha_ndbcluster::complemented_pk_read(const byte *old_data, byte *new_data) op->readTuple(lm) != 0) ERR_RETURN(trans->getNdbError()); - int res; - if ((res= set_primary_key_from_record(op, old_data))) - ERR_RETURN(trans->getNdbError()); + int res; + if ((res= set_primary_key_from_record(op, old_data))) + ERR_RETURN(trans->getNdbError()); // Read all unreferenced non-key field(s) for (i= 0; i < no_fields; i++) From 175f12fdc04ec7a2ede027898359661968170657 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Jul 2005 22:11:38 +0200 Subject: [PATCH 148/216] - The Max package should Require a matching MySQL-server package. Automatically replace the version string with the base version of the current build --- support-files/mysql.spec.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 06e9c2c75f0..2e4f7d12573 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -179,7 +179,7 @@ Summary: MySQL - server with extended functionality Group: Applications/Databases Provides: mysql-Max Obsoletes: mysql-Max -Requires: MySQL-server >= 4.0 +Requires: MySQL-server >= @MYSQL_BASE_VERSION@ %description Max Optional MySQL server binary that supports additional features like: From 1a260574283bbd510745e15862e5f02f7cde14b9 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Jul 2005 22:27:16 +0200 Subject: [PATCH 149/216] Making rpl_until more robust if machine is slow. Removing rpl_trunc_binlog which is wrong now that slave recovers gracefully from a crashed binlog (thx Serg). stat -> my_stat in my_copy.c so that failing stat() does not hang client connection. BitKeeper/deleted/.del-rpl_trunc_binlog.test~961b1f6ac73d37c8: Delete: mysql-test/t/rpl_trunc_binlog.test BitKeeper/deleted/.del-rpl_trunc_binlog.result~14b4a61886a332e8: Delete: mysql-test/r/rpl_trunc_binlog.result mysql-test/std_data/trunc_binlog.000001: Rename: BitKeeper/deleted/.del-trunc_binlog.000001~b504d840c7efde25 -> mysql-test/std_data/trunc_binlog.000001 mysql-test/t/rpl_until.test: making test more robust if machine is slow. We still need to sleep before testing if slave SQL thread stopped, because otherwise it may not have started yet when we test for stop, then we would return too early. When we have "START SLAVE" wait a few secs until slave threads actually started well (WL#2688) these "sleep 2" could be removed. mysys/my_copy.c: Using my_stat() instead of stat(). Reason is that my_stat() reports an error message if wanted (MY_WME), which is critical for an error being sent to the client. Before this patch, a failing stat() caused the client connection to hang (because error was not set because my_error was never called). Adding an assertion to match the comment at the start of the function. --- mysql-test/r/rpl_trunc_binlog.result | 17 -------------- mysql-test/t/rpl_trunc_binlog.test | 35 ---------------------------- mysql-test/t/rpl_until.test | 9 ++++--- mysys/my_copy.c | 18 +++++++------- 4 files changed, 16 insertions(+), 63 deletions(-) delete mode 100644 mysql-test/r/rpl_trunc_binlog.result delete mode 100644 mysql-test/t/rpl_trunc_binlog.test diff --git a/mysql-test/r/rpl_trunc_binlog.result b/mysql-test/r/rpl_trunc_binlog.result deleted file mode 100644 index 2663fffe4d4..00000000000 --- a/mysql-test/r/rpl_trunc_binlog.result +++ /dev/null @@ -1,17 +0,0 @@ -stop slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -reset master; -reset slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -start slave; -stop slave; -flush logs; -create table t1 (a int) engine=bdb; -reset slave; -start slave; -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 4 # # master-bin.000002 Yes Yes 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. A probable cause is that the master died while writing the transaction to its binary log. 0 4 # None 0 No # -select * from t1; -a -drop table t1; diff --git a/mysql-test/t/rpl_trunc_binlog.test b/mysql-test/t/rpl_trunc_binlog.test deleted file mode 100644 index eec36532275..00000000000 --- a/mysql-test/t/rpl_trunc_binlog.test +++ /dev/null @@ -1,35 +0,0 @@ -# We are testing if a binlog which contains BEGIN but not COMMIT (the -# master died while writing the transaction to the binlog) triggers a -# rollback on slave. So we use such a truncated binlog and simulate that -# the master restarted after this. - -source include/master-slave.inc; - -connection slave; -# If we are not supporting transactions in the slave, the unfinished -# transaction won't cause any error, so we need to skip the test. In the 4.0 -# testsuite, the slave always runs without InnoDB, so we check for BDB. -source include/have_bdb.inc; -stop slave; - -connection master; -flush logs; -system mv -f var/log/master-bin.000001 var/log/master-bin.000002; -system cp std_data/trunc_binlog.000001 var/log/master-bin.000001; - -connection slave; - -# truncated binlog contains: BEGIN; INSERT t1 VALUES (1); -# so let's create the table t1 on slave - -create table t1 (a int) engine=bdb; -reset slave; -start slave; -# can't sync_with_master so we must sleep -sleep 3; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 23 # 33 # -show slave status; -select * from t1; -drop table t1; - diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index 714719f5441..c1aee2cb1db 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -26,6 +26,7 @@ show binlog events; connection slave; start slave until master_log_file='master-bin.000001', master_log_pos=319; sleep 2; +wait_for_slave_to_stop; # here table should be still not deleted select * from t1; --replace_result $MASTER_MYPORT MASTER_MYPORT @@ -37,13 +38,15 @@ start slave until master_log_file='master-no-such-bin.000001', master_log_pos=29 # again this table should be still not deleted select * from t1; sleep 2; +wait_for_slave_to_stop; --replace_result $MASTER_MYPORT MASTER_MYPORT --replace_column 1 # 9 # 23 # 33 # show slave status; # try replicate all until second insert to t2; start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746; -sleep 4; +sleep 2; +wait_for_slave_to_stop; select * from t2; --replace_result $MASTER_MYPORT MASTER_MYPORT --replace_column 1 # 9 # 23 # 33 # @@ -59,8 +62,8 @@ stop slave; # this should stop immediately as we are already there start slave until master_log_file='master-bin.000001', master_log_pos=776; -# 2 is not enough when running with valgrind -real_sleep 4 +sleep 2; +wait_for_slave_to_stop; # here the sql slave thread should be stopped --replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004 --replace_column 1 # 9 # 23 # 33 # diff --git a/mysys/my_copy.c b/mysys/my_copy.c index 03f3feb54d3..072492172e3 100644 --- a/mysys/my_copy.c +++ b/mysys/my_copy.c @@ -16,7 +16,7 @@ #define USES_TYPES /* sys/types is included */ #include "mysys_priv.h" -#include +#include /* for stat */ #include #if defined(HAVE_UTIME_H) #include @@ -53,26 +53,28 @@ struct utimbuf { int my_copy(const char *from, const char *to, myf MyFlags) { uint Count; - int new_file_stat, create_flag; + my_bool new_file_stat; /* 1 if we could stat "to" */ + int create_flag; File from_file,to_file; char buff[IO_SIZE]; - struct stat stat_buff,new_stat_buff; + MY_STAT stat_buff,new_stat_buff; DBUG_ENTER("my_copy"); DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags)); from_file=to_file= -1; - new_file_stat=0; + LINT_INIT(new_file_stat); + DBUG_ASSERT(!(MyFlags & (MY_FNABP | MY_NABP))); /* for my_read/my_write */ if (MyFlags & MY_HOLD_ORIGINAL_MODES) /* Copy stat if possible */ - new_file_stat=stat((char*) to, &new_stat_buff); + new_file_stat= test(my_stat((char*) to, &new_stat_buff, MYF(0))); if ((from_file=my_open(from,O_RDONLY | O_SHARE,MyFlags)) >= 0) { - if (stat(from,&stat_buff)) + if (!my_stat(from, &stat_buff, MyFlags)) { my_errno=errno; goto err; } - if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat) + if (MyFlags & MY_HOLD_ORIGINAL_MODES && new_file_stat) stat_buff=new_stat_buff; create_flag= (MyFlags & MY_DONT_OVERWRITE_FILE) ? O_EXCL : O_TRUNC; @@ -91,7 +93,7 @@ int my_copy(const char *from, const char *to, myf MyFlags) /* Copy modes if possible */ - if (MyFlags & MY_HOLD_ORIGINAL_MODES && new_file_stat) + if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat) DBUG_RETURN(0); /* File copyed but not stat */ VOID(chmod(to, stat_buff.st_mode & 07777)); /* Copy modes */ #if !defined(MSDOS) && !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__) From b87b32555eb8bbc0d31afa5e61c6e3b9c74e8f6e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Jul 2005 23:00:23 +0000 Subject: [PATCH 150/216] Fix for BUG#9814: Clear thd->net.no_send_error before each SP instruction execution. Failure to do so caused the erroneous statements to send nothing and hang the client. mysql-test/r/sp-error.result: Testcase for BUG#9814. Note that the result demonstrates that currently mysql-test-run ignores errors in multi-statement if they arrive after first resultset has been received. mysql-test/t/sp-error.test: Testcase for BUG#09814. --- mysql-test/r/sp-error.result | 30 ++++++++++++++++++++++++++++ mysql-test/t/sp-error.test | 38 ++++++++++++++++++++++++++++++++++++ sql/sp_head.cc | 6 ++++++ 3 files changed, 74 insertions(+) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index bfbfb87ac43..171978fdb06 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1,3 +1,4 @@ +drop table if exists t1, t2; delete from mysql.proc; create procedure syntaxerror(t int)| ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 @@ -635,3 +636,32 @@ ERROR 0A000: EXECUTE is not allowed in stored procedures create function f() returns int begin execute stmt; ERROR 0A000: EXECUTE is not allowed in stored procedures deallocate prepare stmt; +create table t1(f1 int); +create table t2(f1 int); +CREATE PROCEDURE SP001() +P1: BEGIN +DECLARE ENDTABLE INT DEFAULT 0; +DECLARE TEMP_NUM INT; +DECLARE TEMP_SUM INT; +DECLARE C1 CURSOR FOR SELECT F1 FROM t1; +DECLARE C2 CURSOR FOR SELECT F1 FROM t2; +DECLARE CONTINUE HANDLER FOR NOT FOUND SET ENDTABLE = 1; +SET ENDTABLE=0; +SET TEMP_SUM=0; +SET TEMP_NUM=0; +OPEN C1; +FETCH C1 INTO TEMP_NUM; +WHILE ENDTABLE = 0 DO +SET TEMP_SUM=TEMP_NUM+TEMP_SUM; +FETCH C1 INTO TEMP_NUM; +END WHILE; +SELECT TEMP_SUM; +CLOSE C1; +CLOSE C1; +SELECT 'end of proc'; +END P1| +call SP001(); +TEMP_SUM +0 +drop procedure SP001; +drop table t1, t2; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index f5a9e53e710..e8243dfd343 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -2,6 +2,10 @@ # Stored PROCEDURE error tests # +--disable_warnings +drop table if exists t1, t2; +--enable_warnings + # Make sure we don't have any procedures left. delete from mysql.proc; @@ -933,3 +937,37 @@ create procedure p() execute stmt; create function f() returns int begin execute stmt; deallocate prepare stmt; +# BUG#9814: Closing a cursor that is not open +create table t1(f1 int); +create table t2(f1 int); + +delimiter |; +CREATE PROCEDURE SP001() +P1: BEGIN + DECLARE ENDTABLE INT DEFAULT 0; + DECLARE TEMP_NUM INT; + DECLARE TEMP_SUM INT; + DECLARE C1 CURSOR FOR SELECT F1 FROM t1; + DECLARE C2 CURSOR FOR SELECT F1 FROM t2; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET ENDTABLE = 1; + + SET ENDTABLE=0; + SET TEMP_SUM=0; + SET TEMP_NUM=0; + + OPEN C1; + + FETCH C1 INTO TEMP_NUM; + WHILE ENDTABLE = 0 DO + SET TEMP_SUM=TEMP_NUM+TEMP_SUM; + FETCH C1 INTO TEMP_NUM; + END WHILE; + SELECT TEMP_SUM; + CLOSE C1; + CLOSE C1; + SELECT 'end of proc'; +END P1| +delimiter ;| +call SP001(); +drop procedure SP001; +drop table t1, t2; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 6be80568186..9bbcaffa5dd 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -642,6 +642,12 @@ sp_head::execute(THD *thd) items made during other permanent subquery transformations). */ thd->current_arena= i; + /* + no_send_error may have been set by the previous SP instruction when it + sent eof. Allow the current SP instruction to produce an error. + (multi-statement execution code clears no_send_error, too) + */ + thd->net.no_send_error= 0; ret= i->execute(thd, &ip); if (i->free_list) cleanup_items(i->free_list); From 5e212a72312e0fde655a92376cd08a1cbc2e0ebd Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Jul 2005 23:40:01 +0000 Subject: [PATCH 151/216] BUG#9814: post-review fixes: clear thd->net.no_send error after SP instruction execution, not before. --- sql/sp_head.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 9bbcaffa5dd..904909a53fa 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -642,13 +642,13 @@ sp_head::execute(THD *thd) items made during other permanent subquery transformations). */ thd->current_arena= i; + ret= i->execute(thd, &ip); /* - no_send_error may have been set by the previous SP instruction when it - sent eof. Allow the current SP instruction to produce an error. - (multi-statement execution code clears no_send_error, too) + If this SP instruction have sent eof, it has caused no_send_error to be + set. Clear it back to allow the next instruction to send error. (multi- + statement execution code clears no_send_error between statements too) */ thd->net.no_send_error= 0; - ret= i->execute(thd, &ip); if (i->free_list) cleanup_items(i->free_list); i->state= Query_arena::EXECUTED; From 73bbed107c80cd0543294ff3bfa53442af180751 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Jul 2005 09:15:37 +0200 Subject: [PATCH 152/216] - removed Docs/README.1st (it's obsolete) BitKeeper/deleted/.del-README.1st~918382b11c609069: Delete: Docs/README.1st --- Docs/README.1st | 76 ------------------------------------------------- 1 file changed, 76 deletions(-) delete mode 100644 Docs/README.1st diff --git a/Docs/README.1st b/Docs/README.1st deleted file mode 100644 index 980c043224a..00000000000 --- a/Docs/README.1st +++ /dev/null @@ -1,76 +0,0 @@ -This ALPHA build of MySQL 4.1 for the Windows platform does not come -with an installer. A full-featured installer is being developed for the -4.1 series, and it is scheduled to be released with MySQL 4.1 BETA. - -** FRESH INSTALL ** - -To install MySQL 4.1 as a 'fresh' install, unzip this archive to a directory -of your choice (we suggest 'c:\', which will cause MySQL to be installed in -a directory named 'mysql' in 'c:\'). You should then follow the directions -in the user manual for starting/stopping MySQL: - -(Windows 9x/ME) http://www.mysql.com/doc/en/Win95_start.html -(Windows NT/2000/XP) http://www.mysql.com/doc/en/NT_start.html - -** UPGRADE INSTALL ** - -To install MySQL 4.1 as an upgrade to your current version of MySQL, you need -to perform the following steps: - -* Back up your original installation (always a good idea!) - -* Unzip the 4.1 archive to a directory that is different than where your - current MySQL installation is located. (Or, if you do unzip this - archive into the same location as your existing installation, do NOT - unpack the 'data' subdirectory. If you unpack the 'data' directory, - your existing databases will be overwritten.) - -* Shut down all MySQL server processes/services. - -* Remove the Win32 MySQL service (if appropriate for your OS): - - c:\mysql\bin\mysqld-nt --remove - -* Exit 'WinMySQLAdmin' (if it is running). - -* If you unzipped this archive into a directory different than that - of your existing MySQL installation, copy from the archive all its - directories and their contents EXCEPT the 'data' directory into the - existing installation. - -* Start the MySQL server with the '--skip-grant-tables' option. Assuming - your MySQL installation is located at 'c:\mysql', the command looks like - this: - - c:\mysql\bin\mysqld-opt --skip-grant-tables - - If your installation is located in some other directory, adjust the - pathname in that command (and in the following commands). - -* Execute the 'mysql_fix_privilege_tables.sql' script that is located in - the 'scripts' directory: - - c:\mysql\bin\mysql -f mysql < c:\mysql\scripts\mysql_fix_privilege_tables.sql - - This script performs any actions necessary to convert your grant tables - to the current format. You may see some "duplicate column" warnings as - it runs; these can be ignored. - -* Stop the server: - - c:\mysql\bin\mysqladmin -u root shutdown - -* Re-install the Win32 MySQL service (if required): - - c:\mysql\bin\mysqld-nt --install - -* Re-start the server or service using your normal startup procedure. - -** Further Questions ** - -You can find further information about running MySQL on Windows in the -manual that ships in the 'Doc' subdirectory, or online at the MySQL AB -web site: - -http://www.mysql.com/doc/en/Windows.html - From 48db5c8ffc5db5fe7da0e56ec04618229ba5a38e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Jul 2005 12:10:20 +0300 Subject: [PATCH 153/216] InnoDB: Fix compile-pentium-debug-max compilation problem. innobase/btr/btr0cur.c: Move #ifdef outside ut_ad() argument. innobase/page/page0cur.c: Move #ifdef outside ut_ad() argument. --- innobase/btr/btr0cur.c | 7 ++++--- innobase/page/page0cur.c | 14 ++++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index d76b139c3c8..f81cce5b8e9 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -392,11 +392,12 @@ btr_cur_search_to_nth_level( page_mode = PAGE_CUR_LE; break; default: - ut_ad(mode == PAGE_CUR_L #ifdef PAGE_CUR_LE_OR_EXTENDS - || mode == PAGE_CUR_LE_OR_EXTENDS + ut_ad(mode == PAGE_CUR_L || mode == PAGE_CUR_LE + || mode == PAGE_CUR_LE_OR_EXTENDS); +#else /* PAGE_CUR_LE_OR_EXTENDS */ + ut_ad(mode == PAGE_CUR_L || mode == PAGE_CUR_LE); #endif /* PAGE_CUR_LE_OR_EXTENDS */ - || mode == PAGE_CUR_LE); page_mode = mode; break; } diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c index 562ef545e41..d0b89e81787 100644 --- a/innobase/page/page0cur.c +++ b/innobase/page/page0cur.c @@ -238,14 +238,16 @@ page_cur_search_with_match( && ilow_matched_fields && ilow_matched_bytes && cursor); ut_ad(dtuple_validate(tuple)); ut_ad(dtuple_check_typed(tuple)); +#ifdef UNIV_DEBUG +# ifdef PAGE_CUR_DBG + if (mode != PAGE_CUR_DBG) +# endif /* PAGE_CUR_DBG */ +# ifdef PAGE_CUR_LE_OR_EXTENDS + if (mode != PAGE_CUR_LE_OR_EXTENDS) +# endif /* PAGE_CUR_LE_OR_EXTENDS */ ut_ad((mode == PAGE_CUR_L) || (mode == PAGE_CUR_LE) -#ifdef PAGE_CUR_DBG - || (mode == PAGE_CUR_DBG) -#endif /* PAGE_CUR_DBG */ -#ifdef PAGE_CUR_LE_OR_EXTENDS - || (mode == PAGE_CUR_LE_OR_EXTENDS) -#endif /* PAGE_CUR_LE_OR_EXTENDS */ || (mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)); +#endif /* UNIV_DEBUG */ page_check_dir(page); From dd72175d0b3b23f1b8873e21e9348e807990e7ce Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Jul 2005 12:23:13 +0300 Subject: [PATCH 154/216] post-merge fixes mysql-test/r/query_cache.result: results moved sql/sql_cache.cc: postmerge fixes --- mysql-test/r/query_cache.result | 179 ++++++++++++++++---------------- sql/sql_cache.cc | 5 +- 2 files changed, 91 insertions(+), 93 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 8123522cd2c..699d81d4cef 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -923,94 +923,6 @@ select group_concat(a) FROM t1 group by b; group_concat(a) 12345678901234567890 set group_concat_max_len=default; -drop table t1; -flush status; -CREATE TABLE t1 ( -`date` datetime NOT NULL default '0000-00-00 00:00:00', -KEY `date` (`date`) -) ENGINE=MyISAM; -INSERT INTO t1 VALUES ('20050326'); -INSERT INTO t1 VALUES ('20050325'); -SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 0:0:0'; -COUNT(*) -0 -Warnings: -Warning 1292 Truncated incorrect datetime value: '20050327 0:0:0' -Warning 1292 Truncated incorrect datetime value: '20050327 0:0:0' -SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 0:0:0'; -COUNT(*) -0 -Warnings: -Warning 1292 Truncated incorrect datetime value: '20050328 0:0:0' -Warning 1292 Truncated incorrect datetime value: '20050328 0:0:0' -SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 0:0:0'; -COUNT(*) -0 -Warnings: -Warning 1292 Truncated incorrect datetime value: '20050327 0:0:0' -Warning 1292 Truncated incorrect datetime value: '20050327 0:0:0' -show status like "Qcache_queries_in_cache"; -Variable_name Value -Qcache_queries_in_cache 0 -show status like "Qcache_inserts"; -Variable_name Value -Qcache_inserts 0 -show status like "Qcache_hits"; -Variable_name Value -Qcache_hits 0 -drop table t1; -create table t1 (a int); -insert into t1 values (1); -reset query cache; -flush status; -select * from (select * from t1) a; -a -1 -show status like "Qcache_queries_in_cache"; -Variable_name Value -Qcache_queries_in_cache 1 -show status like "Qcache_inserts"; -Variable_name Value -Qcache_inserts 1 -show status like "Qcache_hits"; -Variable_name Value -Qcache_hits 0 -select * from (select * from t1) a; -a -1 -show status like "Qcache_queries_in_cache"; -Variable_name Value -Qcache_queries_in_cache 1 -show status like "Qcache_inserts"; -Variable_name Value -Qcache_inserts 1 -show status like "Qcache_hits"; -Variable_name Value -Qcache_hits 1 -insert into t1 values (2); -show status like "Qcache_queries_in_cache"; -Variable_name Value -Qcache_queries_in_cache 0 -show status like "Qcache_inserts"; -Variable_name Value -Qcache_inserts 1 -show status like "Qcache_hits"; -Variable_name Value -Qcache_hits 1 -select * from (select * from t1) a; -a -1 -2 -show status like "Qcache_queries_in_cache"; -Variable_name Value -Qcache_queries_in_cache 1 -show status like "Qcache_inserts"; -Variable_name Value -Qcache_inserts 2 -show status like "Qcache_hits"; -Variable_name Value -Qcache_hits 1 - drop table t1; create table t1 (a int); show status like "Qcache_queries_in_cache"; @@ -1018,7 +930,7 @@ Variable_name Value Qcache_queries_in_cache 0 show status like "Qcache_inserts"; Variable_name Value -Qcache_inserts 19 +Qcache_inserts 18 show status like "Qcache_hits"; Variable_name Value Qcache_hits 6 @@ -1031,7 +943,7 @@ Variable_name Value Qcache_queries_in_cache 1 show status like "Qcache_inserts"; Variable_name Value -Qcache_inserts 20 +Qcache_inserts 19 show status like "Qcache_hits"; Variable_name Value Qcache_hits 7 @@ -1095,6 +1007,93 @@ abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab zyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcba flush query cache; drop table t1, t2; +flush status; +CREATE TABLE t1 ( +`date` datetime NOT NULL default '0000-00-00 00:00:00', +KEY `date` (`date`) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('20050326'); +INSERT INTO t1 VALUES ('20050325'); +SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 0:0:0'; +COUNT(*) +0 +Warnings: +Warning 1292 Incorrect datetime value: '20050327 0:0:0' for column 'date' at row 1 +Warning 1292 Incorrect datetime value: '20050327 0:0:0' for column 'date' at row 1 +SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 0:0:0'; +COUNT(*) +0 +Warnings: +Warning 1292 Incorrect datetime value: '20050328 0:0:0' for column 'date' at row 1 +Warning 1292 Incorrect datetime value: '20050328 0:0:0' for column 'date' at row 1 +SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 0:0:0'; +COUNT(*) +0 +Warnings: +Warning 1292 Incorrect datetime value: '20050327 0:0:0' for column 'date' at row 1 +Warning 1292 Incorrect datetime value: '20050327 0:0:0' for column 'date' at row 1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +drop table t1; +create table t1 (a int); +insert into t1 values (1); +reset query cache; +flush status; +select * from (select * from t1) a; +a +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +select * from (select * from t1) a; +a +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +insert into t1 values (2); +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +select * from (select * from t1) a; +a +1 +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +drop table t1; create table t1 (a int); insert into t1 values (1),(2); CREATE PROCEDURE `p1`() diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 279a1ccb443..e0a15b7d449 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -278,7 +278,6 @@ TODO list: - Move MRG_MYISAM table type processing to handlers, something like: tables_used->table->file->register_used_filenames(callback, first_argument); - - Make derived tables cachable. - QC improvement suggested by Monty: - Add a counter in open_table() for how many MERGE (ISAM or MyISAM) tables are cached in the table cache. @@ -2137,7 +2136,7 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used, { if (tables_used->derived) { - DBUG_PRINT("qcache", ("derived table skipped"); + DBUG_PRINT("qcache", ("derived table skipped")); n--; block_table--; continue; @@ -2785,7 +2784,7 @@ static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used, tables_used->table->s->table_name, tables_used->table->s->table_cache_key, tables_used->table->s->db_type)); - if (table_used->derived) + if (tables_used->derived) { table_count--; DBUG_PRINT("qcache", ("derived table skipped")); From 200f03fdd4b5a6272789c18a1250f1d790b9e177 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Jul 2005 13:36:36 +0300 Subject: [PATCH 155/216] added processing of view grants to table grants (BUG#9795) mysql-test/r/grant.result: test of new table privileges mysql-test/r/system_mysql_db.result: added new table priveleges mysql-test/r/view_grant.result: error changed mysql-test/t/grant.test: test of new table privileges mysql-test/t/view_grant.test: error changed scripts/mysql_create_system_tables.sh: add new table privileges scripts/mysql_fix_privilege_tables.sql: fixed system tables fix script sql/sql_acl.h: fixed coding/decoding new tables grants --- mysql-test/r/grant.result | 113 +++++++++++++++++++++++++ mysql-test/r/system_mysql_db.result | 2 +- mysql-test/r/view_grant.result | 2 +- mysql-test/t/grant.test | 67 +++++++++++++++ mysql-test/t/view_grant.test | 2 +- scripts/mysql_create_system_tables.sh | 2 +- scripts/mysql_fix_privilege_tables.sql | 5 ++ sql/sql_acl.h | 11 ++- 8 files changed, 198 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index c8ae8303d99..d84c9317755 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -1,4 +1,5 @@ drop table if exists t1; +drop database if exists mysqltest; SET NAMES binary; delete from mysql.user where user='mysqltest_1'; delete from mysql.db where user='mysqltest_1'; @@ -473,3 +474,115 @@ ERROR 42000: INSERT,CREATE command denied to user 'mysqltest_1'@'localhost' for revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; delete from mysql.user where user=_binary'mysqltest_1'; drop database mysqltest; +CREATE USER dummy@localhost; +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.dummytable (dummyfield INT); +CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; +GRANT ALL PRIVILEGES ON mysqltest.dummytable TO dummy@localhost; +GRANT ALL PRIVILEGES ON mysqltest.dummyview TO dummy@localhost; +SHOW GRANTS FOR dummy@localhost; +Grants for dummy@localhost +GRANT USAGE ON *.* TO 'dummy'@'localhost' +GRANT ALL PRIVILEGES ON `mysqltest`.`dummyview` TO 'dummy'@'localhost' +GRANT ALL PRIVILEGES ON `mysqltest`.`dummytable` TO 'dummy'@'localhost' +use INFORMATION_SCHEMA; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +TABLE_SCHEMA TABLE_NAME PRIVILEGES +mysqltest dummytable ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, UPDATE +mysqltest dummyview ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, UPDATE +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +Grants for dummy@localhost +GRANT USAGE ON *.* TO 'dummy'@'localhost' +GRANT ALL PRIVILEGES ON `mysqltest`.`dummyview` TO 'dummy'@'localhost' +GRANT ALL PRIVILEGES ON `mysqltest`.`dummytable` TO 'dummy'@'localhost' +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +TABLE_SCHEMA TABLE_NAME PRIVILEGES +mysqltest dummytable ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, UPDATE +mysqltest dummyview ALTER, CREATE, CREATE VIEW, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, UPDATE +SHOW FIELDS FROM mysql.tables_priv; +Field Type Null Key Default Extra +Host char(60) NO PRI +Db char(64) NO PRI +User char(16) NO PRI +Table_name char(64) NO PRI +Grantor char(77) NO MUL +Timestamp timestamp YES CURRENT_TIMESTAMP +Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') NO +Column_priv set('Select','Insert','Update','References') NO +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE mysqltest; +CREATE USER dummy@localhost; +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.dummytable (dummyfield INT); +CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; +GRANT CREATE VIEW ON mysqltest.dummytable TO dummy@localhost; +GRANT CREATE VIEW ON mysqltest.dummyview TO dummy@localhost; +SHOW GRANTS FOR dummy@localhost; +Grants for dummy@localhost +GRANT USAGE ON *.* TO 'dummy'@'localhost' +GRANT CREATE VIEW ON `mysqltest`.`dummyview` TO 'dummy'@'localhost' +GRANT CREATE VIEW ON `mysqltest`.`dummytable` TO 'dummy'@'localhost' +use INFORMATION_SCHEMA; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +TABLE_SCHEMA TABLE_NAME PRIVILEGES +mysqltest dummytable CREATE VIEW +mysqltest dummyview CREATE VIEW +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +Grants for dummy@localhost +GRANT USAGE ON *.* TO 'dummy'@'localhost' +GRANT CREATE VIEW ON `mysqltest`.`dummyview` TO 'dummy'@'localhost' +GRANT CREATE VIEW ON `mysqltest`.`dummytable` TO 'dummy'@'localhost' +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +TABLE_SCHEMA TABLE_NAME PRIVILEGES +mysqltest dummytable CREATE VIEW +mysqltest dummyview CREATE VIEW +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE mysqltest; +CREATE USER dummy@localhost; +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.dummytable (dummyfield INT); +CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; +GRANT SHOW VIEW ON mysqltest.dummytable TO dummy@localhost; +GRANT SHOW VIEW ON mysqltest.dummyview TO dummy@localhost; +SHOW GRANTS FOR dummy@localhost; +Grants for dummy@localhost +GRANT USAGE ON *.* TO 'dummy'@'localhost' +GRANT SHOW VIEW ON `mysqltest`.`dummyview` TO 'dummy'@'localhost' +GRANT SHOW VIEW ON `mysqltest`.`dummytable` TO 'dummy'@'localhost' +use INFORMATION_SCHEMA; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +TABLE_SCHEMA TABLE_NAME PRIVILEGES +mysqltest dummytable SHOW VIEW +mysqltest dummyview SHOW VIEW +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +Grants for dummy@localhost +GRANT USAGE ON *.* TO 'dummy'@'localhost' +GRANT SHOW VIEW ON `mysqltest`.`dummyview` TO 'dummy'@'localhost' +GRANT SHOW VIEW ON `mysqltest`.`dummytable` TO 'dummy'@'localhost' +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +TABLE_SCHEMA TABLE_NAME PRIVILEGES +mysqltest dummytable SHOW VIEW +mysqltest dummyview SHOW VIEW +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE mysqltest; diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index 409c9db9f47..b8f96687a73 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -128,7 +128,7 @@ tables_priv CREATE TABLE `tables_priv` ( `Table_name` char(64) collate utf8_bin NOT NULL default '', `Grantor` char(77) collate utf8_bin NOT NULL default '', `Timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, - `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') character set utf8 NOT NULL default '', + `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') character set utf8 NOT NULL default '', `Column_priv` set('Select','Insert','Update','References') character set utf8 NOT NULL default '', PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), KEY `Grantor` (`Grantor`) diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index df8e2b04f47..b77ee59b3ff 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -284,7 +284,7 @@ create table mysqltest.v3 (b int); grant select(b) on mysqltest.v3 to mysqltest_1@localhost; drop table mysqltest.v3; create view mysqltest.v3 as select b from mysqltest.t2; -ERROR 42000: CREATE VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v3' +ERROR 42000: create view command denied to user 'mysqltest_1'@'localhost' for column 'b' in table 'v3' create view v4 as select b+1 from mysqltest.t2; ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'b' in table 't2' grant create view,update,select on test.* to mysqltest_1@localhost; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 34d9a09cba7..e4e0a8b4f1a 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -6,6 +6,7 @@ # Cleanup --disable_warnings drop table if exists t1; +drop database if exists mysqltest; --enable_warnings connect (master,localhost,root,,); @@ -403,3 +404,69 @@ connection root; revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; delete from mysql.user where user=_binary'mysqltest_1'; drop database mysqltest; + +# +# check all new table priveleges +# +CREATE USER dummy@localhost; +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.dummytable (dummyfield INT); +CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; +GRANT ALL PRIVILEGES ON mysqltest.dummytable TO dummy@localhost; +GRANT ALL PRIVILEGES ON mysqltest.dummyview TO dummy@localhost; +SHOW GRANTS FOR dummy@localhost; +use INFORMATION_SCHEMA; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +SHOW FIELDS FROM mysql.tables_priv; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE mysqltest; +# check view only privileges +CREATE USER dummy@localhost; +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.dummytable (dummyfield INT); +CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; +GRANT CREATE VIEW ON mysqltest.dummytable TO dummy@localhost; +GRANT CREATE VIEW ON mysqltest.dummyview TO dummy@localhost; +SHOW GRANTS FOR dummy@localhost; +use INFORMATION_SCHEMA; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE mysqltest; +CREATE USER dummy@localhost; +CREATE DATABASE mysqltest; +CREATE TABLE mysqltest.dummytable (dummyfield INT); +CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; +GRANT SHOW VIEW ON mysqltest.dummytable TO dummy@localhost; +GRANT SHOW VIEW ON mysqltest.dummyview TO dummy@localhost; +SHOW GRANTS FOR dummy@localhost; +use INFORMATION_SCHEMA; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY +PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE += '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; +use test; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE mysqltest; diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index bb603b75daa..6283a1abf11 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -360,7 +360,7 @@ create table mysqltest.v3 (b int); grant select(b) on mysqltest.v3 to mysqltest_1@localhost; drop table mysqltest.v3; connection user1; --- error 1142 +-- error 1143 create view mysqltest.v3 as select b from mysqltest.t2; # Expression need select privileges diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index a8f6c02b057..bc07d857c4b 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -215,7 +215,7 @@ then c_t="$c_t Table_name char(64) binary DEFAULT '' NOT NULL," c_t="$c_t Grantor char(77) DEFAULT '' NOT NULL," c_t="$c_t Timestamp timestamp(14)," - c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') COLLATE utf8_general_ci DEFAULT '' NOT NULL," + c_t="$c_t Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') COLLATE utf8_general_ci DEFAULT '' NOT NULL," c_t="$c_t Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL," c_t="$c_t PRIMARY KEY (Host,Db,User,Table_name)," c_t="$c_t KEY Grantor (Grantor)" diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql index 68b31cf1519..3da2f7504a1 100644 --- a/scripts/mysql_fix_privilege_tables.sql +++ b/scripts/mysql_fix_privilege_tables.sql @@ -260,6 +260,11 @@ ALTER TABLE db ADD Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT ALTER TABLE host ADD Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv; ALTER TABLE user ADD Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_view_priv; +# +# Show/Create views table privileges (v5.0) +# +ALTER TABLE tables_priv MODIFY Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') COLLATE utf8_general_ci DEFAULT '' NOT NULL; + # # Assign create/show view privileges to people who have create provileges # diff --git a/sql/sql_acl.h b/sql/sql_acl.h index f2896889669..eba000a627a 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -106,8 +106,15 @@ (((A) & DB_CHUNK2) >> 6) | \ (((A) & DB_CHUNK3) >> 9) | \ (((A) & DB_CHUNK4) >> 2)) -#define fix_rights_for_table(A) (((A) & 63) | (((A) & ~63) << 4)) -#define get_rights_for_table(A) (((A) & 63) | (((A) & ~63) >> 4)) +#define TBL_CHUNK0 DB_CHUNK0 +#define TBL_CHUNK1 DB_CHUNK1 +#define TBL_CHUNK2 (CREATE_VIEW_ACL | SHOW_VIEW_ACL) +#define fix_rights_for_table(A) (((A) & TBL_CHUNK0) | \ + (((A) << 4) & TBL_CHUNK1) | \ + (((A) << 11) & TBL_CHUNK2)) +#define get_rights_for_table(A) (((A) & TBL_CHUNK0) | \ + (((A) & TBL_CHUNK1) >> 4) | \ + (((A) & TBL_CHUNK2) >> 11)) #define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 8)) #define get_rights_for_column(A) (((A) & 7) | ((A) >> 8)) #define fix_rights_for_procedure(A) ((((A) << 18) & EXECUTE_ACL) | \ From 836f5a5a1ed7475cf791c72892f0ea2527defad2 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Jul 2005 13:37:02 +0300 Subject: [PATCH 156/216] fixed environment creation and cleaning up for processing view one by one during checking (BUG#11337) mysql-test/r/view.result: checking views after some view with error (BUG#11337) mysql-test/t/view.test: checking views after some view with error (BUG#11337) sql/sql_lex.cc: environment cleaning up for processing view one by one sql/sql_lex.h: methods for lex cleunup during view processing one by one sql/sql_table.cc: fixed environment creation and cleaning up for processing view one by one (BUG#11337) --- mysql-test/r/view.result | 53 ++++++++++++++++++++++++++++++++++++++++ mysql-test/t/view.test | 38 ++++++++++++++++++++++++++++ sql/sql_lex.cc | 39 +++++++++++++++++++++++++++++ sql/sql_lex.h | 11 ++++++--- sql/sql_table.cc | 36 +++++++++++++++++++-------- 5 files changed, 164 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 68cc0c4cb57..1dc4148c334 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1831,3 +1831,56 @@ select * from v1; t 01:00 drop view v1; +CREATE TABLE t1 (col1 time); +CREATE TABLE t2 (col1 time); +CREATE VIEW v1 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1; +CREATE VIEW v2 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2; +CREATE VIEW v3 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1; +CREATE VIEW v4 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2; +CREATE VIEW v5 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1; +CREATE VIEW v6 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2; +DROP TABLE t1; +CHECK TABLE v1, v2, v3, v4, v5, v6; +Table Op Msg_type Msg_text +test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) +test.v2 check status OK +test.v3 check error View 'test.v3' references invalid table(s) or column(s) or function(s) +test.v4 check status OK +test.v5 check error View 'test.v5' references invalid table(s) or column(s) or function(s) +test.v6 check status OK +drop view v1, v2, v3, v4, v5, v6; +drop table t2; +CREATE TABLE t1 (col1 time); +CREATE TABLE t2 (col1 time); +CREATE TABLE t3 (col1 time); +create function f1 () returns int return (select max(col1) from t1); +create function f2 () returns int return (select max(col1) from t2); +CREATE VIEW v1 AS SELECT f1() FROM t3; +CREATE VIEW v2 AS SELECT f2() FROM t3; +CREATE VIEW v3 AS SELECT f1() FROM t3; +CREATE VIEW v4 AS SELECT f2() FROM t3; +CREATE VIEW v5 AS SELECT f1() FROM t3; +CREATE VIEW v6 AS SELECT f2() FROM t3; +drop function f1; +CHECK TABLE v1, v2, v3, v4, v5, v6; +Table Op Msg_type Msg_text +test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) +test.v2 check status OK +test.v3 check error View 'test.v3' references invalid table(s) or column(s) or function(s) +test.v4 check status OK +test.v5 check error View 'test.v5' references invalid table(s) or column(s) or function(s) +test.v6 check status OK +create function f1 () returns int return (select max(col1) from t1); +DROP TABLE t1; +CHECK TABLE v1, v2, v3, v4, v5, v6; +Table Op Msg_type Msg_text +test.v1 check error Table 'test.t1' doesn't exist +test.v2 check status OK +test.v3 check error Table 'test.t1' doesn't exist +test.v4 check status OK +test.v5 check error Table 'test.t1' doesn't exist +test.v6 check status OK +drop function f1; +drop function f2; +drop view v1, v2, v3, v4, v5, v6; +drop table t2,t3; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 13a5f8cef1f..532e40ec28c 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1673,3 +1673,41 @@ create view v1(k, K) as select 1,2; create view v1 as SELECT TIME_FORMAT(SEC_TO_TIME(3600),'%H:%i') as t; select * from v1; drop view v1; + +# +# checking views after some view with error (BUG#11337) +# +CREATE TABLE t1 (col1 time); +CREATE TABLE t2 (col1 time); +CREATE VIEW v1 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1; +CREATE VIEW v2 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2; +CREATE VIEW v3 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1; +CREATE VIEW v4 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2; +CREATE VIEW v5 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t1; +CREATE VIEW v6 AS SELECT CONVERT_TZ(col1,'GMT','MET') FROM t2; +DROP TABLE t1; +CHECK TABLE v1, v2, v3, v4, v5, v6; +drop view v1, v2, v3, v4, v5, v6; +drop table t2; + +CREATE TABLE t1 (col1 time); +CREATE TABLE t2 (col1 time); +CREATE TABLE t3 (col1 time); +create function f1 () returns int return (select max(col1) from t1); +create function f2 () returns int return (select max(col1) from t2); +CREATE VIEW v1 AS SELECT f1() FROM t3; +CREATE VIEW v2 AS SELECT f2() FROM t3; +CREATE VIEW v3 AS SELECT f1() FROM t3; +CREATE VIEW v4 AS SELECT f2() FROM t3; +CREATE VIEW v5 AS SELECT f1() FROM t3; +CREATE VIEW v6 AS SELECT f2() FROM t3; +drop function f1; +CHECK TABLE v1, v2, v3, v4, v5, v6; +create function f1 () returns int return (select max(col1) from t1); +DROP TABLE t1; +# following will show underlying table until BUG#11555 fix +CHECK TABLE v1, v2, v3, v4, v5, v6; +drop function f1; +drop function f2; +drop view v1, v2, v3, v4, v5, v6; +drop table t2,t3; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 08f0c3badf7..1067ce0f6e2 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1916,6 +1916,45 @@ void st_lex::link_first_table_back(TABLE_LIST *first, } + +/* + cleanup lex for case when we open table by table for processing + + SYNOPSIS + st_lex::cleanup_after_one_table_open() +*/ + +void st_lex::cleanup_after_one_table_open() +{ + /* + thd->lex->derived_tables & additional units may be set if we open + a view. It is necessary to clear thd->lex->derived_tables flag + to prevent processing of derived tables during next open_and_lock_tables + if next table is a real table and cleanup & remove underlying units + NOTE: all units will be connected to thd->lex->select_lex, because we + have not UNION on most upper level. + */ + if (all_selects_list != &select_lex) + { + derived_tables= 0; + /* cleunup underlying units (units of VIEW) */ + for (SELECT_LEX_UNIT *un= select_lex.first_inner_unit(); + un; + un= un->next_unit()) + un->cleanup(); + /* reduce all selects list to default state */ + all_selects_list= &select_lex; + /* remove underlying units (units of VIEW) subtree */ + select_lex.cut_subtree(); + } + time_zone_tables_used= 0; + if (spfuns.records) + my_hash_reset(&spfuns); + if (spprocs.records) + my_hash_reset(&spprocs); +} + + /* fix some structures at the end of preparation diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a9bfb6da926..ffe3a5ba833 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -371,7 +371,6 @@ typedef class st_select_lex_node SELECT_LEX_NODE; SELECT_LEX_UNIT - unit of selects (UNION, INTERSECT, ...) group SELECT_LEXs */ -struct st_lex; class THD; class select_result; class JOIN; @@ -627,7 +626,13 @@ public: order_list.first= 0; order_list.next= (byte**) &order_list.first; } - + /* + This method created for reiniting LEX in mysql_admin_table() and can be + used only if you are going remove all SELECT_LEX & units except belonger + to LEX (LEX::unit & LEX::select, for other purposes there are + SELECT_LEX_UNIT::exclude_level & SELECT_LEX_UNIT::exclude_tree + */ + void cut_subtree() { slave= 0; } bool test_limit(); friend void lex_start(THD *thd, uchar *buf, uint length); @@ -912,7 +917,7 @@ typedef struct st_lex { return ( query_tables_own_last ? *query_tables_own_last : 0); } - + void cleanup_after_one_table_open(); } LEX; struct st_lex_local: public st_lex diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 121a89555ce..4f8c14a666e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2103,6 +2103,7 @@ end: } + /* RETURN VALUES FALSE Message sent to net (admin operation went ok) @@ -2122,10 +2123,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT *), int (view_operator_func)(THD *, TABLE_LIST*)) { - TABLE_LIST *table, *next_global_table; + TABLE_LIST *table, *save_next_global, *save_next_local; + SELECT_LEX *select= &thd->lex->select_lex; List field_list; Item *item; Protocol *protocol= thd->protocol; + LEX *lex= thd->lex; int result_code; DBUG_ENTER("mysql_admin_table"); @@ -2152,12 +2155,25 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, thd->open_options|= extra_open_options; table->lock_type= lock_type; /* open only one table from local list of command */ - next_global_table= table->next_global; + save_next_global= table->next_global; table->next_global= 0; + save_next_local= table->next_local; + table->next_local= 0; + select->table_list.first= (byte*)table; + /* + Time zone tables and SP tables can be add to lex->query_tables list, + so it have to be prepared. + TODO: Investigate if we can put extra tables into argument instead of + using lex->query_tables + */ + lex->query_tables= table; + lex->query_tables_last= &table->next_global; + lex->query_tables_own_last= 0;; thd->no_warnings_for_error= no_warnings_for_error; open_and_lock_tables(thd, table); thd->no_warnings_for_error= 0; - table->next_global= next_global_table; + table->next_global= save_next_global; + table->next_local= save_next_local; /* if view are unsupported */ if (table->view && view_operator_func == NULL) { @@ -2205,7 +2221,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, err_msg= (const char *)buf; } protocol->store(err_msg, system_charset_info); + lex->cleanup_after_one_table_open(); thd->clear_error(); + /* + View opening can be interrupted in the middle of process so some + tables can be left opening + */ + close_thread_tables(thd); if (protocol->write()) goto err; continue; @@ -2274,6 +2296,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, send_result: + lex->cleanup_after_one_table_open(); thd->clear_error(); // these errors shouldn't get client protocol->prepare_for_resend(); protocol->store(table_name, system_charset_info); @@ -2401,13 +2424,6 @@ send_result_message: } close_thread_tables(thd); table->table=0; // For query cache - /* - thd->lex->derived_tables may be set to non zero value if we open - a view. It is necessary to clear thd->lex->derived_tables flag - to prevent processing of derived tables during next open_and_lock_tables - if next table is a real table. - */ - thd->lex->derived_tables= 0; if (protocol->write()) goto err; } From 28f554af12c934acdaa13d673edc5bd51a4567c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Jul 2005 13:55:54 +0200 Subject: [PATCH 157/216] Bug#11401: Setting thd->lex so that engines (i.e., InnoDB) recognizes this as a LOAD DATA ... REPLACE INTO .. statement. sql/log_event.cc: Setting thd->lex so that engines (i.e., InnoDB) recognizes this as a LOAD DATA ... REPLACE INTO .. statement. --- mysql-test/r/rpl_innodb.result | 37 +++++++++++++++++++++ mysql-test/std_data/loaddata_pair.dat | 2 ++ mysql-test/t/rpl_innodb.test | 46 +++++++++++++++++++++++++++ sql/log_event.cc | 15 +++++++++ 4 files changed, 100 insertions(+) create mode 100644 mysql-test/r/rpl_innodb.result create mode 100644 mysql-test/std_data/loaddata_pair.dat create mode 100644 mysql-test/t/rpl_innodb.test diff --git a/mysql-test/r/rpl_innodb.result b/mysql-test/r/rpl_innodb.result new file mode 100644 index 00000000000..ebf1d79c4d0 --- /dev/null +++ b/mysql-test/r/rpl_innodb.result @@ -0,0 +1,37 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t4 ( +id INT(5) unsigned NOT NULL auto_increment, +name varchar(15) NOT NULL default '', +number varchar(35) NOT NULL default 'default', +PRIMARY KEY (id), +UNIQUE KEY unique_rec (name,number) +) ENGINE=InnoDB; +LOAD DATA +INFILE '../../std_data/loaddata_pair.dat' +REPLACE INTO TABLE t4 +(name,number); +SELECT * FROM t4; +id name number +1 XXX 12345 +2 XXY 12345 +SELECT * FROM t4; +id name number +1 XXX 12345 +2 XXY 12345 +LOAD DATA +INFILE '../../std_data/loaddata_pair.dat' +REPLACE INTO TABLE t4 +(name,number); +SELECT * FROM t4; +id name number +3 XXX 12345 +4 XXY 12345 +SELECT * FROM t4; +id name number +3 XXX 12345 +4 XXY 12345 diff --git a/mysql-test/std_data/loaddata_pair.dat b/mysql-test/std_data/loaddata_pair.dat new file mode 100644 index 00000000000..5a4f6b57af8 --- /dev/null +++ b/mysql-test/std_data/loaddata_pair.dat @@ -0,0 +1,2 @@ +XXX 12345 +XXY 12345 diff --git a/mysql-test/t/rpl_innodb.test b/mysql-test/t/rpl_innodb.test new file mode 100644 index 00000000000..b171dced26e --- /dev/null +++ b/mysql-test/t/rpl_innodb.test @@ -0,0 +1,46 @@ +# File for specialities regarding replication from or to InnoDB +# tables. + +source include/master-slave.inc; +source include/have_innodb.inc; + +# +# Bug#11401: Load data infile 'REPLACE INTO' fails on slave. +# +connection master; +CREATE TABLE t4 ( + id INT(5) unsigned NOT NULL auto_increment, + name varchar(15) NOT NULL default '', + number varchar(35) NOT NULL default 'default', + PRIMARY KEY (id), + UNIQUE KEY unique_rec (name,number) +) ENGINE=InnoDB; + +--disable_warnings +LOAD DATA + INFILE '../../std_data/loaddata_pair.dat' + REPLACE INTO TABLE t4 + (name,number); +--enable_warnings +SELECT * FROM t4; + +sync_slave_with_master; +SELECT * FROM t4; + +connection master; +--disable_warnings +LOAD DATA + INFILE '../../std_data/loaddata_pair.dat' + REPLACE INTO TABLE t4 + (name,number); +--enable_warnings +SELECT * FROM t4; + +sync_slave_with_master; +SELECT * FROM t4; + +connection master; +--disable_query_log +DROP TABLE t4; +--enable_query_log +sync_slave_with_master; diff --git a/sql/log_event.cc b/sql/log_event.cc index a4319f63b83..cda385c911b 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1809,11 +1809,25 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, "` <...>", NullS) - load_data_query); thd->query= load_data_query; } + + /* + We need to set thd->lex->sql_command and thd->lex->duplicates + since InnoDB tests these variables to decide if this is a LOAD + DATA ... REPLACE INTO ... statement even though mysql_parse() + is not called. This is not needed in 5.0 since there the LOAD + DATA ... statement is replicated using mysql_parse(), which + sets the thd->lex fields correctly. + */ + thd->lex->sql_command= SQLCOM_LOAD; if (sql_ex.opt_flags & REPLACE_FLAG) + { + thd->lex->duplicates= DUP_REPLACE; handle_dup= DUP_REPLACE; + } else if (sql_ex.opt_flags & IGNORE_FLAG) { ignore= 1; + thd->lex->duplicates= DUP_ERROR; handle_dup= DUP_ERROR; } else @@ -1831,6 +1845,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, If reading from net (a 3.23 master), mysql_load() will change this to IGNORE. */ + thd->lex->duplicates= DUP_ERROR; handle_dup= DUP_ERROR; } From 74c0d194bee3db964bb834e6d4d0b560f3e212fe Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Jul 2005 17:09:56 +0200 Subject: [PATCH 158/216] - disabled openlogging to satisfy BK when using a commercial license key --- BitKeeper/etc/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config index 9df006ac7d5..90033cad7c9 100644 --- a/BitKeeper/etc/config +++ b/BitKeeper/etc/config @@ -24,7 +24,7 @@ description: MySQL - fast and reliable SQL database # repository is commercial it can be an internal email address or "none" # to disable logging. # -logging: logging@openlogging.org +logging: none # # If this field is set, all checkins will appear to be made by this user, # in effect making this a single user package. Single user packages are From d2119109848ec7129ce5372507f36a7f339cdb1a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Jul 2005 17:27:37 +0200 Subject: [PATCH 159/216] lowercase_table2.test, lowercase_table2.result: Use IF EXISTS in initiation section mysql-test/r/lowercase_table2.result: Use IF EXISTS in initiation section mysql-test/t/lowercase_table2.test: Use IF EXISTS in initiation section --- mysql-test/r/lowercase_table2.result | 2 +- mysql-test/t/lowercase_table2.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/lowercase_table2.result b/mysql-test/r/lowercase_table2.result index f93a10dfbad..44235cbf900 100644 --- a/mysql-test/r/lowercase_table2.result +++ b/mysql-test/r/lowercase_table2.result @@ -1,7 +1,7 @@ DROP TABLE IF EXISTS t1,t2,t3,t2aA,t1Aa; DROP DATABASE IF EXISTS `TEST_$1`; DROP DATABASE IF EXISTS `test_$1`; -DROP DATABASE mysqltest_LC2; +DROP DATABASE IF EXISTS mysqltest_LC2; CREATE TABLE T1 (a int); INSERT INTO T1 VALUES (1); SHOW TABLES LIKE "T1"; diff --git a/mysql-test/t/lowercase_table2.test b/mysql-test/t/lowercase_table2.test index 5e38c59386d..f5cf292482e 100644 --- a/mysql-test/t/lowercase_table2.test +++ b/mysql-test/t/lowercase_table2.test @@ -13,7 +13,7 @@ enable_query_log; DROP TABLE IF EXISTS t1,t2,t3,t2aA,t1Aa; DROP DATABASE IF EXISTS `TEST_$1`; DROP DATABASE IF EXISTS `test_$1`; -DROP DATABASE mysqltest_LC2; +DROP DATABASE IF EXISTS mysqltest_LC2; --enable_warnings CREATE TABLE T1 (a int); From 390bc0d6195a2042d0534fcfbdeee336f8b394fe Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Jul 2005 09:45:32 -0700 Subject: [PATCH 160/216] Add documentation to the escape_*() functions in mysys. mysys/charset.c: Add documentation for escape functions Minor style cleanup --- mysys/charset.c | 68 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/mysys/charset.c b/mysys/charset.c index 53d9c4a72a4..4920e7806a2 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -561,11 +561,30 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, DBUG_RETURN(cs); } + /* + Escape string with backslashes (\) + + SYNOPSIS + escape_string_for_mysql() + charset_info Charset of the strings + to Buffer for escaped string + to_length Length of destination buffer, or 0 + from The string to escape + length The length of the string to escape + + DESCRIPTION + This escapes the contents of a string by adding backslashes before special + characters, and turning others into specific escape sequences, such as + turning newlines into \n and null bytes into \0. + NOTE - to keep old C API, to_length may be 0 to mean "big enough" - RETURN - the length of the escaped string or ~0 if it did not fit. + To maintain compatibility with the old C API, to_length may be 0 to mean + "big enough" + + RETURN VALUES + ~0 The escaped string did not fit in the to buffer + >=0 The length of the escaped string */ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to, ulong to_length, @@ -573,20 +592,20 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, { const char *to_start= to; const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length); - my_bool overflow=0; + my_bool overflow= FALSE; #ifdef USE_MB my_bool use_mb_flag= use_mb(charset_info); #endif for (end= from + length; from < end; from++) { - char escape=0; + char escape= 0; #ifdef USE_MB int tmp_length; if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end))) { if (to + tmp_length > to_end) { - overflow=1; + overflow= TRUE; break; } while (tmp_length--) @@ -636,7 +655,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, { if (to + 2 > to_end) { - overflow=1; + overflow= TRUE; break; } *to++= '\\'; @@ -646,7 +665,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, { if (to + 1 > to_end) { - overflow=1; + overflow= TRUE; break; } *to++= *from; @@ -658,11 +677,28 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, /* + Escape apostrophes by doubling them up + + SYNOPSIS + escape_quotes_for_mysql() + charset_info Charset of the strings + to Buffer for escaped string + to_length Length of destination buffer, or 0 + from The string to escape + length The length of the string to escape + + DESCRIPTION + This escapes the contents of a string by doubling up any apostrophes that + it contains. This is used when the NO_BACKSLASH_ESCAPES SQL_MODE is in + effect on the server. + NOTE - to be consistent with escape_string_for_mysql(), to_length may be 0 to + To be consistent with escape_string_for_mysql(), to_length may be 0 to mean "big enough" - RETURN - the length of the escaped string or ~0 if it did not fit. + + RETURN VALUES + ~0 The escaped string did not fit in the to buffer + >=0 The length of the escaped string */ ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info, char *to, ulong to_length, @@ -670,20 +706,20 @@ ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info, { const char *to_start= to; const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length); - my_bool overflow=0; + my_bool overflow= FALSE; #ifdef USE_MB my_bool use_mb_flag= use_mb(charset_info); #endif for (end= from + length; from < end; from++) { - char escape=0; + char escape= 0; #ifdef USE_MB int tmp_length; if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end))) { if (to + tmp_length > to_end) { - overflow=1; + overflow= TRUE; break; } while (tmp_length--) @@ -701,7 +737,7 @@ ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info, { if (to + 2 > to_end) { - overflow=1; + overflow= TRUE; break; } *to++= '\''; @@ -711,7 +747,7 @@ ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info, { if (to + 1 > to_end) { - overflow=1; + overflow= TRUE; break; } *to++= *from; From b0a6a8e13780182a172b2c0a5b6ef008b6d0645f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Jul 2005 23:24:48 +0200 Subject: [PATCH 161/216] Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir client/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir cmd-line-utils/libedit/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir dbug/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir extra/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir heap/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir isam/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir libmysql/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir libmysql_r/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir libmysqld/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir libmysqld/examples/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir merge/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir myisam/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir myisammrg/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir mysql-test/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir mysys/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir netware/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir regex/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir sql/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir strings/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir tests/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir vio/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir tools/Makefile.am: Added -I$(top_builddir)/include for searching generated header files, when builddir != srcdir --- client/Makefile.am | 4 ++-- cmd-line-utils/libedit/Makefile.am | 3 ++- cmd-line-utils/readline/Makefile.am | 3 ++- dbug/Makefile.am | 3 ++- extra/Makefile.am | 3 ++- heap/Makefile.am | 3 ++- isam/Makefile.am | 3 ++- libmysql/Makefile.am | 3 ++- libmysql_r/Makefile.am | 5 +++-- libmysqld/Makefile.am | 3 ++- libmysqld/examples/Makefile.am | 3 ++- merge/Makefile.am | 3 ++- myisam/Makefile.am | 3 ++- myisammrg/Makefile.am | 3 ++- mysql-test/Makefile.am | 2 +- mysys/Makefile.am | 3 ++- netware/Makefile.am | 2 +- regex/Makefile.am | 3 ++- sql/Makefile.am | 4 ++-- strings/Makefile.am | 3 ++- tests/Makefile.am | 3 ++- tools/Makefile.am | 8 +++++--- vio/Makefile.am | 3 ++- 23 files changed, 48 insertions(+), 28 deletions(-) diff --git a/client/Makefile.am b/client/Makefile.am index da13c3e9763..1e8851fb3b9 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -17,8 +17,8 @@ # This file is public domain and comes with NO WARRANTY of any kind #AUTOMAKE_OPTIONS = nostdinc -INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/regex \ - $(openssl_includes) +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ + -I$(top_srcdir)/regex $(openssl_includes) LIBS = @CLIENT_LIBS@ LDADD= @CLIENT_EXTRA_LDFLAGS@ \ $(top_builddir)/libmysql/libmysqlclient.la diff --git a/cmd-line-utils/libedit/Makefile.am b/cmd-line-utils/libedit/Makefile.am index 03f3eb65fbc..af1bf8b2c97 100644 --- a/cmd-line-utils/libedit/Makefile.am +++ b/cmd-line-utils/libedit/Makefile.am @@ -5,7 +5,8 @@ ASRC=vi.c emacs.c common.c AHDR=vi.h emacs.h common.h -INCLUDES = -I$(top_srcdir)/include -I$(srcdir)/../.. -I.. +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ + -I$(srcdir)/../.. -I.. noinst_LIBRARIES = libedit.a diff --git a/cmd-line-utils/readline/Makefile.am b/cmd-line-utils/readline/Makefile.am index 87880517166..14d25ff62c0 100644 --- a/cmd-line-utils/readline/Makefile.am +++ b/cmd-line-utils/readline/Makefile.am @@ -3,7 +3,8 @@ # Copyright (C) 1994,1996,1997 Free Software Foundation, Inc. # Last -I$(top_srcdir) needed for RedHat! -INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir) +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ + -I$(top_srcdir) noinst_LIBRARIES = libreadline.a diff --git a/dbug/Makefile.am b/dbug/Makefile.am index bd512ee1d1d..3ddb5bc17e1 100644 --- a/dbug/Makefile.am +++ b/dbug/Makefile.am @@ -15,7 +15,8 @@ # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, # MA 02111-1307, USA -INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include +INCLUDES = @MT_INCLUDES@ \ + -I$(top_builddir)/include -I$(top_srcdir)/include LDADD = libdbug.a ../strings/libmystrings.a pkglib_LIBRARIES = libdbug.a noinst_HEADERS = dbug_long.h diff --git a/extra/Makefile.am b/extra/Makefile.am index aec7ad7dda5..467f426f1a5 100644 --- a/extra/Makefile.am +++ b/extra/Makefile.am @@ -14,7 +14,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include \ +INCLUDES = @MT_INCLUDES@ \ + -I$(top_builddir)/include -I$(top_srcdir)/include \ @ndbcluster_includes@ -I$(top_srcdir)/sql LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \ ../dbug/libdbug.a ../strings/libmystrings.a diff --git a/heap/Makefile.am b/heap/Makefile.am index ec631148dce..9ce09757802 100644 --- a/heap/Makefile.am +++ b/heap/Makefile.am @@ -14,7 +14,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include +INCLUDES = @MT_INCLUDES@ \ + -I$(top_builddir)/include -I$(top_srcdir)/include LDADD = libheap.a ../mysys/libmysys.a ../dbug/libdbug.a \ ../strings/libmystrings.a pkglib_LIBRARIES = libheap.a diff --git a/isam/Makefile.am b/isam/Makefile.am index 6d9e4176d43..335346d2423 100644 --- a/isam/Makefile.am +++ b/isam/Makefile.am @@ -14,7 +14,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include +INCLUDES = @MT_INCLUDES@ \ + -I$(top_builddir)/include -I$(top_srcdir)/include LDADD = @CLIENT_EXTRA_LDFLAGS@ libnisam.a ../mysys/libmysys.a \ ../dbug/libdbug.a ../strings/libmystrings.a pkglib_LIBRARIES = libnisam.a diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am index 72ff44ecef3..4bd9eddafb0 100644 --- a/libmysql/Makefile.am +++ b/libmysql/Makefile.am @@ -23,7 +23,8 @@ target = libmysqlclient.la target_defs = -DUNDEF_THREADS_HACK -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@ LIBS = @CLIENT_LIBS@ -INCLUDES = -I$(top_srcdir)/include $(openssl_includes) @ZLIB_INCLUDES@ +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ + $(openssl_includes) @ZLIB_INCLUDES@ include $(srcdir)/Makefile.shared diff --git a/libmysql_r/Makefile.am b/libmysql_r/Makefile.am index 0a5c380ff35..a76ef675189 100644 --- a/libmysql_r/Makefile.am +++ b/libmysql_r/Makefile.am @@ -24,8 +24,9 @@ target = libmysqlclient_r.la target_defs = -DDONT_USE_RAID -DMYSQL_CLIENT @LIB_EXTRA_CCFLAGS@ LIBS = @LIBS@ @ZLIB_LIBS@ @openssl_libs@ -INCLUDES = @MT_INCLUDES@ \ - -I$(top_srcdir)/include $(openssl_includes) @ZLIB_INCLUDES@ +INCLUDES = @MT_INCLUDES@ \ + -I$(top_builddir)/include -I$(top_srcdir)/include \ + $(openssl_includes) @ZLIB_INCLUDES@ ## automake barfs if you don't use $(srcdir) or $(top_srcdir) in include include $(top_srcdir)/libmysql/Makefile.shared diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index f578e87ae4a..f4e9d4e6b39 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -25,7 +25,8 @@ DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \ -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \ -DDATADIR="\"$(MYSQLDATAdir)\"" \ -DSHAREDIR="\"$(MYSQLSHAREdir)\"" -INCLUDES= @MT_INCLUDES@ @bdb_includes@ -I$(top_srcdir)/include \ +INCLUDES= @MT_INCLUDES@ @bdb_includes@ \ + -I$(top_builddir)/include -I$(top_srcdir)/include \ -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples -I$(top_srcdir)/regex \ $(openssl_includes) @ZLIB_INCLUDES@ diff --git a/libmysqld/examples/Makefile.am b/libmysqld/examples/Makefile.am index 278aa66b328..d19023c100f 100644 --- a/libmysqld/examples/Makefile.am +++ b/libmysqld/examples/Makefile.am @@ -30,7 +30,8 @@ link_sources: done; DEFS = -DEMBEDDED_LIBRARY -INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include -I$(srcdir) \ +INCLUDES = @MT_INCLUDES@ \ + -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir) \ -I$(top_srcdir) -I$(top_srcdir)/client -I$(top_srcdir)/regex \ $(openssl_includes) LIBS = @LIBS@ @WRAPLIBS@ @CLIENT_LIBS@ diff --git a/merge/Makefile.am b/merge/Makefile.am index 25e15e9c6ec..080e5e61747 100644 --- a/merge/Makefile.am +++ b/merge/Makefile.am @@ -14,7 +14,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include +INCLUDES = @MT_INCLUDES@ \ + -I$(top_builddir)/include -I$(top_srcdir)/include pkglib_LIBRARIES = libmerge.a noinst_HEADERS = mrg_def.h libmerge_a_SOURCES = mrg_open.c mrg_extra.c mrg_info.c mrg_locking.c \ diff --git a/myisam/Makefile.am b/myisam/Makefile.am index 0b8a25e3404..6f304c8143d 100644 --- a/myisam/Makefile.am +++ b/myisam/Makefile.am @@ -17,7 +17,8 @@ EXTRA_DIST = mi_test_all.sh mi_test_all.res pkgdata_DATA = mi_test_all mi_test_all.res -INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include +INCLUDES = @MT_INCLUDES@ \ + -I$(top_builddir)/include -I$(top_srcdir)/include LDADD = @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/dbug/libdbug.a \ diff --git a/myisammrg/Makefile.am b/myisammrg/Makefile.am index b5b1260385b..3cd8cfdedea 100644 --- a/myisammrg/Makefile.am +++ b/myisammrg/Makefile.am @@ -14,7 +14,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include +INCLUDES = @MT_INCLUDES@ \ + -I$(top_builddir)/include -I$(top_srcdir)/include pkglib_LIBRARIES = libmyisammrg.a noinst_HEADERS = myrg_def.h libmyisammrg_a_SOURCES = myrg_open.c myrg_extra.c myrg_info.c myrg_locking.c \ diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 0c27edb02e7..e7abcd3fc95 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -39,7 +39,7 @@ test_DATA = std_data/client-key.pem std_data/client-cert.pem std_data/cacert.pem std_data/server-cert.pem std_data/server-key.pem CLEANFILES = $(test_SCRIPTS) $(test_DATA) -INCLUDES = -I$(srcdir)/../include -I../include -I.. +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I.. EXTRA_PROGRAMS = mysql_test_run_new noinst_HEADERS = my_manage.h mysql_test_run_new_SOURCES= mysql_test_run_new.c my_manage.c my_create_tables.c diff --git a/mysys/Makefile.am b/mysys/Makefile.am index ab35ccb21ba..a80df810c1c 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -18,7 +18,8 @@ MYSQLDATAdir = $(localstatedir) MYSQLSHAREdir = $(pkgdatadir) MYSQLBASEdir= $(prefix) INCLUDES = @MT_INCLUDES@ \ - @ZLIB_INCLUDES@ -I$(top_srcdir)/include -I$(srcdir) + @ZLIB_INCLUDES@ -I$(top_builddir)/include \ + -I$(top_srcdir)/include -I$(srcdir) pkglib_LIBRARIES = libmysys.a LDADD = libmysys.a ../dbug/libdbug.a \ ../strings/libmystrings.a diff --git a/netware/Makefile.am b/netware/Makefile.am index 2467270f27b..aeb93d1575d 100644 --- a/netware/Makefile.am +++ b/netware/Makefile.am @@ -15,7 +15,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA if HAVE_NETWARE -INCLUDES = -I$(srcdir)/../include -I../include -I.. +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I.. LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \ ../dbug/libdbug.a ../strings/libmystrings.a bin_PROGRAMS = mysqld_safe mysql_install_db mysql_test_run libmysql diff --git a/regex/Makefile.am b/regex/Makefile.am index ee7fc5463b7..bcba6818b1b 100644 --- a/regex/Makefile.am +++ b/regex/Makefile.am @@ -15,7 +15,8 @@ # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, # MA 02111-1307, USA -INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include +INCLUDES = @MT_INCLUDES@ \ + -I$(top_builddir)/include -I$(top_srcdir)/include noinst_LIBRARIES = libregex.a LDADD= libregex.a $(top_builddir)/strings/libmystrings.a noinst_HEADERS = cclass.h cname.h regex2.h utils.h engine.c regex.h diff --git a/sql/Makefile.am b/sql/Makefile.am index a76adbd0d57..ea7cea9c7b9 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -21,8 +21,8 @@ MYSQLSHAREdir = $(pkgdatadir) MYSQLBASEdir= $(prefix) INCLUDES = @MT_INCLUDES@ @ZLIB_INCLUDES@ \ @bdb_includes@ @innodb_includes@ @ndbcluster_includes@ \ - -I$(top_srcdir)/include -I$(top_srcdir)/regex \ - -I$(srcdir) $(openssl_includes) + -I$(top_builddir)/include -I$(top_srcdir)/include \ + -I$(top_srcdir)/regex -I$(srcdir) $(openssl_includes) WRAPLIBS= @WRAPLIBS@ SUBDIRS = share libexec_PROGRAMS = mysqld diff --git a/strings/Makefile.am b/strings/Makefile.am index fa149817270..3f954f3c6a0 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -16,7 +16,8 @@ # This file is public domain and comes with NO WARRANTY of any kind -INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include +INCLUDES = @MT_INCLUDES@ \ + -I$(top_builddir)/include -I$(top_srcdir)/include pkglib_LIBRARIES = libmystrings.a # Exact one of ASSEMBLER_X diff --git a/tests/Makefile.am b/tests/Makefile.am index de4fbb2a4f2..3c781b7e45b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -32,7 +32,8 @@ noinst_PROGRAMS = insert_test select_test thread_test # # C Test for 4.1 protocol # -INCLUDES = -I$(top_srcdir)/include $(openssl_includes) +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ + $(openssl_includes) LIBS = @CLIENT_LIBS@ LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysql/libmysqlclient.la mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) diff --git a/tools/Makefile.am b/tools/Makefile.am index 5528df4dd68..bf81005ca2c 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -15,9 +15,11 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Process this file with automake to create Makefile.in -INCLUDES=@MT_INCLUDES@ -I$(top_srcdir)/include $(openssl_includes) -LDADD= @CLIENT_EXTRA_LDFLAGS@ @openssl_libs@ \ - $(top_builddir)/libmysql_r/libmysqlclient_r.la @ZLIB_LIBS@ +INCLUDES= @MT_INCLUDES@ -I$(top_builddir)/include \ + -I$(top_srcdir)/include $(openssl_includes) +LDADD= @CLIENT_EXTRA_LDFLAGS@ @openssl_libs@ \ + $(top_builddir)/libmysql_r/libmysqlclient_r.la \ + @ZLIB_LIBS@ bin_PROGRAMS= mysqlmanager mysqlmanager_SOURCES= mysqlmanager.c mysqlmanager_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES) diff --git a/vio/Makefile.am b/vio/Makefile.am index 9c961025080..e27daa7ac35 100644 --- a/vio/Makefile.am +++ b/vio/Makefile.am @@ -14,7 +14,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -INCLUDES= -I$(top_srcdir)/include $(openssl_includes) +INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include \ + $(openssl_includes) LDADD= @CLIENT_EXTRA_LDFLAGS@ $(openssl_libs) pkglib_LIBRARIES= libvio.a noinst_PROGRAMS = test-ssl test-sslserver test-sslclient From 8218398c6ae4020c9eae9fd25ebb3a266db45035 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Jul 2005 15:19:04 -0700 Subject: [PATCH 162/216] Fix test cases mysql-test/r/query_cache.result: Remove stray empty line mysql-test/r/grant.result: Update results mysql-test/t/grant.test: Fix test case to --- mysql-test/r/grant.result | 3 ++- mysql-test/r/query_cache.result | 1 - mysql-test/t/grant.test | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 3a793ef55e4..e9e1d4cd620 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -436,6 +436,7 @@ revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; delete from mysql.user where user=_binary'mysqltest_1'; drop database mysqltest; use mysql; -insert into tables_priv values ('','mysqltest_1','test_table','test_grantor','',CURRENT_TIMESTAMP,'Select','Select'); +insert into tables_priv values ('','test_db','mysqltest_1','test_table','test_grantor',CURRENT_TIMESTAMP,'Select','Select'); flush privileges; delete from tables_priv where host = '' and user = 'mysqltest_1'; +flush privileges; diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 3af0d4c3704..2884b9b3fe4 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -1057,6 +1057,5 @@ Qcache_inserts 2 show status like "Qcache_hits"; Variable_name Value Qcache_hits 1 - drop table t1; set GLOBAL query_cache_size=0; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index d80ef638e79..6c38aac1ebd 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -397,6 +397,7 @@ drop database mysqltest; # connection default; use mysql; -insert into tables_priv values ('','mysqltest_1','test_table','test_grantor','',CURRENT_TIMESTAMP,'Select','Select'); +insert into tables_priv values ('','test_db','mysqltest_1','test_table','test_grantor',CURRENT_TIMESTAMP,'Select','Select'); flush privileges; delete from tables_priv where host = '' and user = 'mysqltest_1'; +flush privileges; From de40177365db3a3a36a2f78087ff331ad16c4e16 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Jul 2005 18:23:55 -0700 Subject: [PATCH 163/216] Update test results mysql-test/r/mysqldump.result: Update results --- mysql-test/r/mysqldump.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 091d21cfa20..be2003bbc67 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1665,7 +1665,7 @@ v2 VIEW v3 VIEW show create view v1; View Create View -v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`v3`.`a` AS `a`,`test`.`v3`.`b` AS `b`,`test`.`v3`.`c` AS `c` from `test`.`v3` where (`test`.`v3`.`b` in (1,2,3,4,5,6,7)) +v1 CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `v3`.`a` AS `a`,`v3`.`b` AS `b`,`v3`.`c` AS `c` from `test`.`v3` where (`v3`.`b` in (1,2,3,4,5,6,7)) select * from v1; a b c 1 2 one From ec6b1999a5c51f108a49d3b15a7dd935febb1632 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 09:38:31 +0300 Subject: [PATCH 164/216] InnoDB: Make the srv_thread_concurrency checks more consistent. innobase/include/srv0srv.h: Define SRV_CONCURRENCY_THRESHOLD innobase/srv/srv0srv.c: Remove srv_thread_concurrency check from srv_conc_enter_innodb() and srv_conc_exit_innodb(), as the check is in the (only) caller of these functions, in ha_innodb.cc. srv_conc_force_enter_innodb(), srv_conc_force_exit_innodb(): Check for srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD sql/ha_innodb.cc: Make use of SRV_CONCURRENCY_THRESHOLD --- innobase/include/srv0srv.h | 1 + innobase/srv/srv0srv.c | 17 +++-------------- sql/ha_innodb.cc | 4 ++-- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 6e4241965c1..116ae7b6438 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -182,6 +182,7 @@ extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs, #define kernel_mutex (*kernel_mutex_temp) #define SRV_MAX_N_IO_THREADS 100 +#define SRV_CONCURRENCY_THRESHOLD 20 /* Array of English strings describing the current state of an i/o handler thread */ diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index f901425a5f9..837c5be2bb6 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -260,7 +260,7 @@ semaphore contention and convoy problems can occur withput this restriction. Value 10 should be good if there are less than 4 processors + 4 disks in the computer. Bigger computers need bigger values. */ -ulong srv_thread_concurrency = 8; +ulong srv_thread_concurrency = SRV_CONCURRENCY_THRESHOLD; os_fast_mutex_t srv_conc_mutex; /* this mutex protects srv_conc data structures */ @@ -983,12 +983,6 @@ srv_conc_enter_innodb( srv_conc_slot_t* slot = NULL; ulint i; - if (srv_thread_concurrency >= 500) { - /* Disable the concurrency check */ - - return; - } - /* If trx has 'free tickets' to enter the engine left, then use one such ticket */ @@ -1134,7 +1128,7 @@ srv_conc_force_enter_innodb( trx_t* trx) /* in: transaction object associated with the thread */ { - if (srv_thread_concurrency >= 500) { + if (srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD) { return; } @@ -1160,7 +1154,7 @@ srv_conc_force_exit_innodb( { srv_conc_slot_t* slot = NULL; - if (srv_thread_concurrency >= 500) { + if (srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD) { return; } @@ -1212,11 +1206,6 @@ srv_conc_exit_innodb( trx_t* trx) /* in: transaction object associated with the thread */ { - if (srv_thread_concurrency >= 500) { - - return; - } - if (trx->n_tickets_to_enter_innodb > 0) { /* We will pretend the thread is still inside InnoDB though it now leaves the InnoDB engine. In this way we save diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 8218e4fecc0..e33a0939e27 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -326,7 +326,7 @@ innodb_srv_conc_enter_innodb( /*=========================*/ trx_t* trx) /* in: transaction handle */ { - if (UNIV_LIKELY(srv_thread_concurrency >= 20)) { + if (UNIV_LIKELY(srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD)) { return; } @@ -343,7 +343,7 @@ innodb_srv_conc_exit_innodb( /*========================*/ trx_t* trx) /* in: transaction handle */ { - if (UNIV_LIKELY(srv_thread_concurrency >= 20)) { + if (UNIV_LIKELY(srv_thread_concurrency >= SRV_CONCURRENCY_THRESHOLD)) { return; } From 4727620b0de2f366031e871d632d441fb20d7687 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 11:34:53 +0400 Subject: [PATCH 165/216] After merge fix. mysql-test/t/sp-error.test: Fixed error-codes after merging changes from the main tree. --- mysql-test/t/sp-error.test | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 1290457ad3b..a61c082fb30 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -993,7 +993,7 @@ begin end| # If we allow recursive functions without additional modifications # this will crash server since Item for "IN" is not reenterable. ---error 1423 +--error 1424 select bug11394(2)| drop function bug11394| create function bug11394_1(i int) returns int @@ -1006,7 +1006,7 @@ begin end| # The following statement will crash because some LEX members responsible # for selects cannot be used in reentrant fashion. ---error 1423 +--error 1424 select bug11394_1(2)| drop function bug11394_1| # Note that the following should be allowed since it does not contains @@ -1022,7 +1022,7 @@ begin end| # Again if we allow recursion for stored procedures (without # additional efforts) the following statement will crash the server. ---error 1423 +--error 1424 call bug11394(2, 1)| drop procedure bug11394| delimiter |; From 87b7e20ebd16f65b1d59597f2b5d8109ba6849aa Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 10:16:36 +0200 Subject: [PATCH 166/216] init_db.sql: add new table privileges Makefile.am: Include path to regex dir was accidently removed sql/Makefile.am: Include path to regex dir was accidently removed mysql-test/lib/init_db.sql: add new table privileges --- mysql-test/lib/init_db.sql | 2 +- sql/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/lib/init_db.sql b/mysql-test/lib/init_db.sql index 9671de49ca5..77f9b18cb08 100644 --- a/mysql-test/lib/init_db.sql +++ b/mysql-test/lib/init_db.sql @@ -128,7 +128,7 @@ CREATE TABLE tables_priv ( Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp(14), - Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') COLLATE utf8_general_ci DEFAULT '' NOT NULL, + Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name),KEY Grantor (Grantor) ) engine=MyISAM diff --git a/sql/Makefile.am b/sql/Makefile.am index 4491b8a2e31..cabb4fee905 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -22,7 +22,7 @@ MYSQLBASEdir= $(prefix) INCLUDES = @ZLIB_INCLUDES@ \ @bdb_includes@ @innodb_includes@ @ndbcluster_includes@ \ -I$(top_builddir)/include -I$(top_srcdir)/include \ - -I$(srcdir) $(openssl_includes) + -I$(top_srcdir)/regex -I$(srcdir) $(openssl_includes) WRAPLIBS= @WRAPLIBS@ SUBDIRS = share libexec_PROGRAMS = mysqld From 502aa66c5c176341def1723c8ef24c3be78e8df1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 13:51:53 +0500 Subject: [PATCH 167/216] a fix (bug #11544: Use of missing rint() function on QNX). include/my_global.h: a fix (bug #11544: Use of missing rint() function on QNX). We have to explicitly specify std:: namespace to use rint() and isnan() functions in C++ scope on QNX due to an error in the /usr/include/math.h --- include/my_global.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/my_global.h b/include/my_global.h index 9b53be66db0..f2fa54f3e4a 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -318,6 +318,11 @@ C_MODE_END #undef HAVE_FINITE #undef LONGLONG_MIN /* These get wrongly defined in QNX 6.2 */ #undef LONGLONG_MAX /* standard system library 'limits.h' */ +#ifdef __cplusplus +#define HAVE_RINT /* rint() and isnan() functions are not */ +#define rint(a) std::rint(a) /* visible in C++ scope due to an error */ +#define isnan(a) std::isnan(a) /* in the usr/include/math.h on QNX */ +#endif #endif /* We can not live without the following defines */ From 6ef62738fe196bba171f047a31312b91f3b7e226 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 11:23:36 +0200 Subject: [PATCH 168/216] Fixed handling of failed primary key update in INSERT .. ON DUPLICATE KEY UPDATE .. --- sql/ha_ndbcluster.cc | 15 ++++++++++----- sql/ha_ndbcluster.h | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 4f35bf07cc1..e14d4b13311 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1113,7 +1113,7 @@ int ha_ndbcluster::set_primary_key(NdbOperation *op, const byte *key) } -int ha_ndbcluster::set_primary_key_from_record(NdbOperation *op, const byte *old_data) +int ha_ndbcluster::set_primary_key_from_record(NdbOperation *op, const byte *record) { KEY* key_info= table->key_info + table->primary_key; KEY_PART_INFO* key_part= key_info->key_part; @@ -1124,7 +1124,7 @@ int ha_ndbcluster::set_primary_key_from_record(NdbOperation *op, const byte *old { Field* field= key_part->field; if (set_ndb_key(op, field, - key_part->fieldnr-1, old_data+key_part->offset)) + key_part->fieldnr-1, record+key_part->offset)) ERR_RETURN(op->getNdbError()); } DBUG_RETURN(0); @@ -2009,7 +2009,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) if ((table->primary_key != MAX_KEY) && (key_cmp(table->primary_key, old_data, new_data))) { - int read_res, insert_res, delete_res; + int read_res, insert_res, delete_res, undo_res; DBUG_PRINT("info", ("primary key update, doing pk read+delete+insert")); // Get all old fields, since we optimize away fields not in query @@ -2038,9 +2038,14 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data) DBUG_PRINT("info", ("insert failed")); if (trans->commitStatus() == NdbConnection::Started) { - // Undo write_row(new_data) + // Undo delete_row(old_data) m_primary_key_update= TRUE; - insert_res= write_row((byte *)old_data); + undo_res= write_row((byte *)old_data); + if (undo_res) + push_warning(current_thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + undo_res, + "NDB failed undoing delete at primary key update"); m_primary_key_update= FALSE; } DBUG_RETURN(insert_res); diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 8e44733f905..4b3a30fb9b9 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -196,7 +196,7 @@ class ha_ndbcluster: public handler friend int g_get_ndb_blobs_value(NdbBlob *ndb_blob, void *arg); int get_ndb_blobs_value(NdbBlob *last_ndb_blob); int set_primary_key(NdbOperation *op, const byte *key); - int set_primary_key_from_record(NdbOperation *op, const byte *old_data); + int set_primary_key_from_record(NdbOperation *op, const byte *record); int set_bounds(NdbIndexScanOperation *ndb_op, const key_range *keys[2]); int key_cmp(uint keynr, const byte * old_row, const byte * new_row); void print_results(); From 6dc280da7c8fbea12ee010f92e5698833053c7e9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 12:54:22 +0200 Subject: [PATCH 169/216] Increase version number to 5.0.10, as 5.0.9 has been cloned off. --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index a37963911b9..21494999ca4 100644 --- a/configure.in +++ b/configure.in @@ -6,7 +6,7 @@ AC_PREREQ(2.58)dnl Minimum Autoconf version required. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # Don't forget to also update the NDB lines below. -AM_INIT_AUTOMAKE(mysql, 5.0.9-beta) +AM_INIT_AUTOMAKE(mysql, 5.0.10-beta) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -17,7 +17,7 @@ SHARED_LIB_VERSION=14:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=9 +NDB_VERSION_BUILD=10 NDB_VERSION_STATUS="beta" # Set all version vars based on $VERSION. How do we do this more elegant ? From 2a04d15596aa2f86fcfc1291f1460e8b92060e39 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 13:58:29 +0200 Subject: [PATCH 170/216] - backported a change for make_binary_distribution.sh from 5.0 for easier building of all versions: added an option "--machine" that allows to override the autodetected architecture string (e.g. "i386") that becomes part of the binary package name with a different one - moved the removal of the BASE directory to the end of the make_binary_distribution script scripts/make_binary_distribution.sh: - backported and fixed a change from 5.0 for easier building of all versions: added an option "--machine" that allows to override the autodetected architecture string (e.g. "i386") that becomes part of the binary package name with a different one - moved the removal of the BASE directory to the end of the script --- scripts/make_binary_distribution.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index ffef1648954..0236d8b8bfe 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -15,6 +15,7 @@ MV="mv" STRIP=1 DEBUG=0 SILENT=0 +MACHINE= TMP=/tmp SUFFIX="" @@ -25,6 +26,7 @@ parse_arguments() { --tmp=*) TMP=`echo "$arg" | sed -e "s;--tmp=;;"` ;; --suffix=*) SUFFIX=`echo "$arg" | sed -e "s;--suffix=;;"` ;; --no-strip) STRIP=0 ;; + --machine=*) MACHINE=`echo "$arg" | sed -e "s;--machine=;;"` ;; --silent) SILENT=1 ;; *) echo "Unknown argument '$arg'" @@ -252,8 +254,17 @@ if [ -d $BASE/sql-bench/SCCS ] ; then find $BASE/sql-bench -name SCCS -print | xargs rm -r -f fi +# Use the override --machine if present +if [ -n "$MACHINE" ] ; then + machine=$MACHINE +fi + # Change the distribution to a long descriptive name NEW_NAME=mysql@MYSQL_SERVER_SUFFIX@-$version-$system-$machine$SUFFIX + +# Print the platform name for build logs +echo "PLATFORM NAME: $system-$machine" + BASE2=$TMP/$NEW_NAME rm -r -f $BASE2 mv $BASE $BASE2 From b5081acd660fef8092d119287388f6f37e4c6e49 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 16:17:32 +0200 Subject: [PATCH 171/216] mysql-test-run.pl: Handle case where SHELL isn't set in Cygwin mysql_client_test.dsp: Put output into the "client_debug" and "client_release" directories VC++Files/tests/mysql_client_test.dsp: Put output into the "client_debug" and "client_release" directories mysql-test/mysql-test-run.pl: Handle case where SHELL isn't set in Cygwin --- VC++Files/tests/mysql_client_test.dsp | 8 ++++---- mysql-test/mysql-test-run.pl | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/VC++Files/tests/mysql_client_test.dsp b/VC++Files/tests/mysql_client_test.dsp index 14873c8a94c..d862425d602 100644 --- a/VC++Files/tests/mysql_client_test.dsp +++ b/VC++Files/tests/mysql_client_test.dsp @@ -51,8 +51,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\mysql_client_test.exe" /incremental:yes /libpath:"..\lib_debug\" /debug /pdb:".\Debug\mysql_client_test.pdb" /pdbtype:sept /map:".\Debug\mysql_client_test.map" /subsystem:console -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\mysql_client_test.exe" /incremental:yes /libpath:"..\lib_debug\" /debug /pdb:".\Debug\mysql_client_test.pdb" /pdbtype:sept /map:".\Debug\mysql_client_test.map" /subsystem:console +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\client_debug\mysql_client_test.exe" /incremental:yes /libpath:"..\lib_debug\" /debug /pdb:".\Debug\mysql_client_test.pdb" /pdbtype:sept /map:".\Debug\mysql_client_test.map" /subsystem:console +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib /nologo /out:"..\client_debug\mysql_client_test.exe" /incremental:yes /libpath:"..\lib_debug\" /debug /pdb:".\Debug\mysql_client_test.pdb" /pdbtype:sept /map:".\Debug\mysql_client_test.map" /subsystem:console !ELSEIF "$(CFG)" == "mysql_client_test - Win32 Release" @@ -76,8 +76,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /out:"..\mysql_client_test.exe" /incremental:no /pdb:".\Release\mysql_client_test.pdb" /pdbtype:sept /subsystem:console -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /out:"..\mysql_client_test.exe" /incremental:no /pdb:".\Release\mysql_client_test.pdb" /pdbtype:sept /subsystem:console +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /out:"..\client_release\mysql_client_test.exe" /incremental:no /pdb:".\Release\mysql_client_test.pdb" /pdbtype:sept /subsystem:console +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /out:"..\client_release\mysql_client_test.exe" /incremental:no /pdb:".\Release\mysql_client_test.pdb" /pdbtype:sept /subsystem:console !ENDIF diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 1a31bbee1d5..e2637cfa6ee 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -419,7 +419,8 @@ sub initial_setup () { { # Windows programs like 'mysqld' needs Windows paths $glob_mysql_test_dir= `cygpath -m $glob_mysql_test_dir`; - $glob_cygwin_shell= `cygpath -w $ENV{'SHELL'}`; # The Windows path c:\... + my $shell= $ENV{'SHELL'} || "/bin/bash"; + $glob_cygwin_shell= `cygpath -w $shell`; # The Windows path c:\... chomp($glob_mysql_test_dir); chomp($glob_cygwin_shell); } From 23cc60108998d941431f638abb409f5eb421847e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 16:37:57 +0200 Subject: [PATCH 172/216] Fixed BUG#7088: Stored procedures: labels won't work if character set is utf8. We used 'IDENT' for labels as a temporary fix for the parser conflicts introduced if the proper rule 'ident' was used. Now a specially tailored 'label_ident' rule is used for labels instead. mysql-test/r/sp.result: New test cases for BUG#7088. mysql-test/t/sp.test: New test cases for BUG#7088. sql/sql_yacc.yy: Make labels in stored procedures work with other character sets than latin1. Using a separate 'label_ident' rule (instead of 'ident') and splitting the 'keyword' rule into two got rid of the temporary fix of using 'IDENT' for labels (which didn't heed character sets). --- mysql-test/r/sp.result | 29 ++++++++++++ mysql-test/t/sp.test | 33 ++++++++++++- sql/sql_yacc.yy | 103 ++++++++++++++++++++++++----------------- 3 files changed, 121 insertions(+), 44 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 7b99a3bacd0..6a85c6afc85 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3101,4 +3101,33 @@ call bug11529()| call bug11529()| delete from t1| drop procedure bug11529| +drop procedure if exists bug6063| +drop procedure if exists bug7088_1| +drop procedure if exists bug7088_2| +create procedure bug6063() +lbel: begin end| +call bug6063()| +show create procedure bug6063| +Procedure sql_mode Create Procedure +bug6063 CREATE PROCEDURE `test`.`bug6063`() +l?bel: begin end +set character set utf8| +create procedure bug7088_1() +label1: begin end| +create procedure bug7088_2() +läbel1: begin end| +call bug7088_1()| +call bug7088_2()| +set character set default| +show create procedure bug7088_1| +Procedure sql_mode Create Procedure +bug7088_1 CREATE PROCEDURE `test`.`bug7088_1`() +label1: begin end +show create procedure bug7088_2| +Procedure sql_mode Create Procedure +bug7088_2 CREATE PROCEDURE `test`.`bug7088_2`() +lbel1: begin end +drop procedure bug6063| +drop procedure bug7088_1| +drop procedure bug7088_2| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 7455bc139dc..da9f6be9aed 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -3799,6 +3799,38 @@ delete from t1| drop procedure bug11529| +# +# BUG#6063: Stored procedure labels are subject to restrictions (partial) +# BUG#7088: Stored procedures: labels won't work if character set is utf8 +# +--disable_warnings +drop procedure if exists bug6063| +drop procedure if exists bug7088_1| +drop procedure if exists bug7088_2| +--enable_warnings + +create procedure bug6063() + lbel: begin end| +call bug6063()| +# QQ Known bug: this will not show the label correctly. +show create procedure bug6063| + +set character set utf8| +create procedure bug7088_1() + label1: begin end label1| +create procedure bug7088_2() + läbel1: begin end| +call bug7088_1()| +call bug7088_2()| +set character set default| +show create procedure bug7088_1| +show create procedure bug7088_2| + +drop procedure bug6063| +drop procedure bug7088_1| +drop procedure bug7088_2| + + # # BUG#NNNN: New bug synopsis # @@ -3812,4 +3844,3 @@ drop procedure bug11529| # practical, or create table t3, t4 etc temporarily (and drop them). delimiter ;| drop table t1,t2; - diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4fc9819d0e1..61d80eeaa78 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -676,7 +676,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal NCHAR_STRING opt_component key_cache_name - sp_opt_label BIN_NUM + sp_opt_label BIN_NUM label_ident %type opt_table_alias @@ -764,7 +764,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type udf_func_type -%type FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword +%type FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword keyword_sp %type user grant_user @@ -2053,7 +2053,7 @@ sp_proc_stmt: lex->sphead->backpatch(lex->spcont->pop_label()); } - | LEAVE_SYM IDENT + | LEAVE_SYM label_ident { LEX *lex= Lex; sp_head *sp = lex->sphead; @@ -2083,7 +2083,7 @@ sp_proc_stmt: sp->add_instr(i); } } - | ITERATE_SYM IDENT + | ITERATE_SYM label_ident { LEX *lex= Lex; sp_head *sp= lex->sphead; @@ -2400,7 +2400,7 @@ sp_whens: ; sp_labeled_control: - IDENT ':' + label_ident ':' { LEX *lex= Lex; sp_pcontext *ctx= lex->spcont; @@ -2439,7 +2439,7 @@ sp_labeled_control: sp_opt_label: /* Empty */ { $$= null_lex_str; } - | IDENT { $$= $1; } + | label_ident { $$= $1; } ; sp_unlabeled_control: @@ -7295,6 +7295,16 @@ ident: } ; +label_ident: + IDENT_sys { $$=$1; } + | keyword_sp + { + THD *thd= YYTHD; + $$.str= thd->strmake($1.str, $1.length); + $$.length= $1.length; + } + ; + ident_or_text: ident { $$=$1;} | TEXT_STRING_sys { $$=$1;} @@ -7336,9 +7346,51 @@ user: } }; -/* Keyword that we allow for identifiers */ - +/* Keyword that we allow for identifiers (except SP labels) */ keyword: + keyword_sp {} + | ASCII_SYM {} + | BACKUP_SYM {} + | BEGIN_SYM {} + | BYTE_SYM {} + | CACHE_SYM {} + | CHARSET {} + | CHECKSUM_SYM {} + | CLOSE_SYM {} + | COMMENT_SYM {} + | COMMIT_SYM {} + | CONTAINS_SYM {} + | DEALLOCATE_SYM {} + | DO_SYM {} + | END {} + | EXECUTE_SYM {} + | FLUSH_SYM {} + | HANDLER_SYM {} + | HELP_SYM {} + | LANGUAGE_SYM {} + | NO_SYM {} + | OPEN_SYM {} + | PREPARE_SYM {} + | REPAIR {} + | RESET_SYM {} + | RESTORE_SYM {} + | ROLLBACK_SYM {} + | SAVEPOINT_SYM {} + | SECURITY_SYM {} + | SIGNED_SYM {} + | SLAVE {} + | START_SYM {} + | STOP_SYM {} + | TRUNCATE_SYM {} + | UNICODE_SYM {} + | XA_SYM {} + ; + +/* + * Keywords that we allow for labels in SPs. + * Anything that's the beginning of a statement must be in keyword above. + */ +keyword_sp: ACTION {} | ADDDATE_SYM {} | AFTER_SYM {} @@ -7346,61 +7398,46 @@ keyword: | AGGREGATE_SYM {} | ALGORITHM_SYM {} | ANY_SYM {} - | ASCII_SYM {} | AUTO_INC {} | AVG_ROW_LENGTH {} | AVG_SYM {} - | BACKUP_SYM {} - | BEGIN_SYM {} | BERKELEY_DB_SYM {} | BINLOG_SYM {} | BIT_SYM {} | BOOL_SYM {} | BOOLEAN_SYM {} - | BYTE_SYM {} | BTREE_SYM {} - | CACHE_SYM {} | CASCADED {} | CHAIN_SYM {} | CHANGED {} - | CHARSET {} - | CHECKSUM_SYM {} | CIPHER_SYM {} | CLIENT_SYM {} - | CLOSE_SYM {} | COLLATION_SYM {} | COLUMNS {} - | COMMENT_SYM {} | COMMITTED_SYM {} - | COMMIT_SYM {} | COMPACT_SYM {} | COMPRESSED_SYM {} | CONCURRENT {} | CONSISTENT_SYM {} - | CONTAINS_SYM {} | CUBE_SYM {} | DATA_SYM {} | DATETIME {} | DATE_SYM {} | DAY_SYM {} - | DEALLOCATE_SYM {} | DEFINER_SYM {} | DELAY_KEY_WRITE_SYM {} | DES_KEY_FILE {} | DIRECTORY_SYM {} | DISCARD {} - | DO_SYM {} | DUMPFILE {} | DUPLICATE_SYM {} | DYNAMIC_SYM {} - | END {} | ENUM {} | ENGINE_SYM {} | ENGINES_SYM {} | ERRORS {} | ESCAPE_SYM {} | EVENTS_SYM {} - | EXECUTE_SYM {} | EXPANSION_SYM {} | EXTENDED_SYM {} | FAST_SYM {} @@ -7411,16 +7448,13 @@ keyword: | FILE_SYM {} | FIRST_SYM {} | FIXED_SYM {} - | FLUSH_SYM {} | FRAC_SECOND_SYM {} | GEOMETRY_SYM {} | GEOMETRYCOLLECTION {} | GET_FORMAT {} | GRANTS {} | GLOBAL_SYM {} - | HANDLER_SYM {} | HASH_SYM {} - | HELP_SYM {} | HOSTS_SYM {} | HOUR_SYM {} | IDENTIFIED_SYM {} @@ -7432,7 +7466,6 @@ keyword: | INNOBASE_SYM {} | INSERT_METHOD {} | RELAY_THREAD {} - | LANGUAGE_SYM {} | LAST_SYM {} | LEAVES {} | LEVEL_SYM {} @@ -7480,21 +7513,18 @@ keyword: | NDBCLUSTER_SYM {} | NEXT_SYM {} | NEW_SYM {} - | NO_SYM {} | NONE_SYM {} | NVARCHAR_SYM {} | OFFSET_SYM {} | OLD_PASSWORD {} | ONE_SHOT_SYM {} | ONE_SYM {} - | OPEN_SYM {} | PACK_KEYS_SYM {} | PARTIAL {} | PASSWORD {} | PHASE_SYM {} | POINT_SYM {} | POLYGON {} - | PREPARE_SYM {} | PREV_SYM {} | PRIVILEGES {} | PROCESS {} @@ -7512,41 +7542,31 @@ keyword: | RELAY_LOG_FILE_SYM {} | RELAY_LOG_POS_SYM {} | RELOAD {} - | REPAIR {} | REPEATABLE_SYM {} | REPLICATION {} - | RESET_SYM {} | RESOURCES {} - | RESTORE_SYM {} | RESUME_SYM {} | RETURNS_SYM {} - | ROLLBACK_SYM {} | ROLLUP_SYM {} | ROUTINE_SYM {} | ROWS_SYM {} | ROW_FORMAT_SYM {} | ROW_SYM {} | RTREE_SYM {} - | SAVEPOINT_SYM {} | SECOND_SYM {} - | SECURITY_SYM {} | SERIAL_SYM {} | SERIALIZABLE_SYM {} | SESSION_SYM {} - | SIGNED_SYM {} | SIMPLE_SYM {} | SHARE_SYM {} | SHUTDOWN {} - | SLAVE {} | SNAPSHOT_SYM {} | SOUNDS_SYM {} | SQL_CACHE_SYM {} | SQL_BUFFER_RESULT {} | SQL_NO_CACHE_SYM {} | SQL_THREAD {} - | START_SYM {} | STATUS_SYM {} - | STOP_SYM {} | STORAGE_SYM {} | STRING_SYM {} | SUBDATE_SYM {} @@ -7559,7 +7579,6 @@ keyword: | TEMPTABLE_SYM {} | TEXT_SYM {} | TRANSACTION_SYM {} - | TRUNCATE_SYM {} | TIMESTAMP {} | TIMESTAMP_ADD {} | TIMESTAMP_DIFF {} @@ -7570,7 +7589,6 @@ keyword: | FUNCTION_SYM {} | UNCOMMITTED_SYM {} | UNDEFINED_SYM {} - | UNICODE_SYM {} | UNKNOWN_SYM {} | UNTIL_SYM {} | USER {} @@ -7582,7 +7600,6 @@ keyword: | WEEK_SYM {} | WORK_SYM {} | X509_SYM {} - | XA_SYM {} | YEAR_SYM {} ; From de40b79a637aa6076bed79fddbf39519901013c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 16:56:38 +0200 Subject: [PATCH 173/216] Updated sp.result mysql-test/r/sp.result: Updated test result. --- mysql-test/r/sp.result | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 6a85c6afc85..c77ad5b94f7 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3113,7 +3113,7 @@ bug6063 CREATE PROCEDURE `test`.`bug6063`() l?bel: begin end set character set utf8| create procedure bug7088_1() -label1: begin end| +label1: begin end label1| create procedure bug7088_2() läbel1: begin end| call bug7088_1()| @@ -3122,7 +3122,7 @@ set character set default| show create procedure bug7088_1| Procedure sql_mode Create Procedure bug7088_1 CREATE PROCEDURE `test`.`bug7088_1`() -label1: begin end +label1: begin end label1 show create procedure bug7088_2| Procedure sql_mode Create Procedure bug7088_2 CREATE PROCEDURE `test`.`bug7088_2`() From 39968552a81e60ebd638d8fa780697a6e68373b5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 09:00:17 -0700 Subject: [PATCH 174/216] view.result, view.test: Added a test case for bug #6120. sql_view.cc: Fixed bug #6120. The SP cache must be invalidated when a view is altered. sql/sql_view.cc: Fixed bug #6120. The SP cache must be invalidated when a view is altered. mysql-test/t/view.test: Added a test case for bug #6120. mysql-test/r/view.result: Added a test case for bug #6120. --- mysql-test/r/view.result | 17 +++++++++++++++++ mysql-test/t/view.test | 17 +++++++++++++++++ sql/sql_view.cc | 4 ++++ 3 files changed, 38 insertions(+) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index cebf88464cf..7bcfaf8bdc3 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1923,3 +1923,20 @@ ERROR HY000: Field of view 'test.v2' underlying table doesn't have a default val set sql_mode=default; drop view v2,v1; drop table t1; +CREATE TABLE t1 (s1 int, s2 int); +INSERT INTO t1 VALUES (1,2); +CREATE VIEW v1 AS SELECT s2 AS s1, s1 AS s2 FROM t1; +SELECT * FROM v1; +s1 s2 +2 1 +CREATE PROCEDURE p1 () SELECT * FROM v1; +CALL p1(); +s1 s2 +2 1 +ALTER VIEW v1 AS SELECT s1 AS s1, s2 AS s2 FROM t1; +CALL p1(); +s1 s2 +1 2 +DROP PROCEDURE p1; +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index f3e32754821..6b6b3d8a00f 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1761,3 +1761,20 @@ INSERT INTO v2 (vcol1) VALUES(12); set sql_mode=default; drop view v2,v1; drop table t1; + +# +# Test for bug #6120: SP cache to be invalidated when altering a view +# + +CREATE TABLE t1 (s1 int, s2 int); +INSERT INTO t1 VALUES (1,2); +CREATE VIEW v1 AS SELECT s2 AS s1, s1 AS s2 FROM t1; +SELECT * FROM v1; +CREATE PROCEDURE p1 () SELECT * FROM v1; +CALL p1(); +ALTER VIEW v1 AS SELECT s1 AS s1, s2 AS s2 FROM t1; +CALL p1(); + +DROP PROCEDURE p1; +DROP VIEW v1; +DROP TABLE t1; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index c8abee1e7dc..d74b96de2cd 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -20,6 +20,7 @@ #include "parse_file.h" #include "sp.h" #include "sp_head.h" +#include "sp_cache.h" #define MD5_BUFF_LENGTH 33 @@ -141,6 +142,9 @@ bool mysql_create_view(THD *thd, goto err; } + if (mode != VIEW_CREATE_NEW) + sp_cache_invalidate(); + #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Privilege check for view creation: From 348dfd416396cd6d7b541ddaef0d0ea71667fa67 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 19:49:43 +0200 Subject: [PATCH 175/216] Look in the directory above the executable for the my.cnf/ini, on Windows, as the new installer and GUI tools expect. (Bug #10419) Also, dynamically bind to GetSystemWindowsDirectory() so that it works on all platforms. (Bug #5354) mysys/default.c: Dynamically bind to GetSystemWindowsDirectory() or emulate it, and also look in directory above the executable to find my.cnf/ini on Windows. --- mysys/default.c | 92 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 12 deletions(-) diff --git a/mysys/default.c b/mysys/default.c index 1fa8deaa65c..15c92e816a6 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -48,13 +48,14 @@ char *defaults_extra_file=0; /* Which directories are searched for options (and in which order) */ -#define MAX_DEFAULT_DIRS 5 +#define MAX_DEFAULT_DIRS 6 const char *default_directories[MAX_DEFAULT_DIRS + 1]; #ifdef __WIN__ static const char *f_extensions[]= { ".ini", ".cnf", 0 }; #define NEWLINE "\r\n" -static char system_dir[FN_REFLEN], shared_system_dir[FN_REFLEN]; +static char system_dir[FN_REFLEN], shared_system_dir[FN_REFLEN], + config_dir[FN_REFLEN]; #else static const char *f_extensions[]= { ".cnf", 0 }; #define NEWLINE "\n" @@ -286,8 +287,8 @@ int load_defaults(const char *conf_file, const char **groups, { DYNAMIC_ARRAY args; TYPELIB group; - my_bool found_print_defaults=0; - uint args_used=0; + my_bool found_print_defaults= 0; + uint args_used= 0; int error= 0; MEM_ROOT alloc; char *ptr,**res; @@ -328,8 +329,8 @@ int load_defaults(const char *conf_file, const char **groups, ctx.args= &args; ctx.group= &group; - if (*argc >= 2 + args_used && - is_prefix(argv[0][1+args_used], instance_option)) + if (*argc >= 2 && + is_prefix(argv[0][1], instance_option)) { args_used++; defaults_instance= argv[0][args_used]+sizeof(instance_option)-1; @@ -870,6 +871,45 @@ void print_defaults(const char *conf_file, const char **groups) #include +#ifdef __WIN__ +/* + This wrapper for GetSystemWindowsDirectory() will dynamically bind to the + function if it is available, emulate it on NT4 Terminal Server by stripping + the \SYSTEM32 from the end of the results of GetSystemDirectory(), or just + return GetSystemDirectory(). + */ + +typedef UINT (WINAPI *GET_SYSTEM_WINDOWS_DIRECTORY)(LPSTR, UINT); + +static uint my_get_system_windows_directory(char *buffer, uint size) +{ + GET_SYSTEM_WINDOWS_DIRECTORY + func_ptr= (GET_SYSTEM_WINDOWS_DIRECTORY) + GetProcAddress(GetModuleHandle("kernel32.dll"), + "GetSystemWindowsDirectoryA"); + + if (func_ptr) + return func_ptr(buffer, size); + else + { + /* + Windows NT 4.0 Terminal Server Edition: + To retrieve the shared Windows directory, call GetSystemDirectory and + trim the "System32" element from the end of the returned path. + */ + UINT count= GetSystemDirectory(buffer, size); + + if (count > 8 && stricmp(buffer+(count-8), "\\System32") == 0) + { + count-= 8; + buffer[count] = '\0'; + } + return count; + } +} +#endif + + /* Create the list of default directories. @@ -878,7 +918,8 @@ void print_defaults(const char *conf_file, const char **groups) 2. GetWindowsDirectory() 3. GetSystemWindowsDirectory() 4. getenv(DEFAULT_HOME_ENV) - 5. "" + 5. Direcotry above where the executable is located + 6. "" On Novell NetWare, this is: 1. sys:/etc/ @@ -909,13 +950,10 @@ static void init_default_directories() if (GetWindowsDirectory(system_dir,sizeof(system_dir))) *ptr++= (char*)&system_dir; -#if defined(_MSC_VER) && (_MSC_VER >= 1300) - /* Only VC7 and up */ - /* Only add shared system directory if different from default. */ - if (GetSystemWindowsDirectory(shared_system_dir,sizeof(shared_system_dir)) && + if (my_get_system_windows_directory(shared_system_dir, + sizeof(shared_system_dir)) && strcmp(system_dir, shared_system_dir)) *ptr++= (char *)&shared_system_dir; -#endif #elif defined(__NETWARE__) *ptr++= "sys:/etc/"; @@ -931,6 +969,36 @@ static void init_default_directories() *ptr++= ""; /* Place for defaults_extra_file */ #if !defined(__WIN__) && !defined(__NETWARE__) *ptr++= "~/";; +#elif defined(__WIN__) + if (GetModuleFileName(NULL, config_dir, sizeof(config_dir))) + { + char *last= NULL, *end= strend(config_dir); + /* + Look for the second-to-last \ in the filename, but hang on + to a pointer after the last \ in case we're in the root of + a drive. + */ + for ( ; end > config_dir; end--) + { + if (*end == FN_LIBCHAR) + { + if (last) + break; + last= end; + } + } + + if (last) + { + if (end != config_dir && end[-1] == FN_DEVCHAR) /* Ended up with D:\ */ + end[1]= 0; /* Keep one \ */ + else if (end != config_dir) + end[0]= 0; + else + last[1]= 0; + } + *ptr++= (char *)&config_dir; + } #endif *ptr= 0; /* end marker */ } From 0f06342304519f5b3c5e43045dca2a2b03ff1dc0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 22:21:35 +0200 Subject: [PATCH 176/216] mtr_misc.pl: Corrected appending of .exe to Windows executables Don't alter read only @_ in foreach loop mysql-test-run.pl: Improved cleanup of binlogs Use separate log file for second master Corrected Windows paths to executables mysql-test/mysql-test-run.pl: Improved cleanup of binlogs Use separate log file for second master Corrected Windows paths to executables mysql-test/lib/mtr_misc.pl: Corrected appending of .exe to Windows executables Don't alter read only @_ in foreach loop --- mysql-test/lib/mtr_misc.pl | 11 +++++----- mysql-test/mysql-test-run.pl | 40 +++++++++++++++++++++--------------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl index aba6f78c9de..c1aab340a16 100644 --- a/mysql-test/lib/mtr_misc.pl +++ b/mysql-test/lib/mtr_misc.pl @@ -83,18 +83,19 @@ sub mtr_script_exists (@) { } sub mtr_exe_exists (@) { - foreach my $path ( @_ ) + my @path= @_; + map {$_.= ".exe"} @path if $::glob_win32; + foreach my $path ( @path ) { - $path.= ".exe" if $::opt_win32; return $path if -x $path; } - if ( @_ == 1 ) + if ( @path == 1 ) { - mtr_error("Could not find $_[0]"); + mtr_error("Could not find $path[0]"); } else { - mtr_error("Could not find any of " . join(" ", @_)); + mtr_error("Could not find any of " . join(" ", @path)); } } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index e2637cfa6ee..4272c05f7dc 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -792,13 +792,15 @@ sub executable_setup () { my $path_examples= "$glob_basedir/libmysqld/examples"; $exe_mysqltest= mtr_exe_exists("$path_examples/mysqltest"); $exe_mysql_client_test= - mtr_exe_exists("$path_examples/mysql_client_test_embedded"); + mtr_exe_exists("$path_examples/mysql_client_test_embedded", + "/usr/bin/false"); } else { $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest"); $exe_mysql_client_test= - mtr_exe_exists("$glob_basedir/tests/mysql_client_test"); + mtr_exe_exists("$glob_basedir/tests/mysql_client_test", + "/usr/bin/false"); } $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump"); $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow"); @@ -820,7 +822,8 @@ sub executable_setup () { $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin"); $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql"); $exe_mysql_fix_system_tables= - mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables"); + mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables", + "$glob_basedir/scripts/mysql_fix_privilege_tables"); $path_language= mtr_path_exists("$glob_basedir/share/mysql/english/", "$glob_basedir/share/english/"); @@ -834,13 +837,15 @@ sub executable_setup () { $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest_embedded"); $exe_mysql_client_test= mtr_exe_exists("$glob_basedir/tests/mysql_client_test_embedded", - "$path_client_bindir/mysql_client_test_embedded"); + "$path_client_bindir/mysql_client_test_embedded", + "/usr/bin/false"); } else { $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest"); $exe_mysql_client_test= - mtr_exe_exists("$path_client_bindir/mysql_client_test"); + mtr_exe_exists("$path_client_bindir/mysql_client_test", + "/usr/bin/false"); # FIXME temporary } $path_ndb_tools_dir= "$glob_basedir/bin"; @@ -1552,17 +1557,17 @@ sub do_before_start_master ($$) { $tname ne "rpl_crash_binlog_ib_3b") { # FIXME we really want separate dir for binlogs - foreach my $bin ( glob("$opt_vardir/log/master*-bin.*") ) + foreach my $bin ( glob("$opt_vardir/log/master*-bin*") ) { unlink($bin); } } # Remove old master.info and relay-log.info files - unlink("$opt_vardir/master-data/master.info"); - unlink("$opt_vardir/master-data/relay-log.info"); - unlink("$opt_vardir/master1-data/master.info"); - unlink("$opt_vardir/master1-data/relay-log.info"); + unlink("$master->[0]->{'path_myddir'}/master.info"); + unlink("$master->[0]->{'path_myddir'}/relay-log.info"); + unlink("$master->[1]->{'path_myddir'}/master.info"); + unlink("$master->[1]->{'path_myddir'}/relay-log.info"); # Run master initialization shell script if one exists if ( $init_script ) @@ -1589,13 +1594,13 @@ sub do_before_start_slave ($$) { $tname ne "rpl_crash_binlog_ib_3b" ) { # FIXME we really want separate dir for binlogs - foreach my $bin ( glob("$opt_vardir/log/slave*-bin.*") ) + foreach my $bin ( glob("$opt_vardir/log/slave*-bin*") ) { unlink($bin); } # FIXME really master?! - unlink("$opt_vardir/slave-data/master.info"); - unlink("$opt_vardir/slave-data/relay-log.info"); + unlink("$slave->[0]->{'path_myddir'}/master.info"); + unlink("$slave->[0]->{'path_myddir'}/relay-log.info"); } # Run slave initialization shell script if one exists @@ -1609,8 +1614,10 @@ sub do_before_start_slave ($$) { } } - `rm -f $opt_vardir/slave-data/log.*`; -# unlink("$opt_vardir/slave-data/log.*"); + foreach my $bin ( glob("$slave->[0]->{'path_myddir'}/log.*") ) + { + unlink($bin); + } } sub mysqld_arguments ($$$$$) { @@ -1656,7 +1663,8 @@ sub mysqld_arguments ($$$$$) { if ( $type eq 'master' ) { - mtr_add_arg($args, "%s--log-bin=%s/log/master-bin", $prefix, $opt_vardir); + mtr_add_arg($args, "%s--log-bin=%s/log/master-bin%s", $prefix, + $opt_vardir, $sidx); mtr_add_arg($args, "%s--pid-file=%s", $prefix, $master->[$idx]->{'path_mypid'}); mtr_add_arg($args, "%s--port=%d", $prefix, From e2aa2abd725ea04c2809374e1125d3309b94b88e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 15:54:02 -0700 Subject: [PATCH 177/216] Typo for debug code. Bug #11705 vio/viossl.c: Typo for dbug code BitKeeper/etc/config: turned off openlogging --- BitKeeper/etc/config | 2 +- vio/viossl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config index c609fcdbd49..6ddd492ebc4 100644 --- a/BitKeeper/etc/config +++ b/BitKeeper/etc/config @@ -24,7 +24,7 @@ description: MySQL - fast and reliable SQL database # repository is commercial it can be an internal email address or "none" # to disable logging. # -logging: logging@openlogging.org +logging: none # # If this field is set, all checkins will appear to be made by this user, # in effect making this a single user package. Single user packages are diff --git a/vio/viossl.c b/vio/viossl.c index 043d23f0238..2f608209a53 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -315,7 +315,7 @@ int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout) vio_blocking(vio, net_blocking, &unused); DBUG_RETURN(1); } -#ifndef DBUF_OFF +#ifndef DBUG_OFF DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'" ,SSL_get_cipher_name((SSL*) vio->ssl_arg))); client_cert = SSL_get_peer_certificate ((SSL*) vio->ssl_arg); From f56102ae062e637c6af59a521bc60a7ffa2737c4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Jul 2005 18:56:10 -0700 Subject: [PATCH 178/216] Fix typos that crept into ChangeSet for fix for Bug #11045. sql/ha_federated.cc: Fix typo sql/sql_insert.cc: Fix typo --- sql/ha_federated.cc | 2 +- sql/sql_insert.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 129bd4dadca..383652e4a3a 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -1087,7 +1087,7 @@ int ha_federated::write_row(byte *buf) { uint x= 0, num_fields= 0; Field **field; - query_id_it current_query_id= 1; + query_id_t current_query_id= 1; ulong tmp_query_id= 1; uint all_fields_have_same_query_id= 1; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a2f3334d13d..f5d30f69978 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -199,7 +199,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list, List &update_fields) { TABLE *table= insert_table_list->table; - query_id_it timestamp_query_id; + query_id_t timestamp_query_id; LINT_INIT(timestamp_query_id); /* From ab0e8f2e126a7d6e69d883a083d3ceec89888aa0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Jul 2005 15:19:56 +1000 Subject: [PATCH 179/216] BUG#11516 ndb_mgmd debug core on cluster shutdown with failed data nodes Fix closing of sessions on mgm server shutdown. ndb/include/mgmcommon/ConfigRetriever.hpp: Add disconnect(); ndb/src/common/mgmcommon/ConfigRetriever.cpp: Add disconnect() call so we can disconnect from the mgm server before it shuts down (if we are a mgm server). ndb/src/mgmsrv/main.cpp: Close our ConfigRetriever connection first. Stop sessions, and wait for them to stop. (previously we didn't wait, this was causing core dumps on shutdown with failed nodes). --- ndb/include/mgmcommon/ConfigRetriever.hpp | 1 + ndb/src/common/mgmcommon/ConfigRetriever.cpp | 6 ++++++ ndb/src/mgmsrv/main.cpp | 3 ++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ndb/include/mgmcommon/ConfigRetriever.hpp b/ndb/include/mgmcommon/ConfigRetriever.hpp index 95d257dea23..c0b877af07d 100644 --- a/ndb/include/mgmcommon/ConfigRetriever.hpp +++ b/ndb/include/mgmcommon/ConfigRetriever.hpp @@ -32,6 +32,7 @@ public: ~ConfigRetriever(); int do_connect(int no_retries, int retry_delay_in_seconds, int verbose); + int disconnect(); /** * Get configuration for current node. diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp index eca886c8586..0e9b2a83e2f 100644 --- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp +++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp @@ -107,6 +107,12 @@ ConfigRetriever::do_connect(int no_retries, 0 : -1; } +int +ConfigRetriever::disconnect() +{ + return ndb_mgm_disconnect(m_handle); +} + //**************************************************************************** //**************************************************************************** //**************************************************************************** diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp index 3335fdc827c..c7315c61ba1 100644 --- a/ndb/src/mgmsrv/main.cpp +++ b/ndb/src/mgmsrv/main.cpp @@ -353,7 +353,8 @@ int main(int argc, char** argv) g_eventLogger.info("Shutting down server..."); glob.socketServer->stopServer(); - glob.socketServer->stopSessions(); + glob.mgmObject->get_config_retriever()->disconnect(); + glob.socketServer->stopSessions(true); g_eventLogger.info("Shutdown complete"); return 0; error_end: From 46d472d636a0b33dfffb77b8b61eead94e285839 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Jul 2005 14:44:28 +0200 Subject: [PATCH 180/216] BUG#11635 mysqldump exports TYPE instead of USING for HASH Cluster indexes - Change output from SHOW CREATE TABLE to use USING instead of TYPE mysql-test/r/ctype_utf8.result: Update test results mysql-test/r/show_check.result: Update test results mysql-test/r/sql_mode.result: Update test results mysql-test/t/show_check.test: Add test for BUG#11635 sql/sql_show.cc: Change TYPE to USING as output from SHOW CREATE TABLE --- mysql-test/r/ctype_utf8.result | 8 ++++---- mysql-test/r/show_check.result | 25 ++++++++++++++++++++----- mysql-test/r/sql_mode.result | 6 +++--- mysql-test/t/show_check.test | 9 +++++++++ sql/sql_show.cc | 6 +++--- 5 files changed, 39 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 3a8265b01f7..d4e12ea84b7 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -412,7 +412,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `c` char(10) character set utf8 default NULL, - UNIQUE KEY `a` TYPE HASH (`c`(1)) + UNIQUE KEY `a` USING HASH (`c`(1)) ) ENGINE=HEAP DEFAULT CHARSET=latin1 insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); insert into t1 values ('aa'); @@ -448,7 +448,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `c` char(10) character set utf8 default NULL, - UNIQUE KEY `a` TYPE BTREE (`c`(1)) + UNIQUE KEY `a` USING BTREE (`c`(1)) ) ENGINE=HEAP DEFAULT CHARSET=latin1 insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); insert into t1 values ('aa'); @@ -570,7 +570,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `c` char(10) character set utf8 collate utf8_bin default NULL, - UNIQUE KEY `a` TYPE HASH (`c`(1)) + UNIQUE KEY `a` USING HASH (`c`(1)) ) ENGINE=HEAP DEFAULT CHARSET=latin1 insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); insert into t1 values ('aa'); @@ -606,7 +606,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `c` char(10) character set utf8 collate utf8_bin default NULL, - UNIQUE KEY `a` TYPE BTREE (`c`(1)) + UNIQUE KEY `a` USING BTREE (`c`(1)) ) ENGINE=HEAP DEFAULT CHARSET=latin1 insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); insert into t1 values ('aa'); diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 4a9e28e9ea4..1e5e8f442a8 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -420,7 +420,7 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `i` int(11) default NULL, - KEY `i` TYPE HASH (`i`) + KEY `i` USING HASH (`i`) ) ENGINE=HEAP DEFAULT CHARSET=latin1 DROP TABLE t1; CREATE TABLE t1 (i int, KEY USING BTREE (i)) ENGINE=MEMORY; @@ -428,7 +428,7 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `i` int(11) default NULL, - KEY `i` TYPE BTREE (`i`) + KEY `i` USING BTREE (`i`) ) ENGINE=HEAP DEFAULT CHARSET=latin1 DROP TABLE t1; CREATE TABLE t1 (i int, KEY (i)) ENGINE=MyISAM; @@ -444,7 +444,7 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `i` int(11) default NULL, - KEY `i` TYPE BTREE (`i`) + KEY `i` USING BTREE (`i`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; CREATE TABLE t1 (i int, KEY (i)) ENGINE=MyISAM; @@ -467,14 +467,14 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `i` int(11) default NULL, - KEY `i` TYPE BTREE (`i`) + KEY `i` USING BTREE (`i`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 ALTER TABLE t1 ENGINE=MEMORY; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `i` int(11) default NULL, - KEY `i` TYPE BTREE (`i`) + KEY `i` USING BTREE (`i`) ) ENGINE=HEAP DEFAULT CHARSET=latin1 DROP TABLE t1; CREATE TABLE t1( @@ -498,3 +498,18 @@ def Comment 253 255 0 N 129 31 63 Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t1 0 PRIMARY 1 field1 A 0 1000 NULL BTREE drop table t1; +create table t1 ( +c1 int NOT NULL, +c2 int NOT NULL, +PRIMARY KEY USING HASH (c1), +INDEX USING BTREE(c2) +); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL default '0', + `c2` int(11) NOT NULL default '0', + PRIMARY KEY USING HASH (`c1`), + KEY `c2` USING BTREE (`c2`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index 652913d1fdb..4e1693e15ec 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -17,7 +17,7 @@ t1 CREATE TABLE `t1` ( `pseudo` varchar(35) character set latin2 NOT NULL default '', `email` varchar(60) character set latin2 NOT NULL default '', PRIMARY KEY (`a`), - UNIQUE KEY `email` TYPE BTREE (`email`) + UNIQUE KEY `email` USING BTREE (`email`) ) ENGINE=HEAP DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC set @@sql_mode="ansi_quotes"; show variables like 'sql_mode'; @@ -30,7 +30,7 @@ t1 CREATE TABLE "t1" ( "pseudo" varchar(35) character set latin2 NOT NULL default '', "email" varchar(60) character set latin2 NOT NULL default '', PRIMARY KEY ("a"), - UNIQUE KEY "email" TYPE BTREE ("email") + UNIQUE KEY "email" USING BTREE ("email") ) ENGINE=HEAP DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC set @@sql_mode="no_table_options"; show variables like 'sql_mode'; @@ -43,7 +43,7 @@ t1 CREATE TABLE `t1` ( `pseudo` varchar(35) character set latin2 NOT NULL default '', `email` varchar(60) character set latin2 NOT NULL default '', PRIMARY KEY (`a`), - UNIQUE KEY `email` TYPE BTREE (`email`) + UNIQUE KEY `email` USING BTREE (`email`) ) set @@sql_mode="no_key_options"; show variables like 'sql_mode'; diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index f80e720275a..76691ad79b1 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -368,3 +368,12 @@ show index from t1; --disable_metadata drop table t1; +# Test for BUG#11635: mysqldump exports TYPE instead of USING for HASH +create table t1 ( + c1 int NOT NULL, + c2 int NOT NULL, + PRIMARY KEY USING HASH (c1), + INDEX USING BTREE(c2) +); +SHOW CREATE TABLE t1; +DROP TABLE t1; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 7e0ee0dab68..636c88847eb 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1414,15 +1414,15 @@ store_create_info(THD *thd, TABLE *table, String *packet) !limited_mysql_mode && !foreign_db_mode) { if (key_info->algorithm == HA_KEY_ALG_BTREE) - packet->append(" TYPE BTREE", 11); + packet->append(" USING BTREE", 12); if (key_info->algorithm == HA_KEY_ALG_HASH) - packet->append(" TYPE HASH", 10); + packet->append(" USING HASH", 11); // +BAR: send USING only in non-default case: non-spatial rtree if ((key_info->algorithm == HA_KEY_ALG_RTREE) && !(key_info->flags & HA_SPATIAL)) - packet->append(" TYPE RTREE", 11); + packet->append(" USING RTREE", 12); // No need to send TYPE FULLTEXT, it is sent as FULLTEXT KEY } From 995abb0ed20a19cf91615bf9ae5dca6c2ce44498 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Jul 2005 18:23:30 +0500 Subject: [PATCH 181/216] Fix for bug #10891 (string->decimal conversion crashes server) mysql-test/r/type_newdecimal.result: test result fixed mysql-test/t/type_newdecimal.test: test case added strings/decimal.c: new_point can be 0, and this case should be handled separately --- mysql-test/r/type_newdecimal.result | 3 +++ mysql-test/t/type_newdecimal.test | 5 +++++ strings/decimal.c | 19 ++++++++++++++----- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 79943df18c5..9ff4aea0567 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -934,3 +934,6 @@ select * from t1; col1 -9223372036854775808 drop table t1; +select cast('1.00000001335143196001808973960578441619873046875E-10' as decimal(30,15)); +cast('1.00000001335143196001808973960578441619873046875E-10' as decimal(30,15)) +0.000000000100000 diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 5c4f288983b..41129870d6f 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -973,3 +973,8 @@ create table t1 (col1 bigint default -9223372036854775808); insert into t1 values (default); select * from t1; drop table t1; + +# +# Bug #10891 (converting to decimal crashes server) +# +select cast('1.00000001335143196001808973960578441619873046875E-10' as decimal(30,15)); diff --git a/strings/decimal.c b/strings/decimal.c index be403c5e3fb..76e62080ba0 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -739,11 +739,20 @@ int decimal_shift(decimal_t *dec, int shift) beg= ROUND_UP(beg + 1) - 1; end= ROUND_UP(end) - 1; DBUG_ASSERT(new_point >= 0); - new_point= ROUND_UP(new_point) - 1; - for(; new_point > end; new_point--) - dec->buf[new_point]= 0; - for(; new_point < beg; new_point++) - dec->buf[new_point]= 0; + + /* We don't want negative new_point below */ + if (new_point != 0) + new_point= ROUND_UP(new_point) - 1; + + if (new_point > end) + do + { + dec->buf[new_point]=0; + }while (--new_point > end); + else + for (; new_point < beg; new_point++) + dec->buf[new_point]= 0; + dec->intg= digits_int; dec->frac= digits_frac; return err; From d98461719e8aa50725426ebce4f82e5a9fcf82ea Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Jul 2005 20:28:47 +0500 Subject: [PATCH 182/216] Fix for bug #11708 (real function returns wrongly rounded decimal) mysql-test/r/type_newdecimal.result: test result fixed mysql-test/t/type_newdecimal.test: test case added sql/item_func.cc: Item_real_func::val_decimal implemented sql/item_func.h: Item_real_func::val_decimal declared --- mysql-test/r/type_newdecimal.result | 3 +++ mysql-test/t/type_newdecimal.test | 5 +++++ sql/item_func.cc | 11 +++++++++++ sql/item_func.h | 1 + 4 files changed, 20 insertions(+) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 9ff4aea0567..f4e75402009 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -937,3 +937,6 @@ drop table t1; select cast('1.00000001335143196001808973960578441619873046875E-10' as decimal(30,15)); cast('1.00000001335143196001808973960578441619873046875E-10' as decimal(30,15)) 0.000000000100000 +select ln(14000) c1, convert(ln(14000),decimal(2,3)) c2, cast(ln(14000) as decimal(2,3)) c3; +c1 c2 c3 +9.5468126085974 9.547 9.547 diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 41129870d6f..92f0bc9024b 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -978,3 +978,8 @@ drop table t1; # Bug #10891 (converting to decimal crashes server) # select cast('1.00000001335143196001808973960578441619873046875E-10' as decimal(30,15)); + +# +# Bug #11708 (conversion to decimal fails in decimal part) +# +select ln(14000) c1, convert(ln(14000),decimal(2,3)) c2, cast(ln(14000) as decimal(2,3)) c3; diff --git a/sql/item_func.cc b/sql/item_func.cc index 16296266234..db78c811eb9 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -566,6 +566,17 @@ String *Item_real_func::val_str(String *str) } +my_decimal *Item_real_func::val_decimal(my_decimal *decimal_value) +{ + DBUG_ASSERT(fixed); + double nr= val_real(); + if (null_value) + return 0; /* purecov: inspected */ + double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value); + return decimal_value; +} + + void Item_func::fix_num_length_and_dec() { decimals= 0; diff --git a/sql/item_func.h b/sql/item_func.h index f6bc35e1617..3ca37b1961f 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -187,6 +187,7 @@ public: Item_real_func(Item *a,Item *b) :Item_func(a,b) {} Item_real_func(List &list) :Item_func(list) {} String *val_str(String*str); + my_decimal *val_decimal(my_decimal *decimal_value); longlong val_int() { DBUG_ASSERT(fixed == 1); return (longlong) val_real(); } enum Item_result result_type () const { return REAL_RESULT; } From 6651fd232a99a1257cfae57eebe3c40737bfe487 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Jul 2005 17:44:10 +0200 Subject: [PATCH 183/216] - fixed the "sp-security" test case: drop any possible already existing table to avoid failing if a previous test failure left the t1 table around mysql-test/t/sp-security.test: - drop any possible already existing table to avoid failing if a previous test failure left the t1 table around --- mysql-test/t/sp-security.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index 72fe6c332bf..3dc6b9d07ab 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -15,6 +15,7 @@ grant usage on *.* to user1@localhost; flush privileges; --disable_warnings +drop table if exists t1; drop database if exists db1_secret; --enable_warnings # Create our secret database From c7efc37f4c64c4fedf4dcbe20560a8c4e2245a4a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Jul 2005 17:55:16 +0200 Subject: [PATCH 184/216] - Updated the sp-security result set after updating the test mysql-test/r/sp-security.result: - Updated the result set --- mysql-test/r/sp-security.result | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index 4ace6f59411..3a0d2aa5f36 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -1,6 +1,7 @@ use test; grant usage on *.* to user1@localhost; flush privileges; +drop table if exists t1; drop database if exists db1_secret; create database db1_secret; create procedure db1_secret.dummy() begin end; From a78764e869f78659dad97667b0c1c0bb305d58d3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Jul 2005 18:20:13 +0200 Subject: [PATCH 185/216] Merge to 5.0 mysql-test/r/ctype_utf8.result: Correct wrong merge mysql-test/r/show_check.result: Correct wrong merge Fix output from new test for SHOW CREATE TABLE, default '0' is not displayed in 5.0 mysql-test/r/sql_mode.result: Correct wrong merge --- mysql-test/r/ctype_utf8.result | 8 ++++---- mysql-test/r/show_check.result | 10 +++++----- mysql-test/r/sql_mode.result | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 7b0e4a17538..b8ff3c70aa1 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -413,7 +413,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `c` char(10) character set utf8 default NULL, UNIQUE KEY `a` USING HASH (`c`(1)) -) ENGINE=HEAP DEFAULT CHARSET=latin1 +) ENGINE=MEMORY DEFAULT CHARSET=latin1 insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); insert into t1 values ('aa'); ERROR 23000: Duplicate entry 'aa' for key 1 @@ -449,7 +449,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `c` char(10) character set utf8 default NULL, UNIQUE KEY `a` USING BTREE (`c`(1)) -) ENGINE=HEAP DEFAULT CHARSET=latin1 +) ENGINE=MEMORY DEFAULT CHARSET=latin1 insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); insert into t1 values ('aa'); ERROR 23000: Duplicate entry 'aa' for key 1 @@ -571,7 +571,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `c` char(10) character set utf8 collate utf8_bin default NULL, UNIQUE KEY `a` USING HASH (`c`(1)) -) ENGINE=HEAP DEFAULT CHARSET=latin1 +) ENGINE=MEMORY DEFAULT CHARSET=latin1 insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); insert into t1 values ('aa'); ERROR 23000: Duplicate entry 'aa' for key 1 @@ -607,7 +607,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `c` char(10) character set utf8 collate utf8_bin default NULL, UNIQUE KEY `a` USING BTREE (`c`(1)) -) ENGINE=HEAP DEFAULT CHARSET=latin1 +) ENGINE=MEMORY DEFAULT CHARSET=latin1 insert into t1 values ('a'),('b'),('c'),('d'),('e'),('f'); insert into t1 values ('aa'); ERROR 23000: Duplicate entry 'aa' for key 1 diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 71ffde5779b..dcab877abf9 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -420,7 +420,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `i` int(11) default NULL, KEY `i` USING HASH (`i`) -) ENGINE=HEAP DEFAULT CHARSET=latin1 +) ENGINE=MEMORY DEFAULT CHARSET=latin1 DROP TABLE t1; CREATE TABLE t1 (i int, KEY USING BTREE (i)) ENGINE=MEMORY; SHOW CREATE TABLE t1; @@ -428,7 +428,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `i` int(11) default NULL, KEY `i` USING BTREE (`i`) -) ENGINE=HEAP DEFAULT CHARSET=latin1 +) ENGINE=MEMORY DEFAULT CHARSET=latin1 DROP TABLE t1; CREATE TABLE t1 (i int, KEY (i)) ENGINE=MyISAM; SHOW CREATE TABLE t1; @@ -474,7 +474,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `i` int(11) default NULL, KEY `i` USING BTREE (`i`) -) ENGINE=HEAP DEFAULT CHARSET=latin1 +) ENGINE=MEMORY DEFAULT CHARSET=latin1 DROP TABLE t1; CREATE TABLE t1( field1 text NOT NULL, @@ -506,8 +506,8 @@ INDEX USING BTREE(c2) SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `c1` int(11) NOT NULL default '0', - `c2` int(11) NOT NULL default '0', + `c1` int(11) NOT NULL, + `c2` int(11) NOT NULL, PRIMARY KEY USING HASH (`c1`), KEY `c2` USING BTREE (`c2`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index fa43d527c6a..f65e0421968 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -18,7 +18,7 @@ t1 CREATE TABLE `t1` ( `email` varchar(60) character set latin2 NOT NULL default '', PRIMARY KEY (`a`), UNIQUE KEY `email` USING BTREE (`email`) -) ENGINE=HEAP DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +) ENGINE=MEMORY DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC set @@sql_mode="ansi_quotes"; show variables like 'sql_mode'; Variable_name Value @@ -31,7 +31,7 @@ t1 CREATE TABLE "t1" ( "email" varchar(60) character set latin2 NOT NULL default '', PRIMARY KEY ("a"), UNIQUE KEY "email" USING BTREE ("email") -) ENGINE=HEAP DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +) ENGINE=MEMORY DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC set @@sql_mode="no_table_options"; show variables like 'sql_mode'; Variable_name Value From ce5f68cfa0008145189d4a049fb119926a120621 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Jul 2005 18:41:22 +0200 Subject: [PATCH 186/216] mtr_cases.pl: Added support for the disabled.def file mysql-test/lib/mtr_cases.pl: Added support for the disabled.def file --- mysql-test/lib/mtr_cases.pl | 43 +++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 72cbe72bc0a..12714ddc1ad 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -8,7 +8,7 @@ use File::Basename; use strict; sub collect_test_cases ($); -sub collect_one_test_case ($$$$$); +sub collect_one_test_case ($$$$$$); ############################################################################## # @@ -46,18 +46,36 @@ sub collect_test_cases ($) { { mtr_error("Test case $tname ($testdir/$elem) is not found"); } - collect_one_test_case($testdir,$resdir,$tname,$elem,$cases); + collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,{}); } closedir TESTDIR; } else { + # ---------------------------------------------------------------------- + # Skip some tests listed in disabled.def + # ---------------------------------------------------------------------- + my %skiplist; + my $skipfile= "$testdir/disabled.def"; + if ( open(SKIPFILE, $skipfile) ) + { + while ( ) + { + chomp; + if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ ) + { + $skiplist{$1}= $2; + } + } + close SKIPFILE; + } + foreach my $elem ( sort readdir(TESTDIR) ) { my $tname= mtr_match_extension($elem,"test"); next if ! defined $tname; next if $::opt_do_test and ! defined mtr_match_prefix($elem,$::opt_do_test); - collect_one_test_case($testdir,$resdir,$tname,$elem,$cases); + collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%skiplist); } closedir TESTDIR; } @@ -95,12 +113,13 @@ sub collect_test_cases ($) { ############################################################################## -sub collect_one_test_case($$$$$) { +sub collect_one_test_case($$$$$$) { my $testdir= shift; my $resdir= shift; my $tname= shift; my $elem= shift; my $cases= shift; + my $skiplist=shift; my $path= "$testdir/$elem"; @@ -154,6 +173,14 @@ sub collect_one_test_case($$$$$) { } } + if ( defined mtr_match_prefix($tname,"federated") ) + { + $tinfo->{'slave_num'}= 1; # Default, use one slave + + # FIXME currently we always restart slaves + $tinfo->{'slave_restart'}= 1; + } + # FIXME what about embedded_server + ndbcluster, skip ?! my $master_opt_file= "$testdir/$tname-master.opt"; @@ -264,6 +291,14 @@ sub collect_one_test_case($$$$$) { } } + # FIXME why this late? + if ( $skiplist->{$tname} ) + { + $tinfo->{'skip'}= 1; + $tinfo->{'disable'}= 1; # Sub type of 'skip' + $tinfo->{'comment'}= $skiplist->{$tname} if $skiplist->{$tname}; + } + if ( -f $disabled ) { $tinfo->{'skip'}= 1; From 077e335eb35d7217e2c950a2caa7c025f78f7a3b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Jul 2005 21:47:18 +0500 Subject: [PATCH 187/216] Fix for bug #8449(Silent column changes) mysql-test/r/show_check.result: test result fixed mysql-test/r/sql_mode.result: test result fixed mysql-test/r/type_decimal.result: test result fixed mysql-test/r/type_float.result: test result fixed mysql-test/r/type_newdecimal.result: test result fixed mysql-test/t/type_decimal.test: test fixed mysql-test/t/type_float.test: test fixed mysql-test/t/type_newdecimal.test: test case added sql/share/errmsg.txt: error messages added sql/sql_parse.cc: now precision/scale parameters are handled in required way --- mysql-test/r/show_check.result | 6 ++--- mysql-test/r/sql_mode.result | 6 ++--- mysql-test/r/type_decimal.result | 27 ++----------------- mysql-test/r/type_float.result | 14 ++-------- mysql-test/r/type_newdecimal.result | 15 +++++++++++ mysql-test/t/type_decimal.test | 13 ++------- mysql-test/t/type_float.test | 7 ++--- mysql-test/t/type_newdecimal.test | 15 +++++++++++ sql/share/errmsg.txt | 6 +++++ sql/sql_parse.cc | 41 ++++++++++++++++------------- 10 files changed, 72 insertions(+), 78 deletions(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index dd07e0ba755..13f4a4fe214 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -267,9 +267,9 @@ drop table t1; create table t1 (c decimal(3,3), d double(3,3), f float(3,3)); show columns from t1; Field Type Null Key Default Extra -c decimal(4,3) YES NULL -d double(4,3) YES NULL -f float(4,3) YES NULL +c decimal(3,3) YES NULL +d double(3,3) YES NULL +f float(3,3) YES NULL drop table t1; SET @old_sql_mode= @@sql_mode, sql_mode= ''; SET @old_sql_quote_show_create= @@sql_quote_show_create, sql_quote_show_create= OFF; diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index f65e0421968..9be5f5bc0d2 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -120,7 +120,7 @@ create table t1 ( min_num dec(6,6) default .000001); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `min_num` decimal(7,6) default '0.000001' + `min_num` decimal(6,6) default '0.000001' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1 ; set session sql_mode = 'IGNORE_SPACE'; @@ -128,14 +128,14 @@ create table t1 ( min_num dec(6,6) default 0.000001); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `min_num` decimal(7,6) default '0.000001' + `min_num` decimal(6,6) default '0.000001' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1 ; create table t1 ( min_num dec(6,6) default .000001); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `min_num` decimal(7,6) default '0.000001' + `min_num` decimal(6,6) default '0.000001' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1 ; set @@SQL_MODE=NULL; diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index 93467d1d7da..15f9b839994 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -476,12 +476,7 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp CREATE TABLE t1 (a_dec DECIMAL(-1,1)); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1,1))' at line 1 CREATE TABLE t1 (a_dec DECIMAL(0,11)); -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `a_dec` decimal(11,11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -DROP TABLE t1; +ERROR 42000: Scale may not be larger than the precision (column 'a_dec'). create table t1(a decimal(7,3)); insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000000001'),('10'),('+10'),('-10'),('0000000010'),('+0000000010'),('-0000000010'),('100'),('+100'),('-100'),('0000000100'),('+0000000100'),('-0000000100'),('1000'),('+1000'),('-1000'),('0000001000'),('+0000001000'),('-0000001000'),('10000'),('+10000'),('-10000'),('0000010000'),('+0000010000'),('-0000010000'),('100000'),('+100000'),('-100000'),('0000100000'),('+0000100000'),('-0000100000'),('1000000'),('+1000000'),('-1000000'),('0001000000'),('+0001000000'),('-0001000000'),('10000000'),('+10000000'),('-10000000'),('0010000000'),('+0010000000'),('-0010000000'),('100000000'),('+100000000'),('-100000000'),('0100000000'),('+0100000000'),('-0100000000'),('1000000000'),('+1000000000'),('-1000000000'),('1000000000'),('+1000000000'),('-1000000000'); select * from t1; @@ -699,24 +694,6 @@ select * from t1; d 1 drop table t1; -create table t1 (d decimal(64,99)); -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `d` decimal(64,30) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -insert into t1 values (1); -select * from t1; -d -1.000000000000000000000000000000 -drop table t1; -create table t1 (d decimal(10,12)); -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `d` decimal(13,12) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -drop table t1; create table t1 (d decimal(5)); show create table t1; Table Create Table @@ -732,7 +709,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 (d decimal(66,0)); -ERROR 42000: Incorrect column specifier for column 'd' +ERROR 42000: Too big precision 66 specified for column 'd'. Maximum is 65. CREATE TABLE t1 (i INT, d1 DECIMAL(9,2), d2 DECIMAL(9,2)); INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00), (2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40), diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index b0b3ab147b0..d243985332e 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -103,7 +103,7 @@ select max(a),min(a),avg(a) from t1; max(a) min(a) avg(a) 1 1 1 drop table t1; -create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(5,6)); +create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(7,6)); show full columns from t1; Field Type Collation Null Key Default Extra Privileges Comment f float NULL YES NULL # @@ -133,17 +133,7 @@ min(a) -0.010 drop table t1; create table t1 (a float(200,100), b double(200,100)); -insert t1 values (1.0, 2.0); -select * from t1; -a b -1.000000000000000000000000000000 2.000000000000000000000000000000 -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `a` float(200,30) default NULL, - `b` double(200,30) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -drop table t1; +ERROR 42000: Too big scale 100 specified for column 'a'. Maximum is 30. create table t1 (c20 char); insert into t1 values (5000.0); Warnings: diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index f4e75402009..964a69ffb12 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -940,3 +940,18 @@ cast('1.00000001335143196001808973960578441619873046875E-10' as decimal(30,15)) select ln(14000) c1, convert(ln(14000),decimal(2,3)) c2, cast(ln(14000) as decimal(2,3)) c3; c1 c2 c3 9.5468126085974 9.547 9.547 +create table t1 (sl decimal(70,30)); +ERROR 42000: Too big precision 70 specified for column 'sl'. Maximum is 65. +create table t1 (sl decimal(32,31)); +ERROR 42000: Too big scale 31 specified for column 'sl'. Maximum is 30. +create table t1 (sl decimal(0,38)); +ERROR 42000: Too big scale 38 specified for column 'sl'. Maximum is 30. +create table t1 (sl decimal(0,30)); +ERROR 42000: Scale may not be larger than the precision (column 'sl'). +create table t1 (sl decimal(5, 5)); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `sl` decimal(5,5) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test index 7ce54847506..2901592fd9e 100644 --- a/mysql-test/t/type_decimal.test +++ b/mysql-test/t/type_decimal.test @@ -247,9 +247,8 @@ CREATE TABLE t1 (a_dec DECIMAL(-1,0)); CREATE TABLE t1 (a_dec DECIMAL(-2,1)); --error 1064 CREATE TABLE t1 (a_dec DECIMAL(-1,1)); +--error 1427 CREATE TABLE t1 (a_dec DECIMAL(0,11)); -SHOW CREATE TABLE t1; -DROP TABLE t1; # # Zero prepend overflow bug @@ -293,21 +292,13 @@ create table t1 (d decimal(64,0)); insert into t1 values (1); select * from t1; drop table t1; -create table t1 (d decimal(64,99)); -show create table t1; -insert into t1 values (1); -select * from t1; -drop table t1; -create table t1 (d decimal(10,12)); -show create table t1; -drop table t1; create table t1 (d decimal(5)); show create table t1; drop table t1; create table t1 (d decimal); show create table t1; drop table t1; ---error 1063 +--error 1426 create table t1 (d decimal(66,0)); # diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index 41812ef2652..a27fd4c58b4 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -67,7 +67,7 @@ drop table t1; # FLOAT/DOUBLE/DECIMAL handling # -create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(5,6)); +create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(7,6)); # We mask out Privileges column because it differs for embedded server --replace_column 8 # show full columns from t1; @@ -79,11 +79,8 @@ select a from t1 order by a; select min(a) from t1; drop table t1; +--error 1425 create table t1 (a float(200,100), b double(200,100)); -insert t1 values (1.0, 2.0); -select * from t1; -show create table t1; -drop table t1; # # float in a char(1) field diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 92f0bc9024b..55d004b361f 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -983,3 +983,18 @@ select cast('1.00000001335143196001808973960578441619873046875E-10' as decimal(3 # Bug #11708 (conversion to decimal fails in decimal part) # select ln(14000) c1, convert(ln(14000),decimal(2,3)) c2, cast(ln(14000) as decimal(2,3)) c3; + +# +# Bug #8449 (Silent column changes) +# +--error 1426 +create table t1 (sl decimal(70,30)); +--error 1425 +create table t1 (sl decimal(32,31)); +--error 1425 +create table t1 (sl decimal(0,38)); +--error 1427 +create table t1 (sl decimal(0,30)); +create table t1 (sl decimal(5, 5)); +show create table t1; +drop table t1; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index bdcd88a7205..622c570fa9a 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5362,3 +5362,9 @@ ER_NO_DEFAULT_FOR_VIEW_FIELD eng "Field of view '%-.64s.%-.64s' underlying table doesn't have a default value" ER_SP_NO_RECURSION eng "Recursive stored routines are not allowed." +ER_TOO_BIG_SCALE 42000 S1009 + eng "Too big scale %d specified for column '%-.64s'. Maximum is %d." +ER_TOO_BIG_PRECISION 42000 S1009 + eng "Too big precision %d specified for column '%-.64s'. Maximum is %d." +ER_SCALE_BIGGER_THAN_PRECISION 42000 S1009 + eng "Scale may not be larger than the precision (column '%-.64s')." diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a57ad84da5b..cc10d9c8eac 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5564,8 +5564,14 @@ new_create_field(THD *thd, char *field_name, enum_field_types type, new_field->flags= type_modifier; new_field->unireg_check= (type_modifier & AUTO_INCREMENT_FLAG ? Field::NEXT_NUMBER : Field::NONE); - new_field->decimals= decimals ? (uint) set_zone(atoi(decimals),0, - NOT_FIXED_DEC-1) : 0; + new_field->decimals= decimals ? (uint)atoi(decimals) : 0; + if (new_field->decimals >= NOT_FIXED_DEC) + { + my_error(ER_TOO_BIG_SCALE, MYF(0), new_field->decimals, field_name, + NOT_FIXED_DEC-1); + DBUG_RETURN(NULL); + } + new_field->sql_type=type; new_field->length=0; new_field->change=change; @@ -5586,11 +5592,6 @@ new_create_field(THD *thd, char *field_name, enum_field_types type, length=0; /* purecov: inspected */ sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1; - if (new_field->length && new_field->decimals && - new_field->length < new_field->decimals+1 && - new_field->decimals != NOT_FIXED_DEC) - new_field->length=new_field->decimals+1; /* purecov: inspected */ - switch (type) { case FIELD_TYPE_TINY: if (!length) new_field->length=MAX_TINYINT_WIDTH+sign_len; @@ -5616,22 +5617,24 @@ new_create_field(THD *thd, char *field_name, enum_field_types type, break; case FIELD_TYPE_NEWDECIMAL: if (!length) + new_field->length= 10; + if (new_field->length > DECIMAL_MAX_PRECISION) { - if (!(new_field->length= new_field->decimals)) - new_field->length= 10; // Default length for DECIMAL + my_error(ER_TOO_BIG_PRECISION, MYF(0), new_field->length, field_name, + DECIMAL_MAX_PRECISION); + DBUG_RETURN(NULL); } + if (new_field->length < new_field->decimals) + { + my_error(ER_SCALE_BIGGER_THAN_PRECISION, MYF(0), field_name); + DBUG_RETURN(NULL); + } + new_field->length= + my_decimal_precision_to_length(new_field->length, new_field->decimals, + type_modifier & UNSIGNED_FLAG); new_field->pack_length= my_decimal_get_binary_size(new_field->length, new_field->decimals); - if (new_field->length <= DECIMAL_MAX_PRECISION && - new_field->length >= new_field->decimals) - { - new_field->length= - my_decimal_precision_to_length(new_field->length, new_field->decimals, - type_modifier & UNSIGNED_FLAG); - break; - } - my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name); - DBUG_RETURN(NULL); + break; case MYSQL_TYPE_VARCHAR: /* Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table From 2d4e858aa37f20f1c1861d1fd5925bbc1799b3d2 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Jul 2005 12:54:00 +0500 Subject: [PATCH 188/216] a fix (bug #11809: ps_1general.test fails on QNX). mysql-test/r/ps_1general.result: a fix (bug #11809: ps_1general.test fails on QNX). replace Max_data_length column value with '#' as well mysql-test/t/ps_1general.test: a fix (bug #11809: ps_1general.test fails on QNX). replace Max_data_length column value with '#' as well --- mysql-test/r/ps_1general.result | 4 ++-- mysql-test/t/ps_1general.test | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index 75824aa7213..f2d60ac5025 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -290,11 +290,11 @@ t2 1 t2_idx 1 b A NULL NULL NULL YES BTREE prepare stmt4 from ' show table status from test like ''t2%'' '; execute stmt4; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t2 MyISAM 10 Fixed 0 0 0 4222124650659839 1024 0 NULL # # # latin1_swedish_ci NULL +t2 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # # latin1_swedish_ci NULL prepare stmt4 from ' show table status from test like ''t9%'' '; execute stmt4; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t9 MyISAM 10 Dynamic 2 216 432 281474976710655 2048 0 NULL # # # latin1_swedish_ci NULL +t9 MyISAM 10 Dynamic 2 216 432 # 2048 0 NULL # # # latin1_swedish_ci NULL prepare stmt4 from ' show status like ''Threads_running'' '; execute stmt4; Variable_name Value diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test index 1c247240eb9..ab133e4c347 100644 --- a/mysql-test/t/ps_1general.test +++ b/mysql-test/t/ps_1general.test @@ -307,15 +307,13 @@ prepare stmt4 from ' show index from t2 from test '; execute stmt4; prepare stmt4 from ' show table status from test like ''t2%'' '; # egalize date and time values ---replace_column 12 # 13 # 14 # ---replace_result 2147483647 64424509439 +--replace_column 8 # 12 # 13 # 14 # # Bug#4288 : prepared statement 'show table status ..', wrong output on execute execute stmt4; # try the same with the big table prepare stmt4 from ' show table status from test like ''t9%'' '; # egalize date and time values ---replace_column 12 # 13 # 14 # ---replace_result 2147483647 4294967295 +--replace_column 8 # 12 # 13 # 14 # # Bug#4288 execute stmt4; prepare stmt4 from ' show status like ''Threads_running'' '; From 3d2814d6d43bee9e885053f8e910c8c363f00550 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Jul 2005 11:07:05 +0200 Subject: [PATCH 189/216] - added mysql-test/t/*.def to the source and binary distributions mysql-test/Makefile.am: - added mysql-test/t/*.def to the source distribution and make sure that "make install" installs it, too. scripts/make_binary_distribution.sh: - added mysql-test/t/*.def to the binary distribution --- mysql-test/Makefile.am | 2 ++ scripts/make_binary_distribution.sh | 1 + 2 files changed, 3 insertions(+) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index e7abcd3fc95..7db920b2d80 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -48,6 +48,7 @@ mysql_test_run_new_SOURCES= mysql_test_run_new.c my_manage.c my_create_tables.c dist-hook: mkdir -p $(distdir)/t $(distdir)/r $(distdir)/include \ $(distdir)/std_data $(distdir)/lib + $(INSTALL_DATA) $(srcdir)/t/*.def $(distdir)/t $(INSTALL_DATA) $(srcdir)/t/*.test $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(srcdir)/t/*.slave-mi $(distdir)/t $(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include $(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r @@ -67,6 +68,7 @@ install-data-local: $(DESTDIR)$(testdir)/std_data \ $(DESTDIR)$(testdir)/lib $(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(testdir) + $(INSTALL_DATA) $(srcdir)/t/*.def $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.test $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.opt $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.sh $(DESTDIR)$(testdir)/t diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 3b8cc1ca12a..51bebc3ce31 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -221,6 +221,7 @@ $CP mysql-test/include/*.inc $BASE/mysql-test/include $CP mysql-test/std_data/*.dat mysql-test/std_data/*.*001 $BASE/mysql-test/std_data $CP mysql-test/std_data/des_key_file $BASE/mysql-test/std_data $CP mysql-test/t/*test mysql-test/t/*.opt mysql-test/t/*.slave-mi mysql-test/t/*.sh $BASE/mysql-test/t +$CP mysql-test/t/*.def $BASE/mysql-test/t $CP mysql-test/r/*result mysql-test/r/*.require $BASE/mysql-test/r if [ $BASE_SYSTEM != "netware" ] ; then From 47c921e364b223469d8dd3cc58ce452715b547c9 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Jul 2005 02:12:31 -0700 Subject: [PATCH 190/216] ctype_utf8.test: Added a test case for bug #11484. hp_hash.c: Fixed bug #11484. This bug in the function hp_rec_key_cmp resulted in wrong comparison of varchar multibyte keys if the bytes after string values happened to be different. This caused wrong results for queries returning DISTINCT varchar fields in multibyte charsets (e.g. in utf8). heap/hp_hash.c: Fixed bug #11484. This bug in the function hp_rec_key_cmp resulted in wrong comparison of varchar multibyte keys if the bytes after string values happened to be different. This caused wrong results for queries returning DISTINCT varchar fields in multibyte charsets (e.g. in utf8). mysql-test/t/ctype_utf8.test: Added a test case for bug #11484. --- heap/hp_hash.c | 4 ++-- mysql-test/r/ctype_utf8.result | 19 +++++++++++++++++++ mysql-test/t/ctype_utf8.test | 13 +++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/heap/hp_hash.c b/heap/hp_hash.c index 9e4636ebdc0..d643f776731 100644 --- a/heap/hp_hash.c +++ b/heap/hp_hash.c @@ -552,9 +552,9 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2, if (cs->mbmaxlen > 1) { uint char_length= seg->length / cs->mbmaxlen; - char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length); + char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length1); set_if_smaller(char_length1, seg->length); - char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length); + char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length2); set_if_smaller(char_length2, seg->length); } diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index b8ff3c70aa1..3af13289478 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -950,3 +950,22 @@ hex(a) 5B E880BD drop table t1; +CREATE TABLE t1(id varchar(20) NOT NULL) DEFAULT CHARSET=utf8; +INSERT INTO t1 VALUES ('xxx'), ('aa'), ('yyy'), ('aa'); +SELECT id FROM t1; +id +xxx +aa +yyy +aa +SELECT DISTINCT id FROM t1; +id +xxx +aa +yyy +SELECT DISTINCT id FROM t1 ORDER BY id; +id +aa +xxx +yyy +DROP TABLE t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 0a847057258..86de7d5d761 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -800,3 +800,16 @@ insert into t1 values (_utf8 0xe880bd); insert into t1 values (_utf8 0x5b); select hex(a) from t1; drop table t1; + +# +# Test for bug #11484: wrong results for a DISTINCT varchar column in uft8. +# + +CREATE TABLE t1(id varchar(20) NOT NULL) DEFAULT CHARSET=utf8; +INSERT INTO t1 VALUES ('xxx'), ('aa'), ('yyy'), ('aa'); + +SELECT id FROM t1; +SELECT DISTINCT id FROM t1; +SELECT DISTINCT id FROM t1 ORDER BY id; + +DROP TABLE t1; From 6fcb956277ec9cf29f2b2e42417e5dff640064d9 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Jul 2005 15:36:57 +0200 Subject: [PATCH 191/216] mysql_client_test.dsp: Corrected libs and lib search path for debug target VC++Files/tests/mysql_client_test.dsp: Corrected libs and lib search path for debug target --- VC++Files/tests/mysql_client_test.dsp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/VC++Files/tests/mysql_client_test.dsp b/VC++Files/tests/mysql_client_test.dsp index d862425d602..012129a208b 100644 --- a/VC++Files/tests/mysql_client_test.dsp +++ b/VC++Files/tests/mysql_client_test.dsp @@ -41,8 +41,8 @@ RSC=rc.exe # PROP Output_Dir ".\Debug" # PROP Intermediate_Dir ".\Debug" # PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /I "../include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /Fp".\Debug/mysql_client_test.pch" /Fo".\Debug/" /Fd".\Debug/" /GZ /c /GX -# ADD CPP /nologo /MTd /I "../include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /Fp".\Debug/mysql_client_test.pch" /Fo".\Debug/" /Fd".\Debug/" /GZ /c /GX +# ADD BASE CPP /nologo /MTd /I "../include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /Fp".\Debug/mysql_client_test.pch" /Fo".\Debug/" /Fd".\Debug/" /GZ /FD /c /GX +# ADD CPP /nologo /MTd /I "../include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /Fp".\Debug/mysql_client_test.pch" /Fo".\Debug/" /Fd".\Debug/" /GZ /FD /c /GX # ADD BASE MTL /nologo /tlb".\Debug\mysql_client_test.tlb" /win32 # ADD MTL /nologo /tlb".\Debug\mysql_client_test.tlb" /win32 # ADD BASE RSC /l 1033 @@ -66,8 +66,8 @@ LINK32=link.exe # PROP Output_Dir ".\Release" # PROP Intermediate_Dir ".\Release" # PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /I "../include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /GF /Gy /Fp".\Release/mysql_client_test.pch" /Fo".\Release/" /Fd".\Release/" /c /GX -# ADD CPP /nologo /MTd /I "../include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /GF /Gy /Fp".\Release/mysql_client_test.pch" /Fo".\Release/" /Fd".\Release/" /c /GX +# ADD BASE CPP /nologo /MTd /I "../include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /GF /Gy /Fp".\Release/mysql_client_test.pch" /Fo".\Release/" /Fd".\Release/" /FD /c /GX +# ADD CPP /nologo /MTd /I "../include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /GF /Gy /Fp".\Release/mysql_client_test.pch" /Fo".\Release/" /Fd".\Release/" /FD /c /GX # ADD BASE MTL /nologo /tlb".\Release\mysql_client_test.tlb" /win32 # ADD MTL /nologo /tlb".\Release\mysql_client_test.tlb" /win32 # ADD BASE RSC /l 1033 @@ -76,8 +76,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /out:"..\client_release\mysql_client_test.exe" /incremental:no /pdb:".\Release\mysql_client_test.pdb" /pdbtype:sept /subsystem:console -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /out:"..\client_release\mysql_client_test.exe" /incremental:no /pdb:".\Release\mysql_client_test.pdb" /pdbtype:sept /subsystem:console +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib Ws2_32.lib mysqlclient.lib mysys.lib regex.lib /nologo /out:"..\client_release\mysql_client_test.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\Release\mysql_client_test.pdb" /pdbtype:sept /subsystem:console +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib Ws2_32.lib mysqlclient.lib mysys.lib regex.lib /nologo /out:"..\client_release\mysql_client_test.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\Release\mysql_client_test.pdb" /pdbtype:sept /subsystem:console !ENDIF From accdff5114b99a3703e73d513db59a33e7da0371 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Jul 2005 16:33:15 +0200 Subject: [PATCH 192/216] Fixed BUG#11365: Stored Procedure: Crash on Procedure operation Two separate problems. A key buffer was too small in sp.cc for multi-byte fields, and the creation and fixing of mysql.proc in the scripts hadn't been updated with the correct character sets and collations (like the other system tables had). Note: No special test case, as the use of utf8 for mysql.proc will make any existing crash (if the buffer overrrun wasn't fixed). mysql-test/r/sp-error.result: Updated test case for too long SP names (as the limit has increased with the use of utf8). mysql-test/t/sp-error.test: Updated test case for too long SP names (as the limit has increased with the use of utf8). scripts/mysql_create_system_tables.sh: Use utf8 for mysql.proc, just like for the other system tables. scripts/mysql_fix_privilege_tables.sql: Use utf8 for mysql.proc, just like for the other system tables. (Some tabs also replaced by space) sql/sp.cc: Use a larger key buffer for stored procedures to avoid stack overrun with multi-byte keys. --- mysql-test/r/sp-error.result | 4 +-- mysql-test/t/sp-error.test | 4 +-- scripts/mysql_create_system_tables.sh | 12 ++++--- scripts/mysql_fix_privilege_tables.sql | 45 +++++++++++++++++--------- sql/sp.cc | 2 +- 5 files changed, 41 insertions(+), 26 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 0d624b30d9e..b5f6a7837fa 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -604,10 +604,10 @@ flush tables; return 5; end| ERROR 0A000: FLUSH is not allowed in stored procedures -create procedure bug9529_90123456789012345678901234567890123456789012345678901234567890() +create procedure bug9529_90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123() begin end| -ERROR 42000: Identifier name 'bug9529_90123456789012345678901234567890123456789012345678901234567890' is too long +ERROR 42000: Identifier name 'bug9529_90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890' is too long drop procedure if exists bug10969| create procedure bug10969() begin diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index a61c082fb30..34300cc4737 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -874,9 +874,9 @@ end| # # BUG#9529: Stored Procedures: No Warning on truncation of procedure name # during creation. -# +# Note: When using utf8 for mysql.proc, this limit is much higher than before --error ER_TOO_LONG_IDENT -create procedure bug9529_90123456789012345678901234567890123456789012345678901234567890() +create procedure bug9529_90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123() begin end| diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh index bc07d857c4b..a3036b5c10b 100644 --- a/scripts/mysql_create_system_tables.sh +++ b/scripts/mysql_create_system_tables.sh @@ -669,7 +669,7 @@ fi if test ! -f $mdata/proc.frm then c_p="$c_p CREATE TABLE proc (" - c_p="$c_p db char(64) binary DEFAULT '' NOT NULL," + c_p="$c_p db char(64) collate utf8_bin DEFAULT '' NOT NULL," c_p="$c_p name char(64) DEFAULT '' NOT NULL," c_p="$c_p type enum('FUNCTION','PROCEDURE') NOT NULL," c_p="$c_p specific_name char(64) DEFAULT '' NOT NULL," @@ -684,7 +684,7 @@ then c_p="$c_p param_list blob DEFAULT '' NOT NULL," c_p="$c_p returns char(64) DEFAULT '' NOT NULL," c_p="$c_p body blob DEFAULT '' NOT NULL," - c_p="$c_p definer char(77) binary DEFAULT '' NOT NULL," + c_p="$c_p definer char(77) collate utf8_bin DEFAULT '' NOT NULL," c_p="$c_p created timestamp," c_p="$c_p modified timestamp," c_p="$c_p sql_mode set(" @@ -718,10 +718,12 @@ then c_p="$c_p 'TRADITIONAL'," c_p="$c_p 'NO_AUTO_CREATE_USER'," c_p="$c_p 'HIGH_NOT_PRECEDENCE'" - c_p="$c_p ) DEFAULT 0 NOT NULL," - c_p="$c_p comment char(64) binary DEFAULT '' NOT NULL," + c_p="$c_p ) DEFAULT '' NOT NULL," + c_p="$c_p comment char(64) collate utf8_bin DEFAULT '' NOT NULL," c_p="$c_p PRIMARY KEY (db,name,type)" - c_p="$c_p ) comment='Stored Procedures';" + c_p="$c_p ) engine=MyISAM" + c_p="$c_p character set utf8" + c_p="$c_p comment='Stored Procedures';" fi cat << END_OF_DATA diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql index 3da2f7504a1..b93e0a47b1b 100644 --- a/scripts/mysql_fix_privilege_tables.sql +++ b/scripts/mysql_fix_privilege_tables.sql @@ -412,22 +412,22 @@ PRIMARY KEY TranTime (Transition_time) # CREATE TABLE IF NOT EXISTS proc ( - db char(64) binary DEFAULT '' NOT NULL, + db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum('CONTAINS_SQL', - 'NO_SQL', - 'READS_SQL_DATA', - 'MODIFIES_SQL_DATA' - ) DEFAULT 'CONTAINS_SQL' NOT NULL, + 'NO_SQL', + 'READS_SQL_DATA', + 'MODIFIES_SQL_DATA' + ) DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob DEFAULT '' NOT NULL, returns char(64) DEFAULT '' NOT NULL, body blob DEFAULT '' NOT NULL, - definer char(77) binary DEFAULT '' NOT NULL, + definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( @@ -461,20 +461,22 @@ CREATE TABLE IF NOT EXISTS proc ( 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' - ) DEFAULT 0 NOT NULL, - comment char(64) binary DEFAULT '' NOT NULL, + ) DEFAULT '' NOT NULL, + comment char(64) collate utf8_bin DEFAULT '' NOT NULL, PRIMARY KEY (db,name,type) -) comment='Stored Procedures'; +) engine=MyISAM + character set utf8 + comment='Stored Procedures'; # Correct the name fields to not binary, and expand sql_data_access ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL, MODIFY specific_name char(64) DEFAULT '' NOT NULL, - MODIFY sql_data_access - enum('CONTAINS_SQL', - 'NO_SQL', - 'READS_SQL_DATA', - 'MODIFIES_SQL_DATA' - ) DEFAULT 'CONTAINS_SQL' NOT NULL, + MODIFY sql_data_access + enum('CONTAINS_SQL', + 'NO_SQL', + 'READS_SQL_DATA', + 'MODIFIES_SQL_DATA' + ) DEFAULT 'CONTAINS_SQL' NOT NULL, MODIFY sql_mode set('REAL_AS_FLOAT', 'PIPES_AS_CONCAT', @@ -506,4 +508,15 @@ ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL, 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' - ) DEFAULT 0 NOT NULL; + ) DEFAULT '' NOT NULL + DEFAULT CHARACTER SET utf8; + +# Correct the character set and collation +ALTER TABLE proc CONVERT TO CHARACTER SET utf8; +# Reset some fields after the conversion +ALTER TABLE proc MODIFY db + char(64) collate utf8_bin DEFAULT '' NOT NULL, + MODIFY definer + char(77) collate utf8_bin DEFAULT '' NOT NULL, + MODIFY comment + char(64) collate utf8_bin DEFAULT '' NOT NULL; diff --git a/sql/sp.cc b/sql/sp.cc index 456248db66b..2452b9f6453 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -67,7 +67,7 @@ db_find_routine_aux(THD *thd, int type, sp_name *name, enum thr_lock_type ltype, TABLE **tablep, bool *opened) { TABLE *table; - byte key[NAME_LEN*2+4+1]; // db, name, optional key length type + byte key[MAX_KEY_LENGTH]; // db, name, optional key length type DBUG_ENTER("db_find_routine_aux"); DBUG_PRINT("enter", ("type: %d name: %*s", type, name->m_name.length, name->m_name.str)); From 284e241c46e4ab5badd6400b4c1073e88cb26065 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Jul 2005 21:04:54 +0200 Subject: [PATCH 193/216] - reverted adding mysql-test/t/*.def to the distribution (it is not supported in 4.1 at all) --- mysql-test/Makefile.am | 2 -- scripts/make_binary_distribution.sh | 1 - 2 files changed, 3 deletions(-) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 7db920b2d80..e7abcd3fc95 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -48,7 +48,6 @@ mysql_test_run_new_SOURCES= mysql_test_run_new.c my_manage.c my_create_tables.c dist-hook: mkdir -p $(distdir)/t $(distdir)/r $(distdir)/include \ $(distdir)/std_data $(distdir)/lib - $(INSTALL_DATA) $(srcdir)/t/*.def $(distdir)/t $(INSTALL_DATA) $(srcdir)/t/*.test $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(srcdir)/t/*.slave-mi $(distdir)/t $(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include $(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r @@ -68,7 +67,6 @@ install-data-local: $(DESTDIR)$(testdir)/std_data \ $(DESTDIR)$(testdir)/lib $(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(testdir) - $(INSTALL_DATA) $(srcdir)/t/*.def $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.test $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.opt $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.sh $(DESTDIR)$(testdir)/t diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 51bebc3ce31..3b8cc1ca12a 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -221,7 +221,6 @@ $CP mysql-test/include/*.inc $BASE/mysql-test/include $CP mysql-test/std_data/*.dat mysql-test/std_data/*.*001 $BASE/mysql-test/std_data $CP mysql-test/std_data/des_key_file $BASE/mysql-test/std_data $CP mysql-test/t/*test mysql-test/t/*.opt mysql-test/t/*.slave-mi mysql-test/t/*.sh $BASE/mysql-test/t -$CP mysql-test/t/*.def $BASE/mysql-test/t $CP mysql-test/r/*result mysql-test/r/*.require $BASE/mysql-test/r if [ $BASE_SYSTEM != "netware" ] ; then From de1254ad792fe54b033ba106979db9854de2f976 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Jul 2005 21:13:14 +0200 Subject: [PATCH 194/216] - reverted and optimized a merge --- mysql-test/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 8ae551e2ffd..7c7ceb349a4 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -48,6 +48,7 @@ mysql_test_run_new_SOURCES= mysql_test_run_new.c my_manage.c my_create_tables.c dist-hook: mkdir -p $(distdir)/t $(distdir)/r $(distdir)/include \ $(distdir)/std_data $(distdir)/lib + -$(INSTALL_DATA) $(srcdir)/t/*.def $(distdir)/t $(INSTALL_DATA) $(srcdir)/t/*.test $(distdir)/t $(INSTALL_DATA) $(srcdir)/t/*.sql $(distdir)/t -$(INSTALL_DATA) $(srcdir)/t/*.disabled $(distdir)/t @@ -70,6 +71,7 @@ install-data-local: $(DESTDIR)$(testdir)/std_data \ $(DESTDIR)$(testdir)/lib $(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(testdir) + -$(INSTALL_DATA) $(srcdir)/t/*.def $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.test $(DESTDIR)$(testdir)/t $(INSTALL_DATA) $(srcdir)/t/*.sql $(DESTDIR)$(testdir)/t -$(INSTALL_DATA) $(srcdir)/t/*.disabled $(DESTDIR)$(testdir)/t From 3096eac938a3dde687d85b8033121c7664e5213d Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 9 Jul 2005 08:57:08 -0700 Subject: [PATCH 195/216] Fixed indention issue, made scan_rows an ha_rows type, and fixed show table status so archive rows are displayed as being compressed. sql/examples/ha_archive.h: Fixed indention issues, modified scan_rows to being ha_rows, and fixed the diplsay show table status to mention that rows inside of archive are compressed. --- sql/examples/ha_archive.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sql/examples/ha_archive.h b/sql/examples/ha_archive.h index 454d253abe5..4afdba4b8ed 100644 --- a/sql/examples/ha_archive.h +++ b/sql/examples/ha_archive.h @@ -36,7 +36,7 @@ typedef struct st_archive_share { gzFile archive_write; /* Archive file we are working with */ bool dirty; /* Flag for if a flush should occur */ bool crashed; /* Meta file is crashed */ - ha_rows rows_recorded; /* Number of rows in tables */ + ha_rows rows_recorded; /* Number of rows in tables */ } ARCHIVE_SHARE; /* @@ -53,7 +53,7 @@ class ha_archive: public handler z_off_t current_position; /* The position of the row we just read */ byte byte_buffer[IO_SIZE]; /* Initial buffer for our string */ String buffer; /* Buffer used for blob storage */ - ulonglong scan_rows; /* Number of rows left in scan */ + ha_rows scan_rows; /* Number of rows left in scan */ bool delayed_insert; /* If the insert is delayed */ bool bulk_insert; /* If we are performing a bulk insert */ @@ -102,6 +102,10 @@ public: int repair(THD* thd, HA_CHECK_OPT* check_opt); void start_bulk_insert(ha_rows rows); int end_bulk_insert(); + enum row_type get_row_type() const + { + return ROW_TYPE_COMPRESSED; + } THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type); }; From 14b1f91ba4aa9a4d950450b513d167b221ce6f6d Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 9 Jul 2005 21:51:59 +0400 Subject: [PATCH 196/216] Enable support of access to tables from triggers. Thus fix bug #8406 "Triggers crash if referencing a table" and several other related bugs. Fix for bug #11834 "Re-execution of prepared statement with dropped function crashes server." which was spotted during work on previous bugs. Also couple of nice cleanups: - Replaced two separate hashes for stored routines used by statement with one. - Now instead of doing one pass through all routines used in statement for caching them and then doing another pass for adding their tables to table list, we do only one pass during which do both things. mysql-test/r/sp-error.result: Added test for bug #11834 "Re-execution of prepared statement with dropped function crashes server" also covering handling of prepared statements which use stored functions but does not require prelocking. mysql-test/r/sp.result: Updated test for LOCK TABLES with views in table list. (Old version of statement used in this test will work ok now, since prelocking algorithm was tuned and will lock only one multi-set of tables for each routine even if this routine is used in several different views). mysql-test/r/trigger.result: Added several tests for triggers using tables. mysql-test/t/sp-error.test: Added test for bug #11834 "Re-execution of prepared statement with dropped function crashes server" also covering handling of prepared statements which use stored functions but does not require prelocking. mysql-test/t/sp.test: Updated comment about recursive views to reflect current situation. Updated test for LOCK TABLES with views in table list. (Old version of statement used in this test will work ok now, since prelocking algorithm was tuned and will lock only one multi-set of tables for each routine even if this routine is used in several different views). mysql-test/t/trigger.test: Added several tests for triggers using tables. sql/item_func.cc: Item_func_sp::cleanup(): By next statement execution stored function can be dropped or altered so we can't assume that sp_head object for it will be still valid. sql/sp.cc: - Added Sroutine_hash_entry structure that represents element in the set of stored routines used by statement or routine. We can't as before use LEX_STRING for this purprose because we want link all elements of this set in list. - Replaced sp_add_to_hash() with sp_add_used_routine() which takes into account that now we use one hash for stored routines used by statement instead of two and which mantains list linking all elelemnts in this hash. - Renamed sp_merge_hash() to sp_update_sp_used_routines(). - Introduced sp_update_stmt_used_routines() for adding elements to the set of routines used by statement from another similar set for statement or routine. This function will also mantain list linking elements of destination set. - Now instead of one sp_cache_routines() function we have family of sp_cache_routines_and_add_tables() functions which are also responsible for adding tables used by routines being cached to statement table list. Nice optimization - thanks to list linking all elements in the hash of routines used by statement we don't need to perform several iterations over this hash (as it was before in cases when we have added new elements to it). sql/sp.h: Added declarations of functions used for manipulations with set (hash) of stored routines used by statement. sql/sp_head.cc: sp_name::init_qname(): Now sp_name also holds key identifying routine in the set (hash) of stored routines used by statement. sp_head: Instead of two separate hashes sp_funs/m_spprocs representing sets of stored routines used by this routine we use one hash - m_sroutines. sp_instr_set_trigger_field: Added support for subqueries in assignments to row accessors in triggers. Removed definition of sp_add_sp_tables_to_table_list() and auxilary functions since now we don't have separate stage on which we add tables used by routines used by statement to table list for prelocking. We do it on the same stage as we load those routines in SP cache. So all this functionality moved to sp_cache_routines_and_add_tables() family of functions. sql/sp_head.h: sp_name: Now this class also holds key identifying routine in the set (hash) of stored routines used by statement. sp_head: Instead of two separate hashes sp_funs/m_spprocs representing sets of stored routines used by this routine we use one hash - m_sroutines. sp_instr_set_trigger_field: Added support for subqueries in assignments to row accessors in triggers. Removed declaration of sp_add_sp_tables_to_table_list() since now we don't have separate stage on which we add tables used by routines used by statement to table list for prelocking. We do it on the same stage as we load those routines in SP cache. sql/sql_base.cc: open_tables(): - LEX::spfuns/spprocs hashes were replaced with one LEX::sroutines hash. - Now instead of doing one pass through all routines used in statement for caching them and then doing another pass for adding their tables to table list, we do only one pass during which do both things. It is easy to do since all routines in the set of routines used by statement are linked in the list. This also allows us to calculate table list for prelocking more precisely. - Now triggers properly inform prelocking algorithm about tables they use. sql/sql_lex.cc: lex_start(): Replaced LEX::spfuns/spprocs with with one LEX::sroutines hash. Added LEX::sroutines_list list linking all elements in this hash. st_lex::st_lex(): Moved definition of LEX constructor to sql_lex.cc file to be able use sp_sroutine_key declaration from sp.h in it. sql/sql_lex.h: LEX: Replaced two separate hashes for stored routines used by statement with one. Added list linking all elements in this hash to be able to iterate through all elements and add new elements to this hash at the same time. Moved constructor definition to sql_lex.cc. sql/sql_parse.cc: mysql_execute_command(): Replaced LEX::spfuns/spprocs with one LEX::sroutines hash. sql/sql_trigger.cc: Added missing GNU GPL notice. Table_triggers_list::check_n_load() Added initialization of sroutines_key which stores key representing triggers of this table in the set (hash) of routines used by this statement. sql/sql_trigger.h: Added missing GNU GPL notice. Table_triggers_list: Added sroutines_key member to store key representing triggers of this table in the set (hash) of routines used by this statement. Declared sp_cache_routines_and_add_tables_for_triggers() as friend since it needs access to sroutines_key and trigger bodies. sql/sql_yacc.yy: - Now we use sp_add_used_routine() instead of sp_add_to_hash() for adding elements to the set of stored routines used in statement. - Enabled support of subqueries as right sides in assignments to triggers' row accessors. --- mysql-test/r/sp-error.result | 16 ++ mysql-test/r/sp.result | 2 +- mysql-test/r/trigger.result | 93 ++++++++- mysql-test/t/sp-error.test | 22 ++ mysql-test/t/sp.test | 8 +- mysql-test/t/trigger.test | 83 +++++++- sql/item_func.cc | 1 + sql/sp.cc | 377 +++++++++++++++++++++++++---------- sql/sp.h | 20 +- sql/sp_head.cc | 113 +++-------- sql/sp_head.h | 56 ++++-- sql/sql_base.cc | 25 +-- sql/sql_lex.cc | 29 ++- sql/sql_lex.h | 20 +- sql/sql_parse.cc | 3 +- sql/sql_trigger.cc | 29 +++ sql/sql_trigger.h | 27 +++ sql/sql_yacc.yy | 14 +- 18 files changed, 675 insertions(+), 263 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index b6ba737a8ba..1af88049adb 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -686,3 +686,19 @@ ERROR 0A000: EXECUTE is not allowed in stored procedures create function f() returns int begin execute stmt; ERROR 0A000: EXECUTE is not allowed in stored procedures deallocate prepare stmt; +drop function if exists bug11834_1; +drop function if exists bug11834_2; +create function bug11834_1() returns int return 10; +create function bug11834_2() returns int return bug11834_1(); +prepare stmt from "select bug11834_2()"; +execute stmt; +bug11834_2() +10 +execute stmt; +bug11834_2() +10 +drop function bug11834_1; +execute stmt; +ERROR 42000: FUNCTION test.bug11834_1 does not exist +deallocate prepare stmt; +drop function bug11834_2; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index bf6a4dbf68c..7f6d3be8956 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1229,7 +1229,7 @@ a select * from v1| a 3 -select * from v1, v2| +select * from v1, t1| ERROR HY000: Table 't1' was not locked with LOCK TABLES select f4()| ERROR HY000: Table 't2' was not locked with LOCK TABLES diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 996a692d531..746c900d743 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1,6 +1,7 @@ -drop table if exists t1, t2; +drop table if exists t1, t2, t3; drop view if exists v1; drop database if exists mysqltest; +drop function if exists f1; create table t1 (i int); create trigger trg before insert on t1 for each row set @a:=1; set @a:=0; @@ -182,6 +183,96 @@ select @log; @log (BEFORE_INSERT: new=(id=1, data=5))(BEFORE_UPDATE: old=(id=1, data=4) new=(id=1, data=6))(AFTER_UPDATE: old=(id=1, data=4) new=(id=1, data=6))(BEFORE_INSERT: new=(id=3, data=3))(AFTER_INSERT: new=(id=3, data=3)) drop table t1; +create table t1 (id int primary key, data varchar(10), fk int); +create table t2 (event varchar(100)); +create table t3 (id int primary key); +create trigger t1_ai after insert on t1 for each row +insert into t2 values (concat("INSERT INTO t1 id=", new.id, " data='", new.data, "'")); +insert into t1 (id, data) values (1, "one"), (2, "two"); +select * from t1; +id data fk +1 one NULL +2 two NULL +select * from t2; +event +INSERT INTO t1 id=1 data='one' +INSERT INTO t1 id=2 data='two' +drop trigger t1.t1_ai; +create trigger t1_bi before insert on t1 for each row +begin +if exists (select id from t3 where id=new.fk) then +insert into t2 values (concat("INSERT INTO t1 id=", new.id, " data='", new.data, "' fk=", new.fk)); +else +insert into t2 values (concat("INSERT INTO t1 FAILED id=", new.id, " data='", new.data, "' fk=", new.fk)); +set new.id= NULL; +end if; +end| +insert into t3 values (1); +insert into t1 values (4, "four", 1), (5, "five", 2); +ERROR 23000: Column 'id' cannot be null +select * from t1; +id data fk +1 one NULL +2 two NULL +4 four 1 +select * from t2; +event +INSERT INTO t1 id=1 data='one' +INSERT INTO t1 id=2 data='two' +INSERT INTO t1 id=4 data='four' fk=1 +INSERT INTO t1 FAILED id=5 data='five' fk=2 +drop table t1, t2, t3; +create table t1 (id int primary key, data varchar(10)); +create table t2 (seq int); +insert into t2 values (10); +create function f1 () returns int return (select max(seq) from t2); +create trigger t1_bi before insert on t1 for each row +begin +if new.id > f1() then +set new.id:= f1(); +end if; +end| +select f1(); +f1() +10 +insert into t1 values (1, "first"); +insert into t1 values (f1(), "max"); +select * from t1; +id data +1 first +10 max +drop table t1, t2; +drop function f1; +create table t1 (id int primary key, fk_t2 int); +create table t2 (id int primary key, fk_t3 int); +create table t3 (id int primary key); +insert into t1 values (1,1), (2,1), (3,2); +insert into t2 values (1,1), (2,2); +insert into t3 values (1), (2); +create trigger t3_ad after delete on t3 for each row +delete from t2 where fk_t3=old.id; +create trigger t2_ad after delete on t2 for each row +delete from t1 where fk_t2=old.id; +delete from t3 where id = 1; +select * from t1 left join (t2 left join t3 on t2.fk_t3 = t3.id) on t1.fk_t2 = t2.id; +id fk_t2 id fk_t3 id +3 2 2 2 2 +drop table t1, t2, t3; +create table t1 (id int primary key, copy int); +create table t2 (id int primary key, data int); +insert into t2 values (1,1), (2,2); +create trigger t1_bi before insert on t1 for each row +set new.copy= (select data from t2 where id = new.id); +create trigger t1_bu before update on t1 for each row +set new.copy= (select data from t2 where id = new.id); +insert into t1 values (1,3), (2,4), (3,3); +update t1 set copy= 1 where id = 2; +select * from t1; +id copy +1 1 +2 2 +3 NULL +drop table t1, t2; create table t1 (i int); create trigger trg before insert on t1 for each row set @a:= old.i; ERROR HY000: There is no OLD row in on INSERT trigger diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index faf6d8b4de3..e4cb352e544 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -986,3 +986,25 @@ create procedure p() execute stmt; create function f() returns int begin execute stmt; deallocate prepare stmt; +# +# Bug#11834 "Re-execution of prepared statement with dropped function +# crashes server". Also tests handling of prepared stmts which use +# stored functions but does not require prelocking. +# +--disable_warnings +drop function if exists bug11834_1; +drop function if exists bug11834_2; +--enable_warnings +create function bug11834_1() returns int return 10; +create function bug11834_2() returns int return bug11834_1(); +prepare stmt from "select bug11834_2()"; +execute stmt; +# Re-execution of statement should not crash server. +execute stmt; +drop function bug11834_1; +# Attempt to execute statement should return proper error and +# should not crash server. +--error ER_SP_DOES_NOT_EXIST +execute stmt; +deallocate prepare stmt; +drop function bug11834_2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 20b1a98702c..cbd77ee0221 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1414,7 +1414,8 @@ select * from v1| # views and functions ? create function f1() returns int return (select sum(data) from t1) + (select sum(data) from v1)| -# FIXME All these just exceed file limit for me :) +# This queries will crash server because we can't use LEX in +# reenterable fashion yet. Patch disabling recursion will heal this. #select f1()| #select * from v1| #select * from v2| @@ -1459,15 +1460,12 @@ select * from v2| select * from v1| # These should not work as we have too little instances of tables locked --error 1100 -select * from v1, v2| +select * from v1, t1| --error 1100 select f4()| unlock tables| -# TODO We also should test integration with triggers - - # Cleanup drop function f0| drop function f1| diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 0c5ef077159..75b2f6de57a 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -3,9 +3,10 @@ # --disable_warnings -drop table if exists t1, t2; +drop table if exists t1, t2, t3; drop view if exists v1; drop database if exists mysqltest; +drop function if exists f1; --enable_warnings create table t1 (i int); @@ -199,6 +200,86 @@ select @log; drop table t1; +# +# Let us test triggers which access other tables. +# +# Trivial trigger which inserts data into another table +create table t1 (id int primary key, data varchar(10), fk int); +create table t2 (event varchar(100)); +create table t3 (id int primary key); +create trigger t1_ai after insert on t1 for each row + insert into t2 values (concat("INSERT INTO t1 id=", new.id, " data='", new.data, "'")); +insert into t1 (id, data) values (1, "one"), (2, "two"); +select * from t1; +select * from t2; +drop trigger t1.t1_ai; +# Trigger which uses couple of tables (and partially emulates FK constraint) +delimiter |; +create trigger t1_bi before insert on t1 for each row +begin + if exists (select id from t3 where id=new.fk) then + insert into t2 values (concat("INSERT INTO t1 id=", new.id, " data='", new.data, "' fk=", new.fk)); + else + insert into t2 values (concat("INSERT INTO t1 FAILED id=", new.id, " data='", new.data, "' fk=", new.fk)); + set new.id= NULL; + end if; +end| +delimiter ;| +insert into t3 values (1); +--error 1048 +insert into t1 values (4, "four", 1), (5, "five", 2); +select * from t1; +select * from t2; +drop table t1, t2, t3; +# Trigger which invokes function +create table t1 (id int primary key, data varchar(10)); +create table t2 (seq int); +insert into t2 values (10); +create function f1 () returns int return (select max(seq) from t2); +delimiter |; +create trigger t1_bi before insert on t1 for each row +begin + if new.id > f1() then + set new.id:= f1(); + end if; +end| +delimiter ;| +# Remove this once bug #11554 will be fixed. +select f1(); +insert into t1 values (1, "first"); +insert into t1 values (f1(), "max"); +select * from t1; +drop table t1, t2; +drop function f1; +# Trigger which forces invocation of another trigger +# (emulation of FK on delete cascade policy) +create table t1 (id int primary key, fk_t2 int); +create table t2 (id int primary key, fk_t3 int); +create table t3 (id int primary key); +insert into t1 values (1,1), (2,1), (3,2); +insert into t2 values (1,1), (2,2); +insert into t3 values (1), (2); +create trigger t3_ad after delete on t3 for each row + delete from t2 where fk_t3=old.id; +create trigger t2_ad after delete on t2 for each row + delete from t1 where fk_t2=old.id; +delete from t3 where id = 1; +select * from t1 left join (t2 left join t3 on t2.fk_t3 = t3.id) on t1.fk_t2 = t2.id; +drop table t1, t2, t3; +# Trigger which assigns value selected from table to field of row +# being inserted/updated. +create table t1 (id int primary key, copy int); +create table t2 (id int primary key, data int); +insert into t2 values (1,1), (2,2); +create trigger t1_bi before insert on t1 for each row + set new.copy= (select data from t2 where id = new.id); +create trigger t1_bu before update on t1 for each row + set new.copy= (select data from t2 where id = new.id); +insert into t1 values (1,3), (2,4), (3,3); +update t1 set copy= 1 where id = 2; +select * from t1; +drop table t1, t2; + # # Test of wrong column specifiers in triggers # diff --git a/sql/item_func.cc b/sql/item_func.cc index 4dc7e55f195..ee8f8de5177 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4707,6 +4707,7 @@ Item_func_sp::cleanup() delete result_field; result_field= NULL; } + m_sp= NULL; Item_func::cleanup(); } diff --git a/sql/sp.cc b/sql/sp.cc index 4f89d6ba6da..06d85ad5c60 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -19,6 +19,7 @@ #include "sp.h" #include "sp_head.h" #include "sp_cache.h" +#include "sql_trigger.h" static bool create_string(THD *thd, String *buf, @@ -1072,145 +1073,317 @@ sp_function_exists(THD *thd, sp_name *name) } -byte * -sp_lex_sp_key(const byte *ptr, uint *plen, my_bool first) +/* + Structure that represents element in the set of stored routines + used by statement or routine. +*/ +struct Sroutine_hash_entry; + +struct Sroutine_hash_entry { - LEX_STRING *lsp= (LEX_STRING *)ptr; - *plen= lsp->length; - return (byte *)lsp->str; -} + /* Set key consisting of one-byte routine type and quoted routine name. */ + LEX_STRING key; + /* + Next element in list linking all routines in set. See also comments + for LEX::sroutine/sroutine_list and sp_head::m_sroutines. + */ + Sroutine_hash_entry *next; +}; -void -sp_add_to_hash(HASH *h, sp_name *fun) +extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first) { - if (! hash_search(h, (byte *)fun->m_qname.str, fun->m_qname.length)) - { - LEX_STRING *ls= (LEX_STRING *)sql_alloc(sizeof(LEX_STRING)); - ls->str= sql_strmake(fun->m_qname.str, fun->m_qname.length); - ls->length= fun->m_qname.length; - - my_hash_insert(h, (byte *)ls); - } + Sroutine_hash_entry *rn= (Sroutine_hash_entry *)ptr; + *plen= rn->key.length; + return (byte *)rn->key.str; } /* - Merge contents of two hashes containing LEX_STRING's + Auxilary function that adds new element to the set of stored routines + used by statement. SYNOPSIS - sp_merge_hash() + add_used_routine() + lex - LEX representing statement + arena - arena in which memory for new element will be allocated + key - key for the hash representing set + + NOTES + Will also add element to end of 'LEX::sroutines_list' list. + + In case when statement uses stored routines but does not need + prelocking (i.e. it does not use any tables) we will access the + elements of LEX::sroutines set on prepared statement re-execution. + Because of this we have to allocate memory for both hash element + and copy of its key in persistent arena. + + TODO + When we will got rid of these accesses on re-executions we will be + able to allocate memory for hash elements in non-persitent arena + and directly use key values from sp_head::m_sroutines sets instead + of making their copies. + + RETURN VALUE + TRUE - new element was added. + FALSE - element was not added (because it is already present in the set). +*/ + +static bool add_used_routine(LEX *lex, Item_arena *arena, + const LEX_STRING *key) +{ + if (!hash_search(&lex->sroutines, (byte *)key->str, key->length)) + { + Sroutine_hash_entry *rn= + (Sroutine_hash_entry *)arena->alloc(sizeof(Sroutine_hash_entry) + + key->length); + if (!rn) // OOM. Error will be reported using fatal_error(). + return FALSE; + rn->key.length= key->length; + rn->key.str= (char *)rn + sizeof(Sroutine_hash_entry); + memcpy(rn->key.str, key->str, key->length); + my_hash_insert(&lex->sroutines, (byte *)rn); + lex->sroutines_list.link_in_list((byte *)rn, (byte **)&rn->next); + return TRUE; + } + return FALSE; +} + + +/* + Add routine to the set of stored routines used by statement. + + SYNOPSIS + sp_add_used_routine() + lex - LEX representing statement + arena - arena in which memory for new element of the set + will be allocated + rt - routine name + rt_type - routine type (one of TYPE_ENUM_PROCEDURE/...) + + NOTES + Will also add element to end of 'LEX::sroutines_list' list. + + To be friendly towards prepared statements one should pass + persistent arena as second argument. +*/ + +void sp_add_used_routine(LEX *lex, Item_arena *arena, + sp_name *rt, char rt_type) +{ + rt->set_routine_type(rt_type); + (void)add_used_routine(lex, arena, &rt->m_sroutines_key); +} + + +/* + Merge contents of two hashes representing sets of routines used + by statements or by other routines. + + SYNOPSIS + sp_update_sp_used_routines() dst - hash to which elements should be added src - hash from which elements merged - RETURN VALUE - TRUE - if we have added some new elements to destination hash. - FALSE - there were no new elements in src. + NOTE + This procedure won't create new Sroutine_hash_entry objects, + instead it will simply add elements from source to destination + hash. Thus time of life of elements in destination hash becomes + dependant on time of life of elements from source hash. It also + won't touch lists linking elements in source and destination + hashes. */ -bool -sp_merge_hash(HASH *dst, HASH *src) +void sp_update_sp_used_routines(HASH *dst, HASH *src) { - bool res= FALSE; for (uint i=0 ; i < src->records ; i++) { - LEX_STRING *ls= (LEX_STRING *)hash_element(src, i); - - if (! hash_search(dst, (byte *)ls->str, ls->length)) - { - my_hash_insert(dst, (byte *)ls); - res= TRUE; - } + Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i); + if (!hash_search(dst, (byte *)rt->key.str, rt->key.length)) + my_hash_insert(dst, (byte *)rt); } - return res; } /* - Cache all routines implicitly or explicitly used by query - (or whatever object is represented by LEX). + Add contents of hash representing set of routines to the set of + routines used by statement. SYNOPSIS - sp_cache_routines() + sp_update_stmt_used_routines() thd - thread context - lex - LEX representing query + lex - LEX representing statement + src - hash representing set from which routines will be added + + NOTE + It will also add elements to end of 'LEX::sroutines_list' list. +*/ + +static void sp_update_stmt_used_routines(THD *thd, LEX *lex, HASH *src) +{ + for (uint i=0 ; i < src->records ; i++) + { + Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i); + (void)add_used_routine(lex, thd->current_arena, &rt->key); + } +} + + +/* + Cache sub-set of routines used by statement, add tables used by these + routines to statement table list. Do the same for all routines used + by these routines. + + SYNOPSIS + sp_cache_routines_and_add_tables_aux() + thd - thread context + lex - LEX representing statement + start - first routine from the list of routines to be cached + (this list defines mentioned sub-set). NOTE If some function is missing this won't be reported here. Instead this fact will be discovered during query execution. - TODO - Currently if after passing through routine hashes we discover - that we have added something to them, we do one more pass to - process all routines which were missed on previous pass because - of these additions. We can avoid this if along with hashes - we use lists holding routine names and iterate other these - lists instead of hashes (since addition to the end of list - does not reorder elements in it). + RETURN VALUE + TRUE - some tables were added + FALSE - no tables were added. +*/ + +static bool +sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, + Sroutine_hash_entry *start) +{ + bool result= FALSE; + + DBUG_ENTER("sp_cache_routines_and_add_tables_aux"); + + for (Sroutine_hash_entry *rt= start; rt; rt= rt->next) + { + sp_name name(rt->key.str, rt->key.length); + int type= rt->key.str[0]; + sp_head *sp; + + if (!(sp= sp_cache_lookup((type == TYPE_ENUM_FUNCTION ? + &thd->sp_func_cache : &thd->sp_proc_cache), + &name))) + { + LEX *oldlex= thd->lex; + LEX *newlex= new st_lex; + thd->lex= newlex; + /* Pass hint pointer to mysql.proc table */ + newlex->proc_table= oldlex->proc_table; + newlex->current_select= NULL; + name.m_name.str= strchr(name.m_qname.str, '.'); + name.m_db.length= name.m_name.str - name.m_qname.str; + name.m_db.str= strmake_root(thd->mem_root, name.m_qname.str, + name.m_db.length); + name.m_name.str+= 1; + name.m_name.length= name.m_qname.length - name.m_db.length - 1; + + if (db_find_routine(thd, type, &name, &sp) == SP_OK) + { + if (type == TYPE_ENUM_FUNCTION) + sp_cache_insert(&thd->sp_func_cache, sp); + else + sp_cache_insert(&thd->sp_proc_cache, sp); + } + delete newlex; + thd->lex= oldlex; + } + if (sp) + { + sp_update_stmt_used_routines(thd, lex, &sp->m_sroutines); + result|= sp->add_used_tables_to_table_list(thd, &lex->query_tables_last); + } + } + DBUG_RETURN(result); +} + + +/* + Cache all routines from the set of used by statement, add tables used + by those routines to statement table list. Do the same for all routines + used by those routines. + + SYNOPSIS + sp_cache_routines_and_add_tables() + thd - thread context + lex - LEX representing statement + + RETURN VALUE + TRUE - some tables were added + FALSE - no tables were added. +*/ + +bool +sp_cache_routines_and_add_tables(THD *thd, LEX *lex) +{ + + return sp_cache_routines_and_add_tables_aux(thd, lex, + (Sroutine_hash_entry *)lex->sroutines_list.first); +} + + +/* + Add all routines used by view to the set of routines used by statement. + Add tables used by those routines to statement table list. Do the same + for all routines used by these routines. + + SYNOPSIS + sp_cache_routines_and_add_tables_for_view() + thd - thread context + lex - LEX representing statement + aux_lex - LEX representing view */ void -sp_cache_routines(THD *thd, LEX *lex) +sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex) { - bool routines_added= TRUE; - - DBUG_ENTER("sp_cache_routines"); - - while (routines_added) - { - routines_added= FALSE; - - for (int type= TYPE_ENUM_FUNCTION; type < TYPE_ENUM_TRIGGER; type++) - { - HASH *h= (type == TYPE_ENUM_FUNCTION ? &lex->spfuns : &lex->spprocs); - - for (uint i=0 ; i < h->records ; i++) - { - LEX_STRING *ls= (LEX_STRING *)hash_element(h, i); - sp_name name(*ls); - sp_head *sp; - - name.m_qname= *ls; - if (!(sp= sp_cache_lookup((type == TYPE_ENUM_FUNCTION ? - &thd->sp_func_cache : &thd->sp_proc_cache), - &name))) - { - LEX *oldlex= thd->lex; - LEX *newlex= new st_lex; - - thd->lex= newlex; - /* Pass hint pointer to mysql.proc table */ - newlex->proc_table= oldlex->proc_table; - newlex->current_select= NULL; - name.m_name.str= strchr(name.m_qname.str, '.'); - name.m_db.length= name.m_name.str - name.m_qname.str; - name.m_db.str= strmake_root(thd->mem_root, name.m_qname.str, - name.m_db.length); - name.m_name.str+= 1; - name.m_name.length= name.m_qname.length - name.m_db.length - 1; - - if (db_find_routine(thd, type, &name, &sp) == SP_OK) - { - if (type == TYPE_ENUM_FUNCTION) - sp_cache_insert(&thd->sp_func_cache, sp); - else - sp_cache_insert(&thd->sp_proc_cache, sp); - } - delete newlex; - thd->lex= oldlex; - } - - if (sp) - { - routines_added|= sp_merge_hash(&lex->spfuns, &sp->m_spfuns); - routines_added|= sp_merge_hash(&lex->spprocs, &sp->m_spprocs); - } - } - } - } - DBUG_VOID_RETURN; + Sroutine_hash_entry **last_cached_routine_ptr= + (Sroutine_hash_entry **)lex->sroutines_list.next; + sp_update_stmt_used_routines(thd, lex, &aux_lex->sroutines); + (void)sp_cache_routines_and_add_tables_aux(thd, lex, + *last_cached_routine_ptr); } + +/* + Add triggers for table to the set of routines used by statement. + Add tables used by them to statement table list. Do the same for + all implicitly used routines. + + SYNOPSIS + sp_cache_routines_and_add_tables_for_triggers() + thd - thread context + lex - LEX respresenting statement + triggers - triggers of the table +*/ + +void +sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, + Table_triggers_list *triggers) +{ + if (add_used_routine(lex, thd->current_arena, &triggers->sroutines_key)) + { + Sroutine_hash_entry **last_cached_routine_ptr= + (Sroutine_hash_entry **)lex->sroutines_list.next; + for (int i= 0; i < 3; i++) + for (int j= 0; j < 2; j++) + if (triggers->bodies[i][j]) + { + (void)triggers->bodies[i][j]->add_used_tables_to_table_list(thd, + &lex->query_tables_last); + sp_update_stmt_used_routines(thd, lex, + &triggers->bodies[i][j]->m_sroutines); + } + + (void)sp_cache_routines_and_add_tables_aux(thd, lex, + *last_cached_routine_ptr); + } +} + + /* * Generates the CREATE... string from the table information. * Returns TRUE on success, FALSE on (alloc) failure. diff --git a/sql/sp.h b/sql/sp.h index 16d79026132..1854cee00f9 100644 --- a/sql/sp.h +++ b/sql/sp.h @@ -79,15 +79,19 @@ sp_function_exists(THD *thd, sp_name *name); /* - * For precaching of functions and procedures - */ -void -sp_add_to_hash(HASH *h, sp_name *fun); -bool -sp_merge_hash(HASH *dst, HASH *src); -void -sp_cache_routines(THD *thd, LEX *lex); + Procedures for pre-caching of stored routines and building table list + for prelocking. +*/ +void sp_add_used_routine(LEX *lex, Item_arena *arena, + sp_name *rt, char rt_type); +void sp_update_sp_used_routines(HASH *dst, HASH *src); +bool sp_cache_routines_and_add_tables(THD *thd, LEX *lex); +void sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, + LEX *aux_lex); +void sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, + Table_triggers_list *triggers); +extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first); // // Utilities... diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 29898437cfb..b2e814cee77 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -242,8 +242,11 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type, void sp_name::init_qname(THD *thd) { - m_qname.length= m_db.length+m_name.length+1; - m_qname.str= thd->alloc(m_qname.length+1); + m_sroutines_key.length= m_db.length + m_name.length + 2; + if (!(m_sroutines_key.str= thd->alloc(m_sroutines_key.length + 1))) + return; + m_qname.length= m_sroutines_key.length - 1; + m_qname.str= m_sroutines_key.str + 1; sprintf(m_qname.str, "%*s.%*s", m_db.length, (m_db.length ? m_db.str : ""), m_name.length, m_name.str); @@ -315,16 +318,13 @@ sp_head::sp_head() { extern byte * sp_table_key(const byte *ptr, uint *plen, my_bool first); - extern byte - *sp_lex_sp_key(const byte *ptr, uint *plen, my_bool first); DBUG_ENTER("sp_head::sp_head"); state= INITIALIZED_FOR_SP; m_backpatch.empty(); m_lex.empty(); hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0); - hash_init(&m_spfuns, system_charset_info, 0, 0, 0, sp_lex_sp_key, 0, 0); - hash_init(&m_spprocs, system_charset_info, 0, 0, 0, sp_lex_sp_key, 0, 0); + hash_init(&m_sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0); DBUG_VOID_RETURN; } @@ -527,8 +527,7 @@ sp_head::destroy() } hash_free(&m_sptabs); - hash_free(&m_spfuns); - hash_free(&m_spprocs); + hash_free(&m_sroutines); DBUG_VOID_RETURN; } @@ -1037,11 +1036,10 @@ sp_head::restore_lex(THD *thd) oldlex->trg_table_fields.push_back(&sublex->trg_table_fields); /* - Add routines which are used by statement to respective sets for - this routine + Add routines which are used by statement to respective set for + this routine. */ - sp_merge_hash(&m_spfuns, &sublex->spfuns); - sp_merge_hash(&m_spprocs, &sublex->spprocs); + sp_update_sp_used_routines(&m_sroutines, &sublex->sroutines); /* Merge tables used by this statement (but not by its functions or procedures) to multiset of tables used by this routine. @@ -1578,16 +1576,22 @@ sp_instr_set::print(String *str) int sp_instr_set_trigger_field::execute(THD *thd, uint *nextp) { - int res= 0; - DBUG_ENTER("sp_instr_set_trigger_field::execute"); - /* QQ: Still unsure what should we return in case of error 1 or -1 ? */ - if (!value->fixed && value->fix_fields(thd, 0, &value) || - trigger_field->fix_fields(thd, 0, 0) || - (value->save_in_field(trigger_field->field, 0) < 0)) + DBUG_RETURN(m_lex_keeper.reset_lex_and_exec_core(thd, nextp, TRUE, this)); +} + + +int +sp_instr_set_trigger_field::exec_core(THD *thd, uint *nextp) +{ + int res= 0; + Item *it= sp_prepare_func_item(thd, &value); + if (!it || + !trigger_field->fixed && trigger_field->fix_fields(thd, 0, 0) || + (it->save_in_field(trigger_field->field, 0) < 0)) res= -1; - *nextp= m_ip + 1; - DBUG_RETURN(res); + *nextp = m_ip+1; + return res; } void @@ -2399,72 +2403,3 @@ sp_add_to_query_tables(THD *thd, LEX *lex, return table; } - -/* - Auxilary function for adding tables used by routines used in query - to table lists. - - SYNOPSIS - sp_add_sp_tables_to_table_list_aux() - thd - thread context - lex - LEX to which table list tables will be added - func_hash - routines for which tables should be added - func_cache- SP cache in which this routines should be looked up - - NOTE - See sp_add_sp_tables_to_table_list() for more info. - - RETURN VALUE - TRUE - some tables were added - FALSE - no tables were added. -*/ - -static bool -sp_add_sp_tables_to_table_list_aux(THD *thd, LEX *lex, HASH *func_hash, - sp_cache **func_cache) -{ - uint i; - bool result= FALSE; - - for (i= 0 ; i < func_hash->records ; i++) - { - sp_head *sp; - LEX_STRING *ls= (LEX_STRING *)hash_element(func_hash, i); - sp_name name(*ls); - - name.m_qname= *ls; - if ((sp= sp_cache_lookup(func_cache, &name))) - result|= sp->add_used_tables_to_table_list(thd, &lex->query_tables_last); - } - - return result; -} - - -/* - Add tables used by routines used in query to table list. - - SYNOPSIS - sp_add_sp_tables_to_table_list() - thd - thread context - lex - LEX to which table list tables will be added - func_lex - LEX for which functions we get tables - (useful for adding tables used by view routines) - - NOTE - Elements of list will be allocated in PS memroot, so this - list will be persistent between PS execetutions. - - RETURN VALUE - TRUE - some tables were added - FALSE - no tables were added. -*/ - -bool -sp_add_sp_tables_to_table_list(THD *thd, LEX *lex, LEX *func_lex) -{ - return (sp_add_sp_tables_to_table_list_aux(thd, lex, &func_lex->spfuns, - &thd->sp_func_cache) | - sp_add_sp_tables_to_table_list_aux(thd, lex, &func_lex->spprocs, - &thd->sp_proc_cache)); -} diff --git a/sql/sp_head.h b/sql/sp_head.h index 617d6622037..28048285fb3 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -48,24 +48,50 @@ public: LEX_STRING m_db; LEX_STRING m_name; LEX_STRING m_qname; + /* + Key representing routine in the set of stored routines used by statement. + Consists of 1-byte routine type and m_qname (which usually refences to + same buffer). Note that one must complete initialization of the key by + calling set_routine_type(). + */ + LEX_STRING m_sroutines_key; sp_name(LEX_STRING name) : m_name(name) { - m_db.str= m_qname.str= 0; - m_db.length= m_qname.length= 0; + m_db.str= m_qname.str= m_sroutines_key.str= 0; + m_db.length= m_qname.length= m_sroutines_key.length= 0; } sp_name(LEX_STRING db, LEX_STRING name) : m_db(db), m_name(name) { - m_qname.str= 0; - m_qname.length= 0; + m_qname.str= m_sroutines_key.str= 0; + m_qname.length= m_sroutines_key.length= 0; + } + + /* + Creates temporary sp_name object from key, used mainly + for SP-cache lookups. + */ + sp_name(char *key, uint key_len) + { + m_sroutines_key.str= key; + m_sroutines_key.length= key_len; + m_name.str= m_qname.str= key + 1; + m_name.length= m_qname.length= key_len - 1; + m_db.str= 0; + m_db.length= 0; } // Init. the qualified name from the db and name. void init_qname(THD *thd); // thd for memroot allocation + void set_routine_type(char type) + { + m_sroutines_key.str[0]= type; + } + ~sp_name() {} }; @@ -106,13 +132,13 @@ public: longlong m_created; longlong m_modified; /* - Sets containing names of SP and SF used by this routine. - - TODO Probably we should combine these two hashes in one. It will - decrease memory overhead ans simplify algorithms using them. The - same applies to similar hashes in LEX. + Set containing names of stored routines used by this routine. + Note that unlike elements of similar set for statement elements of this + set are not linked in one list. Because of this we are able save memory + by using for this set same objects that are used in 'sroutines' sets + for statements of which this stored routine consists. */ - HASH m_spfuns, m_spprocs; + HASH m_sroutines; // Pointers set during parsing uchar *m_param_begin, *m_param_end, *m_body_begin; @@ -471,10 +497,11 @@ class sp_instr_set_trigger_field : public sp_instr public: sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx, - Item_trigger_field *trg_fld, Item *val) + Item_trigger_field *trg_fld, + Item *val, LEX *lex) : sp_instr(ip, ctx), trigger_field(trg_fld), - value(val) + value(val), m_lex_keeper(lex, TRUE) {} virtual ~sp_instr_set_trigger_field() @@ -482,11 +509,14 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual int exec_core(THD *thd, uint *nextp); + virtual void print(String *str); private: Item_trigger_field *trigger_field; Item *value; + sp_lex_keeper m_lex_keeper; }; // class sp_instr_trigger_field : public sp_instr @@ -951,7 +981,5 @@ TABLE_LIST * sp_add_to_query_tables(THD *thd, LEX *lex, const char *db, const char *name, thr_lock_type locktype); -bool -sp_add_sp_tables_to_table_list(THD *thd, LEX *lex, LEX *func_lex); #endif /* _SP_HEAD_H_ */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a1887996d00..3fb80544e07 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1792,16 +1792,13 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter) may be still zero for prelocked statement... */ if (!thd->prelocked_mode && !thd->lex->requires_prelocking() && - (thd->lex->spfuns.records || thd->lex->spprocs.records)) + thd->lex->sroutines.records) { - TABLE_LIST **save_query_tables_last; - - sp_cache_routines(thd, thd->lex); - save_query_tables_last= thd->lex->query_tables_last; + TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last; DBUG_ASSERT(thd->lex->query_tables == *start); - if (sp_add_sp_tables_to_table_list(thd, thd->lex, thd->lex) || + if (sp_cache_routines_and_add_tables(thd, thd->lex) || *start) { query_tables_last_own= save_query_tables_last; @@ -1837,19 +1834,16 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter) and add tables used by them to table list. */ if (!thd->prelocked_mode && !thd->lex->requires_prelocking() && - (tables->view->spfuns.records || tables->view->spprocs.records)) + tables->view->sroutines.records) { - // FIXME We should catch recursion for both views and funcs here - sp_cache_routines(thd, tables->view); - /* We have at least one table in TL here */ if (!query_tables_last_own) query_tables_last_own= thd->lex->query_tables_last; - sp_add_sp_tables_to_table_list(thd, thd->lex, tables->view); + sp_cache_routines_and_add_tables_for_view(thd, thd->lex, + tables->view); } /* Cleanup hashes because destructo for this LEX is never called */ - hash_free(&tables->view->spfuns); - hash_free(&tables->view->spprocs); + hash_free(&tables->view->sroutines); continue; } @@ -1904,9 +1898,6 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter) prelocking list. If we lock table for reading we won't update it so there is no need to process its triggers since they never will be activated. - - FIXME Now we are simply turning on prelocking. Proper integration - and testing is to be done later. */ if (!thd->prelocked_mode && !thd->lex->requires_prelocking() && tables->table->triggers && @@ -1914,6 +1905,8 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter) { if (!query_tables_last_own) query_tables_last_own= thd->lex->query_tables_last; + sp_cache_routines_and_add_tables_for_triggers(thd, thd->lex, + tables->table->triggers); } free_root(&new_frm_mem, MYF(MY_KEEP_PREALLOC)); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 1270aab18ae..c82052a39a4 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -172,10 +172,9 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->proc_list.first= 0; lex->query_tables_own_last= 0; - if (lex->spfuns.records) - my_hash_reset(&lex->spfuns); - if (lex->spprocs.records) - my_hash_reset(&lex->spprocs); + if (lex->sroutines.records) + my_hash_reset(&lex->sroutines); + lex->sroutines_list.empty(); DBUG_VOID_RETURN; } @@ -1570,6 +1569,28 @@ void st_select_lex::print_limit(THD *thd, String *str) } +/* + Initialize LEX object. + + SYNOPSIS + st_lex::st_lex() + + NOTE + LEX object initialized with this constructor can be used as part of + THD object for which one can safely call open_tables(), lock_tables() + and close_thread_tables() functions. But it is not yet ready for + statement parsing. On should use lex_start() function to prepare LEX + for this. +*/ + +st_lex::st_lex() + :result(0), sql_command(SQLCOM_END), query_tables_own_last(0) +{ + hash_init(&sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0); + sroutines_list.empty(); +} + + /* Check whether the merging algorithm can be used on this VIEW diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 8af416f0ce8..160ee77e811 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -797,8 +797,14 @@ typedef struct st_lex bool sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */ bool all_privileges; sp_pcontext *spcont; - HASH spfuns; /* Called functions */ - HASH spprocs; /* Called procedures */ + /* Set of stored routines called by statement. */ + HASH sroutines; + /* + List linking elements of 'sroutines' set. Allows you to add new elements + to this set as you iterate through the list of existing elements. + */ + SQL_LIST sroutines_list; + st_sp_chistics sp_chistics; bool only_view; /* used for SHOW CREATE TABLE/VIEW */ /* @@ -831,17 +837,11 @@ typedef struct st_lex */ uchar *fname_start, *fname_end; - st_lex() :result(0), sql_command(SQLCOM_END), query_tables_own_last(0) - { - extern byte *sp_lex_sp_key(const byte *ptr, uint *plen, my_bool first); - hash_init(&spfuns, system_charset_info, 0, 0, 0, sp_lex_sp_key, 0, 0); - hash_init(&spprocs, system_charset_info, 0, 0, 0, sp_lex_sp_key, 0, 0); - } + st_lex(); virtual ~st_lex() { - hash_free(&spfuns); - hash_free(&spprocs); + hash_free(&sroutines); } inline void uncacheable(uint8 cause) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 16c429f40b7..441250da31b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2296,8 +2296,7 @@ mysql_execute_command(THD *thd) Don't reset warnings when executing a stored routine. */ if ((all_tables || &lex->select_lex != lex->all_selects_list || - lex->spfuns.records || lex->spprocs.records) && - !thd->spcont) + lex->sroutines.records) && !thd->spcont) mysql_reset_errors(thd, 0); #ifdef HAVE_REPLICATION diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 95524a6dfbf..af94cf6f9dd 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1,3 +1,20 @@ +/* Copyright (C) 2004-2005 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + #include "mysql_priv.h" #include "sp_head.h" #include "sql_trigger.h" @@ -417,6 +434,18 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, table->triggers= triggers; + /* + Construct key that will represent triggers for this table in the set + of routines used by statement. + */ + triggers->sroutines_key.length= 1+strlen(db)+1+strlen(table_name)+1; + if (!(triggers->sroutines_key.str= + alloc_root(&table->mem_root, triggers->sroutines_key.length))) + DBUG_RETURN(1); + triggers->sroutines_key.str[0]= TYPE_ENUM_TRIGGER; + strmov(strmov(strmov(triggers->sroutines_key.str+1, db), "."), + table_name); + /* TODO: This could be avoided if there is no triggers for UPDATE and DELETE. diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 0547283d0c5..044219d5ac9 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -1,3 +1,20 @@ +/* Copyright (C) 2004-2005 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + /* This class holds all information about triggers of table. @@ -28,6 +45,14 @@ class Table_triggers_list: public Sql_alloc used in CREATE/DROP TRIGGER for looking up trigger by name. */ List names_list; + /* + Key representing triggers for this table in set of all stored + routines used by statement. + TODO: We won't need this member once triggers namespace will be + database-wide instead of table-wide because then we will be able + to use key based on sp_name as for other stored routines. + */ + LEX_STRING sroutines_key; public: /* @@ -112,6 +137,8 @@ public: } friend class Item_trigger_field; + friend void sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, + Table_triggers_list *triggers); private: bool prepare_record1_accessors(TABLE *table); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 892d2516808..72786d180fd 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1532,7 +1532,7 @@ call: lex->sql_command= SQLCOM_CALL; lex->spname= $2; lex->value_list.empty(); - sp_add_to_hash(&lex->spprocs, $2); + sp_add_used_routine(lex, YYTHD, $2, TYPE_ENUM_PROCEDURE); } '(' sp_cparam_list ')' {} ; @@ -4682,7 +4682,7 @@ simple_expr: sp_name *name= new sp_name($1, $3); name->init_qname(YYTHD); - sp_add_to_hash(&lex->spfuns, name); + sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION); if ($5) $$= new Item_func_sp(name, *$5); else @@ -4771,7 +4771,7 @@ simple_expr: LEX *lex= Lex; sp_name *name= sp_name_current_db_new(YYTHD, $1); - sp_add_to_hash(&lex->spfuns, name); + sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION); if ($3) $$= new Item_func_sp(name, *$3); else @@ -7684,12 +7684,6 @@ sys_option_value: yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; } - if (lex->query_tables) - { - my_message(ER_SP_SUBSELECT_NYI, ER(ER_SP_SUBSELECT_NYI), - MYF(0)); - YYABORT; - } if ($4) it= $4; else @@ -7702,7 +7696,7 @@ sys_option_value: $2.base_name.str)) || !(i= new sp_instr_set_trigger_field( lex->sphead->instructions(), lex->spcont, - trg_fld, it))) + trg_fld, it, lex))) YYABORT; /* From d0c69a8264a21d343f0f69e31e4494ae0fbff18f Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 9 Jul 2005 23:11:17 +0400 Subject: [PATCH 197/216] Manual fixes after merging patch for bug #8406 "Triggers crash if referencing a table" with main tree. mysql-test/r/trigger.result: Temporalily disable part of test which exposes bug #11554 (work on which is in progress). mysql-test/t/sp-error.test: After merge fix. Fixed wrong delimiter command. mysql-test/t/trigger.test: Temporalily disable part of test which exposes bug #11554 (work on which is in progress). sql/sp.cc: After merge fix. Item_arena was renamed to Query_arena. sql/sp.h: After merge fix. Item_arena was renamed to Query_arena. sql/sql_lex.cc: After merge fix. LEX::spfuns/spprocs hashes were replaces with one LEX::sroutines hash. --- mysql-test/r/trigger.result | 9 --------- mysql-test/t/sp-error.test | 2 +- mysql-test/t/trigger.test | 23 ++++++++++++----------- sql/sp.cc | 4 ++-- sql/sp.h | 2 +- sql/sql_lex.cc | 6 ++---- 6 files changed, 18 insertions(+), 28 deletions(-) diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 0e8142f2b54..746c900d743 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -573,12 +573,3 @@ i k ts 1 1 0000-00-00 00:00:00 2 2 0000-00-00 00:00:00 drop table t1, t2; -drop function if exists bug5893; -create table t1 (col1 int, col2 int); -insert into t1 values (1, 2); -create function bug5893 () returns int return 5; -create trigger t1_bu before update on t1 for each row set new.col1= bug5893(); -drop function bug5893; -update t1 set col2 = 4; -ERROR 42000: FUNCTION test.bug5893 does not exist -drop table t1; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index aa97c370de0..7f693e13c5b 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1025,7 +1025,7 @@ end| --error 1424 call bug11394(2, 1)| drop procedure bug11394| -delimiter |; +delimiter ;| # # Bug#11834 "Re-execution of prepared statement with dropped function diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 7fcfbcedb60..229cbd3c79c 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -578,14 +578,15 @@ drop table t1, t2; # Test for bug #5893 "Triggers with dropped functions cause crashes" # Appropriate error should be reported instead of crash. ---disable_warnings -drop function if exists bug5893; ---enable_warnings -create table t1 (col1 int, col2 int); -insert into t1 values (1, 2); -create function bug5893 () returns int return 5; -create trigger t1_bu before update on t1 for each row set new.col1= bug5893(); -drop function bug5893; ---error 1305 -update t1 set col2 = 4; -drop table t1; +# Had to disable this test until bug #11554 will be fixed. +#--disable_warnings +#drop function if exists bug5893; +#--enable_warnings +#create table t1 (col1 int, col2 int); +#insert into t1 values (1, 2); +#create function bug5893 () returns int return 5; +#create trigger t1_bu before update on t1 for each row set new.col1= bug5893(); +#drop function bug5893; +#--error 1305 +#update t1 set col2 = 4; +#drop table t1; diff --git a/sql/sp.cc b/sql/sp.cc index 9816fe2bba5..c251d0b8bc2 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1134,7 +1134,7 @@ extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first) FALSE - element was not added (because it is already present in the set). */ -static bool add_used_routine(LEX *lex, Item_arena *arena, +static bool add_used_routine(LEX *lex, Query_arena *arena, const LEX_STRING *key) { if (!hash_search(&lex->sroutines, (byte *)key->str, key->length)) @@ -1173,7 +1173,7 @@ static bool add_used_routine(LEX *lex, Item_arena *arena, persistent arena as second argument. */ -void sp_add_used_routine(LEX *lex, Item_arena *arena, +void sp_add_used_routine(LEX *lex, Query_arena *arena, sp_name *rt, char rt_type) { rt->set_routine_type(rt_type); diff --git a/sql/sp.h b/sql/sp.h index 1854cee00f9..172559a706f 100644 --- a/sql/sp.h +++ b/sql/sp.h @@ -82,7 +82,7 @@ sp_function_exists(THD *thd, sp_name *name); Procedures for pre-caching of stored routines and building table list for prelocking. */ -void sp_add_used_routine(LEX *lex, Item_arena *arena, +void sp_add_used_routine(LEX *lex, Query_arena *arena, sp_name *rt, char rt_type); void sp_update_sp_used_routines(HASH *dst, HASH *src); bool sp_cache_routines_and_add_tables(THD *thd, LEX *lex); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index dc4c8f3727f..4d3de481c8b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1997,10 +1997,8 @@ void st_lex::cleanup_after_one_table_open() select_lex.cut_subtree(); } time_zone_tables_used= 0; - if (spfuns.records) - my_hash_reset(&spfuns); - if (spprocs.records) - my_hash_reset(&spprocs); + if (sroutines.records) + my_hash_reset(&sroutines); } From 46f0327e6b67eba7656f55874308451aebab5dbd Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 10 Jul 2005 18:19:37 -0700 Subject: [PATCH 198/216] Refactoring of write_row() into two parts to allow future additions. Also rewrote the OPTIMIZE TABLE code, to add new extended optimize. This form of optimize rebuilds not only the file, but each individual row. mysql-test/r/archive.result: Update results file for new OPTIMIZE TABLE EXTENDED command. mysql-test/t/archive.test: Added new test for extended optimize sql/examples/ha_archive.cc: Refactored write_row code into two parts. This will allow me to abstract it out once I add in new row format. This also allowed code sharing for the new optimize command (which will be used for new repair code). sql/examples/ha_archive.h: Added new real_write_row() method for writing out rows. --- mysql-test/r/archive.result | 1220 +++++++++++++++++++++++++++++++++++ mysql-test/t/archive.test | 5 + sql/examples/ha_archive.cc | 155 +++-- sql/examples/ha_archive.h | 1 + 4 files changed, 1335 insertions(+), 46 deletions(-) diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result index 793e50cf653..54780dbbd22 100644 --- a/mysql-test/r/archive.result +++ b/mysql-test/r/archive.result @@ -2617,6 +2617,1220 @@ auto fld1 companynr fld3 fld4 fld5 fld6 2 011401 37 breaking dreaded Steinberg W 3 011402 37 Romans scholastics jarring 4 011403 37 intercepted audiology tinily +INSERT INTO t2 VALUES (2,011401,37,'breaking','dreaded','Steinberg','W'); +INSERT INTO t2 VALUES (3,011402,37,'Romans','scholastics','jarring',''); +INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily',''); +OPTIMIZE TABLE t2 EXTENDED; +Table Op Msg_type Msg_text +test.t2 optimize status OK +SELECT * FROM t2; +auto fld1 companynr fld3 fld4 fld5 fld6 +1 000001 00 Omaha teethe neat +2 011401 37 breaking dreaded Steinberg W +3 011402 37 Romans scholastics jarring +4 011403 37 intercepted audiology tinily +5 011501 37 bewilderingly wallet balled +6 011701 37 astound parters persist W +7 011702 37 admonishing eschew attainments +8 011703 37 sumac quitter fanatic +9 012001 37 flanking neat measures FAS +10 012003 37 combed Steinberg rightfulness +11 012004 37 subjective jarring capably +12 012005 37 scatterbrain tinily impulsive +13 012301 37 Eulerian balled starlet +14 012302 36 dubbed persist terminators +15 012303 37 Kane attainments untying +16 012304 37 overlay fanatic announces FAS +17 012305 37 perturb measures featherweight FAS +18 012306 37 goblins rightfulness pessimist FAS +19 012501 37 annihilates capably daughter +20 012602 37 Wotan impulsive decliner FAS +21 012603 37 snatching starlet lawgiver +22 012604 37 concludes terminators stated +23 012605 37 laterally untying readable +24 012606 37 yelped announces attrition +25 012701 37 grazing featherweight cascade FAS +26 012702 37 Baird pessimist motors FAS +27 012703 37 celery daughter interrogate +28 012704 37 misunderstander decliner pests W +29 013601 37 handgun lawgiver stairway +30 013602 37 foldout stated dopers FAS +31 013603 37 mystic readable testicle W +32 013604 37 succumbed attrition Parsifal W +33 013605 37 Nabisco cascade leavings +34 013606 37 fingerings motors postulation W +35 013607 37 aging interrogate squeaking +36 013608 37 afield pests contrasted +37 013609 37 ammonium stairway leftover +38 013610 37 boat dopers whiteners +39 013801 37 intelligibility testicle erases W +40 013802 37 Augustine Parsifal Punjab W +41 013803 37 teethe leavings Merritt +42 013804 37 dreaded postulation Quixotism +43 013901 37 scholastics squeaking sweetish FAS +44 016001 37 audiology contrasted dogging FAS +45 016201 37 wallet leftover scornfully FAS +46 016202 37 parters whiteners bellow +47 016301 37 eschew erases bills +48 016302 37 quitter Punjab cupboard FAS +49 016303 37 neat Merritt sureties FAS +50 016304 37 Steinberg Quixotism puddings +51 018001 37 jarring sweetish tapestry +52 018002 37 tinily dogging fetters +53 018003 37 balled scornfully bivalves +54 018004 37 persist bellow incurring +55 018005 37 attainments bills Adolph +56 018007 37 fanatic cupboard pithed +57 018008 37 measures sureties emergency +58 018009 37 rightfulness puddings Miles +59 018010 37 capably tapestry trimmings +60 018012 37 impulsive fetters tragedies W +61 018013 37 starlet bivalves skulking W +62 018014 37 terminators incurring flint +63 018015 37 untying Adolph flopping W +64 018016 37 announces pithed relaxing FAS +65 018017 37 featherweight emergency offload FAS +66 018018 37 pessimist Miles suites W +67 018019 37 daughter trimmings lists FAS +68 018020 37 decliner tragedies animized FAS +69 018021 37 lawgiver skulking multilayer W +70 018022 37 stated flint standardizes FAS +71 018023 37 readable flopping Judas +72 018024 37 attrition relaxing vacuuming W +73 018025 37 cascade offload dentally W +74 018026 37 motors suites humanness W +75 018027 37 interrogate lists inch W +76 018028 37 pests animized Weissmuller W +77 018029 37 stairway multilayer irresponsibly W +78 018030 37 dopers standardizes luckily FAS +79 018032 37 testicle Judas culled W +80 018033 37 Parsifal vacuuming medical FAS +81 018034 37 leavings dentally bloodbath FAS +82 018035 37 postulation humanness subschema W +83 018036 37 squeaking inch animals W +84 018037 37 contrasted Weissmuller Micronesia +85 018038 37 leftover irresponsibly repetitions +86 018039 37 whiteners luckily Antares +87 018040 37 erases culled ventilate W +88 018041 37 Punjab medical pityingly +89 018042 37 Merritt bloodbath interdependent +90 018043 37 Quixotism subschema Graves FAS +91 018044 37 sweetish animals neonatal +92 018045 37 dogging Micronesia scribbled FAS +93 018046 37 scornfully repetitions chafe W +94 018048 37 bellow Antares honoring +95 018049 37 bills ventilate realtor +96 018050 37 cupboard pityingly elite +97 018051 37 sureties interdependent funereal +98 018052 37 puddings Graves abrogating +99 018053 50 tapestry neonatal sorters +100 018054 37 fetters scribbled Conley +101 018055 37 bivalves chafe lectured +102 018056 37 incurring honoring Abraham +103 018057 37 Adolph realtor Hawaii W +104 018058 37 pithed elite cage +105 018059 36 emergency funereal hushes +106 018060 37 Miles abrogating Simla +107 018061 37 trimmings sorters reporters +108 018101 37 tragedies Conley Dutchman FAS +109 018102 37 skulking lectured descendants FAS +110 018103 37 flint Abraham groupings FAS +111 018104 37 flopping Hawaii dissociate +112 018201 37 relaxing cage coexist W +113 018202 37 offload hushes Beebe +114 018402 37 suites Simla Taoism +115 018403 37 lists reporters Connally +116 018404 37 animized Dutchman fetched FAS +117 018405 37 multilayer descendants checkpoints FAS +118 018406 37 standardizes groupings rusting +119 018409 37 Judas dissociate galling +120 018601 37 vacuuming coexist obliterates +121 018602 37 dentally Beebe traitor +122 018603 37 humanness Taoism resumes FAS +123 018801 37 inch Connally analyzable FAS +124 018802 37 Weissmuller fetched terminator FAS +125 018803 37 irresponsibly checkpoints gritty FAS +126 018804 37 luckily rusting firearm W +127 018805 37 culled galling minima +128 018806 37 medical obliterates Selfridge +129 018807 37 bloodbath traitor disable +130 018808 37 subschema resumes witchcraft W +131 018809 37 animals analyzable betroth W +132 018810 37 Micronesia terminator Manhattanize +133 018811 37 repetitions gritty imprint +134 018812 37 Antares firearm peeked +135 019101 37 ventilate minima swelling +136 019102 37 pityingly Selfridge interrelationships W +137 019103 37 interdependent disable riser +138 019201 37 Graves witchcraft Gandhian W +139 030501 37 neonatal betroth peacock A +140 030502 50 scribbled Manhattanize bee A +141 030503 37 chafe imprint kanji +142 030504 37 honoring peeked dental +143 031901 37 realtor swelling scarf FAS +144 036001 37 elite interrelationships chasm A +145 036002 37 funereal riser insolence A +146 036004 37 abrogating Gandhian syndicate +147 036005 37 sorters peacock alike +148 038001 37 Conley bee imperial A +149 038002 37 lectured kanji convulsion A +150 038003 37 Abraham dental railway A +151 038004 37 Hawaii scarf validate A +152 038005 37 cage chasm normalizes A +153 038006 37 hushes insolence comprehensive +154 038007 37 Simla syndicate chewing +155 038008 37 reporters alike denizen +156 038009 37 Dutchman imperial schemer +157 038010 37 descendants convulsion chronicle +158 038011 37 groupings railway Kline +159 038012 37 dissociate validate Anatole +160 038013 37 coexist normalizes partridges +161 038014 37 Beebe comprehensive brunch +162 038015 37 Taoism chewing recruited +163 038016 37 Connally denizen dimensions W +164 038017 37 fetched schemer Chicana W +165 038018 37 checkpoints chronicle announced +166 038101 37 rusting Kline praised FAS +167 038102 37 galling Anatole employing +168 038103 37 obliterates partridges linear +169 038104 37 traitor brunch quagmire +170 038201 37 resumes recruited western A +171 038202 37 analyzable dimensions relishing +172 038203 37 terminator Chicana serving A +173 038204 37 gritty announced scheduling +174 038205 37 firearm praised lore +175 038206 37 minima employing eventful +176 038208 37 Selfridge linear arteriole A +177 042801 37 disable quagmire disentangle +178 042802 37 witchcraft western cured A +179 046101 37 betroth relishing Fenton W +180 048001 37 Manhattanize serving avoidable A +181 048002 37 imprint scheduling drains A +182 048003 37 peeked lore detectably FAS +183 048004 37 swelling eventful husky +184 048005 37 interrelationships arteriole impelling +185 048006 37 riser disentangle undoes +186 048007 37 Gandhian cured evened +187 048008 37 peacock Fenton squeezes +188 048101 37 bee avoidable destroyer FAS +189 048102 37 kanji drains rudeness +190 048201 37 dental detectably beaner FAS +191 048202 37 scarf husky boorish +192 048203 37 chasm impelling Everhart +193 048204 37 insolence undoes encompass A +194 048205 37 syndicate evened mushrooms +195 048301 37 alike squeezes Alison A +196 048302 37 imperial destroyer externally FAS +197 048303 37 convulsion rudeness pellagra +198 048304 37 railway beaner cult +199 048305 37 validate boorish creek A +200 048401 37 normalizes Everhart Huffman +201 048402 37 comprehensive encompass Majorca FAS +202 048403 37 chewing mushrooms governing A +203 048404 37 denizen Alison gadfly FAS +204 048405 37 schemer externally reassigned FAS +205 048406 37 chronicle pellagra intentness W +206 048407 37 Kline cult craziness +207 048408 37 Anatole creek psychic +208 048409 37 partridges Huffman squabbled +209 048410 37 brunch Majorca burlesque +210 048411 37 recruited governing capped +211 048412 37 dimensions gadfly extracted A +212 048413 37 Chicana reassigned DiMaggio +213 048601 37 announced intentness exclamation FAS +214 048602 37 praised craziness subdirectory +215 048603 37 employing psychic fangs +216 048604 37 linear squabbled buyer A +217 048801 37 quagmire burlesque pithing A +218 050901 37 western capped transistorizing A +219 051201 37 relishing extracted nonbiodegradable +220 056002 37 serving DiMaggio dislocate +221 056003 37 scheduling exclamation monochromatic FAS +222 056004 37 lore subdirectory batting +223 056102 37 eventful fangs postcondition A +224 056203 37 arteriole buyer catalog FAS +225 056204 37 disentangle pithing Remus +226 058003 37 cured transistorizing devices A +227 058004 37 Fenton nonbiodegradable bike A +228 058005 37 avoidable dislocate qualify +229 058006 37 drains monochromatic detained +230 058007 37 detectably batting commended +231 058101 37 husky postcondition civilize +232 058102 37 impelling catalog Elmhurst +233 058103 37 undoes Remus anesthetizing +234 058105 37 evened devices deaf +235 058111 37 squeezes bike Brigham +236 058112 37 destroyer qualify title +237 058113 37 rudeness detained coarse +238 058114 37 beaner commended combinations +239 058115 37 boorish civilize grayness +240 058116 37 Everhart Elmhurst innumerable FAS +241 058117 37 encompass anesthetizing Caroline A +242 058118 37 mushrooms deaf fatty FAS +243 058119 37 Alison Brigham eastbound +244 058120 37 externally title inexperienced +245 058121 37 pellagra coarse hoarder A +246 058122 37 cult combinations scotch W +247 058123 37 creek grayness passport A +248 058124 37 Huffman innumerable strategic FAS +249 058125 37 Majorca Caroline gated +250 058126 37 governing fatty flog +251 058127 37 gadfly eastbound Pipestone +252 058128 37 reassigned inexperienced Dar +253 058201 37 intentness hoarder Corcoran +254 058202 37 craziness scotch flyers A +255 058303 37 psychic passport competitions W +256 058304 37 squabbled strategic suppliers FAS +257 058602 37 burlesque gated skips +258 058603 37 capped flog institutes +259 058604 37 extracted Pipestone troop A +260 058605 37 DiMaggio Dar connective W +261 058606 37 exclamation Corcoran denies +262 058607 37 subdirectory flyers polka +263 060401 36 fangs competitions observations FAS +264 061701 36 buyer suppliers askers +265 066201 36 pithing skips homeless FAS +266 066501 36 transistorizing institutes Anna +267 068001 36 nonbiodegradable troop subdirectories W +268 068002 36 dislocate connective decaying FAS +269 068005 36 monochromatic denies outwitting W +270 068006 36 batting polka Harpy W +271 068007 36 postcondition observations crazed +272 068008 36 catalog askers suffocate +273 068009 36 Remus homeless provers FAS +274 068010 36 devices Anna technically +275 068011 36 bike subdirectories Franklinizations +276 068202 36 qualify decaying considered +277 068302 36 detained outwitting tinnily +278 068303 36 commended Harpy uninterruptedly +279 068401 36 civilize crazed whistled A +280 068501 36 Elmhurst suffocate automate +281 068502 36 anesthetizing provers gutting W +282 068503 36 deaf technically surreptitious +283 068602 36 Brigham Franklinizations Choctaw +284 068603 36 title considered cooks +285 068701 36 coarse tinnily millivolt FAS +286 068702 36 combinations uninterruptedly counterpoise +287 068703 36 grayness whistled Gothicism +288 076001 36 innumerable automate feminine +289 076002 36 Caroline gutting metaphysically W +290 076101 36 fatty surreptitious sanding A +291 076102 36 eastbound Choctaw contributorily +292 076103 36 inexperienced cooks receivers FAS +293 076302 36 hoarder millivolt adjourn +294 076303 36 scotch counterpoise straggled A +295 076304 36 passport Gothicism druggists +296 076305 36 strategic feminine thanking FAS +297 076306 36 gated metaphysically ostrich +298 076307 36 flog sanding hopelessness FAS +299 076402 36 Pipestone contributorily Eurydice +300 076501 36 Dar receivers excitation W +301 076502 36 Corcoran adjourn presumes FAS +302 076701 36 flyers straggled imaginable FAS +303 078001 36 competitions druggists concoct W +304 078002 36 suppliers thanking peering W +305 078003 36 skips ostrich Phelps FAS +306 078004 36 institutes hopelessness ferociousness FAS +307 078005 36 troop Eurydice sentences +308 078006 36 connective excitation unlocks +309 078007 36 denies presumes engrossing W +310 078008 36 polka imaginable Ruth +311 078101 36 observations concoct tying +312 078103 36 askers peering exclaimers +313 078104 36 homeless Phelps synergy +314 078105 36 Anna ferociousness Huey W +315 082101 36 subdirectories sentences merging +316 083401 36 decaying unlocks judges A +317 084001 36 outwitting engrossing Shylock W +318 084002 36 Harpy Ruth Miltonism +319 086001 36 crazed tying hen W +320 086102 36 suffocate exclaimers honeybee FAS +321 086201 36 provers synergy towers +322 088001 36 technically Huey dilutes W +323 088002 36 Franklinizations merging numerals FAS +324 088003 36 considered judges democracy FAS +325 088004 36 tinnily Shylock Ibero- +326 088101 36 uninterruptedly Miltonism invalids +327 088102 36 whistled hen behavior +328 088103 36 automate honeybee accruing +329 088104 36 gutting towers relics A +330 088105 36 surreptitious dilutes rackets +331 088106 36 Choctaw numerals Fischbein W +332 088201 36 cooks democracy phony W +333 088203 36 millivolt Ibero- cross FAS +334 088204 36 counterpoise invalids cleanup +335 088302 37 Gothicism behavior conspirator +336 088303 37 feminine accruing label FAS +337 088305 37 metaphysically relics university +338 088402 37 sanding rackets cleansed FAS +339 088501 36 contributorily Fischbein ballgown +340 088502 36 receivers phony starlet +341 088503 36 adjourn cross aqueous +342 098001 58 straggled cleanup portrayal A +343 098002 58 druggists conspirator despising W +344 098003 58 thanking label distort W +345 098004 58 ostrich university palmed +346 098005 58 hopelessness cleansed faced +347 098006 58 Eurydice ballgown silverware +348 141903 29 excitation starlet assessor +349 098008 58 presumes aqueous spiders +350 098009 58 imaginable portrayal artificially +351 098010 58 concoct despising reminiscence +352 098011 58 peering distort Mexican +353 098012 58 Phelps palmed obnoxious +354 098013 58 ferociousness faced fragile +355 098014 58 sentences silverware apprehensible +356 098015 58 unlocks assessor births +357 098016 58 engrossing spiders garages +358 098017 58 Ruth artificially panty +359 098018 58 tying reminiscence anteater +360 098019 58 exclaimers Mexican displacement A +361 098020 58 synergy obnoxious drovers A +362 098021 58 Huey fragile patenting A +363 098022 58 merging apprehensible far A +364 098023 58 judges births shrieks +365 098024 58 Shylock garages aligning W +366 098025 37 Miltonism panty pragmatism +367 106001 36 hen anteater fevers W +368 108001 36 honeybee displacement reexamines A +369 108002 36 towers drovers occupancies +370 108003 36 dilutes patenting sweats FAS +371 108004 36 numerals far modulators +372 108005 36 democracy shrieks demand W +373 108007 36 Ibero- aligning Madeira +374 108008 36 invalids pragmatism Viennese W +375 108009 36 behavior fevers chillier W +376 108010 36 accruing reexamines wildcats FAS +377 108011 36 relics occupancies gentle +378 108012 36 rackets sweats Angles W +379 108101 36 Fischbein modulators accuracies +380 108102 36 phony demand toggle +381 108103 36 cross Madeira Mendelssohn W +382 108111 50 cleanup Viennese behaviorally +383 108105 36 conspirator chillier Rochford +384 108106 36 label wildcats mirror W +385 108107 36 university gentle Modula +386 108108 50 cleansed Angles clobbering +387 108109 36 ballgown accuracies chronography +388 108110 36 starlet toggle Eskimoizeds +389 108201 36 aqueous Mendelssohn British W +390 108202 36 portrayal behaviorally pitfalls +391 108203 36 despising Rochford verify W +392 108204 36 distort mirror scatter FAS +393 108205 36 palmed Modula Aztecan +394 108301 36 faced clobbering acuity W +395 108302 36 silverware chronography sinking W +396 112101 36 assessor Eskimoizeds beasts FAS +397 112102 36 spiders British Witt W +398 113701 36 artificially pitfalls physicists FAS +399 116001 36 reminiscence verify folksong A +400 116201 36 Mexican scatter strokes FAS +401 116301 36 obnoxious Aztecan crowder +402 116302 36 fragile acuity merry +403 116601 36 apprehensible sinking cadenced +404 116602 36 births beasts alimony A +405 116603 36 garages Witt principled A +406 116701 36 panty physicists golfing +407 116702 36 anteater folksong undiscovered +408 118001 36 displacement strokes irritates +409 118002 36 drovers crowder patriots A +410 118003 36 patenting merry rooms FAS +411 118004 36 far cadenced towering W +412 118005 36 shrieks alimony displease +413 118006 36 aligning principled photosensitive +414 118007 36 pragmatism golfing inking +415 118008 36 fevers undiscovered gainers +416 118101 36 reexamines irritates leaning A +417 118102 36 occupancies patriots hydrant A +418 118103 36 sweats rooms preserve +419 118202 36 modulators towering blinded A +420 118203 36 demand displease interactions A +421 118204 36 Madeira photosensitive Barry +422 118302 36 Viennese inking whiteness A +423 118304 36 chillier gainers pastimes W +424 118305 36 wildcats leaning Edenization +425 118306 36 gentle hydrant Muscat +426 118307 36 Angles preserve assassinated +427 123101 36 accuracies blinded labeled +428 123102 36 toggle interactions glacial A +429 123301 36 Mendelssohn Barry implied W +430 126001 36 behaviorally whiteness bibliographies W +431 126002 36 Rochford pastimes Buchanan +432 126003 36 mirror Edenization forgivably FAS +433 126101 36 Modula Muscat innuendo A +434 126301 36 clobbering assassinated den FAS +435 126302 36 chronography labeled submarines W +436 126402 36 Eskimoizeds glacial mouthful A +437 126601 36 British implied expiring +438 126602 36 pitfalls bibliographies unfulfilled FAS +439 126702 36 verify Buchanan precession +440 128001 36 scatter forgivably nullified +441 128002 36 Aztecan innuendo affects +442 128003 36 acuity den Cynthia +443 128004 36 sinking submarines Chablis A +444 128005 36 beasts mouthful betterments FAS +445 128007 36 Witt expiring advertising +446 128008 36 physicists unfulfilled rubies A +447 128009 36 folksong precession southwest FAS +448 128010 36 strokes nullified superstitious A +449 128011 36 crowder affects tabernacle W +450 128012 36 merry Cynthia silk A +451 128013 36 cadenced Chablis handsomest A +452 128014 36 alimony betterments Persian A +453 128015 36 principled advertising analog W +454 128016 36 golfing rubies complex W +455 128017 36 undiscovered southwest Taoist +456 128018 36 irritates superstitious suspend +457 128019 36 patriots tabernacle relegated +458 128020 36 rooms silk awesome W +459 128021 36 towering handsomest Bruxelles +460 128022 36 displease Persian imprecisely A +461 128023 36 photosensitive analog televise +462 128101 36 inking complex braking +463 128102 36 gainers Taoist true FAS +464 128103 36 leaning suspend disappointing FAS +465 128104 36 hydrant relegated navally W +466 128106 36 preserve awesome circus +467 128107 36 blinded Bruxelles beetles +468 128108 36 interactions imprecisely trumps +469 128202 36 Barry televise fourscore W +470 128203 36 whiteness braking Blackfoots +471 128301 36 pastimes true Grady +472 128302 36 Edenization disappointing quiets FAS +473 128303 36 Muscat navally floundered FAS +474 128304 36 assassinated circus profundity W +475 128305 36 labeled beetles Garrisonian W +476 128307 36 glacial trumps Strauss +477 128401 36 implied fourscore cemented FAS +478 128502 36 bibliographies Blackfoots contrition A +479 128503 36 Buchanan Grady mutations +480 128504 36 forgivably quiets exhibits W +481 128505 36 innuendo floundered tits +482 128601 36 den profundity mate A +483 128603 36 submarines Garrisonian arches +484 128604 36 mouthful Strauss Moll +485 128702 36 expiring cemented ropers +486 128703 36 unfulfilled contrition bombast +487 128704 36 precession mutations difficultly A +488 138001 36 nullified exhibits adsorption +489 138002 36 affects tits definiteness FAS +490 138003 36 Cynthia mate cultivation A +491 138004 36 Chablis arches heals A +492 138005 36 betterments Moll Heusen W +493 138006 36 advertising ropers target FAS +494 138007 36 rubies bombast cited A +495 138008 36 southwest difficultly congresswoman W +496 138009 36 superstitious adsorption Katherine +497 138102 36 tabernacle definiteness titter A +498 138103 36 silk cultivation aspire A +499 138104 36 handsomest heals Mardis +500 138105 36 Persian Heusen Nadia W +501 138201 36 analog target estimating FAS +502 138302 36 complex cited stuck A +503 138303 36 Taoist congresswoman fifteenth A +504 138304 36 suspend Katherine Colombo +505 138401 29 relegated titter survey A +506 140102 29 awesome aspire staffing +507 140103 29 Bruxelles Mardis obtain +508 140104 29 imprecisely Nadia loaded +509 140105 29 televise estimating slaughtered +510 140201 29 braking stuck lights A +511 140701 29 true fifteenth circumference +512 141501 29 disappointing Colombo dull A +513 141502 29 navally survey weekly A +514 141901 29 circus staffing wetness +515 141902 29 beetles obtain visualized +516 142101 29 trumps loaded Tannenbaum +517 142102 29 fourscore slaughtered moribund +518 142103 29 Blackfoots lights demultiplex +519 142701 29 Grady circumference lockings +520 143001 29 quiets dull thugs FAS +521 143501 29 floundered weekly unnerves +522 143502 29 profundity wetness abut +523 148001 29 Garrisonian visualized Chippewa A +524 148002 29 Strauss Tannenbaum stratifications A +525 148003 29 cemented moribund signaled +526 148004 29 contrition demultiplex Italianizes A +527 148005 29 mutations lockings algorithmic A +528 148006 29 exhibits thugs paranoid FAS +529 148007 29 tits unnerves camping A +530 148009 29 mate abut signifying A +531 148010 29 arches Chippewa Patrice W +532 148011 29 Moll stratifications search A +533 148012 29 ropers signaled Angeles A +534 148013 29 bombast Italianizes semblance +535 148023 36 difficultly algorithmic taxed +536 148015 29 adsorption paranoid Beatrice +537 148016 29 definiteness camping retrace +538 148017 29 cultivation signifying lockout +539 148018 29 heals Patrice grammatic +540 148019 29 Heusen search helmsman +541 148020 29 target Angeles uniform W +542 148021 29 cited semblance hamming +543 148022 29 congresswoman taxed disobedience +544 148101 29 Katherine Beatrice captivated A +545 148102 29 titter retrace transferals A +546 148201 29 aspire lockout cartographer A +547 148401 29 Mardis grammatic aims FAS +548 148402 29 Nadia helmsman Pakistani +549 148501 29 estimating uniform burglarized FAS +550 148502 29 stuck hamming saucepans A +551 148503 29 fifteenth disobedience lacerating A +552 148504 29 Colombo captivated corny +553 148601 29 survey transferals megabytes FAS +554 148602 29 staffing cartographer chancellor +555 150701 29 obtain aims bulk A +556 152101 29 loaded Pakistani commits A +557 152102 29 slaughtered burglarized meson W +558 155202 36 lights saucepans deputies +559 155203 29 circumference lacerating northeaster A +560 155204 29 dull corny dipole +561 155205 29 weekly megabytes machining 0 +562 156001 29 wetness chancellor therefore +563 156002 29 visualized bulk Telefunken +564 156102 29 Tannenbaum commits salvaging +565 156301 29 moribund meson Corinthianizes A +566 156302 29 demultiplex deputies restlessly A +567 156303 29 lockings northeaster bromides +568 156304 29 thugs dipole generalized A +569 156305 29 unnerves machining mishaps +570 156306 29 abut therefore quelling +571 156501 29 Chippewa Telefunken spiritual A +572 158001 29 stratifications salvaging beguiles FAS +573 158002 29 signaled Corinthianizes Trobriand FAS +574 158101 29 Italianizes restlessly fleeing A +575 158102 29 algorithmic bromides Armour A +576 158103 29 paranoid generalized chin A +577 158201 29 camping mishaps provers A +578 158202 29 signifying quelling aeronautic A +579 158203 29 Patrice spiritual voltage W +580 158204 29 search beguiles sash +581 158301 29 Angeles Trobriand anaerobic A +582 158302 29 semblance fleeing simultaneous A +583 158303 29 taxed Armour accumulating A +584 158304 29 Beatrice chin Medusan A +585 158305 29 retrace provers shouted A +586 158306 29 lockout aeronautic freakish +587 158501 29 grammatic voltage index FAS +588 160301 29 helmsman sash commercially +589 166101 50 uniform anaerobic mistiness A +590 166102 50 hamming simultaneous endpoint +591 168001 29 disobedience accumulating straight A +592 168002 29 captivated Medusan flurried +593 168003 29 transferals shouted denotative A +594 168101 29 cartographer freakish coming FAS +595 168102 29 aims index commencements FAS +596 168103 29 Pakistani commercially gentleman +597 168104 29 burglarized mistiness gifted +598 168202 29 saucepans endpoint Shanghais +599 168301 29 lacerating straight sportswriting A +600 168502 29 corny flurried sloping A +601 168503 29 megabytes denotative navies +602 168601 29 chancellor coming leaflet A +603 173001 40 bulk commencements shooter +604 173701 40 commits gentleman Joplin FAS +605 173702 40 meson gifted babies +606 176001 40 deputies Shanghais subdivision FAS +607 176101 40 northeaster sportswriting burstiness W +608 176201 40 dipole sloping belted FAS +609 176401 40 machining navies assails FAS +610 176501 40 therefore leaflet admiring W +611 176601 40 Telefunken shooter swaying 0 +612 176602 40 salvaging Joplin Goldstine FAS +613 176603 40 Corinthianizes babies fitting +614 178001 40 restlessly subdivision Norwalk W +615 178002 40 bromides burstiness weakening W +616 178003 40 generalized belted analogy FAS +617 178004 40 mishaps assails deludes +618 178005 40 quelling admiring cokes +619 178006 40 spiritual swaying Clayton +620 178007 40 beguiles Goldstine exhausts +621 178008 40 Trobriand fitting causality +622 178101 40 fleeing Norwalk sating FAS +623 178102 40 Armour weakening icon +624 178103 40 chin analogy throttles +625 178201 40 provers deludes communicants FAS +626 178202 40 aeronautic cokes dehydrate FAS +627 178301 40 voltage Clayton priceless FAS +628 178302 40 sash exhausts publicly +629 178401 40 anaerobic causality incidentals FAS +630 178402 40 simultaneous sating commonplace +631 178403 40 accumulating icon mumbles +632 178404 40 Medusan throttles furthermore W +633 178501 40 shouted communicants cautioned W +634 186002 37 freakish dehydrate parametrized A +635 186102 37 index priceless registration A +636 186201 40 commercially publicly sadly FAS +637 186202 40 mistiness incidentals positioning +638 186203 40 endpoint commonplace babysitting +639 186302 37 straight mumbles eternal A +640 188007 37 flurried furthermore hoarder +641 188008 37 denotative cautioned congregates +642 188009 37 coming parametrized rains +643 188010 37 commencements registration workers W +644 188011 37 gentleman sadly sags A +645 188012 37 gifted positioning unplug W +646 188013 37 Shanghais babysitting garage A +647 188014 37 sportswriting eternal boulder A +648 188015 37 sloping hoarder hollowly A +649 188016 37 navies congregates specifics +650 188017 37 leaflet rains Teresa +651 188102 37 shooter workers Winsett +652 188103 37 Joplin sags convenient A +653 188202 37 babies unplug buckboards FAS +654 188301 40 subdivision garage amenities +655 188302 40 burstiness boulder resplendent FAS +656 188303 40 belted hollowly priding FAS +657 188401 37 assails specifics configurations +658 188402 37 admiring Teresa untidiness A +659 188503 37 swaying Winsett Brice W +660 188504 37 Goldstine convenient sews FAS +661 188505 37 fitting buckboards participated +662 190701 37 Norwalk amenities Simon FAS +663 190703 50 weakening resplendent certificates +664 191701 37 analogy priding Fitzpatrick +665 191702 37 deludes configurations Evanston A +666 191703 37 cokes untidiness misted +667 196001 37 Clayton Brice textures A +668 196002 37 exhausts sews save +669 196003 37 causality participated count +670 196101 37 sating Simon rightful A +671 196103 37 icon certificates chaperone +672 196104 37 throttles Fitzpatrick Lizzy A +673 196201 37 communicants Evanston clenched A +674 196202 37 dehydrate misted effortlessly +675 196203 37 priceless textures accessed +676 198001 37 publicly save beaters A +677 198003 37 incidentals count Hornblower FAS +678 198004 37 commonplace rightful vests A +679 198005 37 mumbles chaperone indulgences FAS +680 198006 37 furthermore Lizzy infallibly A +681 198007 37 cautioned clenched unwilling FAS +682 198008 37 parametrized effortlessly excrete FAS +683 198009 37 registration accessed spools A +684 198010 37 sadly beaters crunches FAS +685 198011 37 positioning Hornblower overestimating FAS +686 198012 37 babysitting vests ineffective +687 198013 37 eternal indulgences humiliation A +688 198014 37 hoarder infallibly sophomore +689 198015 37 congregates unwilling star +690 198017 37 rains excrete rifles +691 198018 37 workers spools dialysis +692 198019 37 sags crunches arriving +693 198020 37 unplug overestimating indulge +694 198021 37 garage ineffective clockers +695 198022 37 boulder humiliation languages +696 198023 50 hollowly sophomore Antarctica A +697 198024 37 specifics star percentage +698 198101 37 Teresa rifles ceiling A +699 198103 37 Winsett dialysis specification +700 198105 37 convenient arriving regimented A +701 198106 37 buckboards indulge ciphers +702 198201 37 amenities clockers pictures A +703 198204 37 resplendent languages serpents A +704 198301 53 priding Antarctica allot A +705 198302 53 configurations percentage realized A +706 198303 53 untidiness ceiling mayoral A +707 198304 53 Brice specification opaquely A +708 198401 37 sews regimented hostess FAS +709 198402 37 participated ciphers fiftieth +710 198403 37 Simon pictures incorrectly +711 202101 37 certificates serpents decomposition FAS +712 202301 37 Fitzpatrick allot stranglings +713 202302 37 Evanston realized mixture FAS +714 202303 37 misted mayoral electroencephalography FAS +715 202304 37 textures opaquely similarities FAS +716 202305 37 save hostess charges W +717 202601 37 count fiftieth freest FAS +718 202602 37 rightful incorrectly Greenberg FAS +719 202605 37 chaperone decomposition tinting +720 202606 37 Lizzy stranglings expelled W +721 202607 37 clenched mixture warm +722 202901 37 effortlessly electroencephalography smoothed +723 202902 37 accessed similarities deductions FAS +724 202903 37 beaters charges Romano W +725 202904 37 Hornblower freest bitterroot +726 202907 37 vests Greenberg corset +727 202908 37 indulgences tinting securing +728 203101 37 infallibly expelled environing FAS +729 203103 37 unwilling warm cute +730 203104 37 excrete smoothed Crays +731 203105 37 spools deductions heiress FAS +732 203401 37 crunches Romano inform FAS +733 203402 37 overestimating bitterroot avenge +734 203404 37 ineffective corset universals +735 203901 37 humiliation securing Kinsey W +736 203902 37 sophomore environing ravines FAS +737 203903 37 star cute bestseller +738 203906 37 rifles Crays equilibrium +739 203907 37 dialysis heiress extents 0 +740 203908 37 arriving inform relatively +741 203909 37 indulge avenge pressure FAS +742 206101 37 clockers universals critiques FAS +743 206201 37 languages Kinsey befouled +744 206202 37 Antarctica ravines rightfully FAS +745 206203 37 percentage bestseller mechanizing FAS +746 206206 37 ceiling equilibrium Latinizes +747 206207 37 specification extents timesharing +748 206208 37 regimented relatively Aden +749 208001 37 ciphers pressure embassies +750 208002 37 pictures critiques males FAS +751 208003 37 serpents befouled shapelessly FAS +752 208004 37 allot rightfully genres FAS +753 208008 37 realized mechanizing mastering +754 208009 37 mayoral Latinizes Newtonian +755 208010 37 opaquely timesharing finishers FAS +756 208011 37 hostess Aden abates +757 208101 37 fiftieth embassies teem +758 208102 37 incorrectly males kiting FAS +759 208103 37 decomposition shapelessly stodgy FAS +760 208104 37 stranglings genres scalps FAS +761 208105 37 mixture mastering feed FAS +762 208110 37 electroencephalography Newtonian guitars +763 208111 37 similarities finishers airships +764 208112 37 charges abates store +765 208113 37 freest teem denounces +766 208201 37 Greenberg kiting Pyle FAS +767 208203 37 tinting stodgy Saxony +768 208301 37 expelled scalps serializations FAS +769 208302 37 warm feed Peruvian FAS +770 208305 37 smoothed guitars taxonomically FAS +771 208401 37 deductions airships kingdom A +772 208402 37 Romano store stint A +773 208403 37 bitterroot denounces Sault A +774 208404 37 corset Pyle faithful +775 208501 37 securing Saxony Ganymede FAS +776 208502 37 environing serializations tidiness FAS +777 208503 37 cute Peruvian gainful FAS +778 208504 37 Crays taxonomically contrary FAS +779 208505 37 heiress kingdom Tipperary FAS +780 210101 37 inform stint tropics W +781 210102 37 avenge Sault theorizers +782 210103 37 universals faithful renew 0 +783 210104 37 Kinsey Ganymede already +784 210105 37 ravines tidiness terminal +785 210106 37 bestseller gainful Hegelian +786 210107 37 equilibrium contrary hypothesizer +787 210401 37 extents Tipperary warningly FAS +788 213201 37 relatively tropics journalizing FAS +789 213203 37 pressure theorizers nested +790 213204 37 critiques renew Lars +791 213205 37 befouled already saplings +792 213206 37 rightfully terminal foothill +793 213207 37 mechanizing Hegelian labeled +794 216101 37 Latinizes hypothesizer imperiously FAS +795 216103 37 timesharing warningly reporters FAS +796 218001 37 Aden journalizing furnishings FAS +797 218002 37 embassies nested precipitable FAS +798 218003 37 males Lars discounts FAS +799 218004 37 shapelessly saplings excises FAS +800 143503 50 genres foothill Stalin +801 218006 37 mastering labeled despot FAS +802 218007 37 Newtonian imperiously ripeness FAS +803 218008 37 finishers reporters Arabia +804 218009 37 abates furnishings unruly +805 218010 37 teem precipitable mournfulness +806 218011 37 kiting discounts boom FAS +807 218020 37 stodgy excises slaughter A +808 218021 50 scalps Stalin Sabine +809 218022 37 feed despot handy FAS +810 218023 37 guitars ripeness rural +811 218024 37 airships Arabia organizer +812 218101 37 store unruly shipyard FAS +813 218102 37 denounces mournfulness civics FAS +814 218103 37 Pyle boom inaccuracy FAS +815 218201 37 Saxony slaughter rules FAS +816 218202 37 serializations Sabine juveniles FAS +817 218203 37 Peruvian handy comprised W +818 218204 37 taxonomically rural investigations +819 218205 37 kingdom organizer stabilizes A +820 218301 37 stint shipyard seminaries FAS +821 218302 37 Sault civics Hunter A +822 218401 37 faithful inaccuracy sporty FAS +823 218402 37 Ganymede rules test FAS +824 218403 37 tidiness juveniles weasels +825 218404 37 gainful comprised CERN +826 218407 37 contrary investigations tempering +827 218408 37 Tipperary stabilizes afore FAS +828 218409 37 tropics seminaries Galatean +829 218410 37 theorizers Hunter techniques W +830 226001 37 renew sporty error +831 226002 37 already test veranda +832 226003 37 terminal weasels severely +833 226004 37 Hegelian CERN Cassites FAS +834 226005 37 hypothesizer tempering forthcoming +835 226006 37 warningly afore guides +836 226007 37 journalizing Galatean vanish FAS +837 226008 37 nested techniques lied A +838 226203 37 Lars error sawtooth FAS +839 226204 37 saplings veranda fated FAS +840 226205 37 foothill severely gradually +841 226206 37 labeled Cassites widens +842 226207 37 imperiously forthcoming preclude +843 226208 37 reporters guides Jobrel +844 226209 37 furnishings vanish hooker +845 226210 37 precipitable lied rainstorm +846 226211 37 discounts sawtooth disconnects +847 228001 37 excises fated cruelty +848 228004 37 Stalin gradually exponentials A +849 228005 37 despot widens affective A +850 228006 37 ripeness preclude arteries +851 228007 37 Arabia Jobrel Crosby FAS +852 228008 37 unruly hooker acquaint +853 228009 37 mournfulness rainstorm evenhandedly +854 228101 37 boom disconnects percentage +855 228108 37 slaughter cruelty disobedience +856 228109 37 Sabine exponentials humility +857 228110 37 handy affective gleaning A +858 228111 37 rural arteries petted A +859 228112 37 organizer Crosby bloater A +860 228113 37 shipyard acquaint minion A +861 228114 37 civics evenhandedly marginal A +862 228115 37 inaccuracy percentage apiary A +863 228116 37 rules disobedience measures +864 228117 37 juveniles humility precaution +865 228118 37 comprised gleaning repelled +866 228119 37 investigations petted primary FAS +867 228120 37 stabilizes bloater coverings +868 228121 37 seminaries minion Artemia A +869 228122 37 Hunter marginal navigate +870 228201 37 sporty apiary spatial +871 228206 37 test measures Gurkha +872 228207 37 weasels precaution meanwhile A +873 228208 37 CERN repelled Melinda A +874 228209 37 tempering primary Butterfield +875 228210 37 afore coverings Aldrich A +876 228211 37 Galatean Artemia previewing A +877 228212 37 techniques navigate glut A +878 228213 37 error spatial unaffected +879 228214 37 veranda Gurkha inmate +880 228301 37 severely meanwhile mineral +881 228305 37 Cassites Melinda impending A +882 228306 37 forthcoming Butterfield meditation A +883 228307 37 guides Aldrich ideas +884 228308 37 vanish previewing miniaturizes W +885 228309 37 lied glut lewdly +886 228310 37 sawtooth unaffected title +887 228311 37 fated inmate youthfulness +888 228312 37 gradually mineral creak FAS +889 228313 37 widens impending Chippewa +890 228314 37 preclude meditation clamored +891 228401 65 Jobrel ideas freezes +892 228402 65 hooker miniaturizes forgivably FAS +893 228403 65 rainstorm lewdly reduce FAS +894 228404 65 disconnects title McGovern W +895 228405 65 cruelty youthfulness Nazis W +896 228406 65 exponentials creak epistle W +897 228407 65 affective Chippewa socializes W +898 228408 65 arteries clamored conceptions +899 228409 65 Crosby freezes Kevin +900 228410 65 acquaint forgivably uncovering +901 230301 37 evenhandedly reduce chews FAS +902 230302 37 percentage McGovern appendixes FAS +903 230303 37 disobedience Nazis raining +904 018062 37 humility epistle infest +905 230501 37 gleaning socializes compartment +906 230502 37 petted conceptions minting +907 230503 37 bloater Kevin ducks +908 230504 37 minion uncovering roped A +909 230505 37 marginal chews waltz +910 230506 37 apiary appendixes Lillian +911 230507 37 measures raining repressions A +912 230508 37 precaution infest chillingly +913 230509 37 repelled compartment noncritical +914 230901 37 primary minting lithograph +915 230902 37 coverings ducks spongers +916 230903 37 Artemia roped parenthood +917 230904 37 navigate waltz posed +918 230905 37 spatial Lillian instruments +919 230906 37 Gurkha repressions filial +920 230907 37 meanwhile chillingly fixedly +921 230908 37 Melinda noncritical relives +922 230909 37 Butterfield lithograph Pandora +923 230910 37 Aldrich spongers watering A +924 230911 37 previewing parenthood ungrateful +925 230912 37 glut posed secures +926 230913 37 unaffected instruments chastisers +927 230914 37 inmate filial icon +928 231304 37 mineral fixedly reuniting A +929 231305 37 impending relives imagining A +930 231306 37 meditation Pandora abiding A +931 231307 37 ideas watering omnisciently +932 231308 37 miniaturizes ungrateful Britannic +933 231309 37 lewdly secures scholastics A +934 231310 37 title chastisers mechanics A +935 231311 37 youthfulness icon humidly A +936 231312 37 creak reuniting masterpiece +937 231313 37 Chippewa imagining however +938 231314 37 clamored abiding Mendelian +939 231315 37 freezes omnisciently jarred +940 232102 37 forgivably Britannic scolds +941 232103 37 reduce scholastics infatuate +942 232104 37 McGovern mechanics willed A +943 232105 37 Nazis humidly joyfully +944 232106 37 epistle masterpiece Microsoft +945 232107 37 socializes however fibrosities +946 232108 37 conceptions Mendelian Baltimorean +947 232601 37 Kevin jarred equestrian +948 232602 37 uncovering scolds Goodrich +949 232603 37 chews infatuate apish A +950 232605 37 appendixes willed Adlerian +5950 1232605 37 appendixes willed Adlerian +5951 1232606 37 appendixes willed Adlerian +5952 1232607 37 appendixes willed Adlerian +5953 1232608 37 appendixes willed Adlerian +5954 1232609 37 appendixes willed Adlerian +951 232606 37 raining joyfully Tropez +952 232607 37 infest Microsoft nouns +953 232608 37 compartment fibrosities distracting +954 232609 37 minting Baltimorean mutton +955 236104 37 ducks equestrian bridgeable A +956 236105 37 roped Goodrich stickers A +957 236106 37 waltz apish transcontinental A +958 236107 37 Lillian Adlerian amateurish +959 236108 37 repressions Tropez Gandhian +960 236109 37 chillingly nouns stratified +961 236110 37 noncritical distracting chamberlains +962 236111 37 lithograph mutton creditably +963 236112 37 spongers bridgeable philosophic +964 236113 37 parenthood stickers ores +965 238005 37 posed transcontinental Carleton +966 238006 37 instruments amateurish tape A +967 238007 37 filial Gandhian afloat A +968 238008 37 fixedly stratified goodness A +969 238009 37 relives chamberlains welcoming +970 238010 37 Pandora creditably Pinsky FAS +971 238011 37 watering philosophic halting +972 238012 37 ungrateful ores bibliography +973 238013 37 secures Carleton decoding +974 240401 41 chastisers tape variance A +975 240402 41 icon afloat allowed A +976 240901 41 reuniting goodness dire A +977 240902 41 imagining welcoming dub A +978 241801 41 abiding Pinsky poisoning +979 242101 41 omnisciently halting Iraqis A +980 242102 41 Britannic bibliography heaving +981 242201 41 scholastics decoding population A +982 242202 41 mechanics variance bomb A +983 242501 41 humidly allowed Majorca A +984 242502 41 masterpiece dire Gershwins +985 246201 41 however dub explorers +986 246202 41 Mendelian poisoning libretto A +987 246203 41 jarred Iraqis occurred +988 246204 41 scolds heaving Lagos +989 246205 41 infatuate population rats +990 246301 41 willed bomb bankruptcies A +991 246302 41 joyfully Majorca crying +992 248001 41 Microsoft Gershwins unexpected +993 248002 41 fibrosities explorers accessed A +994 248003 41 Baltimorean libretto colorful A +995 248004 41 equestrian occurred versatility A +996 248005 41 Goodrich Lagos cosy +997 248006 41 apish rats Darius A +998 248007 41 Adlerian bankruptcies mastering A +999 248008 41 Tropez crying Asiaticizations A +1000 248009 41 nouns unexpected offerers A +1001 248010 41 distracting accessed uncles A +1002 248011 41 mutton colorful sleepwalk +1003 248012 41 bridgeable versatility Ernestine +1004 248013 41 stickers cosy checksumming +1005 248014 41 transcontinental Darius stopped +1006 248015 41 amateurish mastering sicker +1007 248016 41 Gandhian Asiaticizations Italianization +1008 248017 41 stratified offerers alphabetic +1009 248018 41 chamberlains uncles pharmaceutic +1010 248019 41 creditably sleepwalk creator +1011 248020 41 philosophic Ernestine chess +1012 248021 41 ores checksumming charcoal +1013 248101 41 Carleton stopped Epiphany A +1014 248102 41 tape sicker bulldozes A +1015 248201 41 afloat Italianization Pygmalion A +1016 248202 41 goodness alphabetic caressing A +1017 248203 41 welcoming pharmaceutic Palestine A +1018 248204 41 Pinsky creator regimented A +1019 248205 41 halting chess scars A +1020 248206 41 bibliography charcoal realest A +1021 248207 41 decoding Epiphany diffusing A +1022 248208 41 variance bulldozes clubroom A +1023 248209 41 allowed Pygmalion Blythe A +1024 248210 41 dire caressing ahead +1025 248211 50 dub Palestine reviver +1026 250501 34 poisoning regimented retransmitting A +1027 250502 34 Iraqis scars landslide +1028 250503 34 heaving realest Eiffel +1029 250504 34 population diffusing absentee +1030 250505 34 bomb clubroom aye +1031 250601 34 Majorca Blythe forked A +1032 250602 34 Gershwins ahead Peruvianizes +1033 250603 34 explorers reviver clerked +1034 250604 34 libretto retransmitting tutor +1035 250605 34 occurred landslide boulevard +1036 251001 34 Lagos Eiffel shuttered +1037 251002 34 rats absentee quotes A +1038 251003 34 bankruptcies aye Caltech +1039 251004 34 crying forked Mossberg +1040 251005 34 unexpected Peruvianizes kept +1041 251301 34 accessed clerked roundly +1042 251302 34 colorful tutor features A +1043 251303 34 versatility boulevard imaginable A +1044 251304 34 cosy shuttered controller +1045 251305 34 Darius quotes racial +1046 251401 34 mastering Caltech uprisings A +1047 251402 34 Asiaticizations Mossberg narrowed A +1048 251403 34 offerers kept cannot A +1049 251404 34 uncles roundly vest +1050 251405 34 sleepwalk features famine +1051 251406 34 Ernestine imaginable sugars +1052 251801 34 checksumming controller exterminated A +1053 251802 34 stopped racial belays +1054 252101 34 sicker uprisings Hodges A +1055 252102 34 Italianization narrowed translatable +1056 252301 34 alphabetic cannot duality A +1057 252302 34 pharmaceutic vest recording A +1058 252303 34 creator famine rouses A +1059 252304 34 chess sugars poison +1060 252305 34 charcoal exterminated attitude +1061 252306 34 Epiphany belays dusted +1062 252307 34 bulldozes Hodges encompasses +1063 252308 34 Pygmalion translatable presentation +1064 252309 34 caressing duality Kantian +1065 256001 34 Palestine recording imprecision A +1066 256002 34 regimented rouses saving +1067 256003 34 scars poison maternal +1068 256004 34 realest attitude hewed +1069 256005 34 diffusing dusted kerosene +1070 258001 34 clubroom encompasses Cubans +1071 258002 34 Blythe presentation photographers +1072 258003 34 ahead Kantian nymph A +1073 258004 34 reviver imprecision bedlam A +1074 258005 34 retransmitting saving north A +1075 258006 34 landslide maternal Schoenberg A +1076 258007 34 Eiffel hewed botany A +1077 258008 34 absentee kerosene curs +1078 258009 34 aye Cubans solidification +1079 258010 34 forked photographers inheritresses +1080 258011 34 Peruvianizes nymph stiller +1081 258101 68 clerked bedlam t1 A +1082 258102 68 tutor north suite A +1083 258103 34 boulevard Schoenberg ransomer +1084 258104 68 shuttered botany Willy +1085 258105 68 quotes curs Rena A +1086 258106 68 Caltech solidification Seattle A +1087 258107 68 Mossberg inheritresses relaxes A +1088 258108 68 kept stiller exclaim +1089 258109 68 roundly t1 implicated A +1090 258110 68 features suite distinguish +1091 258111 68 imaginable ransomer assayed +1092 258112 68 controller Willy homeowner +1093 258113 68 racial Rena and +1094 258201 34 uprisings Seattle stealth +1095 258202 34 narrowed relaxes coinciding A +1096 258203 34 cannot exclaim founder A +1097 258204 34 vest implicated environing +1098 258205 34 famine distinguish jewelry +1099 258301 34 sugars assayed lemons A +1100 258401 34 exterminated homeowner brokenness A +1101 258402 34 belays and bedpost A +1102 258403 34 Hodges stealth assurers A +1103 258404 34 translatable coinciding annoyers +1104 258405 34 duality founder affixed +1105 258406 34 recording environing warbling +1106 258407 34 rouses jewelry seriously +1107 228123 37 poison lemons boasted +1108 250606 34 attitude brokenness Chantilly +1109 208405 37 dusted bedpost Iranizes +1110 212101 37 encompasses assurers violinist +1111 218206 37 presentation annoyers extramarital +1112 150401 37 Kantian affixed spates +1113 248212 41 imprecision warbling cloakroom +1114 128026 00 saving seriously gazer +1115 128024 00 maternal boasted hand +1116 128027 00 hewed Chantilly tucked +1117 128025 00 kerosene Iranizes gems +1118 128109 00 Cubans violinist clinker +1119 128705 00 photographers extramarital refiner +1120 126303 00 nymph spates callus +1121 128308 00 bedlam cloakroom leopards +1122 128204 00 north gazer comfortingly +1123 128205 00 Schoenberg hand generically +1124 128206 00 botany tucked getters +1125 128207 00 curs gems sexually +1126 118205 00 solidification clinker spear +1127 116801 00 inheritresses refiner serums +1128 116803 00 stiller callus Italianization +1129 116804 00 t1 leopards attendants +1130 116802 00 suite comfortingly spies +1131 128605 00 ransomer generically Anthony +1132 118308 00 Willy getters planar +1133 113702 00 Rena sexually cupped +1134 113703 00 Seattle spear cleanser +1135 112103 00 relaxes serums commuters +1136 118009 00 exclaim Italianization honeysuckle +5136 1118009 00 exclaim Italianization honeysuckle +1137 138011 00 implicated attendants orphanage +1138 138010 00 distinguish spies skies +1139 138012 00 assayed Anthony crushers +1140 068304 00 homeowner planar Puritan +1141 078009 00 and cupped squeezer +1142 108013 00 stealth cleanser bruises +1143 084004 00 coinciding commuters bonfire +1144 083402 00 founder honeysuckle Colombo +1145 084003 00 environing orphanage nondecreasing +1146 088504 00 jewelry skies innocents +1147 088005 00 lemons crushers masked +1148 088007 00 brokenness Puritan file +1149 088006 00 bedpost squeezer brush +1150 148025 00 assurers bruises mutilate +1151 148024 00 annoyers bonfire mommy +1152 138305 00 affixed Colombo bulkheads +1153 138306 00 warbling nondecreasing undeclared +1154 152701 00 seriously innocents displacements +1155 148505 00 boasted masked nieces +1156 158003 00 Chantilly file coeducation +1157 156201 00 Iranizes brush brassy +1158 156202 00 violinist mutilate authenticator +1159 158307 00 extramarital mommy Washoe +1160 158402 00 spates bulkheads penny +1161 158401 00 cloakroom undeclared Flagler +1162 068013 00 gazer displacements stoned +1163 068012 00 hand nieces cranes +1164 068203 00 tucked coeducation masterful +1165 088205 00 gems brassy biracial +1166 068704 00 clinker authenticator steamships +1167 068604 00 refiner Washoe windmills +1168 158502 00 callus penny exploit +1169 123103 00 leopards Flagler riverfront +1170 148026 00 comfortingly stoned sisterly +1171 123302 00 generically cranes sharpshoot +1172 076503 00 getters masterful mittens +1173 126304 00 sexually biracial interdependency +1174 068306 00 spear steamships policy +1175 143504 00 serums windmills unleashing +1176 160201 00 Italianization exploit pretenders +1177 148028 00 attendants riverfront overstatements +1178 148027 00 spies sisterly birthed +1179 143505 00 Anthony sharpshoot opportunism +1180 108014 00 planar mittens showroom +1181 076104 00 cupped interdependency compromisingly +1182 078106 00 cleanser policy Medicare +1183 126102 00 commuters unleashing corresponds +1184 128029 00 honeysuckle pretenders hardware +1185 128028 00 orphanage overstatements implant +1186 018410 00 skies birthed Alicia +1187 128110 00 crushers opportunism requesting +1188 148506 00 Puritan showroom produced +1189 123303 00 squeezer compromisingly criticizes +1190 123304 00 bruises Medicare backer +1191 068504 00 bonfire corresponds positively +1192 068305 00 Colombo hardware colicky +1193 000000 00 nondecreasing implant thrillingly +1 000001 00 Omaha teethe neat +2 011401 37 breaking dreaded Steinberg W +3 011402 37 Romans scholastics jarring +4 011403 37 intercepted audiology tinily +2 011401 37 breaking dreaded Steinberg W +3 011402 37 Romans scholastics jarring +4 011403 37 intercepted audiology tinily REPAIR TABLE t2; Table Op Msg_type Msg_text test.t2 repair status OK @@ -3825,6 +5039,9 @@ auto fld1 companynr fld3 fld4 fld5 fld6 2 011401 37 breaking dreaded Steinberg W 3 011402 37 Romans scholastics jarring 4 011403 37 intercepted audiology tinily +2 011401 37 breaking dreaded Steinberg W +3 011402 37 Romans scholastics jarring +4 011403 37 intercepted audiology tinily INSERT INTO t2 VALUES (1,000001,00,'Omaha','teethe','neat','') , (2,011401,37,'breaking','dreaded','Steinberg','W') , (3,011402,37,'Romans','scholastics','jarring','') , (4,011403,37,'intercepted','audiology','tinily',''); SELECT * FROM t2; auto fld1 companynr fld3 fld4 fld5 fld6 @@ -5031,6 +6248,9 @@ auto fld1 companynr fld3 fld4 fld5 fld6 2 011401 37 breaking dreaded Steinberg W 3 011402 37 Romans scholastics jarring 4 011403 37 intercepted audiology tinily +2 011401 37 breaking dreaded Steinberg W +3 011402 37 Romans scholastics jarring +4 011403 37 intercepted audiology tinily 1 000001 00 Omaha teethe neat 2 011401 37 breaking dreaded Steinberg W 3 011402 37 Romans scholastics jarring diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test index 51334fa62bc..a42a42b2a4e 100644 --- a/mysql-test/t/archive.test +++ b/mysql-test/t/archive.test @@ -1313,6 +1313,11 @@ INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily',''); SELECT * FROM t2; OPTIMIZE TABLE t2; SELECT * FROM t2; +INSERT INTO t2 VALUES (2,011401,37,'breaking','dreaded','Steinberg','W'); +INSERT INTO t2 VALUES (3,011402,37,'Romans','scholastics','jarring',''); +INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily',''); +OPTIMIZE TABLE t2 EXTENDED; +SELECT * FROM t2; REPAIR TABLE t2; SELECT * FROM t2; diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc index 3bf1441852f..41759885838 100644 --- a/sql/examples/ha_archive.cc +++ b/sql/examples/ha_archive.cc @@ -572,36 +572,22 @@ error: DBUG_RETURN(error ? error : -1); } - -/* - Look at ha_archive::open() for an explanation of the row format. - Here we just write out the row. - - Wondering about start_bulk_insert()? We don't implement it for - archive since it optimizes for lots of writes. The only save - for implementing start_bulk_insert() is that we could skip - setting dirty to true each time. +/* + This is where the actual row is written out. */ -int ha_archive::write_row(byte * buf) +int ha_archive::real_write_row(byte *buf, gzFile writer) { z_off_t written; uint *ptr, *end; - DBUG_ENTER("ha_archive::write_row"); + DBUG_ENTER("ha_archive::real_write_row"); - if (share->crashed) - DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); - - statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); - pthread_mutex_lock(&share->mutex); - written= gzwrite(share->archive_write, buf, table->s->reclength); - DBUG_PRINT("ha_archive::write_row", ("Wrote %d bytes expected %d", written, table->s->reclength)); + written= gzwrite(writer, buf, table->s->reclength); + DBUG_PRINT("ha_archive::real_write_row", ("Wrote %d bytes expected %d", written, table->s->reclength)); if (!delayed_insert || !bulk_insert) share->dirty= TRUE; if (written != (z_off_t)table->s->reclength) - goto error; + DBUG_RETURN(errno ? errno : -1); /* We should probably mark the table as damagaged if the record is written but the blob fails. @@ -616,21 +602,43 @@ int ha_archive::write_row(byte * buf) if (size) { ((Field_blob*) table->field[*ptr])->get_ptr(&data_ptr); - written= gzwrite(share->archive_write, data_ptr, (unsigned)size); + written= gzwrite(writer, data_ptr, (unsigned)size); if (written != (z_off_t)size) - goto error; + DBUG_RETURN(errno ? errno : -1); } } - share->rows_recorded++; - pthread_mutex_unlock(&share->mutex); - DBUG_RETURN(0); -error: - pthread_mutex_unlock(&share->mutex); - DBUG_RETURN(errno ? errno : -1); } +/* + Look at ha_archive::open() for an explanation of the row format. + Here we just write out the row. + + Wondering about start_bulk_insert()? We don't implement it for + archive since it optimizes for lots of writes. The only save + for implementing start_bulk_insert() is that we could skip + setting dirty to true each time. +*/ +int ha_archive::write_row(byte *buf) +{ + int rc; + DBUG_ENTER("ha_archive::write_row"); + + if (share->crashed) + DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); + + statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status); + if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) + table->timestamp_field->set_time(); + pthread_mutex_lock(&share->mutex); + share->rows_recorded++; + rc= real_write_row(buf, share->archive_write); + pthread_mutex_unlock(&share->mutex); + + DBUG_RETURN(rc); +} + /* All calls that need to scan the table start with this method. If we are told that it is a table scan we rewind the file to the beginning, otherwise @@ -866,39 +874,94 @@ error: int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) { DBUG_ENTER("ha_archive::optimize"); - int read; // Bytes read, gzread() returns int - gzFile reader, writer; - char block[IO_SIZE]; + int rc; + gzFile writer; char writer_filename[FN_REFLEN]; - /* Closing will cause all data waiting to be flushed */ - gzclose(share->archive_write); - share->archive_write= NULL; + /* Flush any waiting data */ + gzflush(share->archive_write, Z_SYNC_FLUSH); /* Lets create a file to contain the new data */ fn_format(writer_filename, share->table_name, "", ARN, MY_REPLACE_EXT|MY_UNPACK_FILENAME); - if ((reader= gzopen(share->data_file_name, "rb")) == NULL) - DBUG_RETURN(-1); - if ((writer= gzopen(writer_filename, "wb")) == NULL) + DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); + + /* + An extended rebuild is a lot more effort. We open up each row and re-record it. + Any dead rows are removed (aka rows that may have been partially recorded). + */ + + if (check_opt->flags == T_EXTEND) { - gzclose(reader); - DBUG_RETURN(-1); + byte *buf; + + /* + First we create a buffer that we can use for reading rows, and can pass + to get_row(). + */ + if (!(buf= (byte*) my_malloc(table->s->reclength, MYF(MY_WME)))) + { + rc= HA_ERR_OUT_OF_MEM; + goto error; + } + + /* + Now we will rewind the archive file so that we are positioned at the + start of the file. + */ + rc= read_data_header(archive); + + /* + Assuming now error from rewinding the archive file, we now write out the + new header for out data file. + */ + if (!rc) + rc= write_data_header(writer); + + /* + On success of writing out the new header, we now fetch each row and + insert it into the new archive file. + */ + if (!rc) + while (!(rc= get_row(archive, buf))) + real_write_row(buf, writer); + + my_free(buf, MYF(0)); + if (rc && rc != HA_ERR_END_OF_FILE) + goto error; + } + else + { + /* + The quick method is to just read the data raw, and then compress it directly. + */ + int read; // Bytes read, gzread() returns int + char block[IO_SIZE]; + if (gzrewind(archive) == -1) + { + rc= HA_ERR_CRASHED_ON_USAGE; + goto error; + } + + while ((read= gzread(archive, block, IO_SIZE))) + gzwrite(writer, block, read); } - while ((read= gzread(reader, block, IO_SIZE))) - gzwrite(writer, block, read); - - gzclose(reader); - gzclose(writer); + gzflush(writer, Z_SYNC_FLUSH); + gzclose(share->archive_write); + share->archive_write= writer; my_rename(writer_filename,share->data_file_name,MYF(0)); DBUG_RETURN(0); -} +error: + gzclose(writer); + + DBUG_RETURN(rc); +} /* Below is an example of how to setup row level locking. diff --git a/sql/examples/ha_archive.h b/sql/examples/ha_archive.h index 454d253abe5..dce1baa6798 100644 --- a/sql/examples/ha_archive.h +++ b/sql/examples/ha_archive.h @@ -84,6 +84,7 @@ public: int open(const char *name, int mode, uint test_if_locked); int close(void); int write_row(byte * buf); + int real_write_row(byte *buf, gzFile writer); int rnd_init(bool scan=1); int rnd_next(byte *buf); int rnd_pos(byte * buf, byte *pos); From a339be0fb3a16c386fdcf8297ef814e96ceab8ba Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 10 Jul 2005 21:17:03 -0700 Subject: [PATCH 199/216] Fixed 32bit issue, reworked error logic for open tables, and redid the repair table code so that it uses the extended optimize table code. sql/examples/ha_archive.cc: Fixed issue with 32bit systems giving warnings on bit shift (this is due to the fix by Jim to change to ha_rows). The error logic for opening a table was reworked after studing up on a reported issue. It has been reworked to create a share in all situations. The repair table will just have to figure everything out or toss its own error. The read only filesystem and permission denied problems were solved. Repair table code now rebuilds with the new optimize table extended code (so it no longer does the work itself). --- sql/examples/ha_archive.cc | 101 +++++++++---------------------------- 1 file changed, 25 insertions(+), 76 deletions(-) diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc index 41759885838..5ce249e9c61 100644 --- a/sql/examples/ha_archive.cc +++ b/sql/examples/ha_archive.cc @@ -305,12 +305,12 @@ int ha_archive::write_meta_file(File meta_file, ha_rows rows, bool dirty) meta_buffer[0]= (uchar)ARCHIVE_CHECK_HEADER; meta_buffer[1]= (uchar)ARCHIVE_VERSION; - int8store(meta_buffer + 2, rows); + int8store(meta_buffer + 2, (ulonglong)rows); int8store(meta_buffer + 10, check_point); *(meta_buffer + 18)= (uchar)dirty; DBUG_PRINT("ha_archive::write_meta_file", ("Check %d", (uint)ARCHIVE_CHECK_HEADER)); DBUG_PRINT("ha_archive::write_meta_file", ("Version %d", (uint)ARCHIVE_VERSION)); - DBUG_PRINT("ha_archive::write_meta_file", ("Rows %llu", rows)); + DBUG_PRINT("ha_archive::write_meta_file", ("Rows %llu", (ulonglong)rows)); DBUG_PRINT("ha_archive::write_meta_file", ("Checkpoint %llu", check_point)); DBUG_PRINT("ha_archive::write_meta_file", ("Dirty %d", (uint)dirty)); @@ -326,6 +326,9 @@ int ha_archive::write_meta_file(File meta_file, ha_rows rows, bool dirty) /* We create the shared memory space that we will use for the open table. + No matter what we try to get or create a share. This is so that a repair + table operation can occur. + See ha_example.cc for a longer description. */ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table) @@ -363,7 +366,7 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table) */ VOID(pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST)); if ((share->meta_file= my_open(meta_file_name, O_RDWR, MYF(0))) == -1) - goto error; + share->crashed= TRUE; /* After we read, we set the file to dirty. When we close, we will do the @@ -381,27 +384,14 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table) that is shared amoung all open tables. */ if ((share->archive_write= gzopen(share->data_file_name, "ab")) == NULL) - goto error2; - if (my_hash_insert(&archive_open_tables, (byte*) share)) - goto error3; + share->crashed= TRUE; + VOID(my_hash_insert(&archive_open_tables, (byte*) share)); thr_lock_init(&share->lock); } share->use_count++; pthread_mutex_unlock(&archive_mutex); return share; - -error3: - /* We close, but ignore errors since we already have errors */ - (void)gzclose(share->archive_write); -error2: - my_close(share->meta_file,MYF(0)); -error: - pthread_mutex_unlock(&archive_mutex); - VOID(pthread_mutex_destroy(&share->mutex)); - my_free((gptr) share, MYF(0)); - - return NULL; } @@ -458,13 +448,14 @@ int ha_archive::open(const char *name, int mode, uint test_if_locked) DBUG_ENTER("ha_archive::open"); if (!(share= get_share(name, table))) - DBUG_RETURN(-1); + DBUG_RETURN(HA_ERR_OUT_OF_MEM); // Not handled well by calling code! thr_lock_data_init(&share->lock,&lock,NULL); if ((archive= gzopen(share->data_file_name, "rb")) == NULL) { - (void)free_share(share); //We void since we already have an error - DBUG_RETURN(errno ? errno : -1); + if (errno == EROFS || errno == EACCES) + DBUG_RETURN(my_errno= errno); + DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); } DBUG_RETURN(0); @@ -803,68 +794,20 @@ int ha_archive::rnd_pos(byte * buf, byte *pos) /* This method repairs the meta file. It does this by walking the datafile and - rewriting the meta file. + rewriting the meta file. Currently it does this by calling optimize with + the extended flag. */ int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt) { - int rc; - byte *buf; - ha_rows rows_recorded= 0; - gzFile rebuild_file; // Archive file we are working with - File meta_file; // Meta file we use - char data_file_name[FN_REFLEN]; DBUG_ENTER("ha_archive::repair"); + check_opt->flags= T_EXTEND; + int rc= optimize(thd, check_opt); - /* - Open up the meta file to recreate it. - */ - fn_format(data_file_name, share->table_name, "", ARZ, - MY_REPLACE_EXT|MY_UNPACK_FILENAME); - if ((rebuild_file= gzopen(data_file_name, "rb")) == NULL) - DBUG_RETURN(errno ? errno : -1); + if (rc) + DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR); - if ((rc= read_data_header(rebuild_file))) - goto error; - - /* - We malloc up the buffer we will use for counting the rows. - I know, this malloc'ing memory but this should be a very - rare event. - */ - if (!(buf= (byte*) my_malloc(table->s->rec_buff_length > sizeof(ulonglong) +1 ? - table->s->rec_buff_length : sizeof(ulonglong) +1 , - MYF(MY_WME)))) - { - rc= HA_ERR_CRASHED_ON_USAGE; - goto error; - } - - while (!(rc= get_row(rebuild_file, buf))) - rows_recorded++; - - /* - Only if we reach the end of the file do we assume we can rewrite. - At this point we reset rc to a non-message state. - */ - if (rc == HA_ERR_END_OF_FILE) - { - fn_format(data_file_name,share->table_name,"",ARM,MY_REPLACE_EXT|MY_UNPACK_FILENAME); - if ((meta_file= my_open(data_file_name, O_RDWR, MYF(0))) == -1) - { - rc= HA_ERR_CRASHED_ON_USAGE; - goto error; - } - (void)write_meta_file(meta_file, rows_recorded, TRUE); - my_close(meta_file,MYF(0)); - rc= 0; - } - - my_free((gptr) buf, MYF(0)); share->crashed= FALSE; -error: - gzclose(rebuild_file); - - DBUG_RETURN(rc); + DBUG_RETURN(0); } /* @@ -925,8 +868,14 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) insert it into the new archive file. */ if (!rc) + { + share->rows_recorded= 0; while (!(rc= get_row(archive, buf))) + { real_write_row(buf, writer); + share->rows_recorded++; + } + } my_free(buf, MYF(0)); if (rc && rc != HA_ERR_END_OF_FILE) From dce0304a42a7bcecc9db59a3ea7225bd8a56fe89 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Jul 2005 13:20:07 +0500 Subject: [PATCH 200/216] field_conv.cc: Bug#11591 CHAR column with utf8 does not work properly (more chars than expected) do_cut_string didn't call well_formed_length, and copied all data, which was wrong in the case of multibyte character set. ctype_utf8.result, ctype_utf8.test: adding test case sql/field_conv.cc: Bug#11591 CHAR column with utf8 does not work properly (more chars than expected) do_cut_string didn't call well_formed_length, and copied all data, which was wrong in the case of multibyte character set. mysql-test/t/ctype_utf8.test: adding test case mysql-test/r/ctype_utf8.result: adding test caser --- mysql-test/r/ctype_utf8.result | 11 +++++++++++ mysql-test/t/ctype_utf8.test | 10 ++++++++++ sql/field_conv.cc | 31 +++++++++++++++++++------------ 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index d4e12ea84b7..665387e476c 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -939,6 +939,17 @@ content msisdn ERR Имри.Афимим.Аеимимримдмримрмрирор имримримримр имридм ирбднримрфмририримрфмфмим.Ад.Д имдимримрад.Адимримримрмдиримримримр м.Дадимфшьмримд им.Адимимрн имадми 1234567890 11 g 1234567890 DROP TABLE t1,t2; +create table t1 (a char(20) character set utf8); +insert into t1 values ('123456'),('андрей'); +alter table t1 modify a char(2) character set utf8; +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +Warning 1265 Data truncated for column 'a' at row 2 +select char_length(a), length(a), a from t1 order by a; +char_length(a) length(a) a +2 2 12 +2 4 ан +drop table t1; CREATE TABLE t1 ( a varchar(255) NOT NULL default '', KEY a (a) diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 0a847057258..737dcbcf1ed 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -789,6 +789,16 @@ SELECT content, t2.msisdn FROM t1, t2 WHERE t1.msisdn = '1234567890'; DROP TABLE t1,t2; +# +# Bug#11591: CHAR column with utf8 does not work properly +# (more chars than expected) +# +create table t1 (a char(20) character set utf8); +insert into t1 values ('123456'),('андрей'); +alter table t1 modify a char(2) character set utf8; +select char_length(a), length(a), a from t1 order by a; +drop table t1; + # # Bug#9557 MyISAM utf8 table crash # diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 8b362bbf807..625586d8c9b 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -326,21 +326,28 @@ static void do_field_real(Copy_field *copy) static void do_cut_string(Copy_field *copy) { // Shorter string field - memcpy(copy->to_ptr,copy->from_ptr,copy->to_length); + int well_formed_error; + CHARSET_INFO *cs= copy->from_field->charset(); + const char *from_end= copy->from_ptr + copy->from_length; + uint copy_length= cs->cset->well_formed_len(cs, copy->from_ptr, from_end, + copy->to_length / cs->mbmaxlen, + &well_formed_error); + if (copy->to_length < copy_length) + copy_length= copy->to_length; + memcpy(copy->to_ptr, copy->from_ptr, copy_length); - /* Check if we loosed any important characters */ - char *ptr,*end; - for (ptr=copy->from_ptr+copy->to_length,end=copy->from_ptr+copy->from_length ; - ptr != end ; - ptr++) + /* Check if we lost any important characters */ + if (well_formed_error || + cs->cset->scan(cs, copy->from_ptr + copy_length, from_end, + MY_SEQ_SPACES) < (copy->from_length - copy_length)) { - if (!my_isspace(system_charset_info, *ptr)) // QQ: ucs incompatible - { - copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WARN_DATA_TRUNCATED, 1); - break; - } + copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_DATA_TRUNCATED, 1); } + + if (copy_length < copy->to_length) + cs->cset->fill(cs, copy->to_ptr + copy_length, + copy->to_length - copy_length, ' '); } From 799299a5e50b872fb71d55e353983d6c15d782ab Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Jul 2005 04:33:19 -0600 Subject: [PATCH 201/216] sql_insert.cc: Added cast to bool to fix windows compile problem sql/sql_insert.cc: Added cast to bool to fix windows compile problem --- sql/sql_insert.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index f5d30f69978..7774fce97c0 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1118,7 +1118,7 @@ int check_that_all_fields_are_given_values(THD *thd, TABLE *entry, table_list= (table_list->belong_to_view ? table_list->belong_to_view : table_list); - view= (table_list->view); + view= (bool)(table_list->view); } if (view) { From b18b97aace1ad49ce4fcb2ad634bc171ce289869 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Jul 2005 16:51:39 +0500 Subject: [PATCH 202/216] field_conv.cc: Identation fix sql/field_conv.cc: Identation fix --- sql/field_conv.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 625586d8c9b..a447716a818 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -347,7 +347,7 @@ static void do_cut_string(Copy_field *copy) if (copy_length < copy->to_length) cs->cset->fill(cs, copy->to_ptr + copy_length, - copy->to_length - copy_length, ' '); + copy->to_length - copy_length, ' '); } From 313bda9eee9a1790c2c7e79cdc6900a4c31fbe50 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Jul 2005 06:14:42 -0600 Subject: [PATCH 203/216] ha_archive.cc: Added cast to fix windows compile error sql/examples/ha_archive.cc: Added cast to fix windows compile error --- sql/examples/ha_archive.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc index 5ce249e9c61..c362985f565 100644 --- a/sql/examples/ha_archive.cc +++ b/sql/examples/ha_archive.cc @@ -877,7 +877,7 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) } } - my_free(buf, MYF(0)); + my_free((char*)buf, MYF(0)); if (rc && rc != HA_ERR_END_OF_FILE) goto error; } From 990a97d414a772abc620dad3183925d20ef28a67 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Jul 2005 15:57:46 +0200 Subject: [PATCH 204/216] Updated system_mysql_db.result after mysql.proc definition changes. mysql-test/r/system_mysql_db.result: Updated result after mysql.proc definition changes. --- mysql-test/r/system_mysql_db.result | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index b8f96687a73..277115733d4 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -162,7 +162,7 @@ procs_priv CREATE TABLE `procs_priv` ( show create table proc; Table Create Table proc CREATE TABLE `proc` ( - `db` char(64) character set latin1 collate latin1_bin NOT NULL default '', + `db` char(64) character set utf8 collate utf8_bin NOT NULL default '', `name` char(64) NOT NULL default '', `type` enum('FUNCTION','PROCEDURE') NOT NULL, `specific_name` char(64) NOT NULL default '', @@ -173,12 +173,12 @@ proc CREATE TABLE `proc` ( `param_list` blob NOT NULL, `returns` char(64) NOT NULL default '', `body` blob NOT NULL, - `definer` char(77) character set latin1 collate latin1_bin NOT NULL default '', + `definer` char(77) character set utf8 collate utf8_bin NOT NULL default '', `created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, `modified` timestamp NOT NULL default '0000-00-00 00:00:00', `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE') NOT NULL default '', - `comment` char(64) character set latin1 collate latin1_bin NOT NULL default '', + `comment` char(64) character set utf8 collate utf8_bin NOT NULL default '', PRIMARY KEY (`db`,`name`,`type`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Stored Procedures' +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Stored Procedures' show tables; Tables_in_test From c580293e5cc3c1a705ea3e836da21ccabe911d86 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Jul 2005 15:59:49 +0200 Subject: [PATCH 205/216] cmd-line-utils/libedit/chared.c: Fix compile problem caused by use of "uint" which is undefined on QNX. cmd-line-utils/libedit/chared.c: Re-apply vva's fix: cmd-line-utils/libedit/chared.c@1.4, 2004-08-31 17:50:59+05:00, vva@eagle.mysql.r18.ru discarded using of uint because it's undefined on qnx --- cmd-line-utils/libedit/chared.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd-line-utils/libedit/chared.c b/cmd-line-utils/libedit/chared.c index 21fc8bc2c1d..4cb6e00d26e 100644 --- a/cmd-line-utils/libedit/chared.c +++ b/cmd-line-utils/libedit/chared.c @@ -51,13 +51,13 @@ cv_undo(EditLine *el) { c_undo_t *vu = &el->el_chared.c_undo; c_redo_t *r = &el->el_chared.c_redo; - uint size; + int size; /* Save entire line for undo */ size = el->el_line.lastchar - el->el_line.buffer; vu->len = size; vu->cursor = el->el_line.cursor - el->el_line.buffer; - memcpy(vu->buf, el->el_line.buffer, size); + memcpy(vu->buf, el->el_line.buffer, (size_t)size); /* save command info for redo */ r->count = el->el_state.doingarg ? el->el_state.argument : 0; From 96035298818535b813e1e0b6264f6d132fdc777a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Jul 2005 09:52:19 -0700 Subject: [PATCH 206/216] Added a test for glibtoolize so that the autoconf tools that come installed on OSX will work fine (so no need to replace them). BUILD/autorun.sh: Added a test for glibtoolize. This will fix issues with compiling on OSX --- BUILD/autorun.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/BUILD/autorun.sh b/BUILD/autorun.sh index 7daed25e56c..3adfafb0ce6 100755 --- a/BUILD/autorun.sh +++ b/BUILD/autorun.sh @@ -4,8 +4,14 @@ aclocal || (echo "Can't execute aclocal" && exit 1) autoheader || (echo "Can't execute autoheader" && exit 1) # --force means overwrite ltmain.sh script if it already exists -libtoolize --automake --force \ - || (echo "Can't execute libtoolize" && exit 1) +# Added glibtoolize reference to make native OSX autotools work +if [ -f /usr/bin/glibtoolize ] ; then + glibtoolize --automake --force \ + || (echo "Can't execute glibtoolize" && exit 1) +else + libtoolize --automake --force \ + || (echo "Can't execute libtoolize" && exit 1) +fi # --add-missing instructs automake to install missing auxiliary files # and --force to overwrite them if they already exist automake --add-missing --force \ From cc2ad349472b4401d9905f1604f0fd8b8500d4b8 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Jul 2005 19:10:51 +0200 Subject: [PATCH 207/216] Post-review fix. sql/sql_yacc.yy: Added explanation to comment. --- sql/sql_yacc.yy | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6880a2ef6d3..84de06d5604 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7388,7 +7388,9 @@ keyword: /* * Keywords that we allow for labels in SPs. - * Anything that's the beginning of a statement must be in keyword above. + * Anything that's the beginning of a statement or characteristics + * must be in keyword above, otherwise we get (harmful) shift/reduce + * conflicts. */ keyword_sp: ACTION {} From 86f46a346e0ee9086ed6a54d6cb73523384284ff Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Jul 2005 16:56:18 -0700 Subject: [PATCH 208/216] Fix for gcc 4.0 (they have removed min/max operators). include/my_global.h: Fix for gcc 4.0 (they removed min/max) --- include/my_global.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index f2fa54f3e4a..a7e6bba82b6 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -375,10 +375,7 @@ int __void__; #endif /* Define some useful general macros */ -#if defined(__cplusplus) && defined(__GNUC__) -#define max(a, b) ((a) >? (b)) -#define min(a, b) ((a) (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) #endif From c5e573dabcbeac370173c0a181a07f8cbef4310a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Jul 2005 10:31:43 +0200 Subject: [PATCH 209/216] New attempt after Bar's review Added api function mysql_get_character_set_info which provides information about the current client character set. include/mysql.h: Added api function mysql_get_character_set_info which provides information about the current client character set. libmysql/libmysql.c: Added api function mysql_get_character_set_info which provides information about the current client character set. libmysql/libmysql.def: Added api function mysql_get_character_set_info which provides information about the current client character set. tests/mysql_client_test.c: Added api function mysql_get_character_set_info which provides information about the current client character set. --- include/mysql.h | 14 ++++++++++++++ libmysql/libmysql.c | 15 +++++++++++++++ libmysql/libmysql.def | 1 + tests/mysql_client_test.c | 18 ++++++++++++++++++ 4 files changed, 48 insertions(+) diff --git a/include/mysql.h b/include/mysql.h index 84284fa0661..48602e27df5 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -218,6 +218,18 @@ enum mysql_rpl_type MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE, MYSQL_RPL_ADMIN }; +typedef struct character_set +{ + unsigned int number; /* character set number */ + unsigned int state; /* character set state */ + const char *csname; /* collation name */ + const char *name; /* character set name */ + const char *comment; /* comment */ + const char *dir; /* character set directory */ + unsigned int mbminlen; /* min. length for multibyte strings */ + unsigned int mbmaxlen; /* max. length for multibyte strings */ +} CHARACTER_SET; + struct st_mysql_methods; typedef struct st_mysql @@ -418,6 +430,8 @@ my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q, unsigned long length); my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q, unsigned long length); +void STDCALL mysql_get_character_set_info(MYSQL *mysql, + CHARACTER_SET *charset); /* local infile support */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 2a4bc5151c1..d387b48eff6 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1495,6 +1495,21 @@ const char * STDCALL mysql_character_set_name(MYSQL *mysql) return mysql->charset->csname; } +void STDCALL mysql_get_character_set_info(MYSQL *mysql, CHARACTER_SET *csinfo) +{ + csinfo->number = mysql->charset->number; + csinfo->state = mysql->charset->state; + csinfo->csname = mysql->charset->csname; + csinfo->name = mysql->charset->name; + csinfo->comment = mysql->charset->comment; + csinfo->mbminlen = mysql->charset->mbminlen; + csinfo->mbmaxlen = mysql->charset->mbmaxlen; + + if (mysql->options.charset_dir) + csinfo->dir = mysql->options.charset_dir; + else + csinfo->dir = charsets_dir; +} int STDCALL mysql_set_character_set(MYSQL *mysql, char *cs_name) { diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index 2da88c271ba..0688ea5732b 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -149,5 +149,6 @@ EXPORTS mysql_server_init mysql_server_end mysql_set_character_set + mysql_get_character_set_info get_defaults_files modify_defaults_file diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 0c79925c3eb..121e7fa1968 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13626,6 +13626,23 @@ static void test_bug10214() mysql_query(mysql, "set sql_mode=''"); } +static void test_client_character_set() +{ + CHARACTER_SET cs; + const char *csname; + int rc; + + myheader("test_client_character_set"); + + csname = "utf8"; + rc = mysql_set_character_set(mysql, csname); + DIE_UNLESS(rc == 0); + + mysql_get_character_set_info(mysql, &cs); + DIE_UNLESS(!strcmp(cs.csname, "utf8")); + DIE_UNLESS(!strcmp(cs.name, "utf8_general_ci")); +} + /* Read and parse arguments and MySQL options from my.cnf @@ -13850,6 +13867,7 @@ static struct my_tests_st my_tests[]= { { "test_cursors_with_union", test_cursors_with_union }, { "test_truncation", test_truncation }, { "test_truncation_option", test_truncation_option }, + { "test_client_character_set", test_client_character_set }, { "test_bug8330", test_bug8330 }, { "test_bug7990", test_bug7990 }, { "test_bug8378", test_bug8378 }, From 63d25bbd9843378902200d8d54ac4ba57a4b7f75 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Jul 2005 10:39:58 +0200 Subject: [PATCH 210/216] Disabled internal ndb system table test, since it only works on case sensitive systems --- mysql-test/r/ndb_autodiscover.result | 14 -------------- mysql-test/t/ndb_autodiscover.test | 23 ++++++++++++----------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result index b278d6eb048..5a1a82832fa 100644 --- a/mysql-test/r/ndb_autodiscover.result +++ b/mysql-test/r/ndb_autodiscover.result @@ -358,20 +358,6 @@ Database mysql test use test; -CREATE TABLE sys.SYSTAB_0 (a int); -ERROR 42S01: Table 'SYSTAB_0' already exists -select * from sys.SYSTAB_0; -ERROR HY000: Failed to open 'SYSTAB_0', error while unpacking from engine -CREATE TABLE IF NOT EXISTS sys.SYSTAB_0 (a int); -show warnings; -Level Code Message -select * from sys.SYSTAB_0; -ERROR HY000: Failed to open 'SYSTAB_0', error while unpacking from engine -drop table sys.SYSTAB_0; -ERROR 42S02: Unknown table 'SYSTAB_0' -drop table IF EXISTS sys.SYSTAB_0; -Warnings: -Note 1051 Unknown table 'SYSTAB_0' CREATE TABLE t9 ( a int NOT NULL PRIMARY KEY, b int diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test index 49ed8c894fe..1eed78b43df 100644 --- a/mysql-test/t/ndb_autodiscover.test +++ b/mysql-test/t/ndb_autodiscover.test @@ -460,19 +460,20 @@ use test; # a table with tha same name as a table that can't be # discovered( for example a table created via NDBAPI) ---error 1050 -CREATE TABLE sys.SYSTAB_0 (a int); ---error 1105 -select * from sys.SYSTAB_0; +# Test disabled since it doesn't work on case insensitive systems +#--error 1050 +#CREATE TABLE sys.SYSTAB_0 (a int); +#--error 1105 +#select * from sys.SYSTAB_0; -CREATE TABLE IF NOT EXISTS sys.SYSTAB_0 (a int); -show warnings; ---error 1105 -select * from sys.SYSTAB_0; +#CREATE TABLE IF NOT EXISTS sys.SYSTAB_0 (a int); +#show warnings; +#--error 1105 +#select * from sys.SYSTAB_0; ---error 1051 -drop table sys.SYSTAB_0; -drop table IF EXISTS sys.SYSTAB_0; +#--error 1051 +#drop table sys.SYSTAB_0; +#drop table IF EXISTS sys.SYSTAB_0; ###################################################### # Note! This should always be the last step in this From 74e43e8c2f88c50a258fcb1cea5d3445016a536a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Jul 2005 10:58:21 +0200 Subject: [PATCH 211/216] changes after Bar's review: renamed CHARACTER_SET to MY_CHARSET_INFO --- include/mysql.h | 4 ++-- libmysql/libmysql.c | 2 +- tests/mysql_client_test.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index 48602e27df5..daa29f70e16 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -228,7 +228,7 @@ typedef struct character_set const char *dir; /* character set directory */ unsigned int mbminlen; /* min. length for multibyte strings */ unsigned int mbmaxlen; /* max. length for multibyte strings */ -} CHARACTER_SET; +} MY_CHARSET_INFO; struct st_mysql_methods; @@ -431,7 +431,7 @@ my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q, my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q, unsigned long length); void STDCALL mysql_get_character_set_info(MYSQL *mysql, - CHARACTER_SET *charset); + MY_CHARSET_INFO *charset); /* local infile support */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index d387b48eff6..2074abd0f85 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1495,7 +1495,7 @@ const char * STDCALL mysql_character_set_name(MYSQL *mysql) return mysql->charset->csname; } -void STDCALL mysql_get_character_set_info(MYSQL *mysql, CHARACTER_SET *csinfo) +void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *csinfo) { csinfo->number = mysql->charset->number; csinfo->state = mysql->charset->state; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 121e7fa1968..b237387ef35 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13628,7 +13628,7 @@ static void test_bug10214() static void test_client_character_set() { - CHARACTER_SET cs; + MY_CHARSET_INFO cs; const char *csname; int rc; From 66d633b8b3a1d2fc83f1a99e75051011bb70b5e9 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Jul 2005 14:17:59 +0500 Subject: [PATCH 212/216] Fix for bug #11557 (Error during rounding of the DEFAULT values) mysql-test/r/type_newdecimal.result: test result fixed mysql-test/t/type_newdecimal.test: test case added strings/decimal.c: Code to check 999.9 -> 1000 case should work always --- mysql-test/r/type_newdecimal.result | 23 +++++++++++++++++++++++ mysql-test/t/type_newdecimal.test | 17 +++++++++++++++++ strings/decimal.c | 15 +++++++-------- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 964a69ffb12..aed2a478c0e 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -955,3 +955,26 @@ t1 CREATE TABLE `t1` ( `sl` decimal(5,5) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +create table t1 ( +f1 decimal unsigned not null default 17.49, +f2 decimal unsigned not null default 17.68, +f3 decimal unsigned not null default 99.2, +f4 decimal unsigned not null default 99.7, +f5 decimal unsigned not null default 104.49, +f6 decimal unsigned not null default 199.91, +f7 decimal unsigned not null default 999.9, +f8 decimal unsigned not null default 9999.99); +Warnings: +Note 1265 Data truncated for column 'f1' at row 1 +Note 1265 Data truncated for column 'f2' at row 1 +Note 1265 Data truncated for column 'f3' at row 1 +Note 1265 Data truncated for column 'f4' at row 1 +Note 1265 Data truncated for column 'f5' at row 1 +Note 1265 Data truncated for column 'f6' at row 1 +Note 1265 Data truncated for column 'f7' at row 1 +Note 1265 Data truncated for column 'f8' at row 1 +insert into t1 (f1) values (1); +select * from t1; +f1 f2 f3 f4 f5 f6 f7 f8 +1 18 99 100 104 200 1000 10000 +drop table t1; diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 55d004b361f..f54c8d80f09 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -998,3 +998,20 @@ create table t1 (sl decimal(0,30)); create table t1 (sl decimal(5, 5)); show create table t1; drop table t1; + +# +# Bug 11557 (DEFAULT values rounded improperly +# +create table t1 ( + f1 decimal unsigned not null default 17.49, + f2 decimal unsigned not null default 17.68, + f3 decimal unsigned not null default 99.2, + f4 decimal unsigned not null default 99.7, + f5 decimal unsigned not null default 104.49, + f6 decimal unsigned not null default 199.91, + f7 decimal unsigned not null default 999.9, + f8 decimal unsigned not null default 9999.99); +insert into t1 (f1) values (1); +select * from t1; +drop table t1; + diff --git a/strings/decimal.c b/strings/decimal.c index 76e62080ba0..1d75502f0da 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1443,6 +1443,7 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, intg1=ROUND_UP(from->intg + (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX))); dec1 *buf0=from->buf, *buf1=to->buf, x, y, carry=0; + int first_dig; sanity(to); @@ -1578,14 +1579,6 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, *buf1=1; to->intg++; } - else - { - /* Here we check 999.9 -> 1000 case when we need to increase intg */ - int first_dig= to->intg % DIG_PER_DEC1; - /* first_dig==0 should be handled above in the 'if' */ - if (first_dig && (*buf1 >= powers10[first_dig])) - to->intg++; - } } else { @@ -1606,6 +1599,12 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, } } } + + /* Here we check 999.9 -> 1000 case when we need to increase intg */ + first_dig= to->intg % DIG_PER_DEC1; + if (first_dig && (*buf1 >= powers10[first_dig])) + to->intg++; + if (scale<0) scale=0; From 358b6930e1a08747eca7ae3273956884cbf0380d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Jul 2005 11:49:57 +0200 Subject: [PATCH 213/216] Fixed failed merge --- mysql-test/r/ndb_autodiscover.result | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result index 3834c283a1e..0f17160ea99 100644 --- a/mysql-test/r/ndb_autodiscover.result +++ b/mysql-test/r/ndb_autodiscover.result @@ -372,6 +372,7 @@ drop table t1; use test2; drop table t2; drop database test2; +use test; drop database if exists test_only_ndb_tables; create database test_only_ndb_tables; use test_only_ndb_tables; From f36db3540a71af51103ac5a92711e1f7e85b4213 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Jul 2005 05:18:05 -0700 Subject: [PATCH 214/216] view.result, view.test: Added a test case for bug #11771. item.h: Fixed bug #11771. Added method reset_query_id_processor to be able to adjust query_id for fields generated from * in queries like this: SELECT * FROM ... sql_base.cc: Fixed bug #11771. Adjusted query_id for fields generated from * in queries like this: SELECT * FROM ... sql/sql_base.cc: Fixed bug #11771. Adjusted query_id for fields generated from * in queries like this: SELECT * FROM ... sql/item.h: Fixed bug #11771. Added method reset_query_id_processor to be able to adjust query_id for fields generated from * in queries like this: SELECT * FROM ... mysql-test/t/view.test: Added a test case for bug #11771. mysql-test/r/view.result: Added a test case for bug #11771. --- mysql-test/r/view.result | 14 ++++++++++++++ mysql-test/t/view.test | 15 +++++++++++++++ sql/item.h | 8 ++++++++ sql/sql_base.cc | 6 ++++++ 4 files changed, 43 insertions(+) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 7bcfaf8bdc3..1dfe1493665 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1940,3 +1940,17 @@ s1 s2 DROP PROCEDURE p1; DROP VIEW v1; DROP TABLE t1; +CREATE TABLE t1 (f1 char) ENGINE = innodb; +INSERT INTO t1 VALUES ('A'); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES('B'); +SELECT * FROM v1; +f1 +A +B +SELECT * FROM t1; +f1 +A +B +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 6b6b3d8a00f..0fb62b83b4e 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1778,3 +1778,18 @@ CALL p1(); DROP PROCEDURE p1; DROP VIEW v1; DROP TABLE t1; + +# +# Test for bug #11771: wrong query_id in SELECT * FROM +# + +CREATE TABLE t1 (f1 char) ENGINE = innodb; +INSERT INTO t1 VALUES ('A'); +CREATE VIEW v1 AS SELECT * FROM t1; + +INSERT INTO t1 VALUES('B'); +SELECT * FROM v1; +SELECT * FROM t1; + +DROP VIEW v1; +DROP TABLE t1; diff --git a/sql/item.h b/sql/item.h index 560f1124fb4..12acb8dd28d 100644 --- a/sql/item.h +++ b/sql/item.h @@ -641,6 +641,7 @@ public: virtual bool cleanup_processor(byte *arg); virtual bool collect_item_field_processor(byte * arg) { return 0; } virtual bool change_context_processor(byte *context) { return 0; } + virtual bool reset_query_id_processor(byte *query_id) { return 0; } virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual Item *set_no_const_sub(byte *arg) { return this; } @@ -895,6 +896,13 @@ public: bool is_null() { return field->is_null(); } Item *get_tmp_table_item(THD *thd); bool collect_item_field_processor(byte * arg); + bool reset_query_id_processor(byte *arg) + { + field->query_id= *((query_id_t *) arg); + if (result_field) + result_field->query_id= field->query_id; + return 0; + } void cleanup(); Item_equal *find_item_equal(COND_EQUAL *cond_equal); Item *equal_fields_propagator(byte *arg); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7a7f2292703..57f46b59c13 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3495,6 +3495,12 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, field->query_id=thd->query_id; table->used_keys.intersect(field->part_of_key); } + else + { + Item *item= ((Field_iterator_view *) iterator)->item(); + item->walk(&Item::reset_query_id_processor, + (byte *)(&thd->query_id)); + } } /* All fields are used in case if usual tables (in case of view used From 3be7d3fcee831d7fba3e3f347ba0fb1767ea20bc Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Jul 2005 16:30:45 +0000 Subject: [PATCH 215/216] Fix for BUG#11821: Make Item_type_holder be able to work with MIN(field), MAX(field). mysql-test/r/subselect.result: Testcase for BUG#11821 mysql-test/t/subselect.test: Testcase for BUG#11821 --- mysql-test/r/subselect.result | 6 ++++++ mysql-test/t/subselect.test | 8 ++++++++ sql/item.cc | 8 ++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 1f3542802a7..8615c8e661b 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2721,3 +2721,9 @@ SELECT s.ip, count( e.itemid ) FROM `t1` e JOIN t2 s ON s.sessionid = e.sessioni ip count( e.itemid ) 10.10.10.1 1 drop tables t1,t2; +create table t1 (fld enum('0','1')); +insert into t1 values ('1'); +select * from (select max(fld) from t1) as foo; +max(fld) +1 +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index e585022563f..12593438805 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1746,3 +1746,11 @@ CREATE TABLE `t2` ( INSERT INTO `t2` VALUES (1, 1, 1, '10.10.10.1'); SELECT s.ip, count( e.itemid ) FROM `t1` e JOIN t2 s ON s.sessionid = e.sessionid WHERE e.sessionid = ( SELECT sessionid FROM t2 ORDER BY sessionid DESC LIMIT 1 ) GROUP BY s.ip HAVING count( e.itemid ) >0 LIMIT 0 , 30; drop tables t1,t2; + +# BUG#11821 : Select from subselect using aggregate function on an enum +# segfaults: +create table t1 (fld enum('0','1')); +insert into t1 values ('1'); +select * from (select max(fld) from t1) as foo; +drop table t1; + diff --git a/sql/item.cc b/sql/item.cc index c96794ff482..3bdaf856f2a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3121,9 +3121,13 @@ void Item_type_holder::get_full_info(Item *item) if (fld_type == MYSQL_TYPE_ENUM || fld_type == MYSQL_TYPE_SET) { + if (item->type() == Item::SUM_FUNC_ITEM && + (((Item_sum*)item)->sum_func() == Item_sum::MAX_FUNC || + ((Item_sum*)item)->sum_func() == Item_sum::MIN_FUNC)) + item = ((Item_sum*)item)->args[0]; /* - We can have enum/set type after merging only if we have one enum/set - field and number of NULL fields + We can have enum/set type after merging only if we have one enum|set + field (or MIN|MAX(enum|set field)) and number of NULL fields */ DBUG_ASSERT((enum_set_typelib && get_real_type(item) == MYSQL_TYPE_NULL) || From 2ae3cdcf97cdb5a661954651fe3b445c1c5aff8a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Jul 2005 20:45:34 +0400 Subject: [PATCH 216/216] Fix bug #11399 Column alias was lost during view preraration. New item created in find_field_in_table() to fix view's item, was created without taking into account original item's alias. This patch checks if alias is set to the original item and if so sets it to newly created item. sql/sql_base.cc: Fix bug#11399 Alias wasn't set on view column mysql-test/t/view.test: Test case for bug#11399 Use an alias in a select statement on a view mysql-test/r/view.result: Test case for bug#11399 Use an alias in a select statement on a view --- mysql-test/r/view.result | 8 ++++++++ mysql-test/t/view.test | 10 ++++++++++ sql/sql_base.cc | 22 ++++++++++++++++------ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index cad86dc94b8..d11e91a7ba4 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1863,3 +1863,11 @@ ERROR HY000: Field of view 'test.v2' underlying table doesn't have a default val set sql_mode=default; drop view v2,v1; drop table t1; +create table t1 (f1 int); +insert into t1 values (1); +create view v1 as select f1 from t1; +select f1 as alias from v1; +alias +1 +drop view v1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 78d992163fe..fcde8bde4dd 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1714,3 +1714,13 @@ INSERT INTO v2 (vcol1) VALUES(12); set sql_mode=default; drop view v2,v1; drop table t1; + +# +# Bug#11399 Use an alias in a select statement on a view +# +create table t1 (f1 int); +insert into t1 values (1); +create view v1 as select f1 from t1; +select f1 as alias from v1; +drop view v1; +drop table t1; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 383adcadc6a..26c4e6f8605 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2407,9 +2407,11 @@ Field *view_ref_found= (Field*) 0x2; name name of field item_name name of item if it will be created (VIEW) length length of name - ref expression substituted in VIEW should be + ref [in/out] expression substituted in VIEW should be passed using this reference (return view_ref_found) + (*ref != NULL) only if *ref contains + the item that we need to replace. check_grants_table do check columns grants for table? check_grants_view do check columns grants for view? allow_rowid do allow finding of "_rowid" field? @@ -2447,11 +2449,6 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, { if (!my_strcasecmp(system_charset_info, field_it.name(), name)) { - Item *item= field_it.create_item(thd); - if (!item) - { - DBUG_RETURN(0); - } if (table_list->schema_table_reformed) { /* @@ -2470,6 +2467,19 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, name, length)) DBUG_RETURN(WRONG_GRANT); #endif + Item *item= field_it.create_item(thd); + if (!item) + { + DBUG_RETURN(0); + } + /* + *ref != NULL means that *ref contains the item that we need to + replace. If the item was aliased by the user, set the alias to + the replacing item. + */ + if (*ref && !(*ref)->is_autogenerated_name) + item->set_name((*ref)->name, (*ref)->name_length, + system_charset_info); if (register_tree_change) thd->change_item_tree(ref, item); else