diff options
author | unknown <hf@deer.(none)> | 2005-07-27 12:32:39 +0500 |
---|---|---|
committer | unknown <hf@deer.(none)> | 2005-07-27 12:32:39 +0500 |
commit | 981603d97f2bf186e2a2f43c07dbebb30fe22571 (patch) | |
tree | d1292dd47f32fb943938f7ecc73c61c131578728 | |
parent | 1517f4b6e8ff000bc7f33c16f94590e384403d50 (diff) | |
parent | 062258ca7e6d457a978be0be73a6ba727f81b6c8 (diff) | |
download | mariadb-git-981603d97f2bf186e2a2f43c07dbebb30fe22571.tar.gz |
Merge bk@192.168.21.1:/usr/home/bk/mysql-4.1
into deer.(none):/home/hf/work/mysql-4.1.6740
34 files changed, 792 insertions, 430 deletions
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index 63cd41a6d28..280a949c1c5 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -17,7 +17,9 @@ Created 10/21/1995 Heikki Tuuri #include <time.h> #endif +#ifdef UNIV_DO_FLUSH extern ibool os_do_not_call_flush_at_each_write; +#endif /* UNIV_DO_FLUSH */ extern ibool os_has_said_disk_full; extern ibool os_aio_print_debug; diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 4313b7f7019..49f88c0d62a 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -33,9 +33,13 @@ ulint os_innodb_umask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; ulint os_innodb_umask = 0; #endif +#ifdef UNIV_DO_FLUSH /* If the following is set to TRUE, we do not call os_file_flush in every os_file_write. We can set this TRUE when the doublewrite buffer is used. */ ibool os_do_not_call_flush_at_each_write = FALSE; +#else +/* We do not call os_file_flush in every os_file_write. */ +#endif /* UNIV_DO_FLUSH */ /* We use these mutexes to protect lseek + file i/o operation, if the OS does not provide an atomic pread or pwrite, or similar */ @@ -1974,6 +1978,7 @@ os_file_pwrite( os_file_n_pending_pwrites--; os_mutex_exit(os_file_count_mutex); +# ifdef UNIV_DO_FLUSH if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC && srv_unix_file_flush_method != SRV_UNIX_NOSYNC && !os_do_not_call_flush_at_each_write) { @@ -1984,6 +1989,7 @@ os_file_pwrite( ut_a(TRUE == os_file_flush(file)); } +# endif /* UNIV_DO_FLUSH */ return(ret); #else @@ -2006,6 +2012,7 @@ os_file_pwrite( ret = write(file, buf, (ssize_t)n); +# ifdef UNIV_DO_FLUSH if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC && srv_unix_file_flush_method != SRV_UNIX_NOSYNC && !os_do_not_call_flush_at_each_write) { @@ -2016,6 +2023,7 @@ os_file_pwrite( ut_a(TRUE == os_file_flush(file)); } +# endif /* UNIV_DO_FLUSH */ os_mutex_exit(os_file_seek_mutexes[i]); @@ -2282,9 +2290,11 @@ retry: /* Always do fsync to reduce the probability that when the OS crashes, a database page is only partially physically written to disk. */ +# ifdef UNIV_DO_FLUSH if (!os_do_not_call_flush_at_each_write) { ut_a(TRUE == os_file_flush(file)); } +# endif /* UNIV_DO_FLUSH */ os_mutex_exit(os_file_seek_mutexes[i]); @@ -3498,10 +3508,12 @@ os_aio_windows_handle( if (ret && len == slot->len) { ret_val = TRUE; +# ifdef UNIV_DO_FLUSH if (slot->type == OS_FILE_WRITE && !os_do_not_call_flush_at_each_write) { ut_a(TRUE == os_file_flush(slot->file)); } +# endif /* UNIV_DO_FLUSH */ } else { os_file_handle_error(slot->name, "Windows aio"); @@ -3582,10 +3594,12 @@ os_aio_posix_handle( *message1 = slot->message1; *message2 = slot->message2; +# ifdef UNIV_DO_FLUSH if (slot->type == OS_FILE_WRITE && !os_do_not_call_flush_at_each_write) { ut_a(TRUE == os_file_flush(slot->file)); } +# endif /* UNIV_DO_FLUSH */ os_mutex_exit(array->mutex); diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c index 51e193d563b..c7292fb7650 100644 --- a/innobase/trx/trx0sys.c +++ b/innobase/trx/trx0sys.c @@ -97,8 +97,9 @@ trx_doublewrite_init( /* Since we now start to use the doublewrite buffer, no need to call fsync() after every write to a data file */ - +#ifdef UNIV_DO_FLUSH os_do_not_call_flush_at_each_write = TRUE; +#endif /* UNIV_DO_FLUSH */ mutex_create(&(trx_doublewrite->mutex)); mutex_set_level(&(trx_doublewrite->mutex), SYNC_DOUBLEWRITE); diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index 57c97ab08ee..dce91c1e4c1 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -147,4 +147,6 @@ EXPORTS mysql_slave_query mysql_embedded mysql_set_character_set + mysql_server_init + mysql_server_end get_defaults_files diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 7a256edc91a..661793821a0 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -445,6 +445,30 @@ group_concat(distinct b order by b) Warnings: Warning 1260 2 line(s) were cut by GROUP_CONCAT() drop table t1; +create table t1 (a varchar(255) character set cp1250 collate cp1250_general_ci, +b varchar(255) character set koi8r); +insert into t1 values ('xxx','yyy'); +select collation(a) from t1; +collation(a) +cp1250_general_ci +select collation(group_concat(a)) from t1; +collation(group_concat(a)) +cp1250_general_ci +create table t2 select group_concat(a) as a from t1; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` longtext character set cp1250 +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select collation(group_concat(a,_koi8r'test')) from t1; +collation(group_concat(a,_koi8r'test')) +cp1250_general_ci +select collation(group_concat(a,_koi8r 0xC1C2)) from t1; +ERROR HY000: Illegal mix of collations (cp1250_general_ci,IMPLICIT) and (koi8r_general_ci,COERCIBLE) for operation 'group_concat' +select collation(group_concat(a,b)) from t1; +ERROR HY000: Illegal mix of collations (cp1250_general_ci,IMPLICIT) and (koi8r_general_ci,IMPLICIT) for operation 'group_concat' +drop table t1; +drop table t2; CREATE TABLE t1 (id int); SELECT GROUP_CONCAT(id) AS gc FROM t1 HAVING gc IS NULL; gc diff --git a/mysql-test/r/ndb_config.result b/mysql-test/r/ndb_config.result new file mode 100644 index 00000000000..f720b8e98df --- /dev/null +++ b/mysql-test/r/ndb_config.result @@ -0,0 +1,5 @@ +ndbd,1,localhost ndbd,2,localhost ndb_mgmd,3, mysqld,4, mysqld,5, mysqld,6, mysqld,7, +1,localhost,41943040,12582912 2,localhost,41943040,12582912 +1 localhost 41943040 12582912 +2 localhost 41943040 12582912 +1 2 diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 5f02db7707c..edb4d42e3c2 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -264,6 +264,24 @@ select group_concat(distinct b order by b) from t1 group by a; drop table t1; # +# Bug#10201 +# +create table t1 (a varchar(255) character set cp1250 collate cp1250_general_ci, + b varchar(255) character set koi8r); +insert into t1 values ('xxx','yyy'); +select collation(a) from t1; +select collation(group_concat(a)) from t1; +create table t2 select group_concat(a) as a from t1; +show create table t2; +select collation(group_concat(a,_koi8r'test')) from t1; +--error 1267 +select collation(group_concat(a,_koi8r 0xC1C2)) from t1; +--error 1267 +select collation(group_concat(a,b)) from t1; +drop table t1; +drop table t2; + +# # bug #7769: group_concat returning null is checked in having # CREATE TABLE t1 (id int); diff --git a/mysql-test/t/ndb_config.test b/mysql-test/t/ndb_config.test new file mode 100644 index 00000000000..ea78a32b1ba --- /dev/null +++ b/mysql-test/t/ndb_config.test @@ -0,0 +1,7 @@ +-- source include/have_ndb.inc +-- source include/not_embedded.inc + +--exec $NDB_TOOLS_DIR/ndb_config --no-defaults --query=type,nodeid,host 2> /dev/null +--exec $NDB_TOOLS_DIR/ndb_config --no-defaults --query=nodeid,host,DataMemory,IndexMemory --type=ndbd 2> /dev/null +--exec $NDB_TOOLS_DIR/ndb_config --no-defaults -r \\n -f " " --query=nodeid,host,DataMemory,IndexMemory --type=ndbd 2> /dev/null +--exec $NDB_TOOLS_DIR/ndb_config --no-defaults --query=nodeid --type=ndbd --host=localhost 2> /dev/null diff --git a/mysys/charset.c b/mysys/charset.c index 4b7ad3e59f4..cabdbad3413 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -383,26 +383,28 @@ static my_bool init_available_charsets(myf myflags) while we may changing the cs_info_table */ pthread_mutex_lock(&THR_LOCK_charset); - - bzero(&all_charsets,sizeof(all_charsets)); - init_compiled_charsets(myflags); - - /* Copy compiled charsets */ - for (cs=all_charsets; - cs < all_charsets+array_elements(all_charsets)-1 ; - cs++) + if (!charset_initialized) { - if (*cs) + bzero(&all_charsets,sizeof(all_charsets)); + init_compiled_charsets(myflags); + + /* Copy compiled charsets */ + for (cs=all_charsets; + cs < all_charsets+array_elements(all_charsets)-1 ; + cs++) { - if (cs[0]->ctype) - if (init_state_maps(*cs)) - *cs= NULL; + if (*cs) + { + if (cs[0]->ctype) + if (init_state_maps(*cs)) + *cs= NULL; + } } + + strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); + error= my_read_charset_file(fname,myflags); + charset_initialized=1; } - - strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); - error= my_read_charset_file(fname,myflags); - charset_initialized=1; pthread_mutex_unlock(&THR_LOCK_charset); } return error; diff --git a/ndb/include/mgmapi/mgmapi.h b/ndb/include/mgmapi/mgmapi.h index fa0774afa06..26b9dc65947 100644 --- a/ndb/include/mgmapi/mgmapi.h +++ b/ndb/include/mgmapi/mgmapi.h @@ -49,6 +49,7 @@ * @{ */ +#include <stdio.h> #include <ndb_types.h> #include "mgmapi_config_parameters.h" @@ -351,6 +352,12 @@ extern "C" { int ndb_mgm_get_latest_error_line(const NdbMgmHandle handle); #endif + /** + * Set error stream + */ + void ndb_mgm_set_error_stream(NdbMgmHandle, FILE *); + + /** @} *********************************************************************/ /** * @name Functions: Create/Destroy Management Server Handles diff --git a/ndb/include/mgmapi/mgmapi_config_parameters.h b/ndb/include/mgmapi/mgmapi_config_parameters.h index 432854d1d36..2e3b47eb42e 100644 --- a/ndb/include/mgmapi/mgmapi_config_parameters.h +++ b/ndb/include/mgmapi/mgmapi_config_parameters.h @@ -50,8 +50,11 @@ #define CFG_DB_FILESYSTEM_PATH 125 #define CFG_DB_NO_REDOLOG_FILES 126 -#define CFG_DB_DISC_BANDWIDTH 127 -#define CFG_DB_SR_DISC_BANDWITH 128 + +#define CFG_DB_LCP_DISC_PAGES_TUP 127 +#define CFG_DB_LCP_DISC_PAGES_TUP_SR 128 +#define CFG_DB_LCP_DISC_PAGES_ACC 137 +#define CFG_DB_LCP_DISC_PAGES_ACC_SR 138 #define CFG_DB_TRANSACTION_CHECK_INTERVAL 129 #define CFG_DB_TRANSACTION_INACTIVE_TIMEOUT 130 diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp index 3313e22fe3a..1f0053e209a 100644 --- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp +++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp @@ -722,10 +722,12 @@ void Dbacc::execREAD_CONFIG_REQ(Signal* signal) ndbrestart1Lab(signal); clblPagesPerTick = 50; - //ndb_mgm_get_int_parameter(p, CFG_DB_, &clblPagesPerTick); + ndb_mgm_get_int_parameter(p, CFG_DB_LCP_DISC_PAGES_ACC_SR, + &clblPagesPerTick); clblPagesPerTickAfterSr = 50; - //ndb_mgm_get_int_parameter(p, CFG_DB_, &clblPagesPerTickAfterSr); + ndb_mgm_get_int_parameter(p, CFG_DB_LCP_DISC_PAGES_ACC, + &clblPagesPerTickAfterSr); tdata0 = 0; initialiseRecordsLab(signal, ref, senderData); diff --git a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp index 0d7430e662d..27f817d8abc 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp @@ -663,10 +663,12 @@ void Dbtup::execREAD_CONFIG_REQ(Signal* signal) initialiseRecordsLab(signal, 0, ref, senderData); clblPagesPerTick = 50; - //ndb_mgm_get_int_parameter(p, CFG_DB_, &clblPagesPerTick); + ndb_mgm_get_int_parameter(p, CFG_DB_LCP_DISC_PAGES_TUP_SR, + &clblPagesPerTick); clblPagesPerTickAfterSr = 50; - //ndb_mgm_get_int_parameter(p, CFG_DB_, &clblPagesPerTickAfterSr); + ndb_mgm_get_int_parameter(p, CFG_DB_LCP_DISC_PAGES_TUP, + &clblPagesPerTickAfterSr); }//Dbtup::execSIZEALT_REP() diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index 6a949c6006d..bf78adec970 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -100,6 +100,7 @@ struct ndb_mgm_handle { #ifdef MGMAPI_LOG FILE* logfile; #endif + FILE *errstream; }; #define SET_ERROR(h, e, s) setError(h, e, __LINE__, s) @@ -153,6 +154,7 @@ ndb_mgm_create_handle() h->read_timeout = 50000; h->write_timeout = 100; h->cfg_i = 0; + h->errstream = stdout; strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE); @@ -213,6 +215,13 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle) DBUG_VOID_RETURN; } +extern "C" +void +ndb_mgm_set_error_stream(NdbMgmHandle handle, FILE * file) +{ + handle->errstream = file; +} + /***************************************************************************** * Error handling *****************************************************************************/ @@ -382,8 +391,8 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries, break; if (verbose > 0) { char buf[1024]; - ndbout_c("Unable to connect with connect string: %s", - cfg.makeConnectString(buf,sizeof(buf))); + fprintf(handle->errstream, "Unable to connect with connect string: %s\n", + cfg.makeConnectString(buf,sizeof(buf))); verbose= -1; } if (no_retries == 0) { @@ -392,32 +401,35 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries, "Unable to connect with connect string: %s", cfg.makeConnectString(buf,sizeof(buf))); if (verbose == -2) - ndbout << ", failed." << endl; + fprintf(handle->errstream, ", failed.\n"); return -1; } if (verbose == -1) { - ndbout << "Retrying every " << retry_delay_in_seconds << " seconds"; + fprintf(handle->errstream, "Retrying every %d seconds", + retry_delay_in_seconds); if (no_retries > 0) - ndbout << ". Attempts left:"; + fprintf(handle->errstream, ". Attempts left:"); else - ndbout << ", until connected.";; - ndbout << flush; + fprintf(handle->errstream, ", until connected."); + fflush(handle->errstream); verbose= -2; } if (no_retries > 0) { if (verbose == -2) { - ndbout << " " << no_retries; - ndbout << flush; + fprintf(handle->errstream, " %d", no_retries); + fflush(handle->errstream); } no_retries--; } NdbSleep_SecSleep(retry_delay_in_seconds); } if (verbose == -2) - ndbout << endl; - + { + fprintf(handle->errstream, "\n"); + fflush(handle->errstream); + } handle->cfg_i = i; - + handle->socket = sockfd; handle->connected = 1; @@ -469,7 +481,9 @@ ndb_mgm_match_node_type(const char * type) for(int i = 0; i<no_of_type_values; i++) if(strcmp(type, type_values[i].str) == 0) return type_values[i].value; - + else if(strcmp(type, type_values[i].alias) == 0) + return type_values[i].value; + return NDB_MGM_NODE_TYPE_UNKNOWN; } @@ -1664,28 +1678,28 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) { do { const char * buf; if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ - ndbout_c("ERROR Message: %s\n", buf); + fprintf(handle->errstream, "ERROR Message: %s\n\n", buf); break; } buf = "<Unspecified>"; if(!prop->get("Content-Type", &buf) || strcmp(buf, "ndbconfig/octet-stream") != 0){ - ndbout_c("Unhandled response type: %s", buf); + fprintf(handle->errstream, "Unhandled response type: %s\n", buf); break; } buf = "<Unspecified>"; if(!prop->get("Content-Transfer-Encoding", &buf) || strcmp(buf, "base64") != 0){ - ndbout_c("Unhandled encoding: %s", buf); + fprintf(handle->errstream, "Unhandled encoding: %s\n", buf); break; } buf = "<Content-Length Unspecified>"; Uint32 len = 0; if(!prop->get("Content-Length", &len)){ - ndbout_c("Invalid response: %s\n", buf); + fprintf(handle->errstream, "Invalid response: %s\n\n", buf); break; } @@ -1710,14 +1724,14 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) { const int res = base64_decode(buf64, len-1, tmp); delete[] buf64; if(res != 0){ - ndbout_c("Failed to decode buffer"); + fprintf(handle->errstream, "Failed to decode buffer\n"); break; } ConfigValuesFactory cvf; const int res2 = cvf.unpack(tmp); if(!res2){ - ndbout_c("Failed to unpack buffer"); + fprintf(handle->errstream, "Failed to unpack buffer\n"); break; } @@ -1821,7 +1835,7 @@ ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype) } Uint32 _nodeid; if(!prop->get("nodeid", &_nodeid) != 0){ - ndbout_c("ERROR Message: <nodeid Unspecified>\n"); + fprintf(handle->errstream, "ERROR Message: <nodeid Unspecified>\n"); break; } nodeid= _nodeid; @@ -1897,7 +1911,7 @@ ndb_mgm_set_int_parameter(NdbMgmHandle handle, do { const char * buf; if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ - ndbout_c("ERROR Message: %s\n", buf); + fprintf(handle->errstream, "ERROR Message: %s\n", buf); break; } res= 0; @@ -1940,7 +1954,7 @@ ndb_mgm_set_int64_parameter(NdbMgmHandle handle, do { const char * buf; if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ - ndbout_c("ERROR Message: %s\n", buf); + fprintf(handle->errstream, "ERROR Message: %s\n", buf); break; } res= 0; @@ -1983,7 +1997,7 @@ ndb_mgm_set_string_parameter(NdbMgmHandle handle, do { const char * buf; if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ - ndbout_c("ERROR Message: %s\n", buf); + fprintf(handle->errstream, "ERROR Message: %s\n", buf); break; } res= 0; @@ -2020,7 +2034,7 @@ ndb_mgm_purge_stale_sessions(NdbMgmHandle handle, char **purged){ do { const char * buf; if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){ - ndbout_c("ERROR Message: %s\n", buf); + fprintf(handle->errstream, "ERROR Message: %s\n", buf); break; } if (purged) { diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp index 03119ef3609..bc078b711dc 100644 --- a/ndb/src/mgmsrv/ConfigInfo.cpp +++ b/ndb/src/mgmsrv/ConfigInfo.cpp @@ -915,7 +915,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { STR_VALUE(MAX_INT_RNIL) }, { - KEY_INTERNAL, + CFG_DB_LCP_DISC_PAGES_TUP_SR, "NoOfDiskPagesToDiskDuringRestartTUP", DB_TOKEN, "?", @@ -927,7 +927,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { STR_VALUE(MAX_INT_RNIL) }, { - KEY_INTERNAL, + CFG_DB_LCP_DISC_PAGES_TUP, "NoOfDiskPagesToDiskAfterRestartTUP", DB_TOKEN, "?", @@ -939,7 +939,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { STR_VALUE(MAX_INT_RNIL) }, { - KEY_INTERNAL, + CFG_DB_LCP_DISC_PAGES_ACC_SR, "NoOfDiskPagesToDiskDuringRestartACC", DB_TOKEN, "?", @@ -951,7 +951,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { STR_VALUE(MAX_INT_RNIL) }, { - KEY_INTERNAL, + CFG_DB_LCP_DISC_PAGES_ACC, "NoOfDiskPagesToDiskAfterRestartACC", DB_TOKEN, "?", diff --git a/ndb/src/mgmsrv/ConfigInfo.hpp b/ndb/src/mgmsrv/ConfigInfo.hpp index 871ee62040e..788619db7fe 100644 --- a/ndb/src/mgmsrv/ConfigInfo.hpp +++ b/ndb/src/mgmsrv/ConfigInfo.hpp @@ -127,14 +127,14 @@ private: Properties m_info; Properties m_systemDefaults; - static const ParamInfo m_ParamInfo[]; - static const int m_NoOfParams; - static const AliasPair m_sectionNameAliases[]; static const char* m_sectionNames[]; static const int m_noOfSectionNames; public: + static const ParamInfo m_ParamInfo[]; + static const int m_NoOfParams; + static const SectionRule m_SectionRules[]; static const ConfigRule m_ConfigRules[]; static const int m_NoOfRules; diff --git a/ndb/tools/Makefile.am b/ndb/tools/Makefile.am index c350fb0a141..1f11122fb70 100644 --- a/ndb/tools/Makefile.am +++ b/ndb/tools/Makefile.am @@ -9,7 +9,7 @@ ndbtools_PROGRAMS = \ ndb_show_tables \ ndb_select_all \ ndb_select_count \ - ndb_restore + ndb_restore ndb_config tools_common_sources = ../test/src/NDBT_ReturnCodes.cpp \ ../test/src/NDBT_Table.cpp \ @@ -32,6 +32,16 @@ ndb_restore_SOURCES = restore/restore_main.cpp \ restore/consumer_printer.cpp \ restore/Restore.cpp +ndb_config_SOURCES = config.cpp \ + ../src/mgmsrv/Config.cpp \ + ../src/mgmsrv/ConfigInfo.cpp \ + ../src/mgmsrv/InitConfigFileParser.cpp +ndb_config_CXXFLAGS = -I$(top_srcdir)/ndb/src/mgmapi \ + -I$(top_srcdir)/ndb/src/mgmsrv \ + -I$(top_srcdir)/ndb/include/mgmcommon \ + -DMYSQLCLUSTERDIR="\"\"" + + include $(top_srcdir)/ndb/config/common.mk.am include $(top_srcdir)/ndb/config/type_ndbapitools.mk.am @@ -45,6 +55,7 @@ ndb_show_tables_LDFLAGS = @ndb_bin_am_ldflags@ ndb_select_all_LDFLAGS = @ndb_bin_am_ldflags@ ndb_select_count_LDFLAGS = @ndb_bin_am_ldflags@ ndb_restore_LDFLAGS = @ndb_bin_am_ldflags@ +ndb_config_LDFLAGS = @ndb_bin_am_ldflags@ # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/ndb/tools/config.cpp b/ndb/tools/config.cpp new file mode 100644 index 00000000000..7944f66f71c --- /dev/null +++ b/ndb/tools/config.cpp @@ -0,0 +1,407 @@ +/* Copyright (C) 2003 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 */ + +/** + * ndb_config --nodes --query=nodeid --type=ndbd --host=local1 + */ + +#include <ndb_global.h> +#include <my_sys.h> +#include <my_getopt.h> +#include <mysql_version.h> + +#include <NdbOut.hpp> +#include <mgmapi.h> +#include <mgmapi_configuration.hpp> +#include <ConfigInfo.hpp> + +static int g_verbose = 0; +static int try_reconnect = 3; + +static int g_nodes = 1; +static const char * g_connectstring = 0; +static const char * g_query = 0; + +static int g_nodeid = 0; +static const char * g_type = 0; +static const char * g_host = 0; +static const char * g_field_delimiter=","; +static const char * g_row_delimiter=" "; + +int g_print_full_config, opt_ndb_shm; + +typedef ndb_mgm_configuration_iterator Iter; + +static void ndb_std_print_version() +{ + printf("MySQL distrib %s, for %s (%s)\n", + MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); +} + +static struct my_option my_long_options[] = +{ + { "usage", '?', "Display this help and exit.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "help", '?', "Display this help and exit.", + 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 }, + { "ndb-connectstring", 256, + "Set connect string for connecting to ndb_mgmd. " + "Syntax: \"[nodeid=<id>;][host=]<hostname>[:<port>]\". " + "Overides specifying entries in NDB_CONNECTSTRING and Ndb.cfg", + (gptr*) &g_connectstring, (gptr*) &g_connectstring, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "nodes", 256, "Print nodes", + (gptr*) &g_nodes, (gptr*) &g_nodes, + 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + { "query", 'q', "Query option(s)", + (gptr*) &g_query, (gptr*) &g_query, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + { "host", 257, "Host", + (gptr*) &g_host, (gptr*) &g_host, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + { "type", 258, "Type of node/connection", + (gptr*) &g_type, (gptr*) &g_type, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + { "id", 258, "Nodeid", + (gptr*) &g_nodeid, (gptr*) &g_nodeid, + 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + { "nodeid", 258, "Nodeid", + (gptr*) &g_nodeid, (gptr*) &g_nodeid, + 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + { "fields", 'f', "Field separator", + (gptr*) &g_field_delimiter, (gptr*) &g_field_delimiter, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + { "rows", 'r', "Row separator", + (gptr*) &g_row_delimiter, (gptr*) &g_row_delimiter, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} +}; + +static void usage() +{ + char desc[] = + "This program will retreive config options for a ndb cluster\n"; + ndb_std_print_version(); + my_print_help(my_long_options); + my_print_variables(my_long_options); +} +static my_bool +ndb_std_get_one_option(int optid, + const struct my_option *opt __attribute__((unused)), + char *argument) +{ + switch (optid) { + case 'V': + ndb_std_print_version(); + exit(0); + case '?': + usage(); + exit(0); + } + return 0; +} + +/** + * Match/Apply framework + */ +struct Match +{ + int m_key; + BaseString m_value; + virtual int eval(NdbMgmHandle, const Iter&); +}; + +struct Apply +{ + Apply() {} + Apply(int val) { m_key = val;} + int m_key; + virtual int apply(NdbMgmHandle, const Iter&); +}; + +struct NodeTypeApply : public Apply +{ + virtual int apply(NdbMgmHandle, const Iter&); +}; + +static int parse_query(Vector<Apply*>&, int &argc, char**& argv); +static int parse_where(Vector<Match*>&, int &argc, char**& argv); +static int eval(NdbMgmHandle, const Iter&, const Vector<Match*>&); +static int apply(NdbMgmHandle, const Iter&, const Vector<Apply*>&); +int +main(int argc, char** argv){ + NDB_INIT(argv[0]); + const char *load_default_groups[]= { "mysql_cluster",0 }; + load_defaults("my",load_default_groups,&argc,&argv); + int ho_error; + if ((ho_error=handle_options(&argc, &argv, my_long_options, + ndb_std_get_one_option))) + return -1; + + NdbMgmHandle mgm = ndb_mgm_create_handle(); + if(mgm == NULL) { + fprintf(stderr, "Cannot create handle to management server.\n"); + exit(-1); + } + + ndb_mgm_set_error_stream(mgm, stderr); + + if (ndb_mgm_set_connectstring(mgm, g_connectstring)) + { + fprintf(stderr, "* %5d: %s\n", + ndb_mgm_get_latest_error(mgm), + ndb_mgm_get_latest_error_msg(mgm)); + fprintf(stderr, + "* %s", ndb_mgm_get_latest_error_desc(mgm)); + exit(-1); + } + + if(ndb_mgm_connect(mgm, try_reconnect-1, 5, 1)) + { + fprintf(stderr, "Connect failed"); + fprintf(stderr, " code: %d, msg: %s\n", + ndb_mgm_get_latest_error(mgm), + ndb_mgm_get_latest_error_msg(mgm)); + exit(-1); + } + else if(g_verbose) + { + fprintf(stderr, "Connected to %s:%d\n", + ndb_mgm_get_connected_host(mgm), + ndb_mgm_get_connected_port(mgm)); + } + + ndb_mgm_configuration * conf = ndb_mgm_get_configuration(mgm, 0); + if(conf == 0) + { + fprintf(stderr, "Could not get configuration"); + fprintf(stderr, "code: %d, msg: %s\n", + ndb_mgm_get_latest_error(mgm), + ndb_mgm_get_latest_error_msg(mgm)); + exit(-1); + } + else if(g_verbose) + { + fprintf(stderr, "Fetched configuration\n"); + } + + Vector<Apply*> select_list; + Vector<Match*> where_clause; + + if(strcmp(g_row_delimiter, "\\n") == 0) + g_row_delimiter = "\n"; + if(strcmp(g_field_delimiter, "\\n") == 0) + g_field_delimiter = "\n"; + + if(parse_query(select_list, argc, argv)) + { + exit(0); + } + + if(parse_where(where_clause, argc, argv)) + { + exit(0); + } + + Iter iter(* conf, CFG_SECTION_NODE); + bool prev= false; + iter.first(); + for(iter.first(); iter.valid(); iter.next()) + { + if(eval(mgm, iter, where_clause)) + { + if(prev) + printf("%s", g_row_delimiter); + prev= true; + apply(mgm, iter, select_list); + } + } + printf("\n"); + return 0; +} + +static +int +parse_query(Vector<Apply*>& select, int &argc, char**& argv) +{ + if(g_query) + { + BaseString q(g_query); + Vector<BaseString> list; + q.split(list, ","); + for(unsigned i = 0; i<list.size(); i++) + { + const char * str= list[i].c_str(); + if(strcasecmp(str, "id") == 0 || strcasecmp(str, "nodeid") == 0) + select.push_back(new Apply(CFG_NODE_ID)); + else if(strncasecmp(str, "host", 4) == 0) + select.push_back(new Apply(CFG_NODE_HOST)); + else if(strcasecmp(str, "type") == 0) + select.push_back(new NodeTypeApply()); + else if(g_nodes) + { + bool found = false; + for(int p = 0; p<ConfigInfo::m_NoOfParams; p++) + { + if(0)ndbout_c("%s %s", + ConfigInfo::m_ParamInfo[p]._section, + ConfigInfo::m_ParamInfo[p]._fname); + if(strcmp(ConfigInfo::m_ParamInfo[p]._section, "DB") == 0 || + strcmp(ConfigInfo::m_ParamInfo[p]._section, "API") == 0 || + strcmp(ConfigInfo::m_ParamInfo[p]._section, "MGM") == 0) + { + if(strcasecmp(ConfigInfo::m_ParamInfo[p]._fname, str) == 0) + { + select.push_back(new Apply(ConfigInfo::m_ParamInfo[p]._paramId)); + found = true; + break; + } + } + } + if(!found) + { + fprintf(stderr, "Unknown query option: %s\n", str); + return 1; + } + } + else + { + fprintf(stderr, "Unknown query option: %s\n", str); + return 1; + } + } + } + return 0; +} + +static +int +parse_where(Vector<Match*>& where, int &argc, char**& argv) +{ + Match m; + if(g_host) + { + m.m_key = CFG_NODE_HOST; + m.m_value.assfmt("%s", g_host); + where.push_back(new Match(m)); + } + + if(g_type) + { + m.m_key = CFG_TYPE_OF_SECTION; + m.m_value.assfmt("%d", ndb_mgm_match_node_type(g_type)); + where.push_back(new Match(m)); + } + + if(g_nodeid) + { + m.m_key = CFG_NODE_ID; + m.m_value.assfmt("%d", g_nodeid); + where.push_back(new Match(m)); + } + return 0; +} + +template class Vector<Apply*>; +template class Vector<Match*>; + +static +int +eval(NdbMgmHandle mgm, const Iter& iter, const Vector<Match*>& where) +{ + for(unsigned i = 0; i<where.size(); i++) + { + if(where[i]->eval(mgm, iter) == 0) + return 0; + } + + return 1; +} + +static +int +apply(NdbMgmHandle mgm, const Iter& iter, const Vector<Apply*>& list) +{ + for(unsigned i = 0; i<list.size(); i++) + { + list[i]->apply(mgm, iter); + if(i + 1 != list.size()) + printf("%s", g_field_delimiter); + } + return 0; +} + +int +Match::eval(NdbMgmHandle h, const Iter& iter) +{ + Uint32 val32; + Uint64 val64; + const char* valc; + if (iter.get(m_key, &val32) == 0) + { + if(atoi(m_value.c_str()) != val32) + return 0; + } + else if(iter.get(m_key, &val64) == 0) + { + if(atoll(m_value.c_str()) != val64) + return 0; + } + else if(iter.get(m_key, &valc) == 0) + { + if(strcmp(m_value.c_str(), valc) != 0) + return 0; + } + else + { + return 0; + } + return 1; +} + +int +Apply::apply(NdbMgmHandle h, const Iter& iter) +{ + Uint32 val32; + Uint64 val64; + const char* valc; + if (iter.get(m_key, &val32) == 0) + { + printf("%u", val32); + } + else if(iter.get(m_key, &val64) == 0) + { + printf("%llu", val64); + } + else if(iter.get(m_key, &valc) == 0) + { + printf("%s", valc); + } + return 0; +} + +int +NodeTypeApply::apply(NdbMgmHandle h, const Iter& iter) +{ + Uint32 val32; + if (iter.get(CFG_TYPE_OF_SECTION, &val32) == 0) + { + printf("%s", ndb_mgm_get_node_type_alias_string((ndb_mgm_node_type)val32, 0)); + } + return 0; +} diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 7614148ae3e..dd8f4fb505b 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -35,10 +35,13 @@ bin_SCRIPTS = @server_scripts@ \ mysqld_multi \ mysql_create_system_tables +noinst_SCRIPTS = make_binary_distribution \ + make_sharedlib_distribution \ + make_win_src_distribution + EXTRA_SCRIPTS = make_binary_distribution.sh \ make_sharedlib_distribution.sh \ make_win_src_distribution.sh \ - make_win_binary_distribution.sh \ msql2mysql.sh \ mysql_config.sh \ mysql_fix_privilege_tables.sh \ @@ -147,5 +150,3 @@ SUFFIXES = .sh # Don't update the files from bitkeeper %::SCCS/s.% - -all: make_win_src_distribution make_binary_distribution make_sharedlib_distribution diff --git a/scripts/make_win_binary_distribution.sh b/scripts/make_win_binary_distribution.sh deleted file mode 100644 index c611454450c..00000000000 --- a/scripts/make_win_binary_distribution.sh +++ /dev/null @@ -1,185 +0,0 @@ -#!/bin/sh - -# -# Script to create a Windows binary package -# -# This is intended to be used under Cygwin, and will generate -# an archive named in the form mysql<suffix>-<version>-noinstall.zip - -version=@VERSION@ - -DEBUG=0 -SUFFIX="" -DIRNAME="" -EXTRA="" - -# -# This script must run from MySQL top directory -# - -if [ ! -f scripts/make_win_binary_distribution ]; then - echo "ERROR : You must run this script from the MySQL top-level directory" - exit 1 -fi - -# -# Debug print of the status -# - -print_debug() -{ - for statement - do - if [ "$DEBUG" = "1" ] ; then - echo $statement - fi - done -} - -# -# Usage of the script -# - -show_usage() -{ - echo "MySQL utility script to create a Windows binary package" - echo "" - echo "This is intended to be used under Cygwin, and will generate" - echo "an archive named in the form mysql<suffix>-<version>-noinstall.zip" - echo "Takes the following arguments:" - echo "" - echo " --dirname Directory to use for copying files" - echo " --extra Directory to get extra files from" - echo " --suffix Name to append to 'mysql' for this binary" - echo " --help Show this help message" - exit 0 -} - -# -# Parse the input arguments -# - -parse_arguments() { - for arg do - case "$arg" in - --debug) DEBUG=1;; - --extra=*) EXTRA=`echo "$arg" | sed -e "s;--extra=;;"` ;; - --suffix=*) SUFFIX=`echo "$arg" | sed -e "s;--suffix=;;"` ;; - --dirname=*) DIRNAME=`echo "$arg" | sed -e "s;--dirname=;;"` ;; - --help) show_usage ;; - *) - echo "Unknown argument '$arg'" - exit 1 - ;; - esac - done -} - -parse_arguments "$@" - -if [ -z "$DIRNAME" ]; then - $DIRNAME="dist" -fi - -print_debug "Making directories" -mkdir $DIRNAME -$DIRNAME="$DIRNAME/mysql-$version" -mkdir $DIRNAME - -for dir in bin lib lib/opt lib/debug Embedded Embedded/DLL Embedded/DLL/debug Embedded/DLL/release Embedded/static Embedded/static/release examples examples/libmysqltest -do - mkdir $DIRNAME/$dir -done - -if [ $EXTRA ]; then - print_debug "Copying extra files" - cp -fr $EXTRA/* $DIRNAME -fi - -# Dirs to be copied as-is -for dir in data Docs include scripts share -do - print_debug "Copying $dir to $DIRNAME/" - cp -fr $dir $DIRNAME -done - -print_debug "Copying tests to $DIRNAME/examples/" -cp -fr tests $DIRNAME/examples - -print_debug "Copying sql-bench to $DIRNAME/bench" -mkdir $DIRNAME/bench -cp -fr sql-bench/* $DIRNAME/bench - -print_debug "Copying mysql-test to $DIRNAME/mysql-test" -mkdir $DIRNAME/mysql-test -cp -fr mysql-test/* $DIRNAME/mysql-test - -print_debug "Copying support-files to $DIRNAME" -cp support-files/* $DIRNAME - -# Files for bin -for i in client_release/* client_debug/mysqld.exe lib_release/libmySQL.dll -do - print_debug "Copying $i to $DIRNAME/bin" - cp $i $DIRNAME/bin -done - -# Files for include -for i in libmysql/libmysql.def libmysqld/libmysqld.def -do - print_debug "Copying $i to $DIRNAME/include" - cp $i $DIRNAME/include -done - -# Windows users are used to having dbug.h ? -cp include/my_dbug.h $DIRNAME/include/dbug.h - -# Libraries found in lib_release and lib_debug -for i in libmySQL.dll libmysql.lib zlib.lib mysqlclient.lib mysys.lib regex.lib strings.lib -do - print_debug "Copying lib_release/$i to $DIRNAME/lib/opt" - cp lib_release/$i $DIRNAME/lib/opt - print_debug "Copying lib_debug/$i to $DIRNAME/lib/debug" - cp lib_debug/$i $DIRNAME/lib/debug -done - -print_debug "Copying lib_release/mysys-max.lib to $DIRNAME/lib/opt" -cp lib_release/mysys-max.lib $DIRNAME/lib/opt - -# Embedded server -for i in libmysqld.dll libmysqld.lib libmysqld.exp -do - print_debug "Copying lib_release/$i to $DIRNAME/Embedded/DLL/release" - cp lib_release/$i $DIRNAME/Embedded/DLL/release - print_debug "Copying lib_debug/$i to $DIRNAME/Embedded/DLL/debug" - cp lib_debug/$i $DIRNAME/Embedded/DLL/debug -done - -# Static embedded -print_debug "Copying lib_release/mysqlserver.lib to $DIRNAME/Embedded/static/release" -cp lib_release/mysqlserver.lib $DIRNAME/Embedded/static/release - -# libmysqltest -for i in mytest.c mytest.dsp mytest.dsw mytest.exe -do - print_debug "Copying libmysqltest/release/$i to $DIRNAME/examples/libmysqltest" - cp libmysqltest/release/$i $DIRNAME/examples/libmysqltest -done - -print_debug "Copying README.txt" -cp README.txt $DIRNAME - -if [ -f MySQLEULA.txt ]; then - print_debug "Commercial version: copying MySQLEULA.txt" - cp MySQLEULA.txt $DIRNAME - rm $DIRNAME/Docs/COPYING -else - print_debug "GPL version: copying COPYING" - cp Docs/COPYING $DIRNAME -fi - -print_debug "Invoking zip to package the binary" -zip -r mysql$SUFFIX-$version-win-noinstall.zip $DIRNAME - -print_debug "Deleting intermediate directory" -rm -rf $DIRNAME diff --git a/sql/item.cc b/sql/item.cc index 71940c824e7..84dbc382a52 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -523,6 +523,170 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags) return 0; } +/******************************/ +static +void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) +{ + my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), + c1.collation->name,c1.derivation_name(), + c2.collation->name,c2.derivation_name(), + fname); +} + + +static +void my_coll_agg_error(DTCollation &c1, DTCollation &c2, DTCollation &c3, + const char *fname) +{ + my_error(ER_CANT_AGGREGATE_3COLLATIONS,MYF(0), + c1.collation->name,c1.derivation_name(), + c2.collation->name,c2.derivation_name(), + c3.collation->name,c3.derivation_name(), + fname); +} + + +static +void my_coll_agg_error(Item** args, uint count, const char *fname) +{ + if (count == 2) + my_coll_agg_error(args[0]->collation, args[1]->collation, fname); + else if (count == 3) + my_coll_agg_error(args[0]->collation, args[1]->collation, + args[2]->collation, fname); + else + my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),fname); +} + + +bool agg_item_collations(DTCollation &c, const char *fname, + Item **av, uint count, uint flags) +{ + uint i; + c.set(av[0]->collation); + for (i= 1; i < count; i++) + { + if (c.aggregate(av[i]->collation, flags)) + { + my_coll_agg_error(av, count, fname); + return TRUE; + } + } + if ((flags & MY_COLL_DISALLOW_NONE) && + c.derivation == DERIVATION_NONE) + { + my_coll_agg_error(av, count, fname); + return TRUE; + } + return FALSE; +} + + +bool agg_item_collations_for_comparison(DTCollation &c, const char *fname, + Item **av, uint count, uint flags) +{ + return (agg_item_collations(c, fname, av, count, + flags | MY_COLL_DISALLOW_NONE)); +} + + +/* + Collect arguments' character sets together. + We allow to apply automatic character set conversion in some cases. + The conditions when conversion is possible are: + - arguments A and B have different charsets + - A wins according to coercibility rules + (i.e. a column is stronger than a string constant, + an explicit COLLATE clause is stronger than a column) + - character set of A is either superset for character set of B, + or B is a string constant which can be converted into the + character set of A without data loss. + + If all of the above is true, then it's possible to convert + B into the character set of A, and then compare according + to the collation of A. + + For functions with more than two arguments: + + collect(A,B,C) ::= collect(collect(A,B),C) +*/ + +bool agg_item_charsets(DTCollation &coll, const char *fname, + Item **args, uint nargs, uint flags) +{ + Item **arg, **last, *safe_args[2]; + if (agg_item_collations(coll, fname, args, nargs, flags)) + return TRUE; + + /* + For better error reporting: save the first and the second argument. + We need this only if the the number of args is 3 or 2: + - for a longer argument list, "Illegal mix of collations" + doesn't display each argument's characteristics. + - if nargs is 1, then this error cannot happen. + */ + if (nargs >=2 && nargs <= 3) + { + safe_args[0]= args[0]; + safe_args[1]= args[1]; + } + + THD *thd= current_thd; + Item_arena *arena, backup; + bool res= FALSE; + /* + In case we're in statement prepare, create conversion item + in its memory: it will be reused on each execute. + */ + arena= thd->change_arena_if_needed(&backup); + + for (arg= args, last= args + nargs; arg < last; arg++) + { + Item* conv; + uint32 dummy_offset; + if (!String::needs_conversion(0, coll.collation, + (*arg)->collation.collation, + &dummy_offset)) + continue; + + if (!(conv= (*arg)->safe_charset_converter(coll.collation))) + { + if (nargs >=2 && nargs <= 3) + { + /* restore the original arguments for better error message */ + args[0]= safe_args[0]; + args[1]= safe_args[1]; + } + my_coll_agg_error(args, nargs, fname); + res= TRUE; + break; // we cannot return here, we need to restore "arena". + } + conv->fix_fields(thd, 0, &conv); + /* + If in statement prepare, then we create a converter for two + constant items, do it once and then reuse it. + If we're in execution of a prepared statement, arena is NULL, + and the conv was created in runtime memory. This can be + the case only if the argument is a parameter marker ('?'), + because for all true constants the charset converter has already + been created in prepare. In this case register the change for + rollback. + */ + if (arena) + *arg= conv; + else + thd->change_item_tree(arg, conv); + } + if (arena) + thd->restore_backup_item_arena(arena, &backup); + return res; +} + + + + +/**********************************************/ + Item_field::Item_field(Field *f) :Item_ident(NullS, f->table_name, f->field_name) { diff --git a/sql/item.h b/sql/item.h index 895463ceeca..825b37fe64c 100644 --- a/sql/item.h +++ b/sql/item.h @@ -330,6 +330,15 @@ public: }; +bool agg_item_collations(DTCollation &c, const char *name, + Item **items, uint nitems, uint flags= 0); +bool agg_item_collations_for_comparison(DTCollation &c, const char *name, + Item **items, uint nitems, + uint flags= 0); +bool agg_item_charsets(DTCollation &c, const char *name, + Item **items, uint nitems, uint flags= 0); + + class Item_num: public Item { public: diff --git a/sql/item_func.cc b/sql/item_func.cc index 44917eb48e4..2514a4beacf 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -39,73 +39,6 @@ bool check_reserved_words(LEX_STRING *name) } -static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, - const char *fname) -{ - my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), - c1.collation->name,c1.derivation_name(), - c2.collation->name,c2.derivation_name(), - fname); -} - -static void my_coll_agg_error(DTCollation &c1, - DTCollation &c2, - DTCollation &c3, - const char *fname) -{ - my_error(ER_CANT_AGGREGATE_3COLLATIONS,MYF(0), - c1.collation->name,c1.derivation_name(), - c2.collation->name,c2.derivation_name(), - c3.collation->name,c3.derivation_name(), - fname); -} - - -static void my_coll_agg_error(Item** args, uint count, const char *fname) -{ - if (count == 2) - my_coll_agg_error(args[0]->collation, args[1]->collation, fname); - else if (count == 3) - my_coll_agg_error(args[0]->collation, - args[1]->collation, - args[2]->collation, - fname); - else - my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),fname); -} - - -bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint count, - uint flags) -{ - uint i; - c.set(av[0]->collation); - for (i= 1; i < count; i++) - { - if (c.aggregate(av[i]->collation, flags)) - { - my_coll_agg_error(av, count, func_name()); - return TRUE; - } - } - if ((flags & MY_COLL_DISALLOW_NONE) && - c.derivation == DERIVATION_NONE) - { - my_coll_agg_error(av, count, func_name()); - return TRUE; - } - return FALSE; -} - - -bool Item_func::agg_arg_collations_for_comparison(DTCollation &c, - Item **av, uint count, - uint flags) -{ - return (agg_arg_collations(c, av, count, flags | MY_COLL_DISALLOW_NONE)); -} - - /* return TRUE if item is a constant */ bool @@ -115,101 +48,6 @@ eval_const_cond(COND *cond) } - -/* - Collect arguments' character sets together. - We allow to apply automatic character set conversion in some cases. - The conditions when conversion is possible are: - - arguments A and B have different charsets - - A wins according to coercibility rules - (i.e. a column is stronger than a string constant, - an explicit COLLATE clause is stronger than a column) - - character set of A is either superset for character set of B, - or B is a string constant which can be converted into the - character set of A without data loss. - - If all of the above is true, then it's possible to convert - B into the character set of A, and then compare according - to the collation of A. - - For functions with more than two arguments: - - collect(A,B,C) ::= collect(collect(A,B),C) -*/ - -bool Item_func::agg_arg_charsets(DTCollation &coll, - Item **args, uint nargs, uint flags) -{ - Item **arg, **last, *safe_args[2]; - if (agg_arg_collations(coll, args, nargs, flags)) - return TRUE; - - /* - For better error reporting: save the first and the second argument. - We need this only if the the number of args is 3 or 2: - - for a longer argument list, "Illegal mix of collations" - doesn't display each argument's characteristics. - - if nargs is 1, then this error cannot happen. - */ - if (nargs >=2 && nargs <= 3) - { - safe_args[0]= args[0]; - safe_args[1]= args[1]; - } - - THD *thd= current_thd; - Item_arena *arena, backup; - bool res= FALSE; - /* - In case we're in statement prepare, create conversion item - in its memory: it will be reused on each execute. - */ - arena= thd->change_arena_if_needed(&backup); - - for (arg= args, last= args + nargs; arg < last; arg++) - { - Item* conv; - uint32 dummy_offset; - if (!String::needs_conversion(0, coll.collation, - (*arg)->collation.collation, - &dummy_offset)) - continue; - - if (!(conv= (*arg)->safe_charset_converter(coll.collation))) - { - if (nargs >=2 && nargs <= 3) - { - /* restore the original arguments for better error message */ - args[0]= safe_args[0]; - args[1]= safe_args[1]; - } - my_coll_agg_error(args, nargs, func_name()); - res= TRUE; - break; // we cannot return here, we need to restore "arena". - } - conv->fix_fields(thd, 0, &conv); - /* - If in statement prepare, then we create a converter for two - constant items, do it once and then reuse it. - If we're in execution of a prepared statement, arena is NULL, - and the conv was created in runtime memory. This can be - the case only if the argument is a parameter marker ('?'), - because for all true constants the charset converter has already - been created in prepare. In this case register the change for - rollback. - */ - if (arena) - *arg= conv; - else - thd->change_item_tree(arg, conv); - } - if (arena) - thd->restore_backup_item_arena(arena, &backup); - return res; -} - - - void Item_func::set_arguments(List<Item> &list) { allowed_arg_cols= 1; diff --git a/sql/item_func.h b/sql/item_func.h index 5e36f9863bb..5d6cc445317 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -145,12 +145,22 @@ public: Item *get_tmp_table_item(THD *thd); bool agg_arg_collations(DTCollation &c, Item **items, uint nitems, - uint flags= 0); + uint flags= 0) + { + return agg_item_collations(c, func_name(), items, nitems, flags); + } bool agg_arg_collations_for_comparison(DTCollation &c, Item **items, uint nitems, - uint flags= 0); + uint flags= 0) + { + return agg_item_collations_for_comparison(c, func_name(), + items, nitems, flags); + } bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems, - uint flags= 0); + uint flags= 0) + { + return agg_item_charsets(c, func_name(), items, nitems, flags); + } bool walk(Item_processor processor, byte *arg); }; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 0e252259f53..6ca3f024f61 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1925,6 +1925,10 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) maybe_null|= args[i]->maybe_null; } + if (agg_item_charsets(collation, func_name(), + args, arg_count, MY_COLL_ALLOW_CONV)) + return 1; + result_field= 0; null_value= 1; max_length= group_concat_max_len; diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index ff4ce6fdb51..b467c8c5ba3 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6309,7 +6309,7 @@ uint my_well_formed_len_big5(CHARSET_INFO *cs __attribute__((unused)), break; } } - return b - b0; + return (uint) (b - b0); } diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c index c77ce858dff..be3526519cb 100644 --- a/strings/ctype-cp932.c +++ b/strings/ctype-cp932.c @@ -213,7 +213,7 @@ static int my_strnncoll_cp932_internal(CHARSET_INFO *cs, uint a_char= cp932code(*a, *(a+1)); uint b_char= cp932code(*b, *(b+1)); if (a_char != b_char) - return a_char - b_char; + return (int) a_char - (int) b_char; a += 2; b += 2; } else @@ -5449,7 +5449,7 @@ uint my_well_formed_len_cp932(CHARSET_INFO *cs __attribute__((unused)), break; } } - return b - b0; + return (uint) (b - b0); } diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index 6fb072d266d..7196d004ad5 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -9956,7 +9956,7 @@ uint my_well_formed_len_gbk(CHARSET_INFO *cs __attribute__((unused)), break; } } - return b - b0; + return (uint) (b - b0); } diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index cbbd035c631..4b22f158284 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -260,7 +260,7 @@ uint my_charpos_mb(CHARSET_INFO *cs __attribute__((unused)), pos+= (mblen= my_ismbchar(cs, pos, end)) ? mblen : 1; length--; } - return length ? end+2-start : pos-start; + return length ? (uint) (end + 2 - start) : (uint) (pos - start); } @@ -282,7 +282,7 @@ uint my_well_formed_len_mb(CHARSET_INFO *cs, const char *b, const char *e, b+= mblen; pos--; } - return b - b_start; + return (uint) (b - b_start); } diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 9e3a328ec26..af673b78254 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -1051,7 +1051,7 @@ ulong my_scan_8bit(CHARSET_INFO *cs, const char *str, const char *end, int sq) if (*str == '.') { for(str++ ; str != end && *str == '0' ; str++); - return str-str0; + return (ulong) (str - str0); } return 0; @@ -1061,7 +1061,7 @@ ulong my_scan_8bit(CHARSET_INFO *cs, const char *str, const char *end, int sq) if (!my_isspace(cs,*str)) break; } - return str-str0; + return (ulong) (str - str0); default: return 0; } @@ -1078,14 +1078,14 @@ void my_fill_8bit(CHARSET_INFO *cs __attribute__((unused)), uint my_numchars_8bit(CHARSET_INFO *cs __attribute__((unused)), const char *b, const char *e) { - return e-b; + return (uint) (e - b); } uint my_numcells_8bit(CHARSET_INFO *cs __attribute__((unused)), const char *b, const char *e) { - return e-b; + return (uint) (e - b); } diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 7f34ee3fa2d..900acefd4ea 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -213,7 +213,7 @@ static int my_strnncoll_sjis_internal(CHARSET_INFO *cs, uint a_char= sjiscode(*a, *(a+1)); uint b_char= sjiscode(*b, *(b+1)); if (a_char != b_char) - return a_char - b_char; + return (int) a_char - (int) b_char; a += 2; b += 2; } else @@ -4605,7 +4605,7 @@ uint my_well_formed_len_sjis(CHARSET_INFO *cs __attribute__((unused)), break; } } - return b - b0; + return (uint) (b - b0); } diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index c3caaeadfb3..025fdd5a7f6 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -215,7 +215,7 @@ static int my_strnncoll_ucs2(CHARSET_INFO *cs, s+=s_res; t+=t_res; } - return t_is_prefix ? t-te : ((se-s) - (te-t)); + return t_is_prefix ? (int) (t - te) : (int) ((se - s) - (te - t)); } /* @@ -326,7 +326,7 @@ static int my_strncasecmp_ucs2(CHARSET_INFO *cs, s+=s_res; t+=t_res; } - return ( (se-s) - (te-t) ); + return (int) ( (se-s) - (te-t) ); } @@ -1349,7 +1349,7 @@ int my_strnncoll_ucs2_bin(CHARSET_INFO *cs, s+=s_res; t+=t_res; } - return t_is_prefix ? t-te : ((se-s) - (te-t)); + return t_is_prefix ? (int) (t - te) : (int) ((se-s) - (te-t)); } static int my_strnncollsp_ucs2_bin(CHARSET_INFO *cs, @@ -1494,7 +1494,7 @@ ulong my_scan_ucs2(CHARSET_INFO *cs __attribute__((unused)), if (str[0] != '\0' || str[1] != ' ') break; } - return str - str0; + return (ulong) (str - str0); default: return 0; } diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index 612dda2b3eb..f20e2756810 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8270,7 +8270,7 @@ uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)), if (b >= (uchar *) end) /* need more bytes */ { *error= 1; - return chbeg - beg; /* unexpected EOL */ + return (uint) (chbeg - beg); /* unexpected EOL */ } if (ch == 0x8E) /* [x8E][xA0-xDF] */ @@ -8278,7 +8278,7 @@ uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)), if (*b >= 0xA0 && *b <= 0xDF) continue; *error= 1; - return chbeg - beg; /* invalid sequence */ + return (uint) (chbeg - beg); /* invalid sequence */ } if (ch == 0x8F) /* [x8F][xA1-xFE][xA1-xFE] */ @@ -8287,7 +8287,7 @@ uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)), if (b >= (uchar*) end) { *error= 1; - return chbeg - beg; /* unexpected EOL */ + return (uint) (chbeg - beg);/* unexpected EOL */ } } @@ -8295,9 +8295,9 @@ uint my_well_formed_len_ujis(CHARSET_INFO *cs __attribute__((unused)), *b >= 0xA1 && *b <= 0xFE) /* [xA1-xFE][xA1-xFE] */ continue; *error= 1; - return chbeg - beg; /* invalid sequence */ + return (uint) (chbeg - beg); /* invalid sequence */ } - return b - (uchar *) beg; + return (uint) (b - (uchar *) beg); } diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 205701e87c7..0bf57967630 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2008,7 +2008,7 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs, s+=s_res; t+=t_res; } - return t_is_prefix ? t-te : ((se-s) - (te-t)); + return t_is_prefix ? (int) (t-te) : (int) ((se-s) - (te-t)); } |