diff options
author | igor@rurik.mysql.com <> | 2006-07-14 14:45:23 -0700 |
---|---|---|
committer | igor@rurik.mysql.com <> | 2006-07-14 14:45:23 -0700 |
commit | 6e75a11b0121f50f61cf77a7df78e557f65c37bd (patch) | |
tree | a475d8d28c7331408aa0ed735d377f2be7051407 | |
parent | ce57588434a8b1a5775201c69c05fb382e9d8399 (diff) | |
parent | 10b2590c0b8a0d766f1b15330f3d9681aa41f9aa (diff) | |
download | mariadb-git-6e75a11b0121f50f61cf77a7df78e557f65c37bd.tar.gz |
Merge ibabaev@bk-internal.mysql.com:/home/bk/mysql-5.0-opt
into rurik.mysql.com:/home/igor/mysql-5.0-opt
211 files changed, 5806 insertions, 7397 deletions
diff --git a/.bzrignore b/.bzrignore index ef02a085144..68e8120fae0 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1,3 +1,5 @@ +*.Plo +*.Po *.a *.bb *.bbg @@ -9,6 +11,7 @@ *.gcov *.idb *.la +*.lai *.lib *.lo *.map @@ -20,6 +23,7 @@ *.res *.sbr *.so +*.so.* *.spec */*_pure_*warnings */.pure @@ -48,6 +52,7 @@ 50 =6 BUILD/compile-pentium-maintainer +BitKeeper/etc/RESYNC_TREE BitKeeper/etc/config BitKeeper/etc/csets BitKeeper/etc/csets-in @@ -279,6 +284,7 @@ build_tags.sh client/#mysql.cc# client/*.ds? client/*.vcproj +client/.libs -prune client/completion_hash.cpp client/decimal.c client/insert_test @@ -558,6 +564,7 @@ libmysqld/sql_insert.cc libmysqld/sql_lex.cc libmysqld/sql_list.cc libmysqld/sql_load.cc +libmysqld/sql_locale.cc libmysqld/sql_manager.cc libmysqld/sql_map.cc libmysqld/sql_olap.cc @@ -669,6 +676,7 @@ mysql-test/mysql-test-run.log mysql-test/mysql_test_run_new mysql-test/ndb/ndbcluster mysql-test/r/*.err +mysql-test/r/*.log mysql-test/r/*.out mysql-test/r/*.reject mysql-test/r/alter_table.err @@ -1061,6 +1069,7 @@ scripts/mysql_secure_installation scripts/mysql_setpermission scripts/mysql_tableinfo scripts/mysql_upgrade +scripts/mysql_upgrade_shell scripts/mysql_zap scripts/mysqlaccess scripts/mysqlbug @@ -1262,6 +1271,7 @@ test1/* test_xml tests/*.ds? tests/*.vcproj +tests/.libs -prune tests/client_test tests/connect_test tests/mysql_client_test @@ -1269,6 +1279,7 @@ thr_insert_test/* thr_test/* thread_test tmp/* +tools/.libs -prune tools/my_vsnprintf.c tools/mysqlmanager tools/mysqlmngd @@ -1285,4 +1296,3 @@ vio/viotest-sslconnect.cpp vio/viotest.cpp zlib/*.ds? zlib/*.vcproj -BitKeeper/etc/RESYNC_TREE diff --git a/VC++Files/libmysqld/libmysqld.dsp b/VC++Files/libmysqld/libmysqld.dsp index 8c1a5271656..32c0aac5e54 100644 --- a/VC++Files/libmysqld/libmysqld.dsp +++ b/VC++Files/libmysqld/libmysqld.dsp @@ -623,6 +623,10 @@ SOURCE=..\sql\time.cpp SOURCE=..\sql\tztime.cpp # End Source File # Begin Source File +# +SOURCE=..\sql\sql_locale.cpp +# End Source File +# Begin Source File SOURCE=..\sql\uniques.cpp
# End Source File
diff --git a/VC++Files/libmysqld/libmysqld.vcproj b/VC++Files/libmysqld/libmysqld.vcproj index fe791d702a3..52b4d4c4eba 100644 --- a/VC++Files/libmysqld/libmysqld.vcproj +++ b/VC++Files/libmysqld/libmysqld.vcproj @@ -4314,6 +4314,42 @@ </FileConfiguration> </File> <File + RelativePath="..\sql\sql_locale.cpp"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__;$(NoInherit)" + BasicRuntimeChecks="3"/> + </FileConfiguration> + <FileConfiguration + Name="pro|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + AdditionalIncludeDirectories="" + PreprocessorDefinitions="WIN32;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;EMBEDDED_LIBRARY;USE_TLS;__WIN__;MYSQL_SERVER;LICENSE=Commercial;_MBCS;HAVE_DLOPEN;HAVE_INNOBASE_DB;DBUG_OFF;NDEBUG;_WINDOWS;_CONSOLE;$(NoInherit)"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + AdditionalIncludeDirectories="" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;DBUG_OFF;USE_TLS;__WIN__;$(NoInherit)"/> + </FileConfiguration> + <FileConfiguration + Name="classic|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + AdditionalIncludeDirectories="" + PreprocessorDefinitions="WIN32;_WINDOWS;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;USE_TLS;__WIN__;LICENSE=Commercial;DBUG_OFF;_MBCS;NDEBUG;$(NoInherit)"/> + </FileConfiguration> + </File> + <File RelativePath="..\sql\uniques.cpp"> <FileConfiguration Name="Debug|Win32"> diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index d44e61d8399..68197a5168b 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -2023,6 +2023,10 @@ SOURCE=.\tztime.cpp # End Source File # Begin Source File +SOURCE=.\sql_locale.cpp +# End Source File +# Begin Source File + SOURCE=.\uniques.cpp # End Source File # Begin Source File diff --git a/VC++Files/sql/mysqld.vcproj b/VC++Files/sql/mysqld.vcproj index c9675f3fd8a..d8cf5cedb2a 100644 --- a/VC++Files/sql/mysqld.vcproj +++ b/VC++Files/sql/mysqld.vcproj @@ -85,7 +85,7 @@ InlineFunctionExpansion="1" OptimizeForProcessor="2" AdditionalIncludeDirectories="../bdb/build_win32,../include,../regex,../extra/yassl/include,../zlib" - PreprocessorDefinitions="__NT__;NDEBUG;DBUG_OFF;USE_SYMDIR;HAVE_INNOBASE_DB;HAVE_BERKELEY_DB;HAVE_ARCHIVE_DB;HAVE_BLACKHOLE_DB;HAVE_EXAMPLE_DB;HAVE_FEDERATED_DB;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN" + PreprocessorDefinitions="USE_SYMDIR;NDEBUG;DBUG_OFF;HAVE_INNOBASE_DB;HAVE_BERKELEY_DB;HAVE_ARCHIVE_DB;HAVE_BLACKHOLE_DB;HAVE_EXAMPLE_DB;HAVE_FEDERATED_DB;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN" StringPooling="TRUE" RuntimeLibrary="0" EnableFunctionLevelLinking="TRUE" @@ -145,7 +145,7 @@ InlineFunctionExpansion="1" OptimizeForProcessor="2" AdditionalIncludeDirectories="../bdb/build_win32,../include,../regex,../extra/yassl/include,../zlib" - PreprocessorDefinitions="NDEBUG;__NT__;DBUG_OFF;HAVE_INNOBASE_DB;HAVE_BERKELEY_DB;HAVE_ARCHIVE_DB;HAVE_BLACKHOLE_DB;HAVE_EXAMPLE_DB;HAVE_FEDERATED_DB;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN" + PreprocessorDefinitions="__NT__;NDEBUG;DBUG_OFF;HAVE_INNOBASE_DB;HAVE_BERKELEY_DB;HAVE_ARCHIVE_DB;HAVE_BLACKHOLE_DB;HAVE_EXAMPLE_DB;HAVE_FEDERATED_DB;MYSQL_SERVER;_WINDOWS;_CONSOLE;HAVE_DLOPEN" StringPooling="TRUE" RuntimeLibrary="0" EnableFunctionLevelLinking="TRUE" @@ -8571,6 +8571,81 @@ </FileConfiguration> </File> <File + RelativePath="sql_locale.cpp"> + <FileConfiguration + Name="classic nt|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + AdditionalIncludeDirectories="" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="Max|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + AdditionalIncludeDirectories="" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="Max nt|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + AdditionalIncludeDirectories="" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="nt|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + AdditionalIncludeDirectories="" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="pro nt|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + AdditionalIncludeDirectories="" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="pro|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + AdditionalIncludeDirectories="" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="classic|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + AdditionalIncludeDirectories="" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + AdditionalIncludeDirectories="" + PreprocessorDefinitions=""/> + </FileConfiguration> + </File> + <File RelativePath="uniques.cpp"> <FileConfiguration Name="classic nt|Win32"> diff --git a/configure.in b/configure.in index 48454a11309..192b35f56d8 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.24) +AM_INIT_AUTOMAKE(mysql, 5.0.25) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -19,7 +19,7 @@ SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=24 +NDB_VERSION_BUILD=25 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? @@ -382,18 +382,18 @@ fi AC_SUBST(LD_VERSION_SCRIPT) # Avoid bug in fcntl on some versions of linux -AC_MSG_CHECKING("if we should use 'skip-locking' as default for $target_os") +AC_MSG_CHECKING([if we should use 'skip-external-locking' as default for $target_os]) # Any variation of Linux if expr "$target_os" : "[[Ll]]inux.*" > /dev/null then - MYSQLD_DEFAULT_SWITCHES="--skip-locking" + MYSQLD_DEFAULT_SWITCHES="--skip-external-locking" TARGET_LINUX="true" - AC_MSG_RESULT("yes") + AC_MSG_RESULT([yes]) AC_DEFINE([TARGET_OS_LINUX], [1], [Whether we build for Linux]) else MYSQLD_DEFAULT_SWITCHES="" TARGET_LINUX="false" - AC_MSG_RESULT("no") + AC_MSG_RESULT([no]) fi AC_SUBST(MYSQLD_DEFAULT_SWITCHES) AC_SUBST(TARGET_LINUX) diff --git a/heap/hp_test1.c b/heap/hp_test1.c index dd696528eb8..703b39b1e2d 100644 --- a/heap/hp_test1.c +++ b/heap/hp_test1.c @@ -44,6 +44,7 @@ int main(int argc, char **argv) get_options(argc,argv); bzero(&hp_create_info, sizeof(hp_create_info)); + hp_create_info.max_table_size= 1024L*1024L; keyinfo[0].keysegs=1; keyinfo[0].seg=keyseg; @@ -58,7 +59,7 @@ int main(int argc, char **argv) bzero((gptr) flags,sizeof(flags)); printf("- Creating heap-file\n"); - if (heap_create(filename,1,keyinfo,30,(ulong) flag*100000l,10l, + if (heap_create(filename,1,keyinfo,30,(ulong) flag*100000L,10L, &hp_create_info) || !(file= heap_open(filename, 2))) goto err; diff --git a/heap/hp_test2.c b/heap/hp_test2.c index 2de49bcb66b..ff07b402f4d 100644 --- a/heap/hp_test2.c +++ b/heap/hp_test2.c @@ -74,6 +74,7 @@ int main(int argc, char *argv[]) get_options(argc,argv); bzero(&hp_create_info, sizeof(hp_create_info)); + hp_create_info.max_table_size= 1024L*1024L; write_count=update=opt_delete=0; key_check=0; diff --git a/include/my_base.h b/include/my_base.h index 076eed9998f..05ba38e77eb 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -152,7 +152,16 @@ enum ha_extra_function { other fields intact. When this is off (by default) InnoDB will use memcpy to overwrite entire row. */ - HA_EXTRA_KEYREAD_PRESERVE_FIELDS + HA_EXTRA_KEYREAD_PRESERVE_FIELDS, + /* + Informs handler that write_row() which tries to insert new row into the + table and encounters some already existing row with same primary/unique + key can replace old row with new row instead of reporting error (basically + it informs handler that we do REPLACE instead of simple INSERT). + Off by default. + */ + HA_EXTRA_WRITE_CAN_REPLACE, + HA_EXTRA_WRITE_CANNOT_REPLACE }; /* The following is parameter to ha_panic() */ diff --git a/include/my_global.h b/include/my_global.h index c9f27e0031e..909755aef87 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -1071,8 +1071,8 @@ do { doubleget_union _tmp; \ #define doublestore(T,V) do { *((long *) T) = ((doubleget_union *)&V)->m[0]; \ *(((long *) T)+1) = ((doubleget_union *)&V)->m[1]; \ } while (0) -#define float4get(V,M) do { *((long *) &(V)) = *((long*) (M)); } while(0) -#define float8get(V,M) doubleget((V),(M)) +#define float4get(V,M) do { *((float *) &(V)) = *((float*) (M)); } while(0) +#define float8get(V,M) doubleget((V),(M)) #define float4store(V,M) memcpy((byte*) V,(byte*) (&M),sizeof(float)) #define floatstore(T,V) memcpy((byte*)(T), (byte*)(&V),sizeof(float)) #define floatget(V,M) memcpy((byte*) &V,(byte*) (M),sizeof(float)) diff --git a/include/my_handler.h b/include/my_handler.h index d531e0fb3e1..61665090853 100644 --- a/include/my_handler.h +++ b/include/my_handler.h @@ -18,7 +18,6 @@ #ifndef _my_handler_h #define _my_handler_h -#include "my_global.h" #include "my_base.h" #include "m_ctype.h" #include "myisampack.h" diff --git a/include/my_sys.h b/include/my_sys.h index b00b59c4779..9b283ace029 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -597,7 +597,7 @@ extern gptr _my_memdup(const byte *from,uint length, const char *sFile, uint uLine,myf MyFlag); extern my_string _my_strdup(const char *from, const char *sFile, uint uLine, myf MyFlag); -extern char *_my_strdup_with_length(const byte *from, uint length, +extern char *_my_strdup_with_length(const char *from, uint length, const char *sFile, uint uLine, myf MyFlag); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index c1e0703af10..a851d62b108 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2391,10 +2391,9 @@ static void net_store_datetime(NET *net, MYSQL_TIME *tm) static void store_param_date(NET *net, MYSQL_BIND *param) { - MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer; - tm->hour= tm->minute= tm->second= 0; - tm->second_part= 0; - net_store_datetime(net, tm); + MYSQL_TIME tm= *((MYSQL_TIME *) param->buffer); + tm.hour= tm.minute= tm.second= tm.second_part= 0; + net_store_datetime(net, &tm); } static void store_param_datetime(NET *net, MYSQL_BIND *param) diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 54eb27be037..89b473fb815 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -51,7 +51,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \ key.cc lock.cc log.cc log_event.cc sql_state.c \ protocol.cc net_serv.cc opt_range.cc \ opt_sum.cc procedure.cc records.cc sql_acl.cc \ - sql_load.cc discover.cc \ + sql_load.cc discover.cc sql_locale.cc \ sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \ sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \ sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc sql_parse.cc \ diff --git a/myisam/mi_check.c b/myisam/mi_check.c index e0f04965650..a3195ebce7f 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -1158,13 +1158,14 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) #ifdef HAVE_RTREE_KEYS (keyinfo->flag & HA_SPATIAL) ? rtree_find_first(info, key, info->lastkey, key_length, - SEARCH_SAME) : + MBR_EQUAL | MBR_DATA) : #endif _mi_search(info,keyinfo,info->lastkey,key_length, SEARCH_SAME, info->s->state.key_root[key]); if (search_result) { - mi_check_print_error(param,"Record at: %10s Can't find key for index: %2d", + mi_check_print_error(param,"Record at: %10s " + "Can't find key for index: %2d", llstr(start_recpos,llbuff),key+1); if (error++ > MAXERR || !(param->testflag & T_VERBOSE)) goto err2; diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 1a17febe94a..c6e9da03adf 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -59,6 +59,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, my_off_t key_root[MI_MAX_POSSIBLE_KEY],key_del[MI_MAX_KEY_BLOCK_SIZE]; MI_CREATE_INFO tmp_create_info; DBUG_ENTER("mi_create"); + DBUG_PRINT("enter", ("keys: %u columns: %u uniques: %u flags: %u", + keys, columns, uniques, flags)); if (!ci) { @@ -471,6 +473,16 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, uniques * MI_UNIQUEDEF_SIZE + (key_segs + unique_key_parts)*HA_KEYSEG_SIZE+ columns*MI_COLUMNDEF_SIZE); + DBUG_PRINT("info", ("info_length: %u", info_length)); + /* There are only 16 bits for the total header length. */ + if (info_length > 65535) + { + my_printf_error(0, "MyISAM table '%s' has too many columns and/or " + "indexes and/or unique constraints.", + MYF(0), name + dirname_length(name)); + my_errno= HA_WRONG_CREATE_OPTION; + goto err; + } bmove(share.state.header.file_version,(byte*) myisam_file_magic,4); ci->old_options=options| (ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD ? @@ -545,9 +557,20 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, if (ci->index_file_name) { - fn_format(filename, ci->index_file_name,"",MI_NAME_IEXT,4); - fn_format(linkname,name, "",MI_NAME_IEXT,4); - linkname_ptr=linkname; + if (options & HA_OPTION_TMP_TABLE) + { + char *path; + /* chop off the table name, tempory tables use generated name */ + if ((path= strrchr(ci->index_file_name, FN_LIBCHAR))) + *path= '\0'; + fn_format(filename, name, ci->index_file_name, MI_NAME_IEXT, + MY_REPLACE_DIR | MY_UNPACK_FILENAME); + } + else + fn_format(filename, ci->index_file_name, "", + MI_NAME_IEXT, MY_UNPACK_FILENAME); + fn_format(linkname, name, "", MI_NAME_IEXT, MY_UNPACK_FILENAME); + linkname_ptr= linkname; /* Don't create the table if the link or file exists to ensure that one doesn't accidently destroy another table. @@ -601,10 +624,21 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, { if (ci->data_file_name) { - fn_format(filename, ci->data_file_name,"",MI_NAME_DEXT,4); - fn_format(linkname, name, "",MI_NAME_DEXT,4); - linkname_ptr=linkname; - create_flag=0; + if (options & HA_OPTION_TMP_TABLE) + { + char *path; + /* chop off the table name, tempory tables use generated name */ + if ((path= strrchr(ci->data_file_name, FN_LIBCHAR))) + *path= '\0'; + fn_format(filename, name, ci->data_file_name, MI_NAME_DEXT, + MY_REPLACE_DIR | MY_UNPACK_FILENAME); + } + else + fn_format(filename, ci->data_file_name, "", + MI_NAME_DEXT, MY_UNPACK_FILENAME); + fn_format(linkname, name, "", MI_NAME_DEXT, MY_UNPACK_FILENAME); + linkname_ptr= linkname; + create_flag= 0; } else { @@ -620,6 +654,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, errpos=3; } + DBUG_PRINT("info", ("write state info and base info")); if (mi_state_info_write(file, &share.state, 2) || mi_base_info_write(file, &share.base)) goto err; @@ -633,6 +668,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, #endif /* Write key and keyseg definitions */ + DBUG_PRINT("info", ("write key and keyseg definitions")); for (i=0 ; i < share.base.keys - uniques; i++) { uint sp_segs=(keydefs[i].flag & HA_SPATIAL) ? 2*SPDIMS : 0; @@ -683,6 +719,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, } /* Save unique definition */ + DBUG_PRINT("info", ("write unique definitions")); for (i=0 ; i < share.state.header.uniques ; i++) { HA_KEYSEG *keyseg_end; @@ -713,6 +750,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, goto err; } } + DBUG_PRINT("info", ("write field definitions")); for (i=0 ; i < share.base.fields ; i++) if (mi_recinfo_write(file, &recinfo[i])) goto err; @@ -727,6 +765,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, #endif /* Enlarge files */ + DBUG_PRINT("info", ("enlarge to keystart: %lu", (ulong) share.base.keystart)); if (my_chsize(file,(ulong) share.base.keystart,0,MYF(0))) goto err; diff --git a/myisam/mi_delete_table.c b/myisam/mi_delete_table.c index 6843881568d..2fba31cf8be 100644 --- a/myisam/mi_delete_table.c +++ b/myisam/mi_delete_table.c @@ -34,12 +34,24 @@ int mi_delete_table(const char *name) #ifdef USE_RAID { MI_INFO *info; - /* we use 'open_for_repair' to be able to delete a crashed table */ - if (!(info=mi_open(name, O_RDONLY, HA_OPEN_FOR_REPAIR))) - DBUG_RETURN(my_errno); - raid_type = info->s->base.raid_type; - raid_chunks = info->s->base.raid_chunks; - mi_close(info); + /* + When built with RAID support, we need to determine if this table + makes use of the raid feature. If yes, we need to remove all raid + chunks. This is done with my_raid_delete(). Unfortunately it is + necessary to open the table just to check this. We use + 'open_for_repair' to be able to open even a crashed table. If even + this open fails, we assume no raid configuration for this table + and try to remove the normal data file only. This may however + leave the raid chunks behind. + */ + if (!(info= mi_open(name, O_RDONLY, HA_OPEN_FOR_REPAIR))) + raid_type= 0; + else + { + raid_type= info->s->base.raid_type; + raid_chunks= info->s->base.raid_chunks; + mi_close(info); + } } #ifdef EXTRA_DEBUG check_table_is_closed(name,"delete"); diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index 8de500a7351..bc0389980b9 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -1155,6 +1155,9 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf) info->rec_cache.pos_in_file <= block_info.next_filepos && flush_io_cache(&info->rec_cache)) goto err; + /* A corrupted table can have wrong pointers. (Bug# 19835) */ + if (block_info.next_filepos == HA_OFFSET_ERROR) + goto panic; info->rec_cache.seek_not_done=1; if ((b_type=_mi_get_block_info(&block_info,file, block_info.next_filepos)) diff --git a/myisam/mi_key.c b/myisam/mi_key.c index 17ea56f0210..01bd0c43119 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -64,7 +64,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, TODO: nulls processing */ #ifdef HAVE_SPATIAL - return sp_make_key(info,keynr,key,record,filepos); + DBUG_RETURN(sp_make_key(info,keynr,key,record,filepos)); #else DBUG_ASSERT(0); /* mi_open should check that this never happens*/ #endif diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index e6f4d39ab49..a9a8cbacb4b 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -68,6 +68,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (fast_mi_readinfo(info)) goto err; + if (share->concurrent_insert) rw_rdlock(&share->key_root_lock[inx]); @@ -90,24 +91,35 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, case HA_KEY_ALG_BTREE: default: if (!_mi_search(info, keyinfo, key_buff, use_key_length, - myisam_read_vec[search_flag], info->s->state.key_root[inx])) + myisam_read_vec[search_flag], info->s->state.key_root[inx])) { - while (info->lastpos >= info->state->data_file_length) + /* + If we are searching for an exact key (including the data pointer) + and this was added by an concurrent insert, + then the result is "key not found". + */ + if ((search_flag == HA_READ_KEY_EXACT) && + (info->lastpos >= info->state->data_file_length)) + { + my_errno= HA_ERR_KEY_NOT_FOUND; + info->lastpos= HA_OFFSET_ERROR; + } + else while (info->lastpos >= info->state->data_file_length) { /* Skip rows that are inserted by other threads since we got a lock Note that this can only happen if we are not searching after an exact key, because the keys are sorted according to position */ - if (_mi_search_next(info, keyinfo, info->lastkey, - info->lastkey_length, - myisam_readnext_vec[search_flag], - info->s->state.key_root[inx])) + info->lastkey_length, + myisam_readnext_vec[search_flag], + info->s->state.key_root[inx])) break; } } } + if (share->concurrent_insert) rw_unlock(&share->key_root_lock[inx]); diff --git a/myisam/rt_index.c b/myisam/rt_index.c index 97554dca4e6..1806476dc39 100644 --- a/myisam/rt_index.c +++ b/myisam/rt_index.c @@ -183,9 +183,11 @@ int rtree_find_first(MI_INFO *info, uint keynr, uchar *key, uint key_length, return -1; } - /* Save searched key */ - memcpy(info->first_mbr_key, key, keyinfo->keylength - - info->s->base.rec_reflength); + /* + Save searched key, include data pointer. + The data pointer is required if the search_flag contains MBR_DATA. + */ + memcpy(info->first_mbr_key, key, keyinfo->keylength); info->last_rkey_length = key_length; info->rtree_recursion_depth = -1; diff --git a/myisam/rt_mbr.c b/myisam/rt_mbr.c index c43daec2f7c..897862c1c9a 100644 --- a/myisam/rt_mbr.c +++ b/myisam/rt_mbr.c @@ -52,10 +52,14 @@ if (EQUAL_CMP(amin, amax, bmin, bmax)) \ return 1; \ } \ - else /* if (nextflag & MBR_DISJOINT) */ \ + else if (nextflag & MBR_DISJOINT) \ { \ if (DISJOINT_CMP(amin, amax, bmin, bmax)) \ return 1; \ + }\ + else /* if unknown comparison operator */ \ + { \ + DBUG_ASSERT(0); \ } #define RT_CMP_KORR(type, korr_func, len, nextflag) \ diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 73074397086..39fc425bf06 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -101,15 +101,15 @@ uninstall-local: @RM@ -f -r $(DESTDIR)$(testdir) std_data/client-key.pem: $(top_srcdir)/SSL/$(@F) - @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data + @RM@ -f $@; @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data std_data/client-cert.pem: $(top_srcdir)/SSL/$(@F) - @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data + @RM@ -f $@; @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data std_data/cacert.pem: $(top_srcdir)/SSL/$(@F) - @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data + @RM@ -f $@; @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data std_data/server-cert.pem: $(top_srcdir)/SSL/$(@F) - @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data + @RM@ -f $@; @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data std_data/server-key.pem: $(top_srcdir)/SSL/$(@F) - @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data + @RM@ -f $@; @CP@ $(top_srcdir)/SSL/$(@F) $(srcdir)/std_data SUFFIXES = .sh diff --git a/mysql-test/include/ndb_default_cluster.inc b/mysql-test/include/ndb_default_cluster.inc index 2f900b6a0b4..de7eda3c596 100644 --- a/mysql-test/include/ndb_default_cluster.inc +++ b/mysql-test/include/ndb_default_cluster.inc @@ -1,4 +1,4 @@ -- require r/ndb_default_cluster.require disable_query_log; -show status like "Ndb_connected_host"; +show status like "Ndb_config_from_host"; enable_query_log; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 5226e6f80df..14bd9b198a2 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -534,6 +534,11 @@ sub command_line_setup () { "($opt_master_myport - $opt_master_myport + 10)"); } + # This is needed for test log evaluation in "gen-build-status-page" + # in all cases where the calling tool does not log the commands + # directly before it executes them, like "make test-force-pl" in RPM builds. + print "Logging: $0 ", join(" ", @ARGV), "\n"; + # Read the command line # Note: Keep list, and the order, in sync with usage at end of this file diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index bcdd8294eee..590885b3d46 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -1381,16 +1381,16 @@ start_master() if [ x$DO_DDD = x1 ] then - $ECHO "set args $master_args" > $GDB_MASTER_INIT + $ECHO "set args $master_args" > $GDB_MASTER_INIT$1 manager_launch master ddd -display $DISPLAY --debugger \ - "gdb -x $GDB_MASTER_INIT" $MASTER_MYSQLD + "gdb -x $GDB_MASTER_INIT$1" $MASTER_MYSQLD elif [ x$DO_GDB = x1 ] then if [ x$MANUAL_GDB = x1 ] then - $ECHO "set args $master_args" > $GDB_MASTER_INIT + $ECHO "set args $master_args" > $GDB_MASTER_INIT$1 $ECHO "To start gdb for the master , type in another window:" - $ECHO "cd $CWD ; gdb -x $GDB_MASTER_INIT $MASTER_MYSQLD" + $ECHO "cd $CWD ; gdb -x $GDB_MASTER_INIT$1 $MASTER_MYSQLD" wait_for_master=1500 else ( $ECHO set args $master_args; @@ -1402,9 +1402,9 @@ disa 1 end r EOF - fi ) > $GDB_MASTER_INIT + fi ) > $GDB_MASTER_INIT$1 manager_launch master $XTERM -display $DISPLAY \ - -title "Master" -e gdb -x $GDB_MASTER_INIT $MASTER_MYSQLD + -title "Master" -e gdb -x $GDB_MASTER_INIT$1 $MASTER_MYSQLD fi else manager_launch master $MASTER_MYSQLD $master_args @@ -2088,13 +2088,7 @@ then fi start_manager - -# Do not automagically start daemons if we are in gdb or running only one test -# case - if [ -z "$DO_GDB" ] && [ -z "$DO_DDD" ] - then - mysql_start - fi + mysql_start $ECHO "Loading Standard Test Databases" mysql_loadstd fi diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result index f4e547dbc66..56f67cce4d6 100644 --- a/mysql-test/r/analyse.result +++ b/mysql-test/r/analyse.result @@ -39,10 +39,10 @@ t2 CREATE TABLE `t2` ( `Field_name` varbinary(255) NOT NULL default '', `Min_value` varbinary(255) default NULL, `Max_value` varbinary(255) default NULL, - `Min_length` bigint(11) NOT NULL default '0', - `Max_length` bigint(11) NOT NULL default '0', - `Empties_or_zeros` bigint(11) NOT NULL default '0', - `Nulls` bigint(11) NOT NULL default '0', + `Min_length` int(11) NOT NULL default '0', + `Max_length` int(11) NOT NULL default '0', + `Empties_or_zeros` int(11) NOT NULL default '0', + `Nulls` int(11) NOT NULL default '0', `Avg_value_or_avg_length` varbinary(255) NOT NULL default '', `Std` varbinary(255) default NULL, `Optimal_fieldtype` varbinary(64) NOT NULL default '' @@ -58,10 +58,10 @@ t2 CREATE TABLE `t2` ( `Field_name` varbinary(255) NOT NULL default '', `Min_value` varbinary(255) default NULL, `Max_value` varbinary(255) default NULL, - `Min_length` bigint(11) NOT NULL default '0', - `Max_length` bigint(11) NOT NULL default '0', - `Empties_or_zeros` bigint(11) NOT NULL default '0', - `Nulls` bigint(11) NOT NULL default '0', + `Min_length` int(11) NOT NULL default '0', + `Max_length` int(11) NOT NULL default '0', + `Empties_or_zeros` int(11) NOT NULL default '0', + `Nulls` int(11) NOT NULL default '0', `Avg_value_or_avg_length` varbinary(255) NOT NULL default '', `Std` varbinary(255) default NULL, `Optimal_fieldtype` varbinary(64) NOT NULL default '' @@ -81,10 +81,10 @@ t2 CREATE TABLE `t2` ( `Field_name` varbinary(255) NOT NULL default '', `Min_value` varbinary(255) default NULL, `Max_value` varbinary(255) default NULL, - `Min_length` bigint(11) NOT NULL default '0', - `Max_length` bigint(11) NOT NULL default '0', - `Empties_or_zeros` bigint(11) NOT NULL default '0', - `Nulls` bigint(11) NOT NULL default '0', + `Min_length` int(11) NOT NULL default '0', + `Max_length` int(11) NOT NULL default '0', + `Empties_or_zeros` int(11) NOT NULL default '0', + `Nulls` int(11) NOT NULL default '0', `Avg_value_or_avg_length` varbinary(255) NOT NULL default '', `Std` varbinary(255) default NULL, `Optimal_fieldtype` varbinary(64) NOT NULL default '' diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result index 3cdf4b17027..edc18319603 100644 --- a/mysql-test/r/bigint.result +++ b/mysql-test/r/bigint.result @@ -174,7 +174,7 @@ create table t1 select 1 as 'a'; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` bigint(1) NOT NULL default '0' + `a` int(1) NOT NULL default '0' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 select 9223372036854775809 as 'a'; diff --git a/mysql-test/r/blackhole.result b/mysql-test/r/blackhole.result index a4c057f256c..140d7e73d48 100644 --- a/mysql-test/r/blackhole.result +++ b/mysql-test/r/blackhole.result @@ -123,11 +123,3 @@ master-bin.000001 # Query 1 # use `test`; create table t3 like t1 master-bin.000001 # Query 1 # use `test`; insert into t1 select * from t3 master-bin.000001 # Query 1 # use `test`; replace into t1 select * from t3 drop table t1,t2,t3; -drop table if exists t1; -Warnings: -Note 1051 Unknown table 't1' -create table t1 (c char(20)) engine=MyISAM; -insert into t1 values ("Monty"),("WAX"),("Walrus"); -alter table t1 engine=blackhole; -ERROR HY000: Table storage engine for 't1' doesn't have this option -drop table t1; diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index c5b77ea4925..aa8c6d3d277 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -668,7 +668,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `b` int(11) NOT NULL, `a` varchar(12) character set utf8 collate utf8_bin NOT NULL, - `c` bigint(1) NOT NULL default '0', + `c` int(1) NOT NULL default '0', PRIMARY KEY (`a`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; @@ -681,7 +681,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `b` int(11) default NULL, `a` varchar(12) character set utf8 collate utf8_bin NOT NULL, - `c` bigint(1) NOT NULL default '0', + `c` int(1) NOT NULL default '0', PRIMARY KEY (`a`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result index 77a3473e9fe..45078800910 100644 --- a/mysql-test/r/date_formats.result +++ b/mysql-test/r/date_formats.result @@ -495,6 +495,22 @@ f1 f2 Warnings: Warning 1292 Truncated incorrect date value: '2003-04-05 g' Warning 1292 Truncated incorrect datetime value: '2003-04-05 10:11:12.101010234567' +set names latin1; +select date_format('2004-01-01','%W (%a), %e %M (%b) %Y'); +date_format('2004-01-01','%W (%a), %e %M (%b) %Y') +Thursday (Thu), 1 January (Jan) 2004 +set lc_time_names=ru_RU; +set names koi8r; +select date_format('2004-01-01','%W (%a), %e %M (%b) %Y'); +date_format('2004-01-01','%W (%a), %e %M (%b) %Y') +þÅÔ×ÅÒÇ (þÔ×), 1 ñÎ×ÁÒÑ (ñÎ×) 2004 +set lc_time_names=de_DE; +set names latin1; +select date_format('2004-01-01','%W (%a), %e %M (%b) %Y'); +date_format('2004-01-01','%W (%a), %e %M (%b) %Y') +Donnerstag (Do), 1 Januar (Jan) 2004 +set names latin1; +set lc_time_names=en_US; create table t1 (f1 datetime); insert into t1 (f1) values ("2005-01-01"); insert into t1 (f1) values ("2005-02-01"); diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index 2eb0c81ec2e..709e44579e2 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -1689,6 +1689,50 @@ id c1 c2 9 abc ppc drop table federated.t1, federated.t2; drop table federated.t1, federated.t2; +drop table if exists federated.t1; +create table federated.t1 (a int, b int, c int); +drop table if exists federated.t1; +drop table if exists federated.t2; +create table federated.t1 (a int, b int, c int) engine=federated connection='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +create trigger federated.t1_bi before insert on federated.t1 for each row set new.c= new.a * new.b; +create table federated.t2 (a int, b int); +insert into federated.t2 values (13, 17), (19, 23); +insert into federated.t1 (a, b) values (1, 2), (3, 5), (7, 11); +select * from federated.t1; +a b c +1 2 2 +3 5 15 +7 11 77 +delete from federated.t1; +insert into federated.t1 (a, b) select * from federated.t2; +select * from federated.t1; +a b c +13 17 221 +19 23 437 +delete from federated.t1; +load data infile '../std_data_ln/loaddata5.dat' into table federated.t1 fields terminated by '' enclosed by '' ignore 1 lines (a, b); +select * from federated.t1; +a b c +3 4 12 +5 6 30 +drop tables federated.t1, federated.t2; +drop table federated.t1; +create table t1 (id int not null auto_increment primary key, val int); +create table t1 +(id int not null auto_increment primary key, val int) engine=federated +connection='mysql://root@127.0.0.1:SLAVE_PORT/test/t1'; +insert into t1 values (1,0),(2,0); +update t1 set val = NULL where id = 1; +select * from t1; +id val +1 NULL +2 0 +select * from t1; +id val +1 NULL +2 0 +drop table t1; +drop table t1; DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 1485809ba70..720529a9f11 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1038,6 +1038,21 @@ select * from t1 where f1='test' and (f2= sha("TEST") or f2= sha("test")); f1 f2 test a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 drop table t1; +CREATE TABLE t1 (a varchar(10)); +INSERT INTO t1 VALUES ('abc'), ('xyz'); +SELECT a, CONCAT(a,' ',a) AS c FROM t1 +HAVING LEFT(c,LENGTH(c)-INSTR(REVERSE(c)," ")) = a; +a c +abc abc abc +xyz xyz xyz +SELECT a, CONCAT(a,' ',a) AS c FROM t1 +HAVING LEFT(CONCAT(a,' ',a), +LENGTH(CONCAT(a,' ',a))- +INSTR(REVERSE(CONCAT(a,' ',a))," ")) = a; +a c +abc abc abc +xyz xyz xyz +DROP TABLE t1; End of 4.1 tests create table t1 (d decimal default null); insert into t1 values (null); diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 96591086f00..66fe355ffce 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -361,12 +361,6 @@ extract(SECOND FROM "1999-01-02 10:11:12") select extract(MONTH FROM "2001-02-00"); extract(MONTH FROM "2001-02-00") 2 -SELECT DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); -DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE) -9999-12-31 00:00:00 -SELECT DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); -DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE) -9999-12-31 00:00:00 SELECT EXTRACT(QUARTER FROM '2004-01-15') AS quarter; quarter 1 @@ -403,6 +397,12 @@ quarter SELECT EXTRACT(QUARTER FROM '2004-12-15') AS quarter; quarter 4 +SELECT DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); +DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE) +9999-12-31 00:00:00 +SELECT DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); +DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE) +9999-12-31 00:00:00 SELECT "1900-01-01 00:00:00" + INTERVAL 2147483648 SECOND; "1900-01-01 00:00:00" + INTERVAL 2147483648 SECOND 1968-01-20 03:14:08 diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result index 5b49e9d108d..28c59053435 100644 --- a/mysql-test/r/gis-rtree.result +++ b/mysql-test/r/gis-rtree.result @@ -816,3 +816,43 @@ check table t1 extended; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; +CREATE TABLE t1 ( +c1 geometry NOT NULL default '', +SPATIAL KEY i1 (c1(32)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +INSERT INTO t1 (c1) VALUES ( +PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +CREATE TABLE t1 ( +c1 geometry NOT NULL default '', +SPATIAL KEY i1 (c1(32)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +INSERT INTO t1 (c1) VALUES ( +PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +INSERT INTO t1 (c1) VALUES ( +PolygonFromText('POLYGON((-65.7402776999 -96.6686111000, + -65.7372222000 -96.5516666000, + -65.8502777000 -96.5461111000, + -65.8527777000 -96.6627777000, + -65.7402776999 -96.6686111000))')); +INSERT INTO t1 (c1) VALUES ( +PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 64969fcdf44..a2feba7ad5d 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -294,26 +294,26 @@ show create function sub1; ERROR 42000: FUNCTION sub1 does not exist select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ROUTINE_NAME ROUTINE_DEFINITION -sel2 -sub1 +sel2 NULL +sub1 NULL grant all privileges on test.* to mysqltest_1@localhost; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ROUTINE_NAME ROUTINE_DEFINITION -sel2 -sub1 +sel2 NULL +sub1 NULL create function sub2(i int) returns int return i+1; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ROUTINE_NAME ROUTINE_DEFINITION -sel2 -sub1 +sel2 NULL +sub1 NULL sub2 return i+1 show create procedure sel2; Procedure sql_mode Create Procedure -sel2 +sel2 NULL show create function sub1; Function sql_mode Create Function -sub1 +sub1 NULL show create function sub2; Function sql_mode Create Function sub2 CREATE DEFINER=`mysqltest_1`@`localhost` FUNCTION `sub2`(i int) RETURNS int(11) @@ -1134,3 +1134,39 @@ concat(@a, table_name) @a table_name .t1 . t1 .t2 . t2 drop table t1,t2; +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +CREATE PROCEDURE p1() SET @a= 1; +CREATE FUNCTION f1() RETURNS INT RETURN @a + 1; +CREATE USER mysql_bug20230@localhost; +GRANT EXECUTE ON PROCEDURE p1 TO mysql_bug20230@localhost; +GRANT EXECUTE ON FUNCTION f1 TO mysql_bug20230@localhost; +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +ROUTINE_NAME ROUTINE_DEFINITION +f1 RETURN @a + 1 +p1 SET @a= 1 +SHOW CREATE PROCEDURE p1; +Procedure sql_mode Create Procedure +p1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() +SET @a= 1 +SHOW CREATE FUNCTION f1; +Function sql_mode Create Function +f1 CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) +RETURN @a + 1 +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +ROUTINE_NAME ROUTINE_DEFINITION +f1 NULL +p1 NULL +SHOW CREATE PROCEDURE p1; +Procedure sql_mode Create Procedure +p1 NULL +SHOW CREATE FUNCTION f1; +Function sql_mode Create Function +f1 NULL +CALL p1(); +SELECT f1(); +f1() +2 +DROP FUNCTION f1; +DROP PROCEDURE p1; +DROP USER mysql_bug20230@localhost; diff --git a/mysql-test/r/init_connect.result b/mysql-test/r/init_connect.result index eeae422edc4..f90ee5913a1 100644 --- a/mysql-test/r/init_connect.result +++ b/mysql-test/r/init_connect.result @@ -22,3 +22,117 @@ set GLOBAL init_connect="adsfsdfsdfs"; select @a; Got one of the listed errors drop table t1; +End of 4.1 tests +create table t1 (x int); +insert into t1 values (3), (5), (7); +create table t2 (y int); +create user mysqltest1@localhost; +grant all privileges on test.* to mysqltest1@localhost; +set global init_connect="create procedure p1() select * from t1"; +call p1(); +x +3 +5 +7 +drop procedure p1; +set global init_connect="create procedure p1(x int)\ +begin\ + select count(*) from t1;\ + select * from t1;\ + set @x = x; +end"; +call p1(42); +count(*) +3 +x +3 +5 +7 +select @x; +@x +42 +set global init_connect="call p1(4711)"; +select @x; +@x +4711 +set global init_connect="drop procedure if exists p1"; +call p1(); +ERROR 42000: PROCEDURE test.p1 does not exist +create procedure p1(out sum int) +begin +declare n int default 0; +declare c cursor for select * from t1; +declare exit handler for not found +begin +close c; +set sum = n; +end; +open c; +loop +begin +declare x int; +fetch c into x; +if x > 3 then +set n = n + x; +end if; +end; +end loop; +end| +set global init_connect="call p1(@sum)"; +select @sum; +@sum +12 +drop procedure p1; +create procedure p1(tbl char(10), v int) +begin +set @s = concat('insert into ', tbl, ' values (?)'); +set @v = v; +prepare stmt1 from @s; +execute stmt1 using @v; +deallocate prepare stmt1; +end| +set global init_connect="call p1('t1', 11)"; +select * from t1; +x +3 +5 +7 +11 +drop procedure p1; +create function f1() returns int +begin +declare n int; +select count(*) into n from t1; +return n; +end| +set global init_connect="set @x = f1()"; +select @x; +@x +4 +set global init_connect="create view v1 as select f1()"; +select * from v1; +f1() +4 +set global init_connect="drop view v1"; +select * from v1; +ERROR 42S02: Table 'test.v1' doesn't exist +drop function f1; +create trigger trg1 +after insert on t2 +for each row +insert into t1 values (new.y); +set global init_connect="insert into t2 values (13), (17), (19)"; +select * from t1; +x +3 +5 +7 +11 +13 +17 +19 +drop trigger trg1; +set global init_connect=default; +revoke all privileges, grant option from mysqltest1@localhost; +drop user mysqltest1@localhost; +drop table t1, t2; diff --git a/mysql-test/r/init_file.result b/mysql-test/r/init_file.result index 9766475a418..1569f2c3d68 100644 --- a/mysql-test/r/init_file.result +++ b/mysql-test/r/init_file.result @@ -1 +1,16 @@ ok +end of 4.1 tests +select * from t1; +x +3 +5 +7 +11 +13 +select * from t2; +y +30 +3 +11 +13 +drop table t1, t2; diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 8dbfa906fe1..bf0c4ff1f42 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -54,6 +54,35 @@ c.c_id = 218 and expiredate is null; slai_id 12 drop table t1, t2; +CREATE TABLE t1 (a int, b int, KEY b (b)) Engine=InnoDB; +CREATE TABLE t2 (a int, b int, PRIMARY KEY (a,b)) Engine=InnoDB; +CREATE TABLE t3 (a int, b int, c int, PRIMARY KEY (a), +UNIQUE KEY b (b,c), KEY a (a,b,c)) Engine=InnoDB; +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 SELECT a + 1, b + 1 FROM t1; +INSERT INTO t1 SELECT a + 2, b + 2 FROM t1; +INSERT INTO t2 VALUES (1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8); +INSERT INTO t2 SELECT a + 1, b FROM t2; +DELETE FROM t2 WHERE a = 1 AND b < 2; +INSERT INTO t3 VALUES (1,1,1),(2,1,2); +INSERT INTO t3 SELECT a + 2, a + 2, 3 FROM t3; +INSERT INTO t3 SELECT a + 4, a + 4, 3 FROM t3; +SELECT STRAIGHT_JOIN SQL_NO_CACHE t1.b, t1.a FROM t1, t3, t2 WHERE +t3.a = t2.a AND t2.b = t1.a AND t3.b = 1 AND t3.c IN (1, 2) +ORDER BY t1.b LIMIT 2; +b a +1 1 +2 2 +SELECT STRAIGHT_JOIN SQL_NO_CACHE t1.b, t1.a FROM t1, t3, t2 WHERE +t3.a = t2.a AND t2.b = t1.a AND t3.b = 1 AND t3.c IN (1, 2) +ORDER BY t1.b LIMIT 5; +b a +1 1 +2 2 +2 2 +3 3 +3 3 +DROP TABLE t1, t2, t3; create table t1m (a int) engine=myisam; create table t1i (a int) engine=innodb; create table t2m (a int) engine=myisam; diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index a6f05143b3e..0174ea45935 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -336,8 +336,16 @@ UNIQUE i1idx (i1), UNIQUE i2idx (i2)); desc t1; Field Type Null Key Default Extra -i1 int(11) NO UNI +i1 int(11) NO PRI i2 int(11) NO UNI +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i1` int(11) NOT NULL, + `i2` int(11) NOT NULL, + UNIQUE KEY `i1idx` (`i1`), + UNIQUE KEY `i2idx` (`i2`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 ( c1 int, diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 568f83b7d6d..b1abe16a091 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -768,14 +768,6 @@ Table Op Msg_type Msg_text test.t1 check status OK test.t2 check status OK drop table t1, t2, t3; -drop table if exists t1; -Warnings: -Note 1051 Unknown table 't1' -create table t1 (c char(20)) engine=MyISAM; -insert into t1 values ("Monty"),("WAX"),("Walrus"); -alter table t1 engine=MERGE; -ERROR HY000: Table storage engine for 't1' doesn't have this option -drop table t1; create table t1 (b bit(1)); create table t2 (b bit(1)); create table tm (b bit(1)) engine = merge union = (t1,t2); diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 780287fb807..c7d8f5c128d 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -1454,3 +1454,16 @@ create table t3 (c1 int) engine=myisam pack_keys=default; create table t4 (c1 int) engine=myisam pack_keys=2; 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 '2' at line 1 drop table t1, t2, t3; +show create table t1; +show create table t1; +create table t1 (a int) engine=myisam select 42 a; +select * from t1; +a +9 +select * from t1; +a +99 +select * from t1; +a +42 +drop table t1; diff --git a/mysql-test/r/ndb_default_cluster.require b/mysql-test/r/ndb_default_cluster.require index aa4988cdca3..3616ae0f343 100644 --- a/mysql-test/r/ndb_default_cluster.require +++ b/mysql-test/r/ndb_default_cluster.require @@ -1,2 +1,2 @@ Variable_name Value -Ndb_connected_host localhost +Ndb_config_from_host localhost diff --git a/mysql-test/r/ndb_replace.result b/mysql-test/r/ndb_replace.result index cdfcd6a7a43..4d63c397d60 100644 --- a/mysql-test/r/ndb_replace.result +++ b/mysql-test/r/ndb_replace.result @@ -30,7 +30,8 @@ REPLACE INTO t1 (i,j) VALUES (17,2); SELECT * from t1 ORDER BY i; i j k 3 1 42 -17 2 24 +17 2 NULL +DROP TABLE t1; CREATE TABLE t2 (a INT(11) NOT NULL, b INT(11) NOT NULL, c INT(11) NOT NULL, @@ -52,3 +53,47 @@ SELECT * FROM t2 ORDER BY id; a b c x y z id i 1 1 1 b b b 5 2 DROP TABLE t2; +drop table if exists t1; +create table t1 (pk int primary key, apk int unique, data int) engine=ndbcluster; +insert into t1 values (1, 1, 1), (2, 2, 2), (3, 3, 3); +replace into t1 (pk, apk) values (4, 1), (5, 2); +select * from t1 order by pk; +pk apk data +3 3 3 +4 1 NULL +5 2 NULL +delete from t1; +insert into t1 values (1, 1, 1), (2, 2, 2), (3, 3, 3); +replace into t1 (pk, apk) values (1, 4), (2, 5); +select * from t1 order by pk; +pk apk data +1 4 NULL +2 5 NULL +3 3 3 +delete from t1; +insert into t1 values (1, 1, 1), (4, 4, 4), (6, 6, 6); +load data infile '../std_data_ln/loaddata5.dat' replace into table t1 fields terminated by '' enclosed by '' ignore 1 lines (pk, apk); +select * from t1 order by pk; +pk apk data +1 1 1 +3 4 NULL +5 6 NULL +delete from t1; +insert into t1 values (1, 1, 1), (3, 3, 3), (5, 5, 5); +load data infile '../std_data_ln/loaddata5.dat' replace into table t1 fields terminated by '' enclosed by '' ignore 1 lines (pk, apk); +select * from t1 order by pk; +pk apk data +1 1 1 +3 4 NULL +5 6 NULL +delete from t1; +insert into t1 values (1, 1, 1), (2, 2, 2), (3, 3, 3); +replace into t1 (pk, apk) select 4, 1; +replace into t1 (pk, apk) select 2, 4; +select * from t1 order by pk; +pk apk data +2 4 NULL +3 3 3 +4 1 NULL +drop table t1; +End of 5.0 tests. diff --git a/mysql-test/r/ndb_restore.result b/mysql-test/r/ndb_restore.result index c78a4137468..e5bf4315e5c 100644 --- a/mysql-test/r/ndb_restore.result +++ b/mysql-test/r/ndb_restore.result @@ -1,6 +1,6 @@ use test; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; +drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c,t10_c; CREATE TABLE `t1` ( `capgoaledatta` smallint(5) unsigned NOT NULL auto_increment, `goaledatta` char(2) NOT NULL default '', @@ -116,6 +116,8 @@ CREATE TABLE `t9` ( PRIMARY KEY (`kattjame`,`hunderaaarbagefa`,`hassetistart`,`hassetino`) ) ENGINE=myisam DEFAULT CHARSET=latin1; INSERT INTO `t9` VALUES ('3g4jh8gar2t','joe','q3.net','elredun.com','q3.net','436643316120','436643316939','91341234568968','695595699','1.1.1.1','2.2.6.2','3','86989','34','x','x','2012-03-12 18:35:04','2012-12-05 12:35:04',3123123,9569,6565,1),('4tt45345235','pap','q3plus.qt','q3plus.qt','q3.net','436643316120','436643316939','8956234534568968','5254595969','1.1.1.1','8.6.2.2','4','86989','34','x','x','2012-03-12 12:55:34','2012-12-05 11:20:04',3223433,3369,9565,2),('4545435545','john','q3.net','q3.net','acne.li','436643316120','436643316939','45345234568968','995696699','1.1.1.1','2.9.9.2','2','86998','34','x','x','2012-03-12 11:35:03','2012-12-05 08:50:04',8823123,169,3565,3); +create table t10 (a int auto_increment key); +insert into t10 values (1),(2),(3); create table t1_c engine=ndbcluster as select * from t1; create table t2_c engine=ndbcluster as select * from t2; create table t3_c engine=ndbcluster as select * from t3; @@ -125,10 +127,12 @@ create table t6_c engine=ndbcluster as select * from t6; create table t7_c engine=ndbcluster as select * from t7; create table t8_c engine=ndbcluster as select * from t8; create table t9_c engine=ndbcluster as select * from t9; -drop table t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c; +create table t10_c engine=ndbcluster as select * from t10; +drop table t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c, t10_c; show tables; Tables_in_test t1 +t10 t2 t3 t4 @@ -137,14 +141,15 @@ t6 t7 t8 t9 -t8_c +t3_c t9_c t1_c +t8_c t7_c t6_c t5_c t4_c -t3_c +t10_c t2_c select count(*) from t1; count(*) @@ -245,6 +250,11 @@ from (select * from t9 union select * from t9_c) a; count(*) 3 -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c; +select * from t10_c order by a; +a +1 +2 +3 +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9, t10; +drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c, t10_c; 520093696,1 diff --git a/mysql-test/r/ndb_trigger.result b/mysql-test/r/ndb_trigger.result new file mode 100644 index 00000000000..27f83df70c9 --- /dev/null +++ b/mysql-test/r/ndb_trigger.result @@ -0,0 +1,119 @@ +drop table if exists t1, t2, t3; +create table t1 (id int primary key, a int not null, b decimal (63,30) default 0) engine=ndb; +create table t2 (op char(1), a int not null, b decimal (63,30)); +create table t3 select 1 as i; +create trigger t1_bu before update on t1 for each row +begin +insert into t2 values ("u", old.a, old.b); +set new.b = old.b + 10; +end;// +create trigger t1_bd before delete on t1 for each row +begin +insert into t2 values ("d", old.a, old.b); +end;// +insert into t1 values (1, 1, 1.05), (2, 2, 2.05), (3, 3, 3.05), (4, 4, 4.05); +update t1 set a=5 where a != 3; +select * from t1 order by id; +id a b +1 5 11.050000000000000000000000000000 +2 5 12.050000000000000000000000000000 +3 3 3.050000000000000000000000000000 +4 5 14.050000000000000000000000000000 +select * from t2 order by op, a, b; +op a b +u 1 1.050000000000000000000000000000 +u 2 2.050000000000000000000000000000 +u 4 4.050000000000000000000000000000 +delete from t2; +update t1, t3 set a=6 where a = 5; +select * from t1 order by id; +id a b +1 6 21.050000000000000000000000000000 +2 6 22.050000000000000000000000000000 +3 3 3.050000000000000000000000000000 +4 6 24.050000000000000000000000000000 +select * from t2 order by op, a, b; +op a b +u 5 11.050000000000000000000000000000 +u 5 12.050000000000000000000000000000 +u 5 14.050000000000000000000000000000 +delete from t2; +delete from t1 where a != 3; +select * from t1 order by id; +id a b +3 3 3.050000000000000000000000000000 +select * from t2 order by op, a, b; +op a b +d 6 21.050000000000000000000000000000 +d 6 22.050000000000000000000000000000 +d 6 24.050000000000000000000000000000 +delete from t2; +insert into t1 values (1, 1, 1.05), (2, 2, 2.05), (4, 4, 4.05); +delete t1 from t1, t3 where a != 3; +select * from t1 order by id; +id a b +3 3 3.050000000000000000000000000000 +select * from t2 order by op, a, b; +op a b +d 1 1.050000000000000000000000000000 +d 2 2.050000000000000000000000000000 +d 4 4.050000000000000000000000000000 +delete from t2; +insert into t1 values (4, 4, 4.05); +insert into t1 (id, a) values (4, 1), (3, 1) on duplicate key update a= a + 1; +select * from t1 order by id; +id a b +3 4 13.050000000000000000000000000000 +4 5 14.050000000000000000000000000000 +select * from t2 order by op, a, b; +op a b +u 3 3.050000000000000000000000000000 +u 4 4.050000000000000000000000000000 +delete from t2; +delete from t3; +insert into t3 values (4), (3); +insert into t1 (id, a) (select i, 1 from t3) on duplicate key update a= a + 1; +select * from t1 order by id; +id a b +3 5 23.050000000000000000000000000000 +4 6 24.050000000000000000000000000000 +select * from t2 order by op, a, b; +op a b +u 4 13.050000000000000000000000000000 +u 5 14.050000000000000000000000000000 +delete from t2; +replace into t1 (id, a) values (4, 1), (3, 1); +select * from t1 order by id; +id a b +3 1 0.000000000000000000000000000000 +4 1 0.000000000000000000000000000000 +select * from t2 order by op, a, b; +op a b +d 5 23.050000000000000000000000000000 +d 6 24.050000000000000000000000000000 +delete from t1; +delete from t2; +insert into t1 values (3, 1, 1.05), (4, 1, 2.05); +replace into t1 (id, a) (select i, 2 from t3); +select * from t1 order by id; +id a b +3 2 0.000000000000000000000000000000 +4 2 0.000000000000000000000000000000 +select * from t2 order by op, a, b; +op a b +d 1 1.050000000000000000000000000000 +d 1 2.050000000000000000000000000000 +delete from t1; +delete from t2; +insert into t1 values (3, 1, 1.05), (5, 2, 2.05); +load data infile '../std_data_ln/loaddata5.dat' replace into table t1 fields terminated by '' enclosed by '' ignore 1 lines (id, a); +select * from t1 order by id; +id a b +3 4 0.000000000000000000000000000000 +5 6 0.000000000000000000000000000000 +select * from t2 order by op, a, b; +op a b +d 1 1.050000000000000000000000000000 +d 2 2.050000000000000000000000000000 +drop tables t1, t2, t3; +End of 5.0 tests diff --git a/mysql-test/r/odbc.result b/mysql-test/r/odbc.result index 2d9d39393b1..5629d3dab33 100644 --- a/mysql-test/r/odbc.result +++ b/mysql-test/r/odbc.result @@ -14,3 +14,14 @@ explain select * from t1 where b is null; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE drop table t1; +CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY); +INSERT INTO t1 VALUES (NULL); +SELECT sql_no_cache a, last_insert_id() FROM t1 WHERE a IS NULL; +a last_insert_id() +1 1 +SELECT sql_no_cache a, last_insert_id() FROM t1 WHERE a IS NULL; +a last_insert_id() +SELECT sql_no_cache a, last_insert_id() FROM t1; +a last_insert_id() +1 1 +DROP TABLE t1; diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index 225e306b3cf..28c1dc59540 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -620,8 +620,8 @@ CREATE VIEW v1 AS SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP; DESC v1; Field Type Null Key Default Extra -a bigint(11) YES NULL -LENGTH(a) bigint(10) YES NULL +a int(11) YES 0 +LENGTH(a) int(10) YES NULL COUNT(*) bigint(21) NO 0 SELECT * FROM v1; a LENGTH(a) COUNT(*) diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 207d9ea7475..aa355067d1f 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -1775,7 +1775,7 @@ NULL as const12, @arg12 as param12, show create table t5 ; Table Create Table t5 CREATE TABLE `t5` ( - `const01` bigint(1) NOT NULL default '0', + `const01` int(1) NOT NULL default '0', `param01` bigint(20) default NULL, `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, @@ -1805,7 +1805,7 @@ t5 CREATE TABLE `t5` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t5 t5 const01 const01 8 1 1 N 32769 0 63 +def test t5 t5 const01 const01 3 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 13aa549949c..ea7ed9371e8 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -1758,7 +1758,7 @@ NULL as const12, @arg12 as param12, show create table t5 ; Table Create Table t5 CREATE TABLE `t5` ( - `const01` bigint(1) NOT NULL default '0', + `const01` int(1) NOT NULL default '0', `param01` bigint(20) default NULL, `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, @@ -1788,7 +1788,7 @@ t5 CREATE TABLE `t5` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t5 t5 const01 const01 8 1 1 N 32769 0 63 +def test t5 t5 const01 const01 3 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index a08dae945bd..fe4de89d6c7 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -1759,7 +1759,7 @@ NULL as const12, @arg12 as param12, show create table t5 ; Table Create Table t5 CREATE TABLE `t5` ( - `const01` bigint(1) NOT NULL default '0', + `const01` int(1) NOT NULL default '0', `param01` bigint(20) default NULL, `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, @@ -1789,7 +1789,7 @@ t5 CREATE TABLE `t5` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t5 t5 const01 const01 8 1 1 N 32769 0 63 +def test t5 t5 const01 const01 3 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 6682b085097..bee7b2400b8 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -1695,7 +1695,7 @@ NULL as const12, @arg12 as param12, show create table t5 ; Table Create Table t5 CREATE TABLE `t5` ( - `const01` bigint(1) NOT NULL default '0', + `const01` int(1) NOT NULL default '0', `param01` bigint(20) default NULL, `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, @@ -1725,7 +1725,7 @@ t5 CREATE TABLE `t5` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t5 t5 const01 const01 8 1 1 N 32769 0 63 +def test t5 t5 const01 const01 3 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 @@ -4709,7 +4709,7 @@ NULL as const12, @arg12 as param12, show create table t5 ; Table Create Table t5 CREATE TABLE `t5` ( - `const01` bigint(1) NOT NULL default '0', + `const01` int(1) NOT NULL default '0', `param01` bigint(20) default NULL, `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, @@ -4739,7 +4739,7 @@ t5 CREATE TABLE `t5` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t5 t5 const01 const01 8 1 1 N 32769 0 63 +def test t5 t5 const01 const01 3 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index dc3b984949d..d352ec9f9e2 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -1758,7 +1758,7 @@ NULL as const12, @arg12 as param12, show create table t5 ; Table Create Table t5 CREATE TABLE `t5` ( - `const01` bigint(1) NOT NULL default '0', + `const01` int(1) NOT NULL default '0', `param01` bigint(20) default NULL, `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, @@ -1788,7 +1788,7 @@ t5 CREATE TABLE `t5` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t5 t5 const01 const01 8 1 1 N 32769 0 63 +def test t5 t5 const01 const01 3 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index 000a20da655..8ce4c624fbc 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -1758,7 +1758,7 @@ NULL as const12, @arg12 as param12, show create table t5 ; Table Create Table t5 CREATE TABLE `t5` ( - `const01` bigint(1) NOT NULL default '0', + `const01` int(1) NOT NULL default '0', `param01` bigint(20) default NULL, `const02` decimal(2,1) NOT NULL default '0.0', `param02` decimal(65,30) default NULL, @@ -1788,7 +1788,7 @@ t5 CREATE TABLE `t5` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select * from t5 ; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t5 t5 const01 const01 8 1 1 N 32769 0 63 +def test t5 t5 const01 const01 3 1 1 N 32769 0 63 def test t5 t5 param01 param01 8 20 1 Y 32768 0 63 def test t5 t5 const02 const02 246 4 3 N 1 1 63 def test t5 t5 param02 param02 246 67 32 Y 0 30 63 diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index f6b7409ea6a..a1f03a292c5 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -644,6 +644,27 @@ SELECT count(*) FROM t1 WHERE CLIENT='000' AND (ARG1 != ' 2' OR ARG1 != ' 1'); count(*) 4 drop table t1; +create table t1 (a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +CREATE TABLE t2 ( +pk1 int(11) NOT NULL, +pk2 int(11) NOT NULL, +pk3 int(11) NOT NULL, +pk4 int(11) NOT NULL, +filler char(82), +PRIMARY KEY (pk1,pk2,pk3,pk4) +) DEFAULT CHARSET=latin1; +insert into t2 select 1, A.a+10*B.a, 432, 44, 'fillerZ' from t1 A, t1 B; +INSERT INTO t2 VALUES (2621, 2635, 0, 0,'filler'), (2621, 2635, 1, 0,'filler'), +(2621, 2635, 10, 0,'filler'), (2621, 2635, 11, 0,'filler'), +(2621, 2635, 14, 0,'filler'), (2621, 2635, 1000015, 0,'filler'); +SELECT * FROM t2 +WHERE ((((pk4 =0) AND (pk1 =2621) AND (pk2 =2635))) +OR ((pk4 =1) AND (((pk1 IN ( 7, 2, 1 ))) OR (pk1 =522)) AND ((pk2 IN ( 0, 2635)))) +) AND (pk3 >=1000000); +pk1 pk2 pk3 pk4 filler +2621 2635 1000015 0 filler +drop table t1, t2; CREATE TABLE t1 ( id int(11) NOT NULL auto_increment, status varchar(20), diff --git a/mysql-test/r/rpl_auto_increment.result b/mysql-test/r/rpl_auto_increment.result index 9eca51ad2d9..ea4815e5e64 100644 --- a/mysql-test/r/rpl_auto_increment.result +++ b/mysql-test/r/rpl_auto_increment.result @@ -183,3 +183,47 @@ a 32 42 drop table t1; +create table t1 (a tinyint not null auto_increment primary key) engine=myisam; +insert into t1 values(103); +set auto_increment_increment=11; +set auto_increment_offset=4; +insert into t1 values(null); +insert into t1 values(null); +insert into t1 values(null); +ERROR 23000: Duplicate entry '125' for key 1 +select a, mod(a-@@auto_increment_offset,@@auto_increment_increment) from t1 order by a; +a mod(a-@@auto_increment_offset,@@auto_increment_increment) +103 0 +114 0 +125 0 +create table t2 (a tinyint unsigned not null auto_increment primary key) engine=myisam; +set auto_increment_increment=10; +set auto_increment_offset=1; +set insert_id=1000; +insert into t2 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select a, mod(a-@@auto_increment_offset,@@auto_increment_increment) from t2 order by a; +a mod(a-@@auto_increment_offset,@@auto_increment_increment) +251 0 +create table t3 like t1; +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t3 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t3 order by a; +a +127 +select * from t1 order by a; +a +103 +114 +125 +select * from t2 order by a; +a +251 +select * from t3 order by a; +a +127 +drop table t1,t2,t3; diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index b11f1b92020..3aa82bf1d63 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -74,6 +74,19 @@ SET FOREIGN_KEY_CHECKS=0; INSERT INTO t1 VALUES (1),(1); ERROR 23000: Duplicate entry '1' for key 1 drop table t1; +create table t1(a int auto_increment, key(a)); +create table t2(a int); +insert into t1 (a) values (null); +insert into t2 (a) select a from t1 where a is null; +insert into t2 (a) select a from t1 where a is null; +select * from t2; +a +1 +select * from t2; +a +1 +drop table t1; +drop table t2; drop function if exists bug15728; drop function if exists bug15728_insert; drop table if exists t1, t2; @@ -132,3 +145,68 @@ id last_id drop function bug15728; drop function bug15728_insert; drop table t1, t2; +create table t1 (n int primary key auto_increment not null, +b int, unique(b)); +set sql_log_bin=0; +insert into t1 values(null,100); +replace into t1 values(null,50),(null,100),(null,150); +select * from t1 order by n; +n b +2 50 +3 100 +4 150 +truncate table t1; +set sql_log_bin=1; +insert into t1 values(null,100); +select * from t1 order by n; +n b +1 100 +insert into t1 values(null,200),(null,300); +delete from t1 where b <> 100; +select * from t1 order by n; +n b +1 100 +replace into t1 values(null,100),(null,350); +select * from t1 order by n; +n b +2 100 +3 350 +select * from t1 order by n; +n b +2 100 +3 350 +insert into t1 values (NULL,400),(3,500),(NULL,600) on duplicate key UPDATE n=1000; +select * from t1 order by n; +n b +2 100 +4 400 +1000 350 +1001 600 +select * from t1 order by n; +n b +2 100 +4 400 +1000 350 +1001 600 +drop table t1; +create table t1 (n int primary key auto_increment not null, +b int, unique(b)); +insert into t1 values(null,100); +select * from t1 order by n; +n b +1 100 +insert into t1 values(null,200),(null,300); +delete from t1 where b <> 100; +select * from t1 order by n; +n b +1 100 +insert into t1 values(null,100),(null,350) on duplicate key update n=2; +select * from t1 order by n; +n b +2 100 +3 350 +select * from t1 order by n; +n b +2 100 +3 350 +drop table t1; diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index e6c590489a0..7f01d453906 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -3395,3 +3395,6 @@ a t1.b + 0 t1.c + 0 a t2.b + 0 c d 1 0 1 1 0 1 NULL 2 0 1 NULL NULL NULL NULL drop table t1,t2; +SELECT 0.9888889889 * 1.011111411911; +0.9888889889 * 1.011111411911 +0.9998769417899202067879 diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result index 6b4d7b1a6d3..83ee188bfa4 100644 --- a/mysql-test/r/sp-vars.result +++ b/mysql-test/r/sp-vars.result @@ -1075,3 +1075,18 @@ SELECT f1(); f1() abc DROP FUNCTION f1; +DROP PROCEDURE IF EXISTS p1; +CREATE PROCEDURE p1() +BEGIN +DECLARE v_char VARCHAR(255); +DECLARE v_text TEXT DEFAULT ''; +SET v_char = 'abc'; +SET v_text = v_char; +SET v_char = 'def'; +SET v_text = concat(v_text, '|', v_char); +SELECT v_text; +END| +CALL p1(); +v_text +abc|def +DROP PROCEDURE p1; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 96bf2f01f86..50913fb1b90 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4921,7 +4921,7 @@ create table t3 as select * from v1| show create table t3| Table Create Table t3 CREATE TABLE `t3` ( - `j` bigint(11) default NULL + `j` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select * from t3| j diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result index c8cafe5ace1..bcde32572c2 100644 --- a/mysql-test/r/sp_notembedded.result +++ b/mysql-test/r/sp_notembedded.result @@ -206,3 +206,17 @@ drop procedure bug10100pd| drop procedure bug10100pc| drop view v1| drop table t3| +drop procedure if exists bug15298_1; +drop procedure if exists bug15298_2; +grant all privileges on test.* to 'mysqltest_1'@'localhost'; +create procedure 15298_1 () sql security definer show grants for current_user; +create procedure 15298_2 () sql security definer show grants; +call 15298_1(); +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +call 15298_2(); +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +drop user mysqltest_1@localhost; +drop procedure 15298_1; +drop procedure 15298_2; diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index 271cd7bf486..d0cf11d0511 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -1298,3 +1298,49 @@ t2 CREATE TABLE `t2` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t2,t1; set @@sql_mode= @org_mode; +set @@sql_mode='traditional'; +create table t1 (i int) +comment '123456789*123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*123456789*'; +ERROR HY000: Too long comment for table 't1' +create table t1 ( +i int comment +'123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*'); +ERROR HY000: Too long comment for field 'i' +set @@sql_mode= @org_mode; +create table t1 +(i int comment +'123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*'); +Warnings: +Warning 1105 Unknown error +select column_name, column_comment from information_schema.columns where +table_schema = 'test' and table_name = 't1'; +column_name column_comment +i 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* +drop table t1; +set names utf8; +create table t1 (i int) +comment '123456789*123456789*123456789*123456789*123456789*123456789*'; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='123456789*123456789*123456789*123456789*123456789*123456789*' +drop table t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 07630ffee0f..11dc68fe99b 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1087,24 +1087,24 @@ CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT 1)) a; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` bigint(1) NOT NULL default '0', - `(SELECT 1)` bigint(1) NOT NULL default '0' + `a` int(1) NOT NULL default '0', + `(SELECT 1)` int(1) NOT NULL default '0' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a)) a; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` bigint(1) NOT NULL default '0', - `(SELECT a)` bigint(1) NOT NULL default '0' + `a` int(1) NOT NULL default '0', + `(SELECT a)` int(1) NOT NULL default '0' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; CREATE TABLE t1 SELECT * FROM (SELECT 1 as a,(SELECT a+0)) a; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` bigint(1) NOT NULL default '0', - `(SELECT a+0)` bigint(3) NOT NULL default '0' + `a` int(1) NOT NULL default '0', + `(SELECT a+0)` int(3) NOT NULL default '0' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; CREATE TABLE t1 SELECT (SELECT 1 as a UNION SELECT 1+1 limit 1,1) as a; @@ -2854,6 +2854,40 @@ a 3 4 DROP TABLE t1,t2,t3; +purge master logs before (select adddate(current_timestamp(), interval -4 day)); +CREATE TABLE t1 (f1 INT); +CREATE TABLE t2 (f2 INT); +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 WHERE f1 > ALL (SELECT f2 FROM t2); +f1 +1 +SELECT * FROM t1 WHERE f1 > ALL (SELECT f2 FROM t2 WHERE 1=0); +f1 +1 +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2); +SELECT * FROM t1 WHERE f1 > ALL (SELECT f2 FROM t2 WHERE f2=0); +f1 +1 +DROP TABLE t1, t2; +select 1 from dual where 1 < any (select 2); +1 +1 +select 1 from dual where 1 < all (select 2); +1 +1 +select 1 from dual where 2 > any (select 1); +1 +1 +select 1 from dual where 2 > all (select 1); +1 +1 +select 1 from dual where 1 < any (select 2 from dual); +1 +1 +select 1 from dual where 1 < all (select 2 from dual where 1!=1); +1 +1 create table t1 (df decimal(5,1)); insert into t1 values(1.1); insert into t1 values(2.2); diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result index bd89c09e94d..1310a5b71dd 100644 --- a/mysql-test/r/type_ranges.result +++ b/mysql-test/r/type_ranges.result @@ -273,7 +273,7 @@ create table t2 (primary key (auto)) select auto+1 as auto,1 as t1, 'a' as t2, r show full columns from t2; Field Type Collation Null Key Default Extra Privileges Comment auto bigint(12) unsigned NULL NO PRI 0 # -t1 bigint(1) NULL NO 0 # +t1 int(1) NULL NO 0 # t2 varchar(1) latin1_swedish_ci NO # t3 varchar(256) latin1_swedish_ci NO # t4 varbinary(256) NULL NO # @@ -301,7 +301,7 @@ show full columns from t3; Field Type Collation Null Key Default Extra Privileges Comment c1 int(11) NULL YES NULL # c2 int(11) NULL YES NULL # -const bigint(1) NULL NO 0 # +const int(1) NULL NO 0 # drop table t1,t2,t3; create table t1 ( myfield INT NOT NULL, UNIQUE INDEX (myfield), unique (myfield), index(myfield)); drop table t1; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 72cffb9531c..7d2ab63ca77 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2735,4 +2735,42 @@ m e 4 a 1 b DROP VIEW v1; -DROP TABLE IF EXISTS t1,t2; +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT NOT NULL, b INT NULL DEFAULT NULL); +CREATE VIEW v1 AS SELECT a, b FROM t1; +INSERT INTO v1 (b) VALUES (2); +Warnings: +Warning 1423 Field of view 'test.v1' underlying table doesn't have a default value +SET SQL_MODE = STRICT_ALL_TABLES; +INSERT INTO v1 (b) VALUES (4); +ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default value +SET SQL_MODE = ''; +SELECT * FROM t1; +a b +0 2 +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (firstname text, surname text); +INSERT INTO t1 VALUES +("Bart","Simpson"),("Milhouse","van Houten"),("Montgomery","Burns"); +CREATE VIEW v1 AS SELECT CONCAT(firstname," ",surname) AS name FROM t1; +SELECT CONCAT(LEFT(name,LENGTH(name)-INSTR(REVERSE(name)," ")), +LEFT(name,LENGTH(name)-INSTR(REVERSE(name)," "))) AS f1 +FROM v1; +f1 +BartBart +Milhouse vanMilhouse van +MontgomeryMontgomery +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (i int, j int); +CREATE VIEW v1 AS SELECT COALESCE(i,j) FROM t1; +DESCRIBE v1; +Field Type Null Key Default Extra +COALESCE(i,j) int(11) YES NULL +CREATE TABLE t2 SELECT COALESCE(i,j) FROM t1; +DESCRIBE t2; +Field Type Null Key Default Extra +COALESCE(i,j) int(11) YES NULL +DROP VIEW v1; +DROP TABLE t1,t2; diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 0431957f602..7f63d790fb8 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -659,3 +659,56 @@ DROP VIEW test2.t3; DROP TABLE test2.t1, test1.t0; DROP DATABASE test2; DROP DATABASE test1; +DROP VIEW IF EXISTS v1; +DROP VIEW IF EXISTS v2; +DROP VIEW IF EXISTS v3; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP PROCEDURE IF EXISTS p1; +CREATE SQL SECURITY DEFINER VIEW v1 AS SELECT CURRENT_USER() AS cu; +CREATE FUNCTION f1() RETURNS VARCHAR(77) SQL SECURITY INVOKER +RETURN CURRENT_USER(); +CREATE SQL SECURITY DEFINER VIEW v2 AS SELECT f1() AS cu; +CREATE PROCEDURE p1(OUT cu VARCHAR(77)) SQL SECURITY INVOKER +SET cu= CURRENT_USER(); +CREATE FUNCTION f2() RETURNS VARCHAR(77) SQL SECURITY INVOKER +BEGIN +DECLARE cu VARCHAR(77); +CALL p1(cu); +RETURN cu; +END| +CREATE SQL SECURITY DEFINER VIEW v3 AS SELECT f2() AS cu; +CREATE USER mysqltest_u1@localhost; +GRANT ALL ON test.* TO mysqltest_u1@localhost; + +The following tests should all return 1. + +SELECT CURRENT_USER() = 'mysqltest_u1@localhost'; +CURRENT_USER() = 'mysqltest_u1@localhost' +1 +SELECT f1() = 'mysqltest_u1@localhost'; +f1() = 'mysqltest_u1@localhost' +1 +CALL p1(@cu); +SELECT @cu = 'mysqltest_u1@localhost'; +@cu = 'mysqltest_u1@localhost' +1 +SELECT f2() = 'mysqltest_u1@localhost'; +f2() = 'mysqltest_u1@localhost' +1 +SELECT cu = 'root@localhost' FROM v1; +cu = 'root@localhost' +1 +SELECT cu = 'root@localhost' FROM v2; +cu = 'root@localhost' +1 +SELECT cu = 'root@localhost' FROM v3; +cu = 'root@localhost' +1 +DROP VIEW v3; +DROP FUNCTION f2; +DROP PROCEDURE p1; +DROP FUNCTION f1; +DROP VIEW v2; +DROP VIEW v1; +DROP USER mysqltest_u1@localhost; diff --git a/mysql-test/r/wait_timeout.result b/mysql-test/r/wait_timeout.result index 683986abf5d..b865a17454d 100644 --- a/mysql-test/r/wait_timeout.result +++ b/mysql-test/r/wait_timeout.result @@ -1,3 +1,7 @@ +select 0; +0 +0 +flush status; select 1; 1 1 diff --git a/mysql-test/std_data/init_file.dat b/mysql-test/std_data/init_file.dat index 6105ca2ac1b..814e968eb31 100644 --- a/mysql-test/std_data/init_file.dat +++ b/mysql-test/std_data/init_file.dat @@ -1 +1,29 @@ select * from mysql.user as t1, mysql.user as t2, mysql.user as t3; +use test; + +drop table if exists t1; +create table t1 (x int); +drop table if exists t2; +create table t2 (y int); + +drop procedure if exists p1; +create definer=root@localhost procedure p1() select * from t1; +call p1(); +drop procedure p1; + +create definer=root@localhost procedure p1() insert into t1 values (3),(5),(7); +call p1(); + +drop function if exists f1; +create definer=root@localhost function f1() returns int return (select count(*) from t1); +insert into t2 set y = f1()*10; + +drop view if exists v1; +create definer=root@localhost view v1 as select f1(); +insert into t2 (y) select * from v1; + +create trigger trg1 after insert on t2 for each row insert into t1 values (new.y); +insert into t2 values (11), (13); +drop procedure p1; +drop function f1; +drop view v1; diff --git a/mysql-test/t/blackhole.test b/mysql-test/t/blackhole.test index 493f74ded3e..e40b84eb5cd 100644 --- a/mysql-test/t/blackhole.test +++ b/mysql-test/t/blackhole.test @@ -128,15 +128,3 @@ show binlog events; drop table t1,t2,t3; # End of 4.1 tests - -# -# BUG#10952 - alter table ... lost data without errors and warnings -# -drop table if exists t1; -create table t1 (c char(20)) engine=MyISAM; -insert into t1 values ("Monty"),("WAX"),("Walrus"); ---error 1031 -alter table t1 engine=blackhole; -drop table t1; - -# End of 5.0 tests diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test index c3dd68abb86..21c228145ac 100644 --- a/mysql-test/t/date_formats.test +++ b/mysql-test/t/date_formats.test @@ -262,6 +262,20 @@ select str_to_date("2003-04-05 g", "%Y-%m-%d") as f1, --enable_ps_protocol # +# Test of locale dependent date format (WL#2928 Date Translation NRE) +# +set names latin1; +select date_format('2004-01-01','%W (%a), %e %M (%b) %Y'); +set lc_time_names=ru_RU; +set names koi8r; +select date_format('2004-01-01','%W (%a), %e %M (%b) %Y'); +set lc_time_names=de_DE; +set names latin1; +select date_format('2004-01-01','%W (%a), %e %M (%b) %Y'); +set names latin1; +set lc_time_names=en_US; + +# # Bug #14016 # create table t1 (f1 datetime); diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index a8b16edc80a..773c9121af0 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1365,4 +1365,64 @@ drop table federated.t1, federated.t2; connection slave; drop table federated.t1, federated.t2; +# +# Additional test for bug#18437 "Wrong values inserted with a before +# update trigger on NDB table". SQL-layer didn't properly inform +# handler about fields which were read and set in triggers. In some +# cases this resulted in incorrect (garbage) values of OLD variables +# and lost changes to NEW variables. +# Since for federated engine only operation which is affected by wrong +# fields mark-up is handler::write_row() this file constains coverage +# for ON INSERT triggers only. Tests for other types of triggers reside +# in ndb_trigger.test. +# +--disable_warnings +drop table if exists federated.t1; +--enable_warnings +create table federated.t1 (a int, b int, c int); +connection master; +--disable_warnings +drop table if exists federated.t1; +drop table if exists federated.t2; +--enable_warnings +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval create table federated.t1 (a int, b int, c int) engine=federated connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; +create trigger federated.t1_bi before insert on federated.t1 for each row set new.c= new.a * new.b; +create table federated.t2 (a int, b int); +insert into federated.t2 values (13, 17), (19, 23); +# Each of three statements should correctly set values for all three fields +# insert +insert into federated.t1 (a, b) values (1, 2), (3, 5), (7, 11); +select * from federated.t1; +delete from federated.t1; +# insert ... select +insert into federated.t1 (a, b) select * from federated.t2; +select * from federated.t1; +delete from federated.t1; +# load +load data infile '../std_data_ln/loaddata5.dat' into table federated.t1 fields terminated by '' enclosed by '' ignore 1 lines (a, b); +select * from federated.t1; +drop tables federated.t1, federated.t2; + +connection slave; +drop table federated.t1; +# +# Bug #16494: Updates that set a column to NULL fail sometimes +# +connection slave; +create table t1 (id int not null auto_increment primary key, val int); +connection master; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval create table t1 + (id int not null auto_increment primary key, val int) engine=federated + connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; +insert into t1 values (1,0),(2,0); +update t1 set val = NULL where id = 1; +select * from t1; +connection slave; +select * from t1; +drop table t1; +connection master; +drop table t1; + source include/federated_cleanup.inc; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index b13fe039261..054da668584 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -685,6 +685,23 @@ select * from t1 where f1='test' and (f2= sha("test") or f2= sha("TEST")); select * from t1 where f1='test' and (f2= sha("TEST") or f2= sha("test")); drop table t1; +# +# Bug#18243: REVERSE changes its argument +# + +CREATE TABLE t1 (a varchar(10)); +INSERT INTO t1 VALUES ('abc'), ('xyz'); + +SELECT a, CONCAT(a,' ',a) AS c FROM t1 + HAVING LEFT(c,LENGTH(c)-INSTR(REVERSE(c)," ")) = a; + +SELECT a, CONCAT(a,' ',a) AS c FROM t1 + HAVING LEFT(CONCAT(a,' ',a), + LENGTH(CONCAT(a,' ',a))- + INSTR(REVERSE(CONCAT(a,' ',a))," ")) = a; + +DROP TABLE t1; + --echo End of 4.1 tests # diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 559f6c13d4a..188e5667009 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -143,12 +143,6 @@ select extract(SECOND FROM "1999-01-02 10:11:12"); select extract(MONTH FROM "2001-02-00"); # -# MySQL Bugs: #12356: DATE_SUB or DATE_ADD incorrectly returns null -# -SELECT DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); -SELECT DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); - -# # test EXTRACT QUARTER (Bug #18100) # @@ -164,7 +158,11 @@ SELECT EXTRACT(QUARTER FROM '2004-09-15') AS quarter; SELECT EXTRACT(QUARTER FROM '2004-10-15') AS quarter; SELECT EXTRACT(QUARTER FROM '2004-11-15') AS quarter; SELECT EXTRACT(QUARTER FROM '2004-12-15') AS quarter; - +# +# MySQL Bugs: #12356: DATE_SUB or DATE_ADD incorrectly returns null +# +SELECT DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); +SELECT DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); # # Test big intervals (Bug #3498) diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test index 02e45861706..163f2806ad2 100644 --- a/mysql-test/t/gis-rtree.test +++ b/mysql-test/t/gis-rtree.test @@ -187,4 +187,48 @@ check table t1 extended; drop table t1; +# +# Bug#17877 - Corrupted spatial index +# +CREATE TABLE t1 ( + c1 geometry NOT NULL default '', + SPATIAL KEY i1 (c1(32)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +INSERT INTO t1 (c1) VALUES ( + PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +# This showed a missing key. +CHECK TABLE t1 EXTENDED; +DROP TABLE t1; +# +CREATE TABLE t1 ( + c1 geometry NOT NULL default '', + SPATIAL KEY i1 (c1(32)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +INSERT INTO t1 (c1) VALUES ( + PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +INSERT INTO t1 (c1) VALUES ( + PolygonFromText('POLYGON((-65.7402776999 -96.6686111000, + -65.7372222000 -96.5516666000, + -65.8502777000 -96.5461111000, + -65.8527777000 -96.6627777000, + -65.7402776999 -96.6686111000))')); +# This is the same as the first insert to get a non-unique key. +INSERT INTO t1 (c1) VALUES ( + PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +# This showed (and still shows) OK. +CHECK TABLE t1 EXTENDED; +DROP TABLE t1; + # End of 4.1 tests diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 0bcd9ef8c0b..a2e19112cf9 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -852,3 +852,39 @@ create table t2(f1 char(5)); select concat(@a, table_name), @a, table_name from information_schema.tables where table_schema = 'test'; drop table t1,t2; + + +# +# Bug#20230: routine_definition is not null +# +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +CREATE PROCEDURE p1() SET @a= 1; +CREATE FUNCTION f1() RETURNS INT RETURN @a + 1; +CREATE USER mysql_bug20230@localhost; +GRANT EXECUTE ON PROCEDURE p1 TO mysql_bug20230@localhost; +GRANT EXECUTE ON FUNCTION f1 TO mysql_bug20230@localhost; + +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +SHOW CREATE PROCEDURE p1; +SHOW CREATE FUNCTION f1; + +connect (conn1, localhost, mysql_bug20230,,); + +SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES; +SHOW CREATE PROCEDURE p1; +SHOW CREATE FUNCTION f1; +CALL p1(); +SELECT f1(); + +disconnect conn1; +connection default; + +DROP FUNCTION f1; +DROP PROCEDURE p1; +DROP USER mysql_bug20230@localhost; + +# End of 5.0 tests. diff --git a/mysql-test/t/init_connect.test b/mysql-test/t/init_connect.test index 0ee6387d985..31a98df33df 100644 --- a/mysql-test/t/init_connect.test +++ b/mysql-test/t/init_connect.test @@ -35,4 +35,205 @@ select @a; connection con0; drop table t1; -# End of 4.1 tests +disconnect con1; +disconnect con2; +disconnect con3; +disconnect con4; +disconnect con5; + +--echo End of 4.1 tests +# +# Test 5.* features +# + +create table t1 (x int); +insert into t1 values (3), (5), (7); +create table t2 (y int); + +create user mysqltest1@localhost; +grant all privileges on test.* to mysqltest1@localhost; +# +# Create a simple procedure +# +set global init_connect="create procedure p1() select * from t1"; +connect (con1,localhost,mysqltest1,,); +connection con1; +call p1(); +drop procedure p1; + +connection con0; +disconnect con1; +# +# Create a multi-result set procedure +# +set global init_connect="create procedure p1(x int)\ +begin\ + select count(*) from t1;\ + select * from t1;\ + set @x = x; +end"; +connect (con1,localhost,mysqltest1,,); +connection con1; +call p1(42); +select @x; + +connection con0; +disconnect con1; +# +# Just call it - this will not generate any output +# +set global init_connect="call p1(4711)"; +connect (con1,localhost,mysqltest1,,); +connection con1; +select @x; + +connection con0; +disconnect con1; +# +# Drop the procedure +# +set global init_connect="drop procedure if exists p1"; +connect (con1,localhost,mysqltest1,,); +connection con1; +--error ER_SP_DOES_NOT_EXIST +call p1(); + +connection con0; +disconnect con1; +# +# Execution of a more complex procedure +# +delimiter |; +create procedure p1(out sum int) +begin + declare n int default 0; + declare c cursor for select * from t1; + declare exit handler for not found + begin + close c; + set sum = n; + end; + + open c; + loop + begin + declare x int; + + fetch c into x; + if x > 3 then + set n = n + x; + end if; + end; + end loop; +end| +delimiter ;| +# Call the procedure with a cursor +set global init_connect="call p1(@sum)"; +connect (con1,localhost,mysqltest1,,); +connection con1; +select @sum; + +connection con0; +disconnect con1; +drop procedure p1; +# +# Test Dynamic SQL +# +delimiter |; +create procedure p1(tbl char(10), v int) +begin + set @s = concat('insert into ', tbl, ' values (?)'); + set @v = v; + prepare stmt1 from @s; + execute stmt1 using @v; + deallocate prepare stmt1; +end| +delimiter ;| +# Call the procedure with prepared statements +set global init_connect="call p1('t1', 11)"; +connect (con1,localhost,mysqltest1,,); +connection con1; +select * from t1; + +connection con0; +disconnect con1; +drop procedure p1; +# +# Stored functions +# +delimiter |; +create function f1() returns int +begin + declare n int; + + select count(*) into n from t1; + return n; +end| +delimiter ;| +# Invoke a function +set global init_connect="set @x = f1()"; +connect (con1,localhost,mysqltest1,,); +connection con1; +select @x; + +connection con0; +disconnect con1; +# +# Create a view +# +set global init_connect="create view v1 as select f1()"; +connect (con1,localhost,mysqltest1,,); +connection con1; +select * from v1; + +connection con0; +disconnect con1; +# +# Drop the view +# +set global init_connect="drop view v1"; +connect (con1,localhost,mysqltest1,,); +connection con1; +--error ER_NO_SUCH_TABLE +select * from v1; + +connection con0; +disconnect con1; +drop function f1; + +# We can't test "create trigger", since this requires super privileges +# in 5.0, but with super privileges, init_connect is not executed. +# (However, this can be tested in 5.1) +# +#set global init_connect="create trigger trg1\ +# after insert on t2\ +# for each row\ +# insert into t1 values (new.y)"; +#connect (con1,localhost,mysqltest1,,); +#connection con1; +#insert into t2 values (2), (4); +#select * from t1; +# +#connection con0; +#disconnect con1; + +create trigger trg1 + after insert on t2 + for each row + insert into t1 values (new.y); + +# Invoke trigger +set global init_connect="insert into t2 values (13), (17), (19)"; +connect (con1,localhost,mysqltest1,,); +connection con1; +select * from t1; + +connection con0; +disconnect con1; + +drop trigger trg1; +set global init_connect=default; + +revoke all privileges, grant option from mysqltest1@localhost; +drop user mysqltest1@localhost; +drop table t1, t2; diff --git a/mysql-test/t/init_file.test b/mysql-test/t/init_file.test index 8b4b788777b..6b5e032fd99 100644 --- a/mysql-test/t/init_file.test +++ b/mysql-test/t/init_file.test @@ -6,5 +6,15 @@ # mysql-test/t/init_file-master.opt for the actual test # -# End of 4.1 tests -echo ok; +--echo ok +--echo end of 4.1 tests +# +# Chec 5.x features +# +# Expected: +# 3, 5, 7, 11, 13 +select * from t1; +# Expected: +# 30, 3, 11, 13 +select * from t2; +drop table t1, t2; diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index c7d2e2c0acd..4b512ccce1d 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -59,6 +59,38 @@ where drop table t1, t2; # +# Bug#17212: results not sorted correctly by ORDER BY when using index +# (repeatable only w/innodb because of index props) +# +CREATE TABLE t1 (a int, b int, KEY b (b)) Engine=InnoDB; +CREATE TABLE t2 (a int, b int, PRIMARY KEY (a,b)) Engine=InnoDB; +CREATE TABLE t3 (a int, b int, c int, PRIMARY KEY (a), + UNIQUE KEY b (b,c), KEY a (a,b,c)) Engine=InnoDB; + +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 SELECT a + 1, b + 1 FROM t1; +INSERT INTO t1 SELECT a + 2, b + 2 FROM t1; + +INSERT INTO t2 VALUES (1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8); +INSERT INTO t2 SELECT a + 1, b FROM t2; +DELETE FROM t2 WHERE a = 1 AND b < 2; + +INSERT INTO t3 VALUES (1,1,1),(2,1,2); +INSERT INTO t3 SELECT a + 2, a + 2, 3 FROM t3; +INSERT INTO t3 SELECT a + 4, a + 4, 3 FROM t3; + +# demonstrate a problem when a must-use-sort table flag +# (sort_by_table=1) is being neglected. +SELECT STRAIGHT_JOIN SQL_NO_CACHE t1.b, t1.a FROM t1, t3, t2 WHERE + t3.a = t2.a AND t2.b = t1.a AND t3.b = 1 AND t3.c IN (1, 2) + ORDER BY t1.b LIMIT 2; + +# demonstrate the problem described in the bug report +SELECT STRAIGHT_JOIN SQL_NO_CACHE t1.b, t1.a FROM t1, t3, t2 WHERE + t3.a = t2.a AND t2.b = t1.a AND t3.b = 1 AND t3.c IN (1, 2) + ORDER BY t1.b LIMIT 5; +DROP TABLE t1, t2, t3; +# # Bug #12882 min/max inconsistent on empty table # diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index e7072ae29f6..3767f5f885e 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -334,6 +334,7 @@ create table t1 ( UNIQUE i1idx (i1), UNIQUE i2idx (i2)); desc t1; +show create table t1; drop table t1; # diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 400279a826b..639129e1393 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -381,16 +381,6 @@ drop table t1, t2, t3; # End of 4.1 tests # -# BUG#10952 - alter table ... lost data without errors and warnings -# -drop table if exists t1; -create table t1 (c char(20)) engine=MyISAM; -insert into t1 values ("Monty"),("WAX"),("Walrus"); ---error 1031 -alter table t1 engine=MERGE; -drop table t1; - -# # BUG#19648 - Merge table does not work with bit types # create table t1 (b bit(1)); diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 56e799f00b6..7dee5ebdf41 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -718,8 +718,6 @@ UPDATE t1 AS ta1,t1 AS ta2 SET ta1.b='aaaaaa',ta2.b='bbbbbb'; SELECT * FROM t1; DROP TABLE t1; -# End of 4.1 tests - # # Test varchar # @@ -844,3 +842,39 @@ create table t3 (c1 int) engine=myisam pack_keys=default; --error 1064 create table t4 (c1 int) engine=myisam pack_keys=2; drop table t1, t2, t3; +# +# Bug#8706 - temporary table with data directory option fails +# +connect (session1,localhost,root,,); +connect (session2,localhost,root,,); + +connection session1; +disable_query_log; +eval create temporary table t1 (a int) engine=myisam data directory="$MYSQLTEST_VARDIR/tmp" select 9 a; +enable_query_log; +disable_result_log; +show create table t1; +enable_result_log; + +connection session2; +disable_query_log; +eval create temporary table t1 (a int) engine=myisam data directory="$MYSQLTEST_VARDIR/tmp" select 99 a; +enable_query_log; +disable_result_log; +show create table t1; +enable_result_log; + +connection default; +create table t1 (a int) engine=myisam select 42 a; + +connection session1; +select * from t1; +disconnect session1; +connection session2; +select * from t1; +disconnect session2; +connection default; +select * from t1; +drop table t1; + +# End of 4.1 tests diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 7e4fedb297d..4a355897adb 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -610,7 +610,7 @@ drop database db1; # BUG#15328 Segmentation fault occured if my.cnf is invalid for escape sequence # ---exec $MYSQL_MY_PRINT_DEFAULTS --config-file=$MYSQL_TEST_DIR/std_data/bug15328.cnf mysqldump +--exec $MYSQL_MY_PRINT_DEFAULTS --defaults-file=$MYSQL_TEST_DIR/std_data/bug15328.cnf mysqldump # @@ -1155,12 +1155,11 @@ insert into t values(5, 51); create view v1 as select qty, price, qty*price as value from t; create view v2 as select qty from v1; --echo mysqldump { ---exec $MYSQL_DUMP --compact -F --tab . test ---exec cat v1.sql +--exec $MYSQL_DUMP --compact -F --tab $MYSQLTEST_VARDIR/tmp test +--exec cat $MYSQLTEST_VARDIR/tmp/v1.sql --echo } mysqldump { ---exec cat v2.sql +--exec cat $MYSQLTEST_VARDIR/tmp/v2.sql --echo } mysqldump ---rm v.sql t.sql t.txt drop view v1; drop view v2; drop table t; diff --git a/mysql-test/t/ndb_replace.test b/mysql-test/t/ndb_replace.test index 94a11f7dfb2..476a607ed44 100644 --- a/mysql-test/t/ndb_replace.test +++ b/mysql-test/t/ndb_replace.test @@ -39,6 +39,7 @@ INSERT INTO t1 VALUES (1,1,23),(2,2,24); REPLACE INTO t1 (j,k) VALUES (1,42); REPLACE INTO t1 (i,j) VALUES (17,2); SELECT * from t1 ORDER BY i; +DROP TABLE t1; # bug#19906 CREATE TABLE t2 (a INT(11) NOT NULL, @@ -64,4 +65,40 @@ SELECT * FROM t2 ORDER BY id; DROP TABLE t2; +# +# Bug #20728 "REPLACE does not work correctly for NDB table with PK and +# unique index" +# +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (pk int primary key, apk int unique, data int) engine=ndbcluster; +# Test for plain replace which updates pk +insert into t1 values (1, 1, 1), (2, 2, 2), (3, 3, 3); +replace into t1 (pk, apk) values (4, 1), (5, 2); +select * from t1 order by pk; +delete from t1; +# Another test for plain replace which doesn't touch pk +insert into t1 values (1, 1, 1), (2, 2, 2), (3, 3, 3); +replace into t1 (pk, apk) values (1, 4), (2, 5); +select * from t1 order by pk; +delete from t1; +# Test for load data replace which updates pk +insert into t1 values (1, 1, 1), (4, 4, 4), (6, 6, 6); +load data infile '../std_data_ln/loaddata5.dat' replace into table t1 fields terminated by '' enclosed by '' ignore 1 lines (pk, apk); +select * from t1 order by pk; +delete from t1; +# Now test for load data replace which doesn't touch pk +insert into t1 values (1, 1, 1), (3, 3, 3), (5, 5, 5); +load data infile '../std_data_ln/loaddata5.dat' replace into table t1 fields terminated by '' enclosed by '' ignore 1 lines (pk, apk); +select * from t1 order by pk; +delete from t1; +# Finally test for both types of replace ... select +insert into t1 values (1, 1, 1), (2, 2, 2), (3, 3, 3); +replace into t1 (pk, apk) select 4, 1; +replace into t1 (pk, apk) select 2, 4; +select * from t1 order by pk; +# Clean-up +drop table t1; +--echo End of 5.0 tests. diff --git a/mysql-test/t/ndb_restore.test b/mysql-test/t/ndb_restore.test index 049b07d5a8b..39c7ab67efb 100644 --- a/mysql-test/t/ndb_restore.test +++ b/mysql-test/t/ndb_restore.test @@ -4,8 +4,8 @@ --disable_warnings use test; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; +drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c,t10_c; --enable_warnings CREATE TABLE `t1` ( @@ -132,6 +132,13 @@ CREATE TABLE `t9` ( ) ENGINE=myisam DEFAULT CHARSET=latin1; INSERT INTO `t9` VALUES ('3g4jh8gar2t','joe','q3.net','elredun.com','q3.net','436643316120','436643316939','91341234568968','695595699','1.1.1.1','2.2.6.2','3','86989','34','x','x','2012-03-12 18:35:04','2012-12-05 12:35:04',3123123,9569,6565,1),('4tt45345235','pap','q3plus.qt','q3plus.qt','q3.net','436643316120','436643316939','8956234534568968','5254595969','1.1.1.1','8.6.2.2','4','86989','34','x','x','2012-03-12 12:55:34','2012-12-05 11:20:04',3223433,3369,9565,2),('4545435545','john','q3.net','q3.net','acne.li','436643316120','436643316939','45345234568968','995696699','1.1.1.1','2.9.9.2','2','86998','34','x','x','2012-03-12 11:35:03','2012-12-05 08:50:04',8823123,169,3565,3); +# Bug #20820 +# auto inc table not handled correctly when restored from cluster backup +# - before fix ndb_restore would not set auto inc value correct, +# seen by select below +create table t10 (a int auto_increment key); +insert into t10 values (1),(2),(3); + create table t1_c engine=ndbcluster as select * from t1; create table t2_c engine=ndbcluster as select * from t2; create table t3_c engine=ndbcluster as select * from t3; @@ -141,10 +148,11 @@ create table t6_c engine=ndbcluster as select * from t6; create table t7_c engine=ndbcluster as select * from t7; create table t8_c engine=ndbcluster as select * from t8; create table t9_c engine=ndbcluster as select * from t9; +create table t10_c engine=ndbcluster as select * from t10; --exec $NDB_MGM --no-defaults -e "start backup" >> $NDB_TOOLS_OUTPUT -drop table t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c; +drop table t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c, t10_c; --exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-1 >> $NDB_TOOLS_OUTPUT --exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b 1 -n 2 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-1 >> $NDB_TOOLS_OUTPUT @@ -205,9 +213,12 @@ select count(*) from (select * from t9 union select * from t9_c) a; +# Bug #20820 cont'd +select * from t10_c order by a; + --disable_warnings -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9, t10; +drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c, t10_c; --enable_warnings # @@ -216,4 +227,4 @@ drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c; --exec $NDB_TOOLS_DIR/ndb_select_all --no-defaults -d sys -D , SYSTAB_0 | grep 520093696 -# End of 4.1 tests +# End of 5.0 tests (4.1 test intermixed to save test time) diff --git a/mysql-test/t/ndb_trigger.test b/mysql-test/t/ndb_trigger.test new file mode 100644 index 00000000000..2521ef17842 --- /dev/null +++ b/mysql-test/t/ndb_trigger.test @@ -0,0 +1,92 @@ +# Tests which involve triggers and NDB storage engine +--source include/have_ndb.inc +--source include/not_embedded.inc + +# +# Test for bug#18437 "Wrong values inserted with a before update +# trigger on NDB table". SQL-layer didn't properly inform handler +# about fields which were read and set in triggers. In some cases +# this resulted in incorrect (garbage) values of OLD variables and +# lost changes to NEW variables. +# You can find similar tests for ON INSERT triggers in federated.test +# since this engine so far is the only engine in MySQL which cares +# about field mark-up during handler::write_row() operation. +# + +--disable_warnings +drop table if exists t1, t2, t3; +--enable_warnings + +create table t1 (id int primary key, a int not null, b decimal (63,30) default 0) engine=ndb; +create table t2 (op char(1), a int not null, b decimal (63,30)); +create table t3 select 1 as i; + +delimiter //; +create trigger t1_bu before update on t1 for each row +begin + insert into t2 values ("u", old.a, old.b); + set new.b = old.b + 10; +end;// +create trigger t1_bd before delete on t1 for each row +begin + insert into t2 values ("d", old.a, old.b); +end;// +delimiter ;// +insert into t1 values (1, 1, 1.05), (2, 2, 2.05), (3, 3, 3.05), (4, 4, 4.05); + +# Check that usual update works as it should +update t1 set a=5 where a != 3; +select * from t1 order by id; +select * from t2 order by op, a, b; +delete from t2; +# Check that everything works for multi-update +update t1, t3 set a=6 where a = 5; +select * from t1 order by id; +select * from t2 order by op, a, b; +delete from t2; +# Check for delete +delete from t1 where a != 3; +select * from t1 order by id; +select * from t2 order by op, a, b; +delete from t2; +# Check for multi-delete +insert into t1 values (1, 1, 1.05), (2, 2, 2.05), (4, 4, 4.05); +delete t1 from t1, t3 where a != 3; +select * from t1 order by id; +select * from t2 order by op, a, b; +delete from t2; +# Check for insert ... on duplicate key update +insert into t1 values (4, 4, 4.05); +insert into t1 (id, a) values (4, 1), (3, 1) on duplicate key update a= a + 1; +select * from t1 order by id; +select * from t2 order by op, a, b; +delete from t2; +# Check for insert ... select ... on duplicate key update +delete from t3; +insert into t3 values (4), (3); +insert into t1 (id, a) (select i, 1 from t3) on duplicate key update a= a + 1; +select * from t1 order by id; +select * from t2 order by op, a, b; +delete from t2; +# Check for replace +replace into t1 (id, a) values (4, 1), (3, 1); +select * from t1 order by id; +select * from t2 order by op, a, b; +delete from t1; +delete from t2; +# Check for replace ... select ... +insert into t1 values (3, 1, 1.05), (4, 1, 2.05); +replace into t1 (id, a) (select i, 2 from t3); +select * from t1 order by id; +select * from t2 order by op, a, b; +delete from t1; +delete from t2; +# Check for load data replace +insert into t1 values (3, 1, 1.05), (5, 2, 2.05); +load data infile '../std_data_ln/loaddata5.dat' replace into table t1 fields terminated by '' enclosed by '' ignore 1 lines (id, a); +select * from t1 order by id; +select * from t2 order by op, a, b; + +drop tables t1, t2, t3; + +--echo End of 5.0 tests diff --git a/mysql-test/t/odbc.test b/mysql-test/t/odbc.test index d4b6fc35e74..6a754bb32a7 100644 --- a/mysql-test/t/odbc.test +++ b/mysql-test/t/odbc.test @@ -21,4 +21,14 @@ select * from t1 where a is null; explain select * from t1 where b is null; drop table t1; +# +# Bug #14553: NULL in WHERE resets LAST_INSERT_ID +# +CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY); +INSERT INTO t1 VALUES (NULL); +SELECT sql_no_cache a, last_insert_id() FROM t1 WHERE a IS NULL; +SELECT sql_no_cache a, last_insert_id() FROM t1 WHERE a IS NULL; +SELECT sql_no_cache a, last_insert_id() FROM t1; +DROP TABLE t1; + # End of 4.1 tests diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index f6493bac244..d53b05b98b1 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -490,6 +490,31 @@ SELECT count(*) FROM t1 WHERE CLIENT='000' AND (ARG1 != ' 1' OR ARG1 != ' 2'); SELECT count(*) FROM t1 WHERE CLIENT='000' AND (ARG1 != ' 2' OR ARG1 != ' 1'); drop table t1; +# BUG#16168: Wrong range optimizer results, "Use_count: Wrong count ..." +# warnings in server stderr. +create table t1 (a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +CREATE TABLE t2 ( + pk1 int(11) NOT NULL, + pk2 int(11) NOT NULL, + pk3 int(11) NOT NULL, + pk4 int(11) NOT NULL, + filler char(82), + PRIMARY KEY (pk1,pk2,pk3,pk4) +) DEFAULT CHARSET=latin1; + +insert into t2 select 1, A.a+10*B.a, 432, 44, 'fillerZ' from t1 A, t1 B; +INSERT INTO t2 VALUES (2621, 2635, 0, 0,'filler'), (2621, 2635, 1, 0,'filler'), + (2621, 2635, 10, 0,'filler'), (2621, 2635, 11, 0,'filler'), + (2621, 2635, 14, 0,'filler'), (2621, 2635, 1000015, 0,'filler'); + +SELECT * FROM t2 +WHERE ((((pk4 =0) AND (pk1 =2621) AND (pk2 =2635))) +OR ((pk4 =1) AND (((pk1 IN ( 7, 2, 1 ))) OR (pk1 =522)) AND ((pk2 IN ( 0, 2635)))) +) AND (pk3 >=1000000); +drop table t1, t2; + # End of 4.1 tests # diff --git a/mysql-test/t/rpl_auto_increment.test b/mysql-test/t/rpl_auto_increment.test index 71032404307..caa2b79feb5 100644 --- a/mysql-test/t/rpl_auto_increment.test +++ b/mysql-test/t/rpl_auto_increment.test @@ -96,9 +96,47 @@ select * from t1; sync_slave_with_master; select * from t1; -connection master; +# Test for BUG#20524 "auto_increment_* not observed when inserting +# a too large value". When an autogenerated value was bigger than the +# maximum possible value of the field, it was truncated to that max +# possible value, without being "rounded down" to still honour +# auto_increment_* variables. + +connection master; drop table t1; +create table t1 (a tinyint not null auto_increment primary key) engine=myisam; +insert into t1 values(103); +set auto_increment_increment=11; +set auto_increment_offset=4; +insert into t1 values(null); +insert into t1 values(null); +--error 1062 +insert into t1 values(null); +select a, mod(a-@@auto_increment_offset,@@auto_increment_increment) from t1 order by a; + +# same but with a larger value +create table t2 (a tinyint unsigned not null auto_increment primary key) engine=myisam; +set auto_increment_increment=10; +set auto_increment_offset=1; +set insert_id=1000; +insert into t2 values(null); +select a, mod(a-@@auto_increment_offset,@@auto_increment_increment) from t2 order by a; + +# An offset so big that even first value does not fit +create table t3 like t1; +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t3 values(null); +select * from t3 order by a; +sync_slave_with_master; +select * from t1 order by a; +select * from t2 order by a; +select * from t3 order by a; + +connection master; + +drop table t1,t2,t3; # End cleanup sync_slave_with_master; diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test index e038829760d..fa66306aaa6 100644 --- a/mysql-test/t/rpl_insert_id.test +++ b/mysql-test/t/rpl_insert_id.test @@ -77,6 +77,24 @@ sync_slave_with_master; connection master; drop table t1; sync_slave_with_master; + +# +# Bug#14553: NULL in WHERE resets LAST_INSERT_ID +# +connection master; +create table t1(a int auto_increment, key(a)); +create table t2(a int); +insert into t1 (a) values (null); +insert into t2 (a) select a from t1 where a is null; +insert into t2 (a) select a from t1 where a is null; +select * from t2; +sync_slave_with_master; +connection slave; +select * from t2; +connection master; +drop table t1; +drop table t2; +sync_slave_with_master; # End of 4.1 tests @@ -147,6 +165,69 @@ drop function bug15728; drop function bug15728_insert; drop table t1, t2; +# test of BUG#20188 REPLACE or ON DUPLICATE KEY UPDATE in +# auto_increment breaks binlog + +create table t1 (n int primary key auto_increment not null, +b int, unique(b)); + +# First, test that we do not call restore_auto_increment() too early +# in write_record(): +set sql_log_bin=0; +insert into t1 values(null,100); +replace into t1 values(null,50),(null,100),(null,150); +select * from t1 order by n; +truncate table t1; +set sql_log_bin=1; + +insert into t1 values(null,100); +select * from t1 order by n; +sync_slave_with_master; +# make slave's table autoinc counter bigger +insert into t1 values(null,200),(null,300); +delete from t1 where b <> 100; +# check that slave's table content is identical to master +select * from t1 order by n; +# only the auto_inc counter differs. + +connection master; +replace into t1 values(null,100),(null,350); +select * from t1 order by n; +sync_slave_with_master; +select * from t1 order by n; + +# Same test as for REPLACE, but for ON DUPLICATE KEY UPDATE + +# We first check that if we update a row using a value larger than the +# table's counter, the counter for next row is bigger than the +# after-value of the updated row. +connection master; +insert into t1 values (NULL,400),(3,500),(NULL,600) on duplicate key UPDATE n=1000; +select * from t1 order by n; +sync_slave_with_master; +select * from t1 order by n; + +# and now test for the bug: +connection master; +drop table t1; +create table t1 (n int primary key auto_increment not null, +b int, unique(b)); +insert into t1 values(null,100); +select * from t1 order by n; +sync_slave_with_master; +insert into t1 values(null,200),(null,300); +delete from t1 where b <> 100; +select * from t1 order by n; + +connection master; +insert into t1 values(null,100),(null,350) on duplicate key update n=2; +select * from t1 order by n; +sync_slave_with_master; +select * from t1 order by n; + +connection master; +drop table t1; + # End of 5.0 tests sync_slave_with_master; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index b75d0dd8bb6..b44f682c02e 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2901,3 +2901,8 @@ from t1 left outer join t2 on t1.a = t2.c and t2.b <> 1 where t1.b <> 1 order by t1.a; drop table t1,t2; + +# +# Bug #20569: Garbage in DECIMAL results from some mathematical functions +# +SELECT 0.9888889889 * 1.011111411911; diff --git a/mysql-test/t/sp-vars.test b/mysql-test/t/sp-vars.test index 81504904797..48dbd4de7aa 100644 --- a/mysql-test/t/sp-vars.test +++ b/mysql-test/t/sp-vars.test @@ -1271,3 +1271,39 @@ SELECT f1(); # DROP FUNCTION f1; + + +# +# Bug#17226: Variable set in cursor on first iteration is assigned +# second iterations value +# +# The problem was in incorrect handling of local variables of type +# TEXT (BLOB). +# +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +--enable_warnings + +delimiter |; +CREATE PROCEDURE p1() +BEGIN + DECLARE v_char VARCHAR(255); + DECLARE v_text TEXT DEFAULT ''; + + SET v_char = 'abc'; + + SET v_text = v_char; + + SET v_char = 'def'; + + SET v_text = concat(v_text, '|', v_char); + + SELECT v_text; +END| +delimiter ;| + +CALL p1(); + +DROP PROCEDURE p1; + +# End of 5.0 tests. diff --git a/mysql-test/t/sp_notembedded.test b/mysql-test/t/sp_notembedded.test index 0adbeb2d98b..b087f699f86 100644 --- a/mysql-test/t/sp_notembedded.test +++ b/mysql-test/t/sp_notembedded.test @@ -265,3 +265,23 @@ drop view v1| drop table t3| delimiter ;| + +# +# Bug#15298 SHOW GRANTS FOR CURRENT_USER: Incorrect output in DEFINER context +# +--disable_warnings +drop procedure if exists bug15298_1; +drop procedure if exists bug15298_2; +--enable_warnings +grant all privileges on test.* to 'mysqltest_1'@'localhost'; +create procedure 15298_1 () sql security definer show grants for current_user; +create procedure 15298_2 () sql security definer show grants; + +connect (con1,localhost,mysqltest_1,,test); +call 15298_1(); +call 15298_2(); + +connection default; +drop user mysqltest_1@localhost; +drop procedure 15298_1; +drop procedure 15298_2; diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test index 5044a20ae9f..ce269b42ee9 100644 --- a/mysql-test/t/strict.test +++ b/mysql-test/t/strict.test @@ -1155,3 +1155,42 @@ create table t2 select date from t1; show create table t2; drop table t2,t1; set @@sql_mode= @org_mode; + +# +# Bug #13934 Silent truncation of table comments +# +set @@sql_mode='traditional'; +--error 1105 +create table t1 (i int) +comment '123456789*123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*123456789*'; +--error 1105 +create table t1 ( +i int comment +'123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*'); +set @@sql_mode= @org_mode; +create table t1 +(i int comment + '123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789* + 123456789*123456789*123456789*123456789*'); + +select column_name, column_comment from information_schema.columns where +table_schema = 'test' and table_name = 't1'; +drop table t1; + +set names utf8; +create table t1 (i int) +comment '123456789*123456789*123456789*123456789*123456789*123456789*'; +show create table t1; +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 8916a5cec6d..9fc4f8a8d4e 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1821,6 +1821,36 @@ SELECT * FROM t1 DROP TABLE t1,t2,t3; +# +# BUG #10308: purge log with subselect +# + +purge master logs before (select adddate(current_timestamp(), interval -4 day)); + + +# +# Bug#18503: Queries with a quantified subquery returning empty set may +# return a wrong result. +# +CREATE TABLE t1 (f1 INT); +CREATE TABLE t2 (f2 INT); +INSERT INTO t1 VALUES (1); +SELECT * FROM t1 WHERE f1 > ALL (SELECT f2 FROM t2); +SELECT * FROM t1 WHERE f1 > ALL (SELECT f2 FROM t2 WHERE 1=0); +INSERT INTO t2 VALUES (1); +INSERT INTO t2 VALUES (2); +SELECT * FROM t1 WHERE f1 > ALL (SELECT f2 FROM t2 WHERE f2=0); +DROP TABLE t1, t2; + +# +# Bug#16302: Quantified subquery without any tables gives wrong results +# +select 1 from dual where 1 < any (select 2); +select 1 from dual where 1 < all (select 2); +select 1 from dual where 2 > any (select 1); +select 1 from dual where 2 > all (select 1); +select 1 from dual where 1 < any (select 2 from dual); +select 1 from dual where 1 < all (select 2 from dual where 1!=1); # End of 4.1 tests # diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index a1c1e9b2ad1..88a4d489039 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2595,4 +2595,51 @@ CREATE TABLE t2 SELECT * FROM v1; SELECT * FROM t2; DROP VIEW v1; -DROP TABLE IF EXISTS t1,t2; +DROP TABLE t1,t2; + +# +# Bug#16110: insert permitted into view col w/o default value +# +CREATE TABLE t1 (a INT NOT NULL, b INT NULL DEFAULT NULL); +CREATE VIEW v1 AS SELECT a, b FROM t1; + +INSERT INTO v1 (b) VALUES (2); + +SET SQL_MODE = STRICT_ALL_TABLES; +--error 1423 +INSERT INTO v1 (b) VALUES (4); +SET SQL_MODE = ''; + +SELECT * FROM t1; + +DROP VIEW v1; +DROP TABLE t1; + +# +# Bug #18243: expression over a view column that with the REVERSE function +# + +CREATE TABLE t1 (firstname text, surname text); +INSERT INTO t1 VALUES + ("Bart","Simpson"),("Milhouse","van Houten"),("Montgomery","Burns"); + +CREATE VIEW v1 AS SELECT CONCAT(firstname," ",surname) AS name FROM t1; +SELECT CONCAT(LEFT(name,LENGTH(name)-INSTR(REVERSE(name)," ")), + LEFT(name,LENGTH(name)-INSTR(REVERSE(name)," "))) AS f1 + FROM v1; + +DROP VIEW v1; +DROP TABLE t1; + +# +# Bug #19714: wrong type of a view column specified by an expressions over ints +# + +CREATE TABLE t1 (i int, j int); +CREATE VIEW v1 AS SELECT COALESCE(i,j) FROM t1; +DESCRIBE v1; +CREATE TABLE t2 SELECT COALESCE(i,j) FROM t1; +DESCRIBE t2; + +DROP VIEW v1; +DROP TABLE t1,t2; diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 429a2af6bac..c75e5422de7 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -866,3 +866,65 @@ DROP VIEW test2.t3; DROP TABLE test2.t1, test1.t0; DROP DATABASE test2; DROP DATABASE test1; + + +# +# BUG#20570: CURRENT_USER() in a VIEW with SQL SECURITY DEFINER +# returns invoker name +# +--disable_warnings +DROP VIEW IF EXISTS v1; +DROP VIEW IF EXISTS v2; +DROP VIEW IF EXISTS v3; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP PROCEDURE IF EXISTS p1; +--enable_warnings + +CREATE SQL SECURITY DEFINER VIEW v1 AS SELECT CURRENT_USER() AS cu; + +CREATE FUNCTION f1() RETURNS VARCHAR(77) SQL SECURITY INVOKER + RETURN CURRENT_USER(); +CREATE SQL SECURITY DEFINER VIEW v2 AS SELECT f1() AS cu; + +CREATE PROCEDURE p1(OUT cu VARCHAR(77)) SQL SECURITY INVOKER + SET cu= CURRENT_USER(); +delimiter |; +CREATE FUNCTION f2() RETURNS VARCHAR(77) SQL SECURITY INVOKER +BEGIN + DECLARE cu VARCHAR(77); + CALL p1(cu); + RETURN cu; +END| +delimiter ;| +CREATE SQL SECURITY DEFINER VIEW v3 AS SELECT f2() AS cu; + +CREATE USER mysqltest_u1@localhost; +GRANT ALL ON test.* TO mysqltest_u1@localhost; + +connect (conn1, localhost, mysqltest_u1,,); + +--echo +--echo The following tests should all return 1. +--echo +SELECT CURRENT_USER() = 'mysqltest_u1@localhost'; +SELECT f1() = 'mysqltest_u1@localhost'; +CALL p1(@cu); +SELECT @cu = 'mysqltest_u1@localhost'; +SELECT f2() = 'mysqltest_u1@localhost'; +SELECT cu = 'root@localhost' FROM v1; +SELECT cu = 'root@localhost' FROM v2; +SELECT cu = 'root@localhost' FROM v3; + +disconnect conn1; +connection default; + +DROP VIEW v3; +DROP FUNCTION f2; +DROP PROCEDURE p1; +DROP FUNCTION f1; +DROP VIEW v2; +DROP VIEW v1; +DROP USER mysqltest_u1@localhost; + +# End of 5.0 tests. diff --git a/mysql-test/t/wait_timeout.test b/mysql-test/t/wait_timeout.test index 8387c08c902..195d1a5d3f2 100644 --- a/mysql-test/t/wait_timeout.test +++ b/mysql-test/t/wait_timeout.test @@ -9,16 +9,20 @@ # Connect with another connection and reset counters --disable_query_log connect (wait_con,localhost,root,,test,,); -flush status; # Reset counters connection wait_con; set session wait_timeout=100; let $retries=300; -let $aborted_clients = `SHOW STATUS LIKE 'aborted_clients'`; set @aborted_clients= 0; --enable_query_log # Disable reconnect and do the query connection default; +# If slow host (Valgrind...), we may have already timed out here. +# So force a reconnect if necessary, using a dummy query. And issue a +# 'flush status' to reset the 'aborted_clients' counter. +--enable_reconnect +select 0; +flush status; --disable_reconnect select 1; @@ -46,6 +50,9 @@ connection default; select 2; --enable_reconnect select 3; +# Disconnect so that we will not be confused by a future abort from this +# connection. +disconnect default # # Do the same test as above on a TCP connection @@ -56,7 +63,6 @@ select 3; connection wait_con; flush status; # Reset counters let $retries=300; -let $aborted_clients = `SHOW STATUS LIKE 'aborted_clients'`; set @aborted_clients= 0; --enable_query_log diff --git a/mysys/my_handler.c b/mysys/my_handler.c index 56f2298a9f0..23d28956808 100644 --- a/mysys/my_handler.c +++ b/mysys/my_handler.c @@ -15,6 +15,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +#include <my_global.h> #include "my_handler.h" int mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length, diff --git a/ndb/include/Makefile.am b/ndb/include/Makefile.am index 240101c2004..842f4daabee 100644 --- a/ndb/include/Makefile.am +++ b/ndb/include/Makefile.am @@ -15,7 +15,6 @@ ndbapi/NdbApi.hpp \ ndbapi/NdbTransaction.hpp \ ndbapi/NdbDictionary.hpp \ ndbapi/NdbError.hpp \ -ndbapi/NdbEventOperation.hpp \ ndbapi/NdbIndexOperation.hpp \ ndbapi/NdbOperation.hpp \ ndbapi/ndb_cluster_connection.hpp \ diff --git a/ndb/include/kernel/GlobalSignalNumbers.h b/ndb/include/kernel/GlobalSignalNumbers.h index ca82806f4b1..a645a56a64b 100644 --- a/ndb/include/kernel/GlobalSignalNumbers.h +++ b/ndb/include/kernel/GlobalSignalNumbers.h @@ -587,6 +587,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; #define GSN_BLOCK_COMMIT_ORD 485 #define GSN_UNBLOCK_COMMIT_ORD 486 +#define GSN_NODE_START_REP 502 #define GSN_NODE_STATE_REP 487 #define GSN_CHANGE_NODE_STATE_REQ 488 #define GSN_CHANGE_NODE_STATE_CONF 489 @@ -731,9 +732,11 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; #define GSN_SUB_CREATE_REQ 576 #define GSN_SUB_CREATE_REF 577 #define GSN_SUB_CREATE_CONF 578 +/* #define GSN_SUB_START_REQ 579 #define GSN_SUB_START_REF 580 #define GSN_SUB_START_CONF 581 +*/ #define GSN_SUB_SYNC_REQ 582 #define GSN_SUB_SYNC_REF 583 #define GSN_SUB_SYNC_CONF 584 @@ -899,10 +902,11 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; /** * SUMA restart protocol */ +/* #define GSN_SUMA_START_ME 691 #define GSN_SUMA_HANDOVER_REQ 692 #define GSN_SUMA_HANDOVER_CONF 693 - +*/ /* not used 694 */ /* not used 695 */ /* not used 696 */ @@ -919,6 +923,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; /* * EVENT Signals */ +/* #define GSN_SUB_GCP_COMPLETE_ACC 699 #define GSN_CREATE_EVNT_REQ 700 @@ -928,7 +933,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES; #define GSN_DROP_EVNT_REQ 703 #define GSN_DROP_EVNT_CONF 704 #define GSN_DROP_EVNT_REF 705 - +*/ #define GSN_TUX_BOUND_INFO 710 #define GSN_ACC_LOCKREQ 711 diff --git a/ndb/include/mgmapi/ndbd_exit_codes.h b/ndb/include/mgmapi/ndbd_exit_codes.h index 686641ebef5..1016234c513 100644 --- a/ndb/include/mgmapi/ndbd_exit_codes.h +++ b/ndb/include/mgmapi/ndbd_exit_codes.h @@ -71,6 +71,7 @@ typedef ndbd_exit_classification_enum ndbd_exit_classification; #define NDBD_EXIT_INDEX_NOTINRANGE 2304 #define NDBD_EXIT_ARBIT_SHUTDOWN 2305 #define NDBD_EXIT_POINTER_NOTINRANGE 2306 +#define NDBD_EXIT_PARTITIONED_SHUTDOWN 2307 #define NDBD_EXIT_SR_OTHERNODEFAILED 2308 #define NDBD_EXIT_NODE_NOT_DEAD 2309 #define NDBD_EXIT_SR_REDOLOG 2310 diff --git a/ndb/include/ndbapi/Ndb.hpp b/ndb/include/ndbapi/Ndb.hpp index f128a45f5bf..e7c1e85c02a 100644 --- a/ndb/include/ndbapi/Ndb.hpp +++ b/ndb/include/ndbapi/Ndb.hpp @@ -38,9 +38,6 @@ In addition, the NDB API defines a structure NdbError, which contains the specification for an error. - It is also possible to receive "events" triggered when data in the database in changed. - This is done through the NdbEventOperation class. - There are also some auxiliary classes, which are listed in the class hierarchy. The main structure of an application program is as follows: @@ -968,7 +965,6 @@ class NdbObjectIdMap; class NdbOperation; -class NdbEventOperationImpl; class NdbScanOperation; class NdbIndexScanOperation; class NdbIndexOperation; @@ -981,13 +977,11 @@ class NdbSubroutine; class NdbCall; class Table; class BaseString; -class NdbEventOperation; class NdbBlob; class NdbReceiver; class Ndb_local_table_info; template <class T> struct Ndb_free_list_t; -typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*); #if defined NDB_OSE /** @@ -1049,7 +1043,6 @@ class Ndb #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL friend class NdbReceiver; friend class NdbOperation; - friend class NdbEventOperationImpl; friend class NdbTransaction; friend class Table; friend class NdbApiSignal; @@ -1196,46 +1189,6 @@ public: /** @} *********************************************************************/ /** - * @name Event subscriptions - * @{ - */ - - /** - * Create a subcription to an event defined in the database - * - * @param eventName - * unique identifier of the event - * @param bufferLength - * circular buffer size for storing event data - * - * @return Object representing an event, NULL on failure - */ - NdbEventOperation* createEventOperation(const char* eventName, - const int bufferLength); - /** - * Drop a subscription to an event - * - * @param eventOp - * Event operation - * - * @return 0 on success - */ - int dropEventOperation(NdbEventOperation* eventOp); - - /** - * Wait for an event to occur. Will return as soon as an event - * is detected on any of the created events. - * - * @param aMillisecondNumber - * maximum time to wait - * - * @return the number of events that has occured, -1 on failure - */ - int pollEvents(int aMillisecondNumber); - - /** @} *********************************************************************/ - - /** * @name Starting and Closing Transactions * @{ */ diff --git a/ndb/include/ndbapi/NdbApi.hpp b/ndb/include/ndbapi/NdbApi.hpp index aed4d5efbd7..c8400ed78ce 100644 --- a/ndb/include/ndbapi/NdbApi.hpp +++ b/ndb/include/ndbapi/NdbApi.hpp @@ -29,7 +29,6 @@ #include "NdbScanFilter.hpp" #include "NdbRecAttr.hpp" #include "NdbDictionary.hpp" -#include "NdbEventOperation.hpp" #include "NdbPool.hpp" #include "NdbBlob.hpp" #endif diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp index e67a0253096..db84c3715a5 100644 --- a/ndb/include/ndbapi/NdbDictionary.hpp +++ b/ndb/include/ndbapi/NdbDictionary.hpp @@ -938,165 +938,6 @@ public: }; /** - * @brief Represents an Event in NDB Cluster - * - */ - class Event : public Object { - public: - /** - * Specifies the type of database operations an Event listens to - */ -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL - /** TableEvent must match 1 << TriggerEvent */ -#endif - enum TableEvent { - TE_INSERT=1, ///< Insert event on table - TE_DELETE=2, ///< Delete event on table - TE_UPDATE=4, ///< Update event on table - TE_ALL=7 ///< Any/all event on table (not relevant when - ///< events are received) - }; - /** - * Specifies the durability of an event - * (future version may supply other types) - */ - enum EventDurability { - ED_UNDEFINED -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL - = 0 -#endif -#if 0 // not supported - ,ED_SESSION = 1, - // Only this API can use it - // and it's deleted after api has disconnected or ndb has restarted - - ED_TEMPORARY = 2 - // All API's can use it, - // But's its removed when ndb is restarted -#endif - ,ED_PERMANENT ///< All API's can use it. - ///< It's still defined after a cluster system restart -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL - = 3 -#endif - }; - - /** - * Constructor - * @param name Name of event - */ - Event(const char *name); - /** - * Constructor - * @param name Name of event - * @param table Reference retrieved from NdbDictionary - */ - Event(const char *name, const NdbDictionary::Table& table); - virtual ~Event(); - /** - * Set unique identifier for the event - */ - void setName(const char *name); - /** - * Get unique identifier for the event - */ - const char *getName() const; - /** - * Define table on which events should be detected - * - * @note calling this method will default to detection - * of events on all columns. Calling subsequent - * addEventColumn calls will override this. - * - * @param table reference retrieved from NdbDictionary - */ - void setTable(const NdbDictionary::Table& table); - /** - * Set table for which events should be detected - * - * @note preferred way is using setTable(const NdbDictionary::Table&) - * or constructor with table object parameter - */ - void setTable(const char *tableName); - /** - * Get table name for events - * - * @return table name - */ - const char* getTableName() const; - /** - * Add type of event that should be detected - */ - void addTableEvent(const TableEvent te); - /** - * Set durability of the event - */ - void setDurability(EventDurability); - /** - * Get durability of the event - */ - EventDurability getDurability() const; -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL - void addColumn(const Column &c); -#endif - /** - * Add a column on which events should be detected - * - * @param attrId Column id - * - * @note errors will mot be detected until createEvent() is called - */ - void addEventColumn(unsigned attrId); - /** - * Add a column on which events should be detected - * - * @param columnName Column name - * - * @note errors will not be detected until createEvent() is called - */ - void addEventColumn(const char * columnName); - /** - * Add several columns on which events should be detected - * - * @param n Number of columns - * @param columnNames Column names - * - * @note errors will mot be detected until - * NdbDictionary::Dictionary::createEvent() is called - */ - void addEventColumns(int n, const char ** columnNames); - - /** - * Get no of columns defined in an Event - * - * @return Number of columns, -1 on error - */ - int getNoOfEventColumns() const; - - /** - * Get object status - */ - virtual Object::Status getObjectStatus() const; - - /** - * Get object version - */ - virtual int getObjectVersion() const; - -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL - void print(); -#endif - - private: -#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL - friend class NdbEventImpl; - friend class NdbEventOperationImpl; -#endif - class NdbEventImpl & m_impl; - Event(NdbEventImpl&); - }; - - /** * @class Dictionary * @brief Dictionary for defining and retreiving meta data */ @@ -1215,33 +1056,6 @@ public: int listIndexes(List & list, const char * tableName) const; /** @} *******************************************************************/ - /** - * @name Events - * @{ - */ - - /** - * Create event given defined Event instance - * @param event Event to create - * @return 0 if successful otherwise -1. - */ - int createEvent(const Event &event); - - /** - * Drop event with given name - * @param eventName Name of event to drop. - * @return 0 if successful otherwise -1. - */ - int dropEvent(const char * eventName); - - /** - * Get event with given name. - * @param eventName Name of event to get. - * @return an Event if successful, otherwise NULL. - */ - const Event * getEvent(const char * eventName); - - /** @} *******************************************************************/ /** * @name Table creation diff --git a/ndb/include/ndbapi/NdbIndexScanOperation.hpp b/ndb/include/ndbapi/NdbIndexScanOperation.hpp index 638ecb17779..7ef66f9a30b 100644 --- a/ndb/include/ndbapi/NdbIndexScanOperation.hpp +++ b/ndb/include/ndbapi/NdbIndexScanOperation.hpp @@ -41,7 +41,9 @@ public: * @param parallel No of fragments to scan in parallel (0=max) */ virtual int readTuples(LockMode lock_mode = LM_Read, - Uint32 scan_flags = 0, Uint32 parallel = 0); + Uint32 scan_flags = 0, + Uint32 parallel = 0, + Uint32 batch = 0); #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL /** @@ -69,7 +71,7 @@ public: (SF_ReadRangeNo & -(Int32)read_range_no) | (SF_KeyInfo & -(Int32)keyinfo); - return readTuples(lock_mode, scan_flags, parallel); + return readTuples(lock_mode, scan_flags, parallel, batch); } #endif diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp index 5581e830f82..beaf9402b77 100644 --- a/ndb/include/ndbapi/NdbScanOperation.hpp +++ b/ndb/include/ndbapi/NdbScanOperation.hpp @@ -57,7 +57,9 @@ public: */ virtual int readTuples(LockMode lock_mode = LM_Read, - Uint32 scan_flags = 0, Uint32 parallel = 0); + Uint32 scan_flags = 0, + Uint32 parallel = 0, + Uint32 batch = 0); #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED /** diff --git a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp index 34cae9f618f..572d8f6e3ca 100644 --- a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp +++ b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp @@ -156,12 +156,6 @@ SignalDataPrintFunctions[] = { { GSN_SUB_REMOVE_REQ, printSUB_REMOVE_REQ }, { GSN_SUB_REMOVE_REF, printSUB_REMOVE_REF }, { GSN_SUB_REMOVE_CONF, printSUB_REMOVE_CONF }, - { GSN_SUB_START_REQ, printSUB_START_REQ }, - { GSN_SUB_START_REF, printSUB_START_REF }, - { GSN_SUB_START_CONF, printSUB_START_CONF }, - { GSN_SUB_STOP_REQ, printSUB_STOP_REQ }, - { GSN_SUB_STOP_REF, printSUB_STOP_REF }, - { GSN_SUB_STOP_CONF, printSUB_STOP_CONF }, { GSN_SUB_SYNC_REQ, printSUB_SYNC_REQ }, { GSN_SUB_SYNC_REF, printSUB_SYNC_REF }, { GSN_SUB_SYNC_CONF, printSUB_SYNC_CONF }, diff --git a/ndb/src/common/debugger/signaldata/SignalNames.cpp b/ndb/src/common/debugger/signaldata/SignalNames.cpp index 5162679017a..49e3f505b11 100644 --- a/ndb/src/common/debugger/signaldata/SignalNames.cpp +++ b/ndb/src/common/debugger/signaldata/SignalNames.cpp @@ -399,6 +399,8 @@ const GsnName SignalNames [] = { ,{ GSN_TUP_COM_UNBLOCK, "TUP_COM_UNBLOCK" } ,{ GSN_DUMP_STATE_ORD, "DUMP_STATE_ORD" } + ,{ GSN_NODE_START_REP, "NODE_START_REP" } + ,{ GSN_START_INFOREQ, "START_INFOREQ" } ,{ GSN_START_INFOREF, "START_INFOREF" } ,{ GSN_START_INFOCONF, "START_INFOCONF" } @@ -502,18 +504,6 @@ const GsnName SignalNames [] = { //,{ GSN_TCINDEXNEXTCONF, "TCINDEXNEXTCONF" } //,{ GSN_TCINDEXNEXREF, "TCINDEXNEXREF" } - ,{ GSN_CREATE_EVNT_REQ, "CREATE_EVNT_REQ" } - ,{ GSN_CREATE_EVNT_CONF, "CREATE_EVNT_CONF" } - ,{ GSN_CREATE_EVNT_REF, "CREATE_EVNT_REF" } - - ,{ GSN_SUMA_START_ME, "SUMA_START_ME" } - ,{ GSN_SUMA_HANDOVER_REQ, "SUMA_HANDOVER_REQ"} - ,{ GSN_SUMA_HANDOVER_CONF, "SUMA_HANDOVER_CONF"} - - ,{ GSN_DROP_EVNT_REQ, "DROP_EVNT_REQ" } - ,{ GSN_DROP_EVNT_CONF, "DROP_EVNT_CONF" } - ,{ GSN_DROP_EVNT_REF, "DROP_EVNT_REF" } - ,{ GSN_BACKUP_TRIG_REQ, "BACKUP_TRIG_REQ" } ,{ GSN_BACKUP_REQ, "BACKUP_REQ" } ,{ GSN_BACKUP_DATA, "BACKUP_DATA" } @@ -581,12 +571,6 @@ const GsnName SignalNames [] = { ,{ GSN_SUB_REMOVE_REQ, "SUB_REMOVE_REQ" } ,{ GSN_SUB_REMOVE_REF, "SUB_REMOVE_REF" } ,{ GSN_SUB_REMOVE_CONF, "SUB_REMOVE_CONF" } - ,{ GSN_SUB_START_REQ, "SUB_START_REQ" } - ,{ GSN_SUB_START_REF, "SUB_START_REF" } - ,{ GSN_SUB_START_CONF, "SUB_START_CONF" } - ,{ GSN_SUB_STOP_REQ, "SUB_STOP_REQ" } - ,{ GSN_SUB_STOP_REF, "SUB_STOP_REF" } - ,{ GSN_SUB_STOP_CONF, "SUB_STOP_CONF" } ,{ GSN_SUB_SYNC_REQ, "SUB_SYNC_REQ" } ,{ GSN_SUB_SYNC_REF, "SUB_SYNC_REF" } ,{ GSN_SUB_SYNC_CONF, "SUB_SYNC_CONF" } @@ -596,7 +580,6 @@ const GsnName SignalNames [] = { ,{ GSN_SUB_SYNC_CONTINUE_REF, "SUB_SYNC_CONTINUE_REF" } ,{ GSN_SUB_SYNC_CONTINUE_CONF, "SUB_SYNC_CONTINUE_CONF" } ,{ GSN_SUB_GCP_COMPLETE_REP, "SUB_GCP_COMPLETE_REP" } - ,{ GSN_SUB_GCP_COMPLETE_ACC, "SUB_GCP_COMPLETE_ACC" } ,{ GSN_CREATE_SUBID_REQ, "CREATE_SUBID_REQ" } ,{ GSN_CREATE_SUBID_REF, "CREATE_SUBID_REF" } diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt index ddb99cb6b56..7fee2e92f2b 100644 --- a/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/ndb/src/kernel/blocks/ERROR_codes.txt @@ -2,7 +2,7 @@ Next QMGR 1 Next NDBCNTR 1000 Next NDBFS 2000 Next DBACC 3002 -Next DBTUP 4013 +Next DBTUP 4014 Next DBLQH 5043 Next DBDICT 6007 Next DBDIH 7177 @@ -437,6 +437,8 @@ Drop Table/Index: 8036: Fail next index drop in TC 6006: Crash participant in create index +4013: verify TUP tab descr before and after next DROP TABLE + System Restart: --------------- diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index 133b4d75d8e..efd519339f7 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -1210,10 +1210,6 @@ Dbdict::Dbdict(const class Configuration & conf): c_opDropIndex(c_opRecordPool), c_opAlterIndex(c_opRecordPool), c_opBuildIndex(c_opRecordPool), - c_opCreateEvent(c_opRecordPool), - c_opSubEvent(c_opRecordPool), - c_opDropEvent(c_opRecordPool), - c_opSignalUtil(c_opRecordPool), c_opCreateTrigger(c_opRecordPool), c_opDropTrigger(c_opRecordPool), c_opAlterTrigger(c_opRecordPool), @@ -1273,44 +1269,6 @@ Dbdict::Dbdict(const class Configuration & conf): addRecSignal(GSN_BUILDINDXCONF, &Dbdict::execBUILDINDXCONF); addRecSignal(GSN_BUILDINDXREF, &Dbdict::execBUILDINDXREF); - // Util signals - addRecSignal(GSN_UTIL_PREPARE_CONF, &Dbdict::execUTIL_PREPARE_CONF); - addRecSignal(GSN_UTIL_PREPARE_REF, &Dbdict::execUTIL_PREPARE_REF); - - addRecSignal(GSN_UTIL_EXECUTE_CONF, &Dbdict::execUTIL_EXECUTE_CONF); - addRecSignal(GSN_UTIL_EXECUTE_REF, &Dbdict::execUTIL_EXECUTE_REF); - - addRecSignal(GSN_UTIL_RELEASE_CONF, &Dbdict::execUTIL_RELEASE_CONF); - addRecSignal(GSN_UTIL_RELEASE_REF, &Dbdict::execUTIL_RELEASE_REF); - - // Event signals - addRecSignal(GSN_CREATE_EVNT_REQ, &Dbdict::execCREATE_EVNT_REQ); - addRecSignal(GSN_CREATE_EVNT_CONF, &Dbdict::execCREATE_EVNT_CONF); - addRecSignal(GSN_CREATE_EVNT_REF, &Dbdict::execCREATE_EVNT_REF); - - addRecSignal(GSN_CREATE_SUBID_CONF, &Dbdict::execCREATE_SUBID_CONF); - addRecSignal(GSN_CREATE_SUBID_REF, &Dbdict::execCREATE_SUBID_REF); - - addRecSignal(GSN_SUB_CREATE_CONF, &Dbdict::execSUB_CREATE_CONF); - addRecSignal(GSN_SUB_CREATE_REF, &Dbdict::execSUB_CREATE_REF); - - addRecSignal(GSN_SUB_START_REQ, &Dbdict::execSUB_START_REQ); - addRecSignal(GSN_SUB_START_CONF, &Dbdict::execSUB_START_CONF); - addRecSignal(GSN_SUB_START_REF, &Dbdict::execSUB_START_REF); - - addRecSignal(GSN_SUB_STOP_REQ, &Dbdict::execSUB_STOP_REQ); - addRecSignal(GSN_SUB_STOP_CONF, &Dbdict::execSUB_STOP_CONF); - addRecSignal(GSN_SUB_STOP_REF, &Dbdict::execSUB_STOP_REF); - - addRecSignal(GSN_SUB_SYNC_CONF, &Dbdict::execSUB_SYNC_CONF); - addRecSignal(GSN_SUB_SYNC_REF, &Dbdict::execSUB_SYNC_REF); - - addRecSignal(GSN_DROP_EVNT_REQ, &Dbdict::execDROP_EVNT_REQ); - - addRecSignal(GSN_SUB_REMOVE_REQ, &Dbdict::execSUB_REMOVE_REQ); - addRecSignal(GSN_SUB_REMOVE_CONF, &Dbdict::execSUB_REMOVE_CONF); - addRecSignal(GSN_SUB_REMOVE_REF, &Dbdict::execSUB_REMOVE_REF); - // Trigger signals addRecSignal(GSN_CREATE_TRIG_REQ, &Dbdict::execCREATE_TRIG_REQ); addRecSignal(GSN_CREATE_TRIG_CONF, &Dbdict::execCREATE_TRIG_CONF); @@ -1772,10 +1730,6 @@ void Dbdict::execREAD_CONFIG_REQ(Signal* signal) c_opCreateTable.setSize(8); c_opDropTable.setSize(8); c_opCreateIndex.setSize(8); - c_opCreateEvent.setSize(8); - c_opSubEvent.setSize(8); - c_opDropEvent.setSize(8); - c_opSignalUtil.setSize(8); c_opDropIndex.setSize(8); c_opAlterIndex.setSize(8); c_opBuildIndex.setSize(8); @@ -7449,2171 +7403,6 @@ Dbdict::dropIndex_sendReply(Signal* signal, OpDropIndexPtr opPtr, sendSignal(rep->getUserRef(), gsn, signal, length, JBB); } -/***************************************************** - * - * Util signalling - * - *****************************************************/ - -int -Dbdict::sendSignalUtilReq(Callback *pcallback, - BlockReference ref, - GlobalSignalNumber gsn, - Signal* signal, - Uint32 length, - JobBufferLevel jbuf, - LinearSectionPtr ptr[3], - Uint32 noOfSections) -{ - jam(); - EVENT_TRACE; - OpSignalUtilPtr utilRecPtr; - - // Seize a Util Send record - if (!c_opSignalUtil.seize(utilRecPtr)) { - // Failed to allocate util record - return -1; - } - utilRecPtr.p->m_callback = *pcallback; - - // should work for all util signal classes - UtilPrepareReq *req = (UtilPrepareReq*)signal->getDataPtrSend(); - utilRecPtr.p->m_userData = req->getSenderData(); - req->setSenderData(utilRecPtr.i); - - if (ptr) { - jam(); - sendSignal(ref, gsn, signal, length, jbuf, ptr, noOfSections); - } else { - jam(); - sendSignal(ref, gsn, signal, length, jbuf); - } - - return 0; -} - -int -Dbdict::recvSignalUtilReq(Signal* signal, Uint32 returnCode) -{ - jam(); - EVENT_TRACE; - UtilPrepareConf * const req = (UtilPrepareConf*)signal->getDataPtr(); - OpSignalUtilPtr utilRecPtr; - utilRecPtr.i = req->getSenderData(); - if ((utilRecPtr.p = c_opSignalUtil.getPtr(utilRecPtr.i)) == NULL) { - jam(); - return -1; - } - - req->setSenderData(utilRecPtr.p->m_userData); - Callback c = utilRecPtr.p->m_callback; - c_opSignalUtil.release(utilRecPtr); - - execute(signal, c, returnCode); - return 0; -} - -void Dbdict::execUTIL_PREPARE_CONF(Signal *signal) -{ - jamEntry(); - EVENT_TRACE; - ndbrequire(recvSignalUtilReq(signal, 0) == 0); -} - -void -Dbdict::execUTIL_PREPARE_REF(Signal *signal) -{ - jamEntry(); - EVENT_TRACE; - ndbrequire(recvSignalUtilReq(signal, 1) == 0); -} - -void Dbdict::execUTIL_EXECUTE_CONF(Signal *signal) -{ - jamEntry(); - EVENT_TRACE; - ndbrequire(recvSignalUtilReq(signal, 0) == 0); -} - -void Dbdict::execUTIL_EXECUTE_REF(Signal *signal) -{ - jamEntry(); - EVENT_TRACE; - -#ifdef EVENT_DEBUG - UtilExecuteRef * ref = (UtilExecuteRef *)signal->getDataPtrSend(); - - ndbout_c("execUTIL_EXECUTE_REF"); - ndbout_c("senderData %u",ref->getSenderData()); - ndbout_c("errorCode %u",ref->getErrorCode()); - ndbout_c("TCErrorCode %u",ref->getTCErrorCode()); -#endif - - ndbrequire(recvSignalUtilReq(signal, 1) == 0); -} -void Dbdict::execUTIL_RELEASE_CONF(Signal *signal) -{ - jamEntry(); - EVENT_TRACE; - ndbrequire(false); - ndbrequire(recvSignalUtilReq(signal, 0) == 0); -} -void Dbdict::execUTIL_RELEASE_REF(Signal *signal) -{ - jamEntry(); - EVENT_TRACE; - ndbrequire(false); - ndbrequire(recvSignalUtilReq(signal, 1) == 0); -} - -/** - * MODULE: Create event - * - * Create event in DICT. - * - * - * Request type in CREATE_EVNT signals: - * - * Signalflow see Dbdict.txt - * - */ - -/***************************************************************** - * - * Systable stuff - * - */ - -const Uint32 Dbdict::sysTab_NDBEVENTS_0_szs[EVENT_SYSTEM_TABLE_LENGTH] = { - sizeof(((sysTab_NDBEVENTS_0*)0)->NAME), - sizeof(((sysTab_NDBEVENTS_0*)0)->EVENT_TYPE), - sizeof(((sysTab_NDBEVENTS_0*)0)->TABLE_NAME), - sizeof(((sysTab_NDBEVENTS_0*)0)->ATTRIBUTE_MASK), - sizeof(((sysTab_NDBEVENTS_0*)0)->SUBID), - sizeof(((sysTab_NDBEVENTS_0*)0)->SUBKEY) -}; - -void -Dbdict::prepareTransactionEventSysTable (Callback *pcallback, - Signal* signal, - Uint32 senderData, - UtilPrepareReq::OperationTypeValue prepReq) -{ - // find table id for event system table - TableRecord keyRecord; - strcpy(keyRecord.tableName, EVENT_SYSTEM_TABLE_NAME); - - TableRecordPtr tablePtr; - c_tableRecordHash.find(tablePtr, keyRecord); - - ndbrequire(tablePtr.i != RNIL); // system table must exist - - Uint32 tableId = tablePtr.p->tableId; /* System table */ - Uint32 noAttr = tablePtr.p->noOfAttributes; - ndbrequire(noAttr == EVENT_SYSTEM_TABLE_LENGTH); - - switch (prepReq) { - case UtilPrepareReq::Update: - case UtilPrepareReq::Insert: - case UtilPrepareReq::Write: - case UtilPrepareReq::Read: - jam(); - break; - case UtilPrepareReq::Delete: - jam(); - noAttr = 1; // only involves Primary key which should be the first - break; - } - prepareUtilTransaction(pcallback, signal, senderData, tableId, NULL, - prepReq, noAttr, NULL, NULL); -} - -void -Dbdict::prepareUtilTransaction(Callback *pcallback, - Signal* signal, - Uint32 senderData, - Uint32 tableId, - const char* tableName, - UtilPrepareReq::OperationTypeValue prepReq, - Uint32 noAttr, - Uint32 attrIds[], - const char *attrNames[]) -{ - jam(); - EVENT_TRACE; - - UtilPrepareReq * utilPrepareReq = - (UtilPrepareReq *)signal->getDataPtrSend(); - - utilPrepareReq->setSenderRef(reference()); - utilPrepareReq->setSenderData(senderData); - - const Uint32 pageSizeInWords = 128; - Uint32 propPage[pageSizeInWords]; - LinearWriter w(&propPage[0],128); - w.first(); - w.add(UtilPrepareReq::NoOfOperations, 1); - w.add(UtilPrepareReq::OperationType, prepReq); - if (tableName) { - jam(); - w.add(UtilPrepareReq::TableName, tableName); - } else { - jam(); - w.add(UtilPrepareReq::TableId, tableId); - } - for(Uint32 i = 0; i < noAttr; i++) - if (tableName) { - jam(); - w.add(UtilPrepareReq::AttributeName, attrNames[i]); - } else { - if (attrIds) { - jam(); - w.add(UtilPrepareReq::AttributeId, attrIds[i]); - } else { - jam(); - w.add(UtilPrepareReq::AttributeId, i); - } - } -#ifdef EVENT_DEBUG - // Debugging - SimplePropertiesLinearReader reader(propPage, w.getWordsUsed()); - printf("Dict::prepareInsertTransactions: Sent SimpleProperties:\n"); - reader.printAll(ndbout); -#endif - - struct LinearSectionPtr sectionsPtr[UtilPrepareReq::NoOfSections]; - sectionsPtr[UtilPrepareReq::PROPERTIES_SECTION].p = propPage; - sectionsPtr[UtilPrepareReq::PROPERTIES_SECTION].sz = w.getWordsUsed(); - - sendSignalUtilReq(pcallback, DBUTIL_REF, GSN_UTIL_PREPARE_REQ, signal, - UtilPrepareReq::SignalLength, JBB, - sectionsPtr, UtilPrepareReq::NoOfSections); -} - -/***************************************************************** - * - * CREATE_EVNT_REQ has three types RT_CREATE, RT_GET (from user) - * and RT_DICT_AFTER_GET send from master DICT to slaves - * - * This function just dscpaches these to - * - * createEvent_RT_USER_CREATE - * createEvent_RT_USER_GET - * createEvent_RT_DICT_AFTER_GET - * - * repectively - * - */ - -void -Dbdict::execCREATE_EVNT_REQ(Signal* signal) -{ - jamEntry(); - -#if 0 - { - SafeCounterHandle handle; - { - SafeCounter tmp(c_counterMgr, handle); - tmp.init<CreateEvntRef>(CMVMI, GSN_DUMP_STATE_ORD, /* senderData */ 13); - tmp.clearWaitingFor(); - tmp.setWaitingFor(3); - ndbrequire(!tmp.done()); - ndbout_c("Allocted"); - } - ndbrequire(!handle.done()); - { - SafeCounter tmp(c_counterMgr, handle); - tmp.clearWaitingFor(3); - ndbrequire(tmp.done()); - ndbout_c("Deallocted"); - } - ndbrequire(handle.done()); - } - { - NodeBitmask nodes; - nodes.clear(); - - nodes.set(2); - nodes.set(3); - nodes.set(4); - nodes.set(5); - - { - Uint32 i = 0; - while((i = nodes.find(i)) != NodeBitmask::NotFound){ - ndbout_c("1 Node id = %u", i); - i++; - } - } - - NodeReceiverGroup rg(DBDICT, nodes); - RequestTracker rt2; - ndbrequire(rt2.done()); - ndbrequire(!rt2.hasRef()); - ndbrequire(!rt2.hasConf()); - rt2.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF, 13); - - RequestTracker rt3; - rt3.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF, 13); - - ndbrequire(!rt2.done()); - ndbrequire(!rt3.done()); - - rt2.reportRef(c_counterMgr, 2); - rt3.reportConf(c_counterMgr, 2); - - ndbrequire(!rt2.done()); - ndbrequire(!rt3.done()); - - rt2.reportConf(c_counterMgr, 3); - rt3.reportConf(c_counterMgr, 3); - - ndbrequire(!rt2.done()); - ndbrequire(!rt3.done()); - - rt2.reportConf(c_counterMgr, 4); - rt3.reportConf(c_counterMgr, 4); - - ndbrequire(!rt2.done()); - ndbrequire(!rt3.done()); - - rt2.reportConf(c_counterMgr, 5); - rt3.reportConf(c_counterMgr, 5); - - ndbrequire(rt2.done()); - ndbrequire(rt3.done()); - } -#endif - - if (! assembleFragments(signal)) { - jam(); - return; - } - - CreateEvntReq *req = (CreateEvntReq*)signal->getDataPtr(); - const CreateEvntReq::RequestType requestType = req->getRequestType(); - const Uint32 requestFlag = req->getRequestFlag(); - - OpCreateEventPtr evntRecPtr; - // Seize a Create Event record - if (!c_opCreateEvent.seize(evntRecPtr)) { - // Failed to allocate event record - jam(); - releaseSections(signal); - - CreateEvntRef * ret = (CreateEvntRef *)signal->getDataPtrSend(); - ret->senderRef = reference(); - ret->setErrorCode(CreateEvntRef::SeizeError); - ret->setErrorLine(__LINE__); - ret->setErrorNode(reference()); - sendSignal(signal->senderBlockRef(), GSN_CREATE_EVNT_REF, signal, - CreateEvntRef::SignalLength, JBB); - return; - } - -#ifdef EVENT_DEBUG - ndbout_c("DBDICT::execCREATE_EVNT_REQ from %u evntRecId = (%d)", refToNode(signal->getSendersBlockRef()), evntRecPtr.i); -#endif - - ndbrequire(req->getUserRef() == signal->getSendersBlockRef()); - - evntRecPtr.p->init(req,this); - - if (requestFlag & (Uint32)CreateEvntReq::RT_DICT_AFTER_GET) { - jam(); - EVENT_TRACE; - createEvent_RT_DICT_AFTER_GET(signal, evntRecPtr); - return; - } - if (requestType == CreateEvntReq::RT_USER_GET) { - jam(); - EVENT_TRACE; - createEvent_RT_USER_GET(signal, evntRecPtr); - return; - } - if (requestType == CreateEvntReq::RT_USER_CREATE) { - jam(); - EVENT_TRACE; - createEvent_RT_USER_CREATE(signal, evntRecPtr); - return; - } - -#ifdef EVENT_DEBUG - ndbout << "Dbdict.cpp: Dbdict::execCREATE_EVNT_REQ other" << endl; -#endif - jam(); - releaseSections(signal); - - evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined; - evntRecPtr.p->m_errorLine = __LINE__; - evntRecPtr.p->m_errorNode = reference(); - - createEvent_sendReply(signal, evntRecPtr); -} - -/******************************************************************** - * - * Event creation - * - *****************************************************************/ - -void -Dbdict::createEvent_RT_USER_CREATE(Signal* signal, OpCreateEventPtr evntRecPtr){ - jam(); - evntRecPtr.p->m_request.setUserRef(signal->senderBlockRef()); - -#ifdef EVENT_DEBUG - ndbout << "Dbdict.cpp: Dbdict::execCREATE_EVNT_REQ RT_USER" << endl; - char buf[128] = {0}; - AttributeMask mask = evntRecPtr.p->m_request.getAttrListBitmask(); - mask.getText(buf); - ndbout_c("mask = %s", buf); -#endif - - // Interpret the long signal - - SegmentedSectionPtr ssPtr; - // save name and event properties - signal->getSection(ssPtr, CreateEvntReq::EVENT_NAME_SECTION); - - SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool()); -#ifdef EVENT_DEBUG - r0.printAll(ndbout); -#endif - // event name - if ((!r0.first()) || - (r0.getValueType() != SimpleProperties::StringValue) || - (r0.getValueLen() <= 0)) { - jam(); - releaseSections(signal); - - evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined; - evntRecPtr.p->m_errorLine = __LINE__; - evntRecPtr.p->m_errorNode = reference(); - - createEvent_sendReply(signal, evntRecPtr); - return; - } - r0.getString(evntRecPtr.p->m_eventRec.NAME); - { - int len = strlen(evntRecPtr.p->m_eventRec.NAME); - memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len); -#ifdef EVENT_DEBUG - printf("CreateEvntReq::RT_USER_CREATE; EventName %s, len %u\n", - evntRecPtr.p->m_eventRec.NAME, len); - for(int i = 0; i < MAX_TAB_NAME_SIZE/4; i++) - printf("H'%.8x ", ((Uint32*)evntRecPtr.p->m_eventRec.NAME)[i]); - printf("\n"); -#endif - } - // table name - if ((!r0.next()) || - (r0.getValueType() != SimpleProperties::StringValue) || - (r0.getValueLen() <= 0)) { - jam(); - releaseSections(signal); - - evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined; - evntRecPtr.p->m_errorLine = __LINE__; - evntRecPtr.p->m_errorNode = reference(); - - createEvent_sendReply(signal, evntRecPtr); - return; - } - r0.getString(evntRecPtr.p->m_eventRec.TABLE_NAME); - { - int len = strlen(evntRecPtr.p->m_eventRec.TABLE_NAME); - memset(evntRecPtr.p->m_eventRec.TABLE_NAME+len, 0, MAX_TAB_NAME_SIZE-len); - } - -#ifdef EVENT_DEBUG - ndbout_c("event name: %s",evntRecPtr.p->m_eventRec.NAME); - ndbout_c("table name: %s",evntRecPtr.p->m_eventRec.TABLE_NAME); -#endif - - releaseSections(signal); - - // Send request to SUMA - - CreateSubscriptionIdReq * sumaIdReq = - (CreateSubscriptionIdReq *)signal->getDataPtrSend(); - - // make sure we save the original sender for later - sumaIdReq->senderData = evntRecPtr.i; -#ifdef EVENT_DEBUG - ndbout << "sumaIdReq->senderData = " << sumaIdReq->senderData << endl; -#endif - sendSignal(SUMA_REF, GSN_CREATE_SUBID_REQ, signal, - CreateSubscriptionIdReq::SignalLength, JBB); - // we should now return in either execCREATE_SUBID_CONF - // or execCREATE_SUBID_REF -} - -void Dbdict::execCREATE_SUBID_REF(Signal* signal) -{ - jamEntry(); - EVENT_TRACE; - CreateSubscriptionIdRef * const ref = - (CreateSubscriptionIdRef *)signal->getDataPtr(); - OpCreateEventPtr evntRecPtr; - - evntRecPtr.i = ref->senderData; - ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL); - - evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined; - evntRecPtr.p->m_errorLine = __LINE__; - evntRecPtr.p->m_errorNode = reference(); - - createEvent_sendReply(signal, evntRecPtr); -} - -void Dbdict::execCREATE_SUBID_CONF(Signal* signal) -{ - jamEntry(); - EVENT_TRACE; - - CreateSubscriptionIdConf const * sumaIdConf = - (CreateSubscriptionIdConf *)signal->getDataPtr(); - - Uint32 evntRecId = sumaIdConf->senderData; - OpCreateEvent *evntRec; - - ndbrequire((evntRec = c_opCreateEvent.getPtr(evntRecId)) != NULL); - - evntRec->m_request.setEventId(sumaIdConf->subscriptionId); - evntRec->m_request.setEventKey(sumaIdConf->subscriptionKey); - - releaseSections(signal); - - Callback c = { safe_cast(&Dbdict::createEventUTIL_PREPARE), 0 }; - - prepareTransactionEventSysTable(&c, signal, evntRecId, - UtilPrepareReq::Insert); -} - -void -Dbdict::createEventComplete_RT_USER_CREATE(Signal* signal, - OpCreateEventPtr evntRecPtr){ - jam(); - createEvent_sendReply(signal, evntRecPtr); -} - -/********************************************************************* - * - * UTIL_PREPARE, UTIL_EXECUTE - * - * insert or read systable NDB$EVENTS_0 - */ - -void interpretUtilPrepareErrorCode(UtilPrepareRef::ErrorCode errorCode, - bool& temporary, Uint32& line) -{ - switch (errorCode) { - case UtilPrepareRef::NO_ERROR: - jam(); - line = __LINE__; - EVENT_TRACE; - break; - case UtilPrepareRef::PREPARE_SEIZE_ERROR: - jam(); - temporary = true; - line = __LINE__; - EVENT_TRACE; - break; - case UtilPrepareRef::PREPARE_PAGES_SEIZE_ERROR: - jam(); - line = __LINE__; - EVENT_TRACE; - break; - case UtilPrepareRef::PREPARED_OPERATION_SEIZE_ERROR: - jam(); - line = __LINE__; - EVENT_TRACE; - break; - case UtilPrepareRef::DICT_TAB_INFO_ERROR: - jam(); - line = __LINE__; - EVENT_TRACE; - break; - case UtilPrepareRef::MISSING_PROPERTIES_SECTION: - jam(); - line = __LINE__; - EVENT_TRACE; - break; - default: - jam(); - line = __LINE__; - EVENT_TRACE; - break; - } -} - -void -Dbdict::createEventUTIL_PREPARE(Signal* signal, - Uint32 callbackData, - Uint32 returnCode) -{ - jam(); - EVENT_TRACE; - if (returnCode == 0) { - UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr(); - OpCreateEventPtr evntRecPtr; - jam(); - evntRecPtr.i = req->getSenderData(); - const Uint32 prepareId = req->getPrepareId(); - - ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL); - - Callback c = { safe_cast(&Dbdict::createEventUTIL_EXECUTE), 0 }; - - switch (evntRecPtr.p->m_requestType) { - case CreateEvntReq::RT_USER_GET: -#ifdef EVENT_DEBUG - printf("get type = %d\n", CreateEvntReq::RT_USER_GET); -#endif - jam(); - executeTransEventSysTable(&c, signal, - evntRecPtr.i, evntRecPtr.p->m_eventRec, - prepareId, UtilPrepareReq::Read); - break; - case CreateEvntReq::RT_USER_CREATE: -#ifdef EVENT_DEBUG - printf("create type = %d\n", CreateEvntReq::RT_USER_CREATE); -#endif - { - evntRecPtr.p->m_eventRec.EVENT_TYPE = evntRecPtr.p->m_request.getEventType(); - AttributeMask m = evntRecPtr.p->m_request.getAttrListBitmask(); - memcpy(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK, &m, - sizeof(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK)); - evntRecPtr.p->m_eventRec.SUBID = evntRecPtr.p->m_request.getEventId(); - evntRecPtr.p->m_eventRec.SUBKEY = evntRecPtr.p->m_request.getEventKey(); - } - jam(); - executeTransEventSysTable(&c, signal, - evntRecPtr.i, evntRecPtr.p->m_eventRec, - prepareId, UtilPrepareReq::Insert); - break; - default: -#ifdef EVENT_DEBUG - printf("type = %d\n", evntRecPtr.p->m_requestType); - printf("bet type = %d\n", CreateEvntReq::RT_USER_GET); - printf("create type = %d\n", CreateEvntReq::RT_USER_CREATE); -#endif - ndbrequire(false); - } - } else { // returnCode != 0 - UtilPrepareRef* const ref = (UtilPrepareRef*)signal->getDataPtr(); - - const UtilPrepareRef::ErrorCode errorCode = - (UtilPrepareRef::ErrorCode)ref->getErrorCode(); - - OpCreateEventPtr evntRecPtr; - evntRecPtr.i = ref->getSenderData(); - ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL); - - bool temporary = false; - interpretUtilPrepareErrorCode(errorCode, - temporary, evntRecPtr.p->m_errorLine); - if (temporary) { - evntRecPtr.p->m_errorCode = - CreateEvntRef::makeTemporary(CreateEvntRef::Undefined); - } - - if (evntRecPtr.p->m_errorCode == 0) { - evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined; - } - evntRecPtr.p->m_errorNode = reference(); - - createEvent_sendReply(signal, evntRecPtr); - } -} - -void Dbdict::executeTransEventSysTable(Callback *pcallback, Signal *signal, - const Uint32 ptrI, - sysTab_NDBEVENTS_0& m_eventRec, - const Uint32 prepareId, - UtilPrepareReq::OperationTypeValue prepReq) -{ - jam(); - const Uint32 noAttr = EVENT_SYSTEM_TABLE_LENGTH; - Uint32 total_len = 0; - - Uint32* attrHdr = signal->theData + 25; - Uint32* attrPtr = attrHdr; - - Uint32 id=0; - // attribute 0 event name: Primary Key - { - AttributeHeader::init(attrPtr, id, sysTab_NDBEVENTS_0_szs[id]/4); - total_len += sysTab_NDBEVENTS_0_szs[id]; - attrPtr++; id++; - } - - switch (prepReq) { - case UtilPrepareReq::Read: - jam(); - EVENT_TRACE; - // no more - while ( id < noAttr ) - AttributeHeader::init(attrPtr++, id++, 0); - ndbrequire(id == (Uint32) noAttr); - break; - case UtilPrepareReq::Insert: - jam(); - EVENT_TRACE; - while ( id < noAttr ) { - AttributeHeader::init(attrPtr, id, sysTab_NDBEVENTS_0_szs[id]/4); - total_len += sysTab_NDBEVENTS_0_szs[id]; - attrPtr++; id++; - } - ndbrequire(id == (Uint32) noAttr); - break; - case UtilPrepareReq::Delete: - ndbrequire(id == 1); - break; - default: - ndbrequire(false); - } - - LinearSectionPtr headerPtr; - LinearSectionPtr dataPtr; - - headerPtr.p = attrHdr; - headerPtr.sz = noAttr; - - dataPtr.p = (Uint32*)&m_eventRec; - dataPtr.sz = total_len/4; - - ndbrequire((total_len == sysTab_NDBEVENTS_0_szs[0]) || - (total_len == sizeof(sysTab_NDBEVENTS_0))); - -#if 0 - printf("Header size %u\n", headerPtr.sz); - for(int i = 0; i < (int)headerPtr.sz; i++) - printf("H'%.8x ", attrHdr[i]); - printf("\n"); - - printf("Data size %u\n", dataPtr.sz); - for(int i = 0; i < (int)dataPtr.sz; i++) - printf("H'%.8x ", dataPage[i]); - printf("\n"); -#endif - - executeTransaction(pcallback, signal, - ptrI, - prepareId, - id, - headerPtr, - dataPtr); -} - -void Dbdict::executeTransaction(Callback *pcallback, - Signal* signal, - Uint32 senderData, - Uint32 prepareId, - Uint32 noAttr, - LinearSectionPtr headerPtr, - LinearSectionPtr dataPtr) -{ - jam(); - EVENT_TRACE; - - UtilExecuteReq * utilExecuteReq = - (UtilExecuteReq *)signal->getDataPtrSend(); - - utilExecuteReq->setSenderRef(reference()); - utilExecuteReq->setSenderData(senderData); - utilExecuteReq->setPrepareId(prepareId); - utilExecuteReq->setReleaseFlag(); // must be done after setting prepareId - -#if 0 - printf("Header size %u\n", headerPtr.sz); - for(int i = 0; i < (int)headerPtr.sz; i++) - printf("H'%.8x ", headerBuffer[i]); - printf("\n"); - - printf("Data size %u\n", dataPtr.sz); - for(int i = 0; i < (int)dataPtr.sz; i++) - printf("H'%.8x ", dataBuffer[i]); - printf("\n"); -#endif - - struct LinearSectionPtr sectionsPtr[UtilExecuteReq::NoOfSections]; - sectionsPtr[UtilExecuteReq::HEADER_SECTION].p = headerPtr.p; - sectionsPtr[UtilExecuteReq::HEADER_SECTION].sz = noAttr; - sectionsPtr[UtilExecuteReq::DATA_SECTION].p = dataPtr.p; - sectionsPtr[UtilExecuteReq::DATA_SECTION].sz = dataPtr.sz; - - sendSignalUtilReq(pcallback, DBUTIL_REF, GSN_UTIL_EXECUTE_REQ, signal, - UtilExecuteReq::SignalLength, JBB, - sectionsPtr, UtilExecuteReq::NoOfSections); -} - -void Dbdict::parseReadEventSys(Signal* signal, sysTab_NDBEVENTS_0& m_eventRec) -{ - SegmentedSectionPtr headerPtr, dataPtr; - jam(); - signal->getSection(headerPtr, UtilExecuteReq::HEADER_SECTION); - SectionReader headerReader(headerPtr, getSectionSegmentPool()); - - signal->getSection(dataPtr, UtilExecuteReq::DATA_SECTION); - SectionReader dataReader(dataPtr, getSectionSegmentPool()); - - AttributeHeader header; - Uint32 *dst = (Uint32*)&m_eventRec; - - for (int i = 0; i < EVENT_SYSTEM_TABLE_LENGTH; i++) { - headerReader.getWord((Uint32 *)&header); - int sz = header.getDataSize(); - for (int i=0; i < sz; i++) - dataReader.getWord(dst++); - } - - ndbrequire( ((char*)dst-(char*)&m_eventRec) == sizeof(m_eventRec) ); - - releaseSections(signal); -} - -void Dbdict::createEventUTIL_EXECUTE(Signal *signal, - Uint32 callbackData, - Uint32 returnCode) -{ - jam(); - EVENT_TRACE; - if (returnCode == 0) { - // Entry into system table all set - UtilExecuteConf* const conf = (UtilExecuteConf*)signal->getDataPtr(); - jam(); - OpCreateEventPtr evntRecPtr; - evntRecPtr.i = conf->getSenderData(); - - ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL); - OpCreateEvent *evntRec = evntRecPtr.p; - - switch (evntRec->m_requestType) { - case CreateEvntReq::RT_USER_GET: { -#ifdef EVENT_DEBUG - printf("get type = %d\n", CreateEvntReq::RT_USER_GET); -#endif - parseReadEventSys(signal, evntRecPtr.p->m_eventRec); - - evntRec->m_request.setEventType(evntRecPtr.p->m_eventRec.EVENT_TYPE); - evntRec->m_request.setAttrListBitmask(*(AttributeMask*)evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK); - evntRec->m_request.setEventId(evntRecPtr.p->m_eventRec.SUBID); - evntRec->m_request.setEventKey(evntRecPtr.p->m_eventRec.SUBKEY); - -#ifdef EVENT_DEBUG - printf("EventName: %s\n", evntRec->m_eventRec.NAME); - printf("TableName: %s\n", evntRec->m_eventRec.TABLE_NAME); -#endif - - // find table id for event table - TableRecord keyRecord; - strcpy(keyRecord.tableName, evntRecPtr.p->m_eventRec.TABLE_NAME); - - TableRecordPtr tablePtr; - c_tableRecordHash.find(tablePtr, keyRecord); - - if (tablePtr.i == RNIL) { - jam(); - evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined; - evntRecPtr.p->m_errorLine = __LINE__; - evntRecPtr.p->m_errorNode = reference(); - - createEvent_sendReply(signal, evntRecPtr); - return; - } - - evntRec->m_request.setTableId(tablePtr.p->tableId); - - createEventComplete_RT_USER_GET(signal, evntRecPtr); - return; - } - case CreateEvntReq::RT_USER_CREATE: { -#ifdef EVENT_DEBUG - printf("create type = %d\n", CreateEvntReq::RT_USER_CREATE); -#endif - jam(); - createEventComplete_RT_USER_CREATE(signal, evntRecPtr); - return; - } - break; - default: - ndbrequire(false); - } - } else { // returnCode != 0 - UtilExecuteRef * const ref = (UtilExecuteRef *)signal->getDataPtr(); - OpCreateEventPtr evntRecPtr; - evntRecPtr.i = ref->getSenderData(); - ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL); - jam(); - evntRecPtr.p->m_errorNode = reference(); - evntRecPtr.p->m_errorLine = __LINE__; - - switch (ref->getErrorCode()) { - case UtilExecuteRef::TCError: - switch (ref->getTCErrorCode()) { - case ZNOT_FOUND: - jam(); - evntRecPtr.p->m_errorCode = CreateEvntRef::EventNotFound; - break; - case ZALREADYEXIST: - jam(); - evntRecPtr.p->m_errorCode = CreateEvntRef::EventNameExists; - break; - default: - jam(); - evntRecPtr.p->m_errorCode = CreateEvntRef::UndefinedTCError; - break; - } - break; - default: - jam(); - evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined; - break; - } - - createEvent_sendReply(signal, evntRecPtr); - } -} - -/*********************************************************************** - * - * NdbEventOperation, reading systable, creating event in suma - * - */ - -void -Dbdict::createEvent_RT_USER_GET(Signal* signal, OpCreateEventPtr evntRecPtr){ - jam(); - EVENT_TRACE; -#ifdef EVENT_PH2_DEBUG - ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_REQ::RT_USER_GET evntRecPtr.i = (%d), ref = %u", evntRecPtr.i, evntRecPtr.p->m_request.getUserRef()); -#endif - - SegmentedSectionPtr ssPtr; - - signal->getSection(ssPtr, 0); - - SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool()); -#ifdef EVENT_DEBUG - r0.printAll(ndbout); -#endif - if ((!r0.first()) || - (r0.getValueType() != SimpleProperties::StringValue) || - (r0.getValueLen() <= 0)) { - jam(); - releaseSections(signal); - - evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined; - evntRecPtr.p->m_errorLine = __LINE__; - evntRecPtr.p->m_errorNode = reference(); - - createEvent_sendReply(signal, evntRecPtr); - return; - } - - r0.getString(evntRecPtr.p->m_eventRec.NAME); - int len = strlen(evntRecPtr.p->m_eventRec.NAME); - memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len); - - releaseSections(signal); - - Callback c = { safe_cast(&Dbdict::createEventUTIL_PREPARE), 0 }; - - prepareTransactionEventSysTable(&c, signal, evntRecPtr.i, - UtilPrepareReq::Read); - /* - * Will read systable and fill an OpCreateEventPtr - * and return below - */ -} - -void -Dbdict::createEventComplete_RT_USER_GET(Signal* signal, - OpCreateEventPtr evntRecPtr){ - jam(); - - // Send to oneself and the other DICT's - CreateEvntReq * req = (CreateEvntReq *)signal->getDataPtrSend(); - - *req = evntRecPtr.p->m_request; - req->senderRef = reference(); - req->senderData = evntRecPtr.i; - - req->addRequestFlag(CreateEvntReq::RT_DICT_AFTER_GET); - -#ifdef EVENT_PH2_DEBUG - ndbout_c("DBDICT(Coordinator) sending GSN_CREATE_EVNT_REQ::RT_DICT_AFTER_GET to DBDICT participants evntRecPtr.i = (%d)", evntRecPtr.i); -#endif - - NodeReceiverGroup rg(DBDICT, c_aliveNodes); - RequestTracker & p = evntRecPtr.p->m_reqTracker; - p.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF, evntRecPtr.i); - - sendSignal(rg, GSN_CREATE_EVNT_REQ, signal, CreateEvntReq::SignalLength, JBB); -} - -void -Dbdict::createEvent_nodeFailCallback(Signal* signal, Uint32 eventRecPtrI, - Uint32 returnCode){ - OpCreateEventPtr evntRecPtr; - c_opCreateEvent.getPtr(evntRecPtr, eventRecPtrI); - createEvent_sendReply(signal, evntRecPtr); -} - -void Dbdict::execCREATE_EVNT_REF(Signal* signal) -{ - jamEntry(); - EVENT_TRACE; - CreateEvntRef * const ref = (CreateEvntRef *)signal->getDataPtr(); - OpCreateEventPtr evntRecPtr; - - evntRecPtr.i = ref->getUserData(); - - ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL); - -#ifdef EVENT_PH2_DEBUG - ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_REF evntRecPtr.i = (%d)", evntRecPtr.i); -#endif - - if (ref->errorCode == CreateEvntRef::NF_FakeErrorREF){ - jam(); - evntRecPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(ref->senderRef)); - } else { - jam(); - evntRecPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(ref->senderRef)); - } - createEvent_sendReply(signal, evntRecPtr); - - return; -} - -void Dbdict::execCREATE_EVNT_CONF(Signal* signal) -{ - jamEntry(); - EVENT_TRACE; - CreateEvntConf * const conf = (CreateEvntConf *)signal->getDataPtr(); - OpCreateEventPtr evntRecPtr; - - evntRecPtr.i = conf->getUserData(); - - ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL); - -#ifdef EVENT_PH2_DEBUG - ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_CONF evntRecPtr.i = (%d)", evntRecPtr.i); -#endif - - evntRecPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(conf->senderRef)); - - // we will only have a valid tablename if it the master DICT sending this - // but that's ok - LinearSectionPtr ptr[1]; - ptr[0].p = (Uint32 *)evntRecPtr.p->m_eventRec.TABLE_NAME; - ptr[0].sz = - (strlen(evntRecPtr.p->m_eventRec.TABLE_NAME)+4)/4; // to make sure we have a null - - createEvent_sendReply(signal, evntRecPtr, ptr, 1); - - return; -} - -/************************************************ - * - * Participant stuff - * - */ - -void -Dbdict::createEvent_RT_DICT_AFTER_GET(Signal* signal, OpCreateEventPtr evntRecPtr){ - jam(); - evntRecPtr.p->m_request.setUserRef(signal->senderBlockRef()); - -#ifdef EVENT_PH2_DEBUG - ndbout_c("DBDICT(Participant) got CREATE_EVNT_REQ::RT_DICT_AFTER_GET evntRecPtr.i = (%d)", evntRecPtr.i); -#endif - - // the signal comes from the DICT block that got the first user request! - // This code runs on all DICT nodes, including oneself - - // Seize a Create Event record, the Coordinator will now have two seized - // but that's ok, it's like a recursion - - SubCreateReq * sumaReq = (SubCreateReq *)signal->getDataPtrSend(); - - sumaReq->subscriberRef = reference(); // reference to DICT - sumaReq->subscriberData = evntRecPtr.i; - sumaReq->subscriptionId = evntRecPtr.p->m_request.getEventId(); - sumaReq->subscriptionKey = evntRecPtr.p->m_request.getEventKey(); - sumaReq->subscriptionType = SubCreateReq::TableEvent; - sumaReq->tableId = evntRecPtr.p->m_request.getTableId(); - -#ifdef EVENT_PH2_DEBUG - ndbout_c("sending GSN_SUB_CREATE_REQ"); -#endif - - sendSignal(SUMA_REF, GSN_SUB_CREATE_REQ, signal, - SubCreateReq::SignalLength+1 /*to get table Id*/, JBB); -} - -void Dbdict::execSUB_CREATE_REF(Signal* signal) -{ - jamEntry(); - EVENT_TRACE; - SubCreateRef * const ref = (SubCreateRef *)signal->getDataPtr(); - OpCreateEventPtr evntRecPtr; - - evntRecPtr.i = ref->subscriberData; - ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL); - -#ifdef EVENT_PH2_DEBUG - ndbout_c("DBDICT(Participant) got SUB_CREATE_REF evntRecPtr.i = (%d)", evntRecPtr.i); -#endif - - if (ref->err == GrepError::SUBSCRIPTION_ID_NOT_UNIQUE) { - jam(); -#ifdef EVENT_PH2_DEBUG - ndbout_c("SUBSCRIPTION_ID_NOT_UNIQUE"); -#endif - createEvent_sendReply(signal, evntRecPtr); - return; - } - -#ifdef EVENT_PH2_DEBUG - ndbout_c("Other error"); -#endif - - evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined; - evntRecPtr.p->m_errorLine = __LINE__; - evntRecPtr.p->m_errorNode = reference(); - - createEvent_sendReply(signal, evntRecPtr); -} - -void Dbdict::execSUB_CREATE_CONF(Signal* signal) -{ - jamEntry(); - EVENT_TRACE; - - SubCreateConf * const sumaConf = (SubCreateConf *)signal->getDataPtr(); - - const Uint32 subscriptionId = sumaConf->subscriptionId; - const Uint32 subscriptionKey = sumaConf->subscriptionKey; - const Uint32 evntRecId = sumaConf->subscriberData; - - OpCreateEvent *evntRec; - ndbrequire((evntRec = c_opCreateEvent.getPtr(evntRecId)) != NULL); - -#ifdef EVENT_PH2_DEBUG - ndbout_c("DBDICT(Participant) got SUB_CREATE_CONF evntRecPtr.i = (%d)", evntRecId); -#endif - - SubSyncReq *sumaSync = (SubSyncReq *)signal->getDataPtrSend(); - - sumaSync->subscriptionId = subscriptionId; - sumaSync->subscriptionKey = subscriptionKey; - sumaSync->part = (Uint32) SubscriptionData::MetaData; - sumaSync->subscriberData = evntRecId; - - sendSignal(SUMA_REF, GSN_SUB_SYNC_REQ, signal, - SubSyncReq::SignalLength, JBB); -} - -void Dbdict::execSUB_SYNC_REF(Signal* signal) -{ - jamEntry(); - EVENT_TRACE; - SubSyncRef * const ref = (SubSyncRef *)signal->getDataPtr(); - OpCreateEventPtr evntRecPtr; - - evntRecPtr.i = ref->subscriberData; - ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL); - - evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined; - evntRecPtr.p->m_errorLine = __LINE__; - evntRecPtr.p->m_errorNode = reference(); - - createEvent_sendReply(signal, evntRecPtr); -} - -void Dbdict::execSUB_SYNC_CONF(Signal* signal) -{ - jamEntry(); - EVENT_TRACE; - - SubSyncConf * const sumaSyncConf = (SubSyncConf *)signal->getDataPtr(); - - // Uint32 subscriptionId = sumaSyncConf->subscriptionId; - // Uint32 subscriptionKey = sumaSyncConf->subscriptionKey; - OpCreateEventPtr evntRecPtr; - - evntRecPtr.i = sumaSyncConf->subscriberData; - ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL); - - ndbrequire(sumaSyncConf->part == (Uint32)SubscriptionData::MetaData); - - createEvent_sendReply(signal, evntRecPtr); -} - -/**************************************************** - * - * common create reply method - * - *******************************************************/ - -void Dbdict::createEvent_sendReply(Signal* signal, - OpCreateEventPtr evntRecPtr, - LinearSectionPtr *ptr, int noLSP) -{ - jam(); - EVENT_TRACE; - - // check if we're ready to sent reply - // if we are the master dict we might be waiting for conf/ref - - if (!evntRecPtr.p->m_reqTracker.done()) { - jam(); - return; // there's more to come - } - - if (evntRecPtr.p->m_reqTracker.hasRef()) { - ptr = NULL; // we don't want to return anything if there's an error - if (!evntRecPtr.p->hasError()) { - evntRecPtr.p->m_errorCode = CreateEvntRef::Undefined; - evntRecPtr.p->m_errorLine = __LINE__; - evntRecPtr.p->m_errorNode = reference(); - jam(); - } else - jam(); - } - - // reference to API if master DICT - // else reference to master DICT - Uint32 senderRef = evntRecPtr.p->m_request.getUserRef(); - Uint32 signalLength; - Uint32 gsn; - - if (evntRecPtr.p->hasError()) { - jam(); - EVENT_TRACE; - CreateEvntRef * ret = (CreateEvntRef *)signal->getDataPtrSend(); - - ret->setEventId(evntRecPtr.p->m_request.getEventId()); - ret->setEventKey(evntRecPtr.p->m_request.getEventKey()); - ret->setUserData(evntRecPtr.p->m_request.getUserData()); - ret->senderRef = reference(); - ret->setTableId(evntRecPtr.p->m_request.getTableId()); - ret->setEventType(evntRecPtr.p->m_request.getEventType()); - ret->setRequestType(evntRecPtr.p->m_request.getRequestType()); - - ret->setErrorCode(evntRecPtr.p->m_errorCode); - ret->setErrorLine(evntRecPtr.p->m_errorLine); - ret->setErrorNode(evntRecPtr.p->m_errorNode); - - signalLength = CreateEvntRef::SignalLength; -#ifdef EVENT_PH2_DEBUG - ndbout_c("DBDICT sending GSN_CREATE_EVNT_REF to evntRecPtr.i = (%d) node = %u ref = %u", evntRecPtr.i, refToNode(senderRef), senderRef); - ndbout_c("errorCode = %u", evntRecPtr.p->m_errorCode); - ndbout_c("errorLine = %u", evntRecPtr.p->m_errorLine); -#endif - gsn = GSN_CREATE_EVNT_REF; - - } else { - jam(); - EVENT_TRACE; - CreateEvntConf * evntConf = (CreateEvntConf *)signal->getDataPtrSend(); - - evntConf->setEventId(evntRecPtr.p->m_request.getEventId()); - evntConf->setEventKey(evntRecPtr.p->m_request.getEventKey()); - evntConf->setUserData(evntRecPtr.p->m_request.getUserData()); - evntConf->senderRef = reference(); - evntConf->setTableId(evntRecPtr.p->m_request.getTableId()); - evntConf->setAttrListBitmask(evntRecPtr.p->m_request.getAttrListBitmask()); - evntConf->setEventType(evntRecPtr.p->m_request.getEventType()); - evntConf->setRequestType(evntRecPtr.p->m_request.getRequestType()); - - signalLength = CreateEvntConf::SignalLength; -#ifdef EVENT_PH2_DEBUG - ndbout_c("DBDICT sending GSN_CREATE_EVNT_CONF to evntRecPtr.i = (%d) node = %u ref = %u", evntRecPtr.i, refToNode(senderRef), senderRef); -#endif - gsn = GSN_CREATE_EVNT_CONF; - } - - if (ptr) { - jam(); - sendSignal(senderRef, gsn, signal, signalLength, JBB, ptr, noLSP); - } else { - jam(); - sendSignal(senderRef, gsn, signal, signalLength, JBB); - } - - c_opCreateEvent.release(evntRecPtr); -} - -/*************************************************************/ - -/******************************************************************** - * - * Start event - * - *******************************************************************/ - -void Dbdict::execSUB_START_REQ(Signal* signal) -{ - jamEntry(); - - Uint32 origSenderRef = signal->senderBlockRef(); - - OpSubEventPtr subbPtr; - if (!c_opSubEvent.seize(subbPtr)) { - SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend(); - { // fix - Uint32 subcriberRef = ((SubStartReq*)signal->getDataPtr())->subscriberRef; - ref->subscriberRef = subcriberRef; - } - jam(); - // ret->setErrorCode(SubStartRef::SeizeError); - // ret->setErrorLine(__LINE__); - // ret->setErrorNode(reference()); - ref->senderRef = reference(); - ref->setTemporary(SubStartRef::Busy); - - sendSignal(origSenderRef, GSN_SUB_START_REF, signal, - SubStartRef::SignalLength2, JBB); - return; - } - - { - const SubStartReq* req = (SubStartReq*) signal->getDataPtr(); - subbPtr.p->m_senderRef = req->senderRef; - subbPtr.p->m_senderData = req->senderData; - subbPtr.p->m_errorCode = 0; - } - - if (refToBlock(origSenderRef) != DBDICT) { - /* - * Coordinator - */ - jam(); - - subbPtr.p->m_senderRef = origSenderRef; // not sure if API sets correctly - NodeReceiverGroup rg(DBDICT, c_aliveNodes); - RequestTracker & p = subbPtr.p->m_reqTracker; - p.init<SubStartRef>(c_counterMgr, rg, GSN_SUB_START_REF, subbPtr.i); - - SubStartReq* req = (SubStartReq*) signal->getDataPtrSend(); - - req->senderRef = reference(); - req->senderData = subbPtr.i; - -#ifdef EVENT_PH3_DEBUG - ndbout_c("DBDICT(Coordinator) sending GSN_SUB_START_REQ to DBDICT participants subbPtr.i = (%d)", subbPtr.i); -#endif - - sendSignal(rg, GSN_SUB_START_REQ, signal, SubStartReq::SignalLength2, JBB); - return; - } - /* - * Participant - */ - ndbrequire(refToBlock(origSenderRef) == DBDICT); - - { - SubStartReq* req = (SubStartReq*) signal->getDataPtrSend(); - - req->senderRef = reference(); - req->senderData = subbPtr.i; - -#ifdef EVENT_PH3_DEBUG - ndbout_c("DBDICT(Participant) sending GSN_SUB_START_REQ to SUMA subbPtr.i = (%d)", subbPtr.i); -#endif - sendSignal(SUMA_REF, GSN_SUB_START_REQ, signal, SubStartReq::SignalLength2, JBB); - } -} - -void Dbdict::execSUB_START_REF(Signal* signal) -{ - jamEntry(); - - const SubStartRef* ref = (SubStartRef*) signal->getDataPtr(); - Uint32 senderRef = ref->senderRef; - - OpSubEventPtr subbPtr; - c_opSubEvent.getPtr(subbPtr, ref->senderData); - - if (refToBlock(senderRef) == SUMA) { - /* - * Participant - */ - jam(); - -#ifdef EVENT_PH3_DEBUG - ndbout_c("DBDICT(Participant) got GSN_SUB_START_REF = (%d)", subbPtr.i); -#endif - - if (ref->isTemporary()){ - jam(); - SubStartReq* req = (SubStartReq*)signal->getDataPtrSend(); - { // fix - Uint32 subscriberRef = ref->subscriberRef; - req->subscriberRef = subscriberRef; - } - req->senderRef = reference(); - req->senderData = subbPtr.i; - sendSignal(SUMA_REF, GSN_SUB_START_REQ, - signal, SubStartReq::SignalLength2, JBB); - } else { - jam(); - - SubStartRef* ref = (SubStartRef*) signal->getDataPtrSend(); - ref->senderRef = reference(); - ref->senderData = subbPtr.p->m_senderData; - sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_REF, - signal, SubStartRef::SignalLength2, JBB); - c_opSubEvent.release(subbPtr); - } - return; - } - /* - * Coordinator - */ - ndbrequire(refToBlock(senderRef) == DBDICT); -#ifdef EVENT_PH3_DEBUG - ndbout_c("DBDICT(Coordinator) got GSN_SUB_START_REF = (%d)", subbPtr.i); -#endif - if (ref->errorCode == SubStartRef::NF_FakeErrorREF){ - jam(); - subbPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef)); - } else { - jam(); - subbPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef)); - } - completeSubStartReq(signal,subbPtr.i,0); -} - -void Dbdict::execSUB_START_CONF(Signal* signal) -{ - jamEntry(); - - const SubStartConf* conf = (SubStartConf*) signal->getDataPtr(); - Uint32 senderRef = conf->senderRef; - - OpSubEventPtr subbPtr; - c_opSubEvent.getPtr(subbPtr, conf->senderData); - - if (refToBlock(senderRef) == SUMA) { - /* - * Participant - */ - jam(); - SubStartConf* conf = (SubStartConf*) signal->getDataPtrSend(); - -#ifdef EVENT_PH3_DEBUG - ndbout_c("DBDICT(Participant) got GSN_SUB_START_CONF = (%d)", subbPtr.i); -#endif - - conf->senderRef = reference(); - conf->senderData = subbPtr.p->m_senderData; - - sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_CONF, - signal, SubStartConf::SignalLength2, JBB); - c_opSubEvent.release(subbPtr); - return; - } - /* - * Coordinator - */ - ndbrequire(refToBlock(senderRef) == DBDICT); -#ifdef EVENT_PH3_DEBUG - ndbout_c("DBDICT(Coordinator) got GSN_SUB_START_CONF = (%d)", subbPtr.i); -#endif - subbPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef)); - completeSubStartReq(signal,subbPtr.i,0); -} - -/* - * Coordinator - */ -void Dbdict::completeSubStartReq(Signal* signal, - Uint32 ptrI, - Uint32 returnCode){ - jam(); - - OpSubEventPtr subbPtr; - c_opSubEvent.getPtr(subbPtr, ptrI); - - if (!subbPtr.p->m_reqTracker.done()){ - jam(); - return; - } - - if (subbPtr.p->m_reqTracker.hasRef()) { - jam(); -#ifdef EVENT_DEBUG - ndbout_c("SUB_START_REF"); -#endif - sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_REF, - signal, SubStartRef::SignalLength, JBB); - if (subbPtr.p->m_reqTracker.hasConf()) { - // stopStartedNodes(signal); - } - c_opSubEvent.release(subbPtr); - return; - } -#ifdef EVENT_DEBUG - ndbout_c("SUB_START_CONF"); -#endif - sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_CONF, - signal, SubStartConf::SignalLength, JBB); - c_opSubEvent.release(subbPtr); -} - -/******************************************************************** - * - * Stop event - * - *******************************************************************/ - -void Dbdict::execSUB_STOP_REQ(Signal* signal) -{ - jamEntry(); - - Uint32 origSenderRef = signal->senderBlockRef(); - - OpSubEventPtr subbPtr; - if (!c_opSubEvent.seize(subbPtr)) { - SubStopRef * ref = (SubStopRef *)signal->getDataPtrSend(); - jam(); - // ret->setErrorCode(SubStartRef::SeizeError); - // ret->setErrorLine(__LINE__); - // ret->setErrorNode(reference()); - ref->senderRef = reference(); - ref->setTemporary(SubStopRef::Busy); - - sendSignal(origSenderRef, GSN_SUB_STOP_REF, signal, - SubStopRef::SignalLength, JBB); - return; - } - - { - const SubStopReq* req = (SubStopReq*) signal->getDataPtr(); - subbPtr.p->m_senderRef = req->senderRef; - subbPtr.p->m_senderData = req->senderData; - subbPtr.p->m_errorCode = 0; - } - - if (refToBlock(origSenderRef) != DBDICT) { - /* - * Coordinator - */ - jam(); -#ifdef EVENT_DEBUG - ndbout_c("SUB_STOP_REQ 1"); -#endif - subbPtr.p->m_senderRef = origSenderRef; // not sure if API sets correctly - NodeReceiverGroup rg(DBDICT, c_aliveNodes); - RequestTracker & p = subbPtr.p->m_reqTracker; - p.init<SubStopRef>(c_counterMgr, rg, GSN_SUB_STOP_REF, subbPtr.i); - - SubStopReq* req = (SubStopReq*) signal->getDataPtrSend(); - - req->senderRef = reference(); - req->senderData = subbPtr.i; - - sendSignal(rg, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB); - return; - } - /* - * Participant - */ -#ifdef EVENT_DEBUG - ndbout_c("SUB_STOP_REQ 2"); -#endif - ndbrequire(refToBlock(origSenderRef) == DBDICT); - { - SubStopReq* req = (SubStopReq*) signal->getDataPtrSend(); - - req->senderRef = reference(); - req->senderData = subbPtr.i; - - sendSignal(SUMA_REF, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB); - } -} - -void Dbdict::execSUB_STOP_REF(Signal* signal) -{ - jamEntry(); - const SubStopRef* ref = (SubStopRef*) signal->getDataPtr(); - Uint32 senderRef = ref->senderRef; - - OpSubEventPtr subbPtr; - c_opSubEvent.getPtr(subbPtr, ref->senderData); - - if (refToBlock(senderRef) == SUMA) { - /* - * Participant - */ - jam(); - if (ref->isTemporary()){ - jam(); - SubStopReq* req = (SubStopReq*)signal->getDataPtrSend(); - req->senderRef = reference(); - req->senderData = subbPtr.i; - sendSignal(SUMA_REF, GSN_SUB_STOP_REQ, - signal, SubStopReq::SignalLength, JBB); - } else { - jam(); - SubStopRef* ref = (SubStopRef*) signal->getDataPtrSend(); - ref->senderRef = reference(); - ref->senderData = subbPtr.p->m_senderData; - sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_REF, - signal, SubStopRef::SignalLength, JBB); - c_opSubEvent.release(subbPtr); - } - return; - } - /* - * Coordinator - */ - ndbrequire(refToBlock(senderRef) == DBDICT); - if (ref->errorCode == SubStopRef::NF_FakeErrorREF){ - jam(); - subbPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef)); - } else { - jam(); - subbPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef)); - } - completeSubStopReq(signal,subbPtr.i,0); -} - -void Dbdict::execSUB_STOP_CONF(Signal* signal) -{ - jamEntry(); - - const SubStopConf* conf = (SubStopConf*) signal->getDataPtr(); - Uint32 senderRef = conf->senderRef; - - OpSubEventPtr subbPtr; - c_opSubEvent.getPtr(subbPtr, conf->senderData); - - if (refToBlock(senderRef) == SUMA) { - /* - * Participant - */ - jam(); - SubStopConf* conf = (SubStopConf*) signal->getDataPtrSend(); - - conf->senderRef = reference(); - conf->senderData = subbPtr.p->m_senderData; - - sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_CONF, - signal, SubStopConf::SignalLength, JBB); - c_opSubEvent.release(subbPtr); - return; - } - /* - * Coordinator - */ - ndbrequire(refToBlock(senderRef) == DBDICT); - subbPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef)); - completeSubStopReq(signal,subbPtr.i,0); -} - -/* - * Coordinator - */ -void Dbdict::completeSubStopReq(Signal* signal, - Uint32 ptrI, - Uint32 returnCode){ - OpSubEventPtr subbPtr; - c_opSubEvent.getPtr(subbPtr, ptrI); - - if (!subbPtr.p->m_reqTracker.done()){ - jam(); - return; - } - - if (subbPtr.p->m_reqTracker.hasRef()) { - jam(); -#ifdef EVENT_DEBUG - ndbout_c("SUB_STOP_REF"); -#endif - SubStopRef* ref = (SubStopRef*)signal->getDataPtrSend(); - - ref->senderRef = reference(); - ref->senderData = subbPtr.p->m_senderData; - /* - ref->subscriptionId = subbPtr.p->m_senderData; - ref->subscriptionKey = subbPtr.p->m_senderData; - ref->part = subbPtr.p->m_part; // SubscriptionData::Part - ref->subscriberData = subbPtr.p->m_subscriberData; - ref->subscriberRef = subbPtr.p->m_subscriberRef; - */ - ref->errorCode = subbPtr.p->m_errorCode; - - - sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_REF, - signal, SubStopRef::SignalLength, JBB); - if (subbPtr.p->m_reqTracker.hasConf()) { - // stopStartedNodes(signal); - } - c_opSubEvent.release(subbPtr); - return; - } -#ifdef EVENT_DEBUG - ndbout_c("SUB_STOP_CONF"); -#endif - sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_CONF, - signal, SubStopConf::SignalLength, JBB); - c_opSubEvent.release(subbPtr); -} - -/*************************************************************** - * MODULE: Drop event. - * - * Drop event. - * - * TODO - */ - -void -Dbdict::execDROP_EVNT_REQ(Signal* signal) -{ - jamEntry(); - EVENT_TRACE; - - DropEvntReq *req = (DropEvntReq*)signal->getDataPtr(); - const Uint32 senderRef = signal->senderBlockRef(); - OpDropEventPtr evntRecPtr; - - // Seize a Create Event record - if (!c_opDropEvent.seize(evntRecPtr)) { - // Failed to allocate event record - jam(); - releaseSections(signal); - - DropEvntRef * ret = (DropEvntRef *)signal->getDataPtrSend(); - ret->setErrorCode(DropEvntRef::SeizeError); - ret->setErrorLine(__LINE__); - ret->setErrorNode(reference()); - sendSignal(senderRef, GSN_DROP_EVNT_REF, signal, - DropEvntRef::SignalLength, JBB); - return; - } - -#ifdef EVENT_DEBUG - ndbout_c("DBDICT::execDROP_EVNT_REQ evntRecId = (%d)", evntRecPtr.i); -#endif - - OpDropEvent* evntRec = evntRecPtr.p; - evntRec->init(req); - - SegmentedSectionPtr ssPtr; - - signal->getSection(ssPtr, 0); - - SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool()); -#ifdef EVENT_DEBUG - r0.printAll(ndbout); -#endif - // event name - if ((!r0.first()) || - (r0.getValueType() != SimpleProperties::StringValue) || - (r0.getValueLen() <= 0)) { - jam(); - releaseSections(signal); - - evntRecPtr.p->m_errorCode = DropEvntRef::Undefined; - evntRecPtr.p->m_errorLine = __LINE__; - evntRecPtr.p->m_errorNode = reference(); - - dropEvent_sendReply(signal, evntRecPtr); - return; - } - r0.getString(evntRecPtr.p->m_eventRec.NAME); - { - int len = strlen(evntRecPtr.p->m_eventRec.NAME); - memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len); -#ifdef EVENT_DEBUG - printf("DropEvntReq; EventName %s, len %u\n", - evntRecPtr.p->m_eventRec.NAME, len); - for(int i = 0; i < MAX_TAB_NAME_SIZE/4; i++) - printf("H'%.8x ", ((Uint32*)evntRecPtr.p->m_eventRec.NAME)[i]); - printf("\n"); -#endif - } - - releaseSections(signal); - - Callback c = { safe_cast(&Dbdict::dropEventUTIL_PREPARE_READ), 0 }; - - prepareTransactionEventSysTable(&c, signal, evntRecPtr.i, - UtilPrepareReq::Read); -} - -void -Dbdict::dropEventUTIL_PREPARE_READ(Signal* signal, - Uint32 callbackData, - Uint32 returnCode) -{ - jam(); - EVENT_TRACE; - if (returnCode != 0) { - EVENT_TRACE; - dropEventUtilPrepareRef(signal, callbackData, returnCode); - return; - } - - UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr(); - OpDropEventPtr evntRecPtr; - evntRecPtr.i = req->getSenderData(); - const Uint32 prepareId = req->getPrepareId(); - - ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL); - - Callback c = { safe_cast(&Dbdict::dropEventUTIL_EXECUTE_READ), 0 }; - - executeTransEventSysTable(&c, signal, - evntRecPtr.i, evntRecPtr.p->m_eventRec, - prepareId, UtilPrepareReq::Read); -} - -void -Dbdict::dropEventUTIL_EXECUTE_READ(Signal* signal, - Uint32 callbackData, - Uint32 returnCode) -{ - jam(); - EVENT_TRACE; - if (returnCode != 0) { - EVENT_TRACE; - dropEventUtilExecuteRef(signal, callbackData, returnCode); - return; - } - - OpDropEventPtr evntRecPtr; - UtilExecuteConf * const ref = (UtilExecuteConf *)signal->getDataPtr(); - jam(); - evntRecPtr.i = ref->getSenderData(); - ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL); - - parseReadEventSys(signal, evntRecPtr.p->m_eventRec); - - NodeReceiverGroup rg(DBDICT, c_aliveNodes); - RequestTracker & p = evntRecPtr.p->m_reqTracker; - p.init<SubRemoveRef>(c_counterMgr, rg, GSN_SUB_REMOVE_REF, - evntRecPtr.i); - - SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtrSend(); - - req->senderRef = reference(); - req->senderData = evntRecPtr.i; - req->subscriptionId = evntRecPtr.p->m_eventRec.SUBID; - req->subscriptionKey = evntRecPtr.p->m_eventRec.SUBKEY; - - sendSignal(rg, GSN_SUB_REMOVE_REQ, signal, SubRemoveReq::SignalLength, JBB); -} - -/* - * Participant - */ - -void -Dbdict::execSUB_REMOVE_REQ(Signal* signal) -{ - jamEntry(); - - Uint32 origSenderRef = signal->senderBlockRef(); - - OpSubEventPtr subbPtr; - if (!c_opSubEvent.seize(subbPtr)) { - SubRemoveRef * ref = (SubRemoveRef *)signal->getDataPtrSend(); - jam(); - ref->senderRef = reference(); - ref->setTemporary(SubRemoveRef::Busy); - - sendSignal(origSenderRef, GSN_SUB_REMOVE_REF, signal, - SubRemoveRef::SignalLength, JBB); - return; - } - - { - const SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtr(); - subbPtr.p->m_senderRef = req->senderRef; - subbPtr.p->m_senderData = req->senderData; - subbPtr.p->m_errorCode = 0; - } - - SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtrSend(); - req->senderRef = reference(); - req->senderData = subbPtr.i; - - sendSignal(SUMA_REF, GSN_SUB_REMOVE_REQ, signal, SubRemoveReq::SignalLength, JBB); -} - -/* - * Coordintor/Participant - */ - -void -Dbdict::execSUB_REMOVE_REF(Signal* signal) -{ - jamEntry(); - const SubRemoveRef* ref = (SubRemoveRef*) signal->getDataPtr(); - Uint32 senderRef = ref->senderRef; - - if (refToBlock(senderRef) == SUMA) { - /* - * Participant - */ - jam(); - OpSubEventPtr subbPtr; - c_opSubEvent.getPtr(subbPtr, ref->senderData); - if (ref->errorCode == (Uint32) GrepError::SUBSCRIPTION_ID_NOT_FOUND) { - // conf this since this may occur if a nodefailiure has occured - // earlier so that the systable was not cleared - SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtrSend(); - conf->senderRef = reference(); - conf->senderData = subbPtr.p->m_senderData; - sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_CONF, - signal, SubRemoveConf::SignalLength, JBB); - } else { - SubRemoveRef* ref = (SubRemoveRef*) signal->getDataPtrSend(); - ref->senderRef = reference(); - ref->senderData = subbPtr.p->m_senderData; - sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_REF, - signal, SubRemoveRef::SignalLength, JBB); - } - c_opSubEvent.release(subbPtr); - return; - } - /* - * Coordinator - */ - ndbrequire(refToBlock(senderRef) == DBDICT); - OpDropEventPtr eventRecPtr; - c_opDropEvent.getPtr(eventRecPtr, ref->senderData); - if (ref->errorCode == SubRemoveRef::NF_FakeErrorREF){ - jam(); - eventRecPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef)); - } else { - jam(); - eventRecPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef)); - } - completeSubRemoveReq(signal,eventRecPtr.i,0); -} - -void -Dbdict::execSUB_REMOVE_CONF(Signal* signal) -{ - jamEntry(); - const SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtr(); - Uint32 senderRef = conf->senderRef; - - if (refToBlock(senderRef) == SUMA) { - /* - * Participant - */ - jam(); - OpSubEventPtr subbPtr; - c_opSubEvent.getPtr(subbPtr, conf->senderData); - SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtrSend(); - conf->senderRef = reference(); - conf->senderData = subbPtr.p->m_senderData; - sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_CONF, - signal, SubRemoveConf::SignalLength, JBB); - c_opSubEvent.release(subbPtr); - return; - } - /* - * Coordinator - */ - ndbrequire(refToBlock(senderRef) == DBDICT); - OpDropEventPtr eventRecPtr; - c_opDropEvent.getPtr(eventRecPtr, conf->senderData); - eventRecPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef)); - completeSubRemoveReq(signal,eventRecPtr.i,0); -} - -void -Dbdict::completeSubRemoveReq(Signal* signal, Uint32 ptrI, Uint32 xxx) -{ - OpDropEventPtr evntRecPtr; - c_opDropEvent.getPtr(evntRecPtr, ptrI); - - if (!evntRecPtr.p->m_reqTracker.done()){ - jam(); - return; - } - - if (evntRecPtr.p->m_reqTracker.hasRef()) { - jam(); - evntRecPtr.p->m_errorNode = reference(); - evntRecPtr.p->m_errorLine = __LINE__; - evntRecPtr.p->m_errorCode = DropEvntRef::Undefined; - dropEvent_sendReply(signal, evntRecPtr); - return; - } - - Callback c = { safe_cast(&Dbdict::dropEventUTIL_PREPARE_DELETE), 0 }; - - prepareTransactionEventSysTable(&c, signal, evntRecPtr.i, - UtilPrepareReq::Delete); -} - -void -Dbdict::dropEventUTIL_PREPARE_DELETE(Signal* signal, - Uint32 callbackData, - Uint32 returnCode) -{ - jam(); - EVENT_TRACE; - if (returnCode != 0) { - EVENT_TRACE; - dropEventUtilPrepareRef(signal, callbackData, returnCode); - return; - } - - UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr(); - OpDropEventPtr evntRecPtr; - jam(); - evntRecPtr.i = req->getSenderData(); - const Uint32 prepareId = req->getPrepareId(); - - ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL); -#ifdef EVENT_DEBUG - printf("DropEvntUTIL_PREPARE; evntRecPtr.i len %u\n",evntRecPtr.i); -#endif - - Callback c = { safe_cast(&Dbdict::dropEventUTIL_EXECUTE_DELETE), 0 }; - - executeTransEventSysTable(&c, signal, - evntRecPtr.i, evntRecPtr.p->m_eventRec, - prepareId, UtilPrepareReq::Delete); -} - -void -Dbdict::dropEventUTIL_EXECUTE_DELETE(Signal* signal, - Uint32 callbackData, - Uint32 returnCode) -{ - jam(); - EVENT_TRACE; - if (returnCode != 0) { - EVENT_TRACE; - dropEventUtilExecuteRef(signal, callbackData, returnCode); - return; - } - - OpDropEventPtr evntRecPtr; - UtilExecuteConf * const ref = (UtilExecuteConf *)signal->getDataPtr(); - jam(); - evntRecPtr.i = ref->getSenderData(); - ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL); - - dropEvent_sendReply(signal, evntRecPtr); -} - -void -Dbdict::dropEventUtilPrepareRef(Signal* signal, - Uint32 callbackData, - Uint32 returnCode) -{ - jam(); - EVENT_TRACE; - UtilPrepareRef * const ref = (UtilPrepareRef *)signal->getDataPtr(); - OpDropEventPtr evntRecPtr; - evntRecPtr.i = ref->getSenderData(); - ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL); - - bool temporary = false; - interpretUtilPrepareErrorCode((UtilPrepareRef::ErrorCode)ref->getErrorCode(), - temporary, evntRecPtr.p->m_errorLine); - if (temporary) { - evntRecPtr.p->m_errorCode = (DropEvntRef::ErrorCode) - ((Uint32) DropEvntRef::Undefined | (Uint32) DropEvntRef::Temporary); - } - - if (evntRecPtr.p->m_errorCode == 0) { - evntRecPtr.p->m_errorCode = DropEvntRef::Undefined; - evntRecPtr.p->m_errorLine = __LINE__; - } - evntRecPtr.p->m_errorNode = reference(); - - dropEvent_sendReply(signal, evntRecPtr); -} - -void -Dbdict::dropEventUtilExecuteRef(Signal* signal, - Uint32 callbackData, - Uint32 returnCode) -{ - jam(); - EVENT_TRACE; - OpDropEventPtr evntRecPtr; - UtilExecuteRef * const ref = (UtilExecuteRef *)signal->getDataPtr(); - jam(); - evntRecPtr.i = ref->getSenderData(); - ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL); - - evntRecPtr.p->m_errorNode = reference(); - evntRecPtr.p->m_errorLine = __LINE__; - - switch (ref->getErrorCode()) { - case UtilExecuteRef::TCError: - switch (ref->getTCErrorCode()) { - case ZNOT_FOUND: - jam(); - evntRecPtr.p->m_errorCode = DropEvntRef::EventNotFound; - break; - default: - jam(); - evntRecPtr.p->m_errorCode = DropEvntRef::UndefinedTCError; - break; - } - break; - default: - jam(); - evntRecPtr.p->m_errorCode = DropEvntRef::Undefined; - break; - } - dropEvent_sendReply(signal, evntRecPtr); -} - -void Dbdict::dropEvent_sendReply(Signal* signal, - OpDropEventPtr evntRecPtr) -{ - jam(); - EVENT_TRACE; - Uint32 senderRef = evntRecPtr.p->m_request.getUserRef(); - - if (evntRecPtr.p->hasError()) { - jam(); - DropEvntRef * ret = (DropEvntRef *)signal->getDataPtrSend(); - - ret->setUserData(evntRecPtr.p->m_request.getUserData()); - ret->setUserRef(evntRecPtr.p->m_request.getUserRef()); - - ret->setErrorCode(evntRecPtr.p->m_errorCode); - ret->setErrorLine(evntRecPtr.p->m_errorLine); - ret->setErrorNode(evntRecPtr.p->m_errorNode); - - sendSignal(senderRef, GSN_DROP_EVNT_REF, signal, - DropEvntRef::SignalLength, JBB); - } else { - jam(); - DropEvntConf * evntConf = (DropEvntConf *)signal->getDataPtrSend(); - - evntConf->setUserData(evntRecPtr.p->m_request.getUserData()); - evntConf->setUserRef(evntRecPtr.p->m_request.getUserRef()); - - sendSignal(senderRef, GSN_DROP_EVNT_CONF, signal, - DropEvntConf::SignalLength, JBB); - } - - c_opDropEvent.release(evntRecPtr); -} /** * MODULE: Alter index diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp index 0fa984a4c61..ed8b7e3b822 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp @@ -46,8 +46,6 @@ #include <signaldata/DropIndx.hpp> #include <signaldata/AlterIndx.hpp> #include <signaldata/BuildIndx.hpp> -#include <signaldata/UtilPrepare.hpp> -#include <signaldata/CreateEvnt.hpp> #include <signaldata/CreateTrig.hpp> #include <signaldata/DropTrig.hpp> #include <signaldata/AlterTrig.hpp> @@ -517,45 +515,6 @@ private: void execBACKUP_FRAGMENT_REQ(Signal*); - // Util signals used by Event code - void execUTIL_PREPARE_CONF(Signal* signal); - void execUTIL_PREPARE_REF (Signal* signal); - void execUTIL_EXECUTE_CONF(Signal* signal); - void execUTIL_EXECUTE_REF (Signal* signal); - void execUTIL_RELEASE_CONF(Signal* signal); - void execUTIL_RELEASE_REF (Signal* signal); - - - // Event signals from API - void execCREATE_EVNT_REQ (Signal* signal); - void execCREATE_EVNT_CONF(Signal* signal); - void execCREATE_EVNT_REF (Signal* signal); - - void execDROP_EVNT_REQ (Signal* signal); - - void execSUB_START_REQ (Signal* signal); - void execSUB_START_CONF (Signal* signal); - void execSUB_START_REF (Signal* signal); - - void execSUB_STOP_REQ (Signal* signal); - void execSUB_STOP_CONF (Signal* signal); - void execSUB_STOP_REF (Signal* signal); - - // Event signals from SUMA - - void execCREATE_SUBID_CONF(Signal* signal); - void execCREATE_SUBID_REF (Signal* signal); - - void execSUB_CREATE_CONF(Signal* signal); - void execSUB_CREATE_REF (Signal* signal); - - void execSUB_SYNC_CONF(Signal* signal); - void execSUB_SYNC_REF (Signal* signal); - - void execSUB_REMOVE_REQ(Signal* signal); - void execSUB_REMOVE_CONF(Signal* signal); - void execSUB_REMOVE_REF(Signal* signal); - // Trigger signals void execCREATE_TRIG_REQ(Signal* signal); void execCREATE_TRIG_CONF(Signal* signal); @@ -1386,119 +1345,6 @@ private: typedef Ptr<OpBuildIndex> OpBuildIndexPtr; /** - * Operation record for Util Signals. - */ - struct OpSignalUtil : OpRecordCommon{ - Callback m_callback; - Uint32 m_userData; - }; - typedef Ptr<OpSignalUtil> OpSignalUtilPtr; - - /** - * Operation record for subscribe-start-stop - */ - struct OpSubEvent : OpRecordCommon { - Uint32 m_senderRef; - Uint32 m_senderData; - Uint32 m_errorCode; - RequestTracker m_reqTracker; - }; - typedef Ptr<OpSubEvent> OpSubEventPtr; - - static const Uint32 sysTab_NDBEVENTS_0_szs[]; - - /** - * Operation record for create event. - */ - struct OpCreateEvent : OpRecordCommon { - // original request (event id will be added) - CreateEvntReq m_request; - //AttributeMask m_attrListBitmask; - // AttributeList m_attrList; - sysTab_NDBEVENTS_0 m_eventRec; - // char m_eventName[MAX_TAB_NAME_SIZE]; - // char m_tableName[MAX_TAB_NAME_SIZE]; - - // coordinator DICT - RequestTracker m_reqTracker; - // state info - CreateEvntReq::RequestType m_requestType; - Uint32 m_requestFlag; - // error info - CreateEvntRef::ErrorCode m_errorCode; - Uint32 m_errorLine; - Uint32 m_errorNode; - // ctor - OpCreateEvent() { - memset(&m_request, 0, sizeof(m_request)); - m_requestType = CreateEvntReq::RT_UNDEFINED; - m_requestFlag = 0; - m_errorCode = CreateEvntRef::NoError; - m_errorLine = 0; - m_errorNode = 0; - } - void init(const CreateEvntReq* req, Dbdict* dp) { - m_request = *req; - m_errorCode = CreateEvntRef::NoError; - m_errorLine = 0; - m_errorNode = 0; - m_requestType = req->getRequestType(); - m_requestFlag = req->getRequestFlag(); - } - bool hasError() { - return m_errorCode != CreateEvntRef::NoError; - } - void setError(const CreateEvntRef* ref) { - if (ref != 0 && ! hasError()) { - m_errorCode = ref->getErrorCode(); - m_errorLine = ref->getErrorLine(); - m_errorNode = ref->getErrorNode(); - } - } - - }; - typedef Ptr<OpCreateEvent> OpCreateEventPtr; - - /** - * Operation record for drop event. - */ - struct OpDropEvent : OpRecordCommon { - // original request - DropEvntReq m_request; - // char m_eventName[MAX_TAB_NAME_SIZE]; - sysTab_NDBEVENTS_0 m_eventRec; - RequestTracker m_reqTracker; - // error info - DropEvntRef::ErrorCode m_errorCode; - Uint32 m_errorLine; - Uint32 m_errorNode; - // ctor - OpDropEvent() { - memset(&m_request, 0, sizeof(m_request)); - m_errorCode = DropEvntRef::NoError; - m_errorLine = 0; - m_errorNode = 0; - } - void init(const DropEvntReq* req) { - m_request = *req; - m_errorCode = DropEvntRef::NoError; - m_errorLine = 0; - m_errorNode = 0; - } - bool hasError() { - return m_errorCode != DropEvntRef::NoError; - } - void setError(const DropEvntRef* ref) { - if (ref != 0 && ! hasError()) { - m_errorCode = ref->getErrorCode(); - m_errorLine = ref->getErrorLine(); - m_errorNode = ref->getErrorNode(); - } - } - }; - typedef Ptr<OpDropEvent> OpDropEventPtr; - - /** * Operation record for create trigger. */ struct OpCreateTrigger : OpRecordCommon { @@ -1718,10 +1564,6 @@ public: STATIC_CONST( opDropIndexSize = sizeof(OpDropIndex) ); STATIC_CONST( opAlterIndexSize = sizeof(OpAlterIndex) ); STATIC_CONST( opBuildIndexSize = sizeof(OpBuildIndex) ); - STATIC_CONST( opCreateEventSize = sizeof(OpCreateEvent) ); - STATIC_CONST( opSubEventSize = sizeof(OpSubEvent) ); - STATIC_CONST( opDropEventSize = sizeof(OpDropEvent) ); - STATIC_CONST( opSignalUtilSize = sizeof(OpSignalUtil) ); STATIC_CONST( opCreateTriggerSize = sizeof(OpCreateTrigger) ); STATIC_CONST( opDropTriggerSize = sizeof(OpDropTrigger) ); STATIC_CONST( opAlterTriggerSize = sizeof(OpAlterTrigger) ); @@ -1732,10 +1574,6 @@ private: Uint32 u_opDropTable [PTR_ALIGN(opDropTableSize)]; Uint32 u_opCreateIndex [PTR_ALIGN(opCreateIndexSize)]; Uint32 u_opDropIndex [PTR_ALIGN(opDropIndexSize)]; - Uint32 u_opCreateEvent [PTR_ALIGN(opCreateEventSize)]; - Uint32 u_opSubEvent [PTR_ALIGN(opSubEventSize)]; - Uint32 u_opDropEvent [PTR_ALIGN(opDropEventSize)]; - Uint32 u_opSignalUtil [PTR_ALIGN(opSignalUtilSize)]; Uint32 u_opAlterIndex [PTR_ALIGN(opAlterIndexSize)]; Uint32 u_opBuildIndex [PTR_ALIGN(opBuildIndexSize)]; Uint32 u_opCreateTrigger[PTR_ALIGN(opCreateTriggerSize)]; @@ -1752,10 +1590,6 @@ private: KeyTable2<OpDropIndex, OpRecordUnion> c_opDropIndex; KeyTable2<OpAlterIndex, OpRecordUnion> c_opAlterIndex; KeyTable2<OpBuildIndex, OpRecordUnion> c_opBuildIndex; - KeyTable2<OpCreateEvent, OpRecordUnion> c_opCreateEvent; - KeyTable2<OpSubEvent, OpRecordUnion> c_opSubEvent; - KeyTable2<OpDropEvent, OpRecordUnion> c_opDropEvent; - KeyTable2<OpSignalUtil, OpRecordUnion> c_opSignalUtil; KeyTable2<OpCreateTrigger, OpRecordUnion> c_opCreateTrigger; KeyTable2<OpDropTrigger, OpRecordUnion> c_opDropTrigger; KeyTable2<OpAlterTrigger, OpRecordUnion> c_opAlterTrigger; @@ -2019,101 +1853,6 @@ private: void buildIndex_sendSlaveReq(Signal* signal, OpBuildIndexPtr opPtr); void buildIndex_sendReply(Signal* signal, OpBuildIndexPtr opPtr, bool); - // Events - void - createEventUTIL_PREPARE(Signal* signal, - Uint32 callbackData, - Uint32 returnCode); - void - createEventUTIL_EXECUTE(Signal *signal, - Uint32 callbackData, - Uint32 returnCode); - void - dropEventUTIL_PREPARE_READ(Signal* signal, - Uint32 callbackData, - Uint32 returnCode); - void - dropEventUTIL_EXECUTE_READ(Signal* signal, - Uint32 callbackData, - Uint32 returnCode); - void - dropEventUTIL_PREPARE_DELETE(Signal* signal, - Uint32 callbackData, - Uint32 returnCode); - void - dropEventUTIL_EXECUTE_DELETE(Signal *signal, - Uint32 callbackData, - Uint32 returnCode); - void - dropEventUtilPrepareRef(Signal* signal, - Uint32 callbackData, - Uint32 returnCode); - void - dropEventUtilExecuteRef(Signal* signal, - Uint32 callbackData, - Uint32 returnCode); - int - sendSignalUtilReq(Callback *c, - BlockReference ref, - GlobalSignalNumber gsn, - Signal* signal, - Uint32 length, - JobBufferLevel jbuf, - LinearSectionPtr ptr[3], - Uint32 noOfSections); - int - recvSignalUtilReq(Signal* signal, Uint32 returnCode); - - void completeSubStartReq(Signal* signal, Uint32 ptrI, Uint32 returnCode); - void completeSubStopReq(Signal* signal, Uint32 ptrI, Uint32 returnCode); - void completeSubRemoveReq(Signal* signal, Uint32 ptrI, Uint32 returnCode); - - void dropEvent_sendReply(Signal* signal, - OpDropEventPtr evntRecPtr); - - void createEvent_RT_USER_CREATE(Signal* signal, OpCreateEventPtr evntRecPtr); - void createEventComplete_RT_USER_CREATE(Signal* signal, - OpCreateEventPtr evntRecPtr); - void createEvent_RT_USER_GET(Signal* signal, OpCreateEventPtr evntRecPtr); - void createEventComplete_RT_USER_GET(Signal* signal, OpCreateEventPtr evntRecPtr); - - void createEvent_RT_DICT_AFTER_GET(Signal* signal, OpCreateEventPtr evntRecPtr); - - void createEvent_nodeFailCallback(Signal* signal, Uint32 eventRecPtrI, - Uint32 returnCode); - void createEvent_sendReply(Signal* signal, OpCreateEventPtr evntRecPtr, - LinearSectionPtr *ptr = NULL, int noLSP = 0); - - void prepareTransactionEventSysTable (Callback *c, - Signal* signal, - Uint32 senderData, - UtilPrepareReq::OperationTypeValue prepReq); - void prepareUtilTransaction(Callback *c, - Signal* signal, - Uint32 senderData, - Uint32 tableId, - const char *tableName, - UtilPrepareReq::OperationTypeValue prepReq, - Uint32 noAttr, - Uint32 attrIds[], - const char *attrNames[]); - - void executeTransEventSysTable(Callback *c, - Signal *signal, - const Uint32 ptrI, - sysTab_NDBEVENTS_0& m_eventRec, - const Uint32 prepareId, - UtilPrepareReq::OperationTypeValue prepReq); - void executeTransaction(Callback *c, - Signal* signal, - Uint32 senderData, - Uint32 prepareId, - Uint32 noAttr, - LinearSectionPtr headerPtr, - LinearSectionPtr dataPtr); - - void parseReadEventSys(Signal *signal, sysTab_NDBEVENTS_0& m_eventRec); - // create trigger void createTrigger_recvReply(Signal* signal, const CreateTrigConf* conf, const CreateTrigRef* ref); diff --git a/ndb/src/kernel/blocks/dbdict/DictLock.txt b/ndb/src/kernel/blocks/dbdict/DictLock.txt index 17f24119e9d..72e23ed15a5 100644 --- a/ndb/src/kernel/blocks/dbdict/DictLock.txt +++ b/ndb/src/kernel/blocks/dbdict/DictLock.txt @@ -85,10 +85,14 @@ DIH/s START_MECONF DIH/s -* sp7 - release DICT lock +* (copy data, omitted) -DIH/s - DICT_UNLOCK_ORD - DICT/m +* SL_STARTED - release DICT lock + +CNTR/s + NODE_START_REP + DIH/s + DICT_UNLOCK_ORD + DICT/m # vim: set et sw=4: diff --git a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp index f4a33df9805..5c2cfac5eb1 100644 --- a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp +++ b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp @@ -1599,6 +1599,9 @@ private: */ void startInfoReply(Signal *, Uint32 nodeId); + // DIH specifics for execNODE_START_REP (sendDictUnlockOrd) + void exec_node_start_rep(Signal* signal); + /* * Lock master DICT. Only current use is by starting node * during NR. A pool of slave records is convenient anyway. diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index c8a33715b9c..491aa0849b9 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -1356,24 +1356,6 @@ void Dbdih::execNDB_STTOR(Signal* signal) } ndbrequire(false); break; - case ZNDB_SPH7: - jam(); - switch (typestart) { - case NodeState::ST_INITIAL_START: - case NodeState::ST_SYSTEM_RESTART: - jam(); - ndbsttorry10Lab(signal, __LINE__); - return; - case NodeState::ST_NODE_RESTART: - case NodeState::ST_INITIAL_NODE_RESTART: - jam(); - sendDictUnlockOrd(signal, c_dictLockSlavePtrI_nodeRestart); - c_dictLockSlavePtrI_nodeRestart = RNIL; - ndbsttorry10Lab(signal, __LINE__); - return; - } - ndbrequire(false); - break; default: jam(); ndbsttorry10Lab(signal, __LINE__); @@ -1382,6 +1364,27 @@ void Dbdih::execNDB_STTOR(Signal* signal) }//Dbdih::execNDB_STTOR() void +Dbdih::exec_node_start_rep(Signal* signal) +{ + /* + * Send DICT_UNLOCK_ORD when this node is SL_STARTED. + * + * Sending it before (sp 7) conflicts with code which assumes + * SL_STARTING means we are in copy phase of NR. + * + * NodeState::starting.restartType is not supposed to be used + * when SL_STARTED. Also it seems NODE_START_REP can arrive twice. + * + * For these reasons there are no consistency checks and + * we rely on c_dictLockSlavePtrI_nodeRestart alone. + */ + if (c_dictLockSlavePtrI_nodeRestart != RNIL) { + sendDictUnlockOrd(signal, c_dictLockSlavePtrI_nodeRestart); + c_dictLockSlavePtrI_nodeRestart = RNIL; + } +} + +void Dbdih::createMutexes(Signal * signal, Uint32 count){ Callback c = { safe_cast(&Dbdih::createMutex_done), count }; @@ -1605,6 +1608,7 @@ void Dbdih::nodeRestartPh2Lab(Signal* signal) void Dbdih::recvDictLockConf_nodeRestart(Signal* signal, Uint32 data, Uint32 ret) { ndbrequire(c_dictLockSlavePtrI_nodeRestart == RNIL); + ndbrequire(data != RNIL); c_dictLockSlavePtrI_nodeRestart = data; nodeRestartPh2Lab2(signal); @@ -2018,9 +2022,6 @@ void Dbdih::execINCL_NODECONF(Signal* signal) signal->theData[0] = reference(); signal->theData[1] = c_nodeStartSlave.nodeId; sendSignal(BACKUP_REF, GSN_INCL_NODEREQ, signal, 2, JBB); - - // Suma will not send response to this for now, later... - sendSignal(SUMA_REF, GSN_INCL_NODEREQ, signal, 2, JBB); return; }//if if (TstartNode_or_blockref == numberToRef(BACKUP, getOwnNodeId())){ @@ -8019,12 +8020,6 @@ void Dbdih::writingCopyGciLab(Signal* signal, FileRecordPtr filePtr) if (reason == CopyGCIReq::GLOBAL_CHECKPOINT) { jam(); cgcpParticipantState = GCP_PARTICIPANT_READY; - - SubGcpCompleteRep * const rep = (SubGcpCompleteRep*)signal->getDataPtr(); - rep->gci = coldgcp; - rep->senderData = 0; - sendSignal(SUMA_REF, GSN_SUB_GCP_COMPLETE_REP, signal, - SubGcpCompleteRep::SignalLength, JBB); } jam(); diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp index f8e6292f7f2..d3ba8521226 100644 --- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp +++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp @@ -235,6 +235,7 @@ #define ZSCAN_MARKERS 18 #define ZOPERATION_EVENT_REP 19 #define ZPREP_DROP_TABLE 20 +#define ZENABLE_EXPAND_CHECK 21 /* ------------------------------------------------------------------------- */ /* NODE STATE DURING SYSTEM RESTART, VARIABLES CNODES_SR_STATE */ diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index ecb67d04050..0ea49e47fc7 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -437,6 +437,33 @@ void Dblqh::execCONTINUEB(Signal* signal) checkDropTab(signal); return; break; + case ZENABLE_EXPAND_CHECK: + { + jam(); + fragptr.i = signal->theData[1]; + if (fragptr.i != RNIL) + { + jam(); + ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord); + signal->theData[0] = fragptr.p->tabRef; + signal->theData[1] = fragptr.p->fragId; + sendSignal(DBACC_REF, GSN_EXPANDCHECK2, signal, 2, JBB); + + signal->theData[0] = ZENABLE_EXPAND_CHECK; + signal->theData[1] = fragptr.p->nextFrag; + sendSignal(DBLQH_REF, GSN_CONTINUEB, signal, 2, JBB); + return; + } + else + { + jam(); + StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend(); + conf->startingNodeId = getOwnNodeId(); + sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal, + StartRecConf::SignalLength, JBB); + return; + } + } default: ndbrequire(false); break; @@ -7373,15 +7400,15 @@ void Dblqh::scanLockReleasedLab(Signal* signal) scanptr.p->m_curr_batch_size_rows = 0; scanptr.p->m_curr_batch_size_bytes = 0; closeScanLab(signal); + } else if (scanptr.p->m_last_row && !scanptr.p->scanLockHold) { + jam(); + closeScanLab(signal); + return; } else if (scanptr.p->check_scan_batch_completed() && scanptr.p->scanLockHold != ZTRUE) { jam(); scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ; sendScanFragConf(signal, ZFALSE); - } else if (scanptr.p->m_last_row && !scanptr.p->scanLockHold) { - jam(); - closeScanLab(signal); - return; } else { jam(); /* @@ -15589,20 +15616,21 @@ void Dblqh::srFourthComp(Signal* signal) } else if ((cstartType == NodeState::ST_NODE_RESTART) || (cstartType == NodeState::ST_SYSTEM_RESTART)) { jam(); - StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend(); - conf->startingNodeId = getOwnNodeId(); - sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal, - StartRecConf::SignalLength, JBB); - if(cstartType == NodeState::ST_SYSTEM_RESTART){ - fragptr.i = c_redo_log_complete_frags; - while(fragptr.i != RNIL){ - ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord); - signal->theData[0] = fragptr.p->tabRef; - signal->theData[1] = fragptr.p->fragId; - sendSignal(DBACC_REF, GSN_EXPANDCHECK2, signal, 2, JBB); - fragptr.i = fragptr.p->nextFrag; - } + if(cstartType == NodeState::ST_SYSTEM_RESTART) + { + jam(); + signal->theData[0] = ZENABLE_EXPAND_CHECK; + signal->theData[1] = c_redo_log_complete_frags; + sendSignal(DBLQH_REF, GSN_CONTINUEB, signal, 2, JBB); + } + else + { + jam(); + StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend(); + conf->startingNodeId = getOwnNodeId(); + sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal, + StartRecConf::SignalLength, JBB); } } else { ndbrequire(false); diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index 193e1fea08b..71f3aff05d4 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -7047,6 +7047,18 @@ void Dbtc::checkScanActiveInFailedLqh(Signal* signal, found = true; } } + + ScanFragList deliv(c_scan_frag_pool, scanptr.p->m_delivered_scan_frags); + for(deliv.first(ptr); !ptr.isNull(); deliv.next(ptr)) + { + jam(); + if (refToNode(ptr.p->lqhBlockref) == failedNodeId) + { + jam(); + found = true; + break; + } + } } if(found){ jam(); diff --git a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp index 41194fba82c..0b66d9a45bb 100644 --- a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp +++ b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp @@ -2185,15 +2185,18 @@ private: // Public methods Uint32 getTabDescrOffsets(const Tablerec* regTabPtr, Uint32* offset); Uint32 allocTabDescr(const Tablerec* regTabPtr, Uint32* offset); - void freeTabDescr(Uint32 retRef, Uint32 retNo); + void freeTabDescr(Uint32 retRef, Uint32 retNo, bool normal = true); Uint32 getTabDescrWord(Uint32 index); void setTabDescrWord(Uint32 index, Uint32 word); // Private methods Uint32 sizeOfReadFunction(); void removeTdArea(Uint32 tabDesRef, Uint32 list); - void insertTdArea(Uint32 sizeOfChunk, Uint32 tabDesRef, Uint32 list); - Uint32 itdaMergeTabDescr(Uint32 retRef, Uint32 retNo); + void insertTdArea(Uint32 tabDesRef, Uint32 list); + void itdaMergeTabDescr(Uint32& retRef, Uint32& retNo, bool normal); +#ifdef VM_TRACE + void verifytabdes(); +#endif //------------------------------------------------------------------------------------------------------ // Page Memory Manager diff --git a/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp index 12cd61a17a6..7d2f7d56d48 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp @@ -601,6 +601,11 @@ void Dbtup::execDROP_TAB_REQ(Signal* signal) { ljamEntry(); + if (ERROR_INSERTED(4013)) { +#ifdef VM_TRACE + verifytabdes(); +#endif + } DropTabReq* req = (DropTabReq*)signal->getDataPtr(); TablerecPtr tabPtr; @@ -719,5 +724,11 @@ void Dbtup::execFSREMOVECONF(Signal* signal) releaseTabDescr(tabPtr.p); initTab(tabPtr.p); + if (ERROR_INSERTED(4013)) { + CLEAR_ERROR_INSERT_VALUE; +#ifdef VM_TRACE + verifytabdes(); +#endif + } }//Dbtup::execFSREMOVECONF() diff --git a/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp b/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp index 642ba270760..3e96bc6c14a 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp @@ -24,13 +24,15 @@ #define ljam() { jamLine(22000 + __LINE__); } #define ljamEntry() { jamEntryLine(22000 + __LINE__); } -/* **************************************************************** */ -/* *********** TABLE DESCRIPTOR MEMORY MANAGER ******************** */ -/* **************************************************************** */ -/* This module is used to allocate and deallocate table descriptor */ -/* memory attached to fragments (could be allocated per table */ -/* instead. Performs its task by a buddy algorithm. */ -/* **************************************************************** */ +/* + * TABLE DESCRIPTOR MEMORY MANAGER + * + * Each table has a descriptor which is a contiguous array of words. + * The descriptor is allocated from a global array using a buddy + * algorithm. Free lists exist for each power of 2 words. Freeing + * a piece first merges with free right and left neighbours and then + * divides itself up into free list chunks. + */ Uint32 Dbtup::getTabDescrOffsets(const Tablerec* regTabPtr, Uint32* offset) @@ -59,7 +61,7 @@ Uint32 Dbtup::allocTabDescr(const Tablerec* regTabPtr, Uint32* offset) Uint32 reference = RNIL; Uint32 allocSize = getTabDescrOffsets(regTabPtr, offset); /* ---------------------------------------------------------------- */ -/* ALWAYS ALLOCATE A MULTIPLE OF 16 BYTES */ +/* ALWAYS ALLOCATE A MULTIPLE OF 16 WORDS */ /* ---------------------------------------------------------------- */ allocSize = (((allocSize - 1) >> 4) + 1) << 4; Uint32 list = nextHigherTwoLog(allocSize - 1); /* CALCULATE WHICH LIST IT BELONGS TO */ @@ -72,9 +74,9 @@ Uint32 Dbtup::allocTabDescr(const Tablerec* regTabPtr, Uint32* offset) Uint32 retNo = (1 << i) - allocSize; /* CALCULATE THE DIFFERENCE */ if (retNo >= ZTD_FREE_SIZE) { ljam(); - Uint32 retRef = reference + allocSize; /* SET THE RETURN POINTER */ - retNo = itdaMergeTabDescr(retRef, retNo); /* MERGE WITH POSSIBLE RIGHT NEIGHBOURS */ - freeTabDescr(retRef, retNo); /* RETURN UNUSED TD SPACE TO THE TD AREA */ + // return unused words, of course without attempting left merge + Uint32 retRef = reference + allocSize; + freeTabDescr(retRef, retNo, false); } else { ljam(); allocSize = 1 << i; @@ -100,17 +102,19 @@ Uint32 Dbtup::allocTabDescr(const Tablerec* regTabPtr, Uint32* offset) }//if }//Dbtup::allocTabDescr() -void Dbtup::freeTabDescr(Uint32 retRef, Uint32 retNo) +void Dbtup::freeTabDescr(Uint32 retRef, Uint32 retNo, bool normal) { + itdaMergeTabDescr(retRef, retNo, normal); /* MERGE WITH POSSIBLE NEIGHBOURS */ while (retNo >= ZTD_FREE_SIZE) { ljam(); Uint32 list = nextHigherTwoLog(retNo); list--; /* RETURN TO NEXT LOWER LIST */ Uint32 sizeOfChunk = 1 << list; - insertTdArea(sizeOfChunk, retRef, list); + insertTdArea(retRef, list); retRef += sizeOfChunk; retNo -= sizeOfChunk; }//while + ndbassert(retNo == 0); }//Dbtup::freeTabDescr() Uint32 @@ -127,7 +131,7 @@ Dbtup::setTabDescrWord(Uint32 index, Uint32 word) tableDescriptor[index].tabDescr = word; }//Dbtup::setTabDescrWord() -void Dbtup::insertTdArea(Uint32 sizeOfChunk, Uint32 tabDesRef, Uint32 list) +void Dbtup::insertTdArea(Uint32 tabDesRef, Uint32 list) { ndbrequire(list < 16); setTabDescrWord(tabDesRef + ZTD_FL_HEADER, ZTD_TYPE_FREE); @@ -144,19 +148,14 @@ void Dbtup::insertTdArea(Uint32 sizeOfChunk, Uint32 tabDesRef, Uint32 list) setTabDescrWord((tabDesRef + (1 << list)) - ZTD_TR_SIZE, 1 << list); }//Dbtup::insertTdArea() -/* ---------------------------------------------------------------- */ -/* ----------------------- MERGE_TAB_DESCR ------------------------ */ -/* ---------------------------------------------------------------- */ -/* INPUT: TAB_DESCR_PTR POINTING AT THE CURRENT CHUNK */ -/* */ -/* SHORTNAME: MTD */ -/* -----------------------------------------------------------------*/ -Uint32 Dbtup::itdaMergeTabDescr(Uint32 retRef, Uint32 retNo) +/* + * Merge to-be-removed chunk (which need not be initialized with header + * and trailer) with left and right buddies. The start point retRef + * moves to left and the size retNo increases to match the new chunk. + */ +void Dbtup::itdaMergeTabDescr(Uint32& retRef, Uint32& retNo, bool normal) { - /* THE SIZE OF THE PART TO MERGE MUST BE OF THE SAME SIZE AS THE INSERTED PART */ - /* THIS IS TRUE EITHER IF ONE PART HAS THE SAME SIZE OR THE SUM OF BOTH PARTS */ - /* TOGETHER HAS THE SAME SIZE AS THE PART TO BE INSERTED */ - /* FIND THE SIZES OF THE PARTS TO THE RIGHT OF THE PART TO BE REINSERTED */ + // merge right while ((retRef + retNo) < cnoOfTabDescrRec) { ljam(); Uint32 tabDesRef = retRef + retNo; @@ -170,11 +169,28 @@ Uint32 Dbtup::itdaMergeTabDescr(Uint32 retRef, Uint32 retNo) removeTdArea(tabDesRef, list); } else { ljam(); - return retNo; - }//if - }//while - ndbrequire((retRef + retNo) == cnoOfTabDescrRec); - return retNo; + break; + } + } + // merge left + const bool mergeLeft = normal; + while (mergeLeft && retRef > 0) { + ljam(); + Uint32 trailerWord = getTabDescrWord(retRef - ZTD_TR_TYPE); + if (trailerWord == ZTD_TYPE_FREE) { + ljam(); + Uint32 sizeOfMergedPart = getTabDescrWord(retRef - ZTD_TR_SIZE); + ndbrequire(retRef >= sizeOfMergedPart); + retRef -= sizeOfMergedPart; + retNo += sizeOfMergedPart; + Uint32 list = nextHigherTwoLog(sizeOfMergedPart - 1); + removeTdArea(retRef, list); + } else { + ljam(); + break; + } + } + ndbrequire((retRef + retNo) <= cnoOfTabDescrRec); }//Dbtup::itdaMergeTabDescr() /* ---------------------------------------------------------------- */ @@ -210,3 +226,94 @@ void Dbtup::removeTdArea(Uint32 tabDesRef, Uint32 list) setTabDescrWord(tabDescrPrevPtr + ZTD_FL_NEXT, tabDescrNextPtr); }//if }//Dbtup::removeTdArea() + +#ifdef VM_TRACE +void +Dbtup::verifytabdes() +{ + struct WordType { + short fl; // free list 0-15 + short ti; // table id + WordType() : fl(-1), ti(-1) {} + }; + WordType* wt = new WordType [cnoOfTabDescrRec]; + uint free_frags = 0; + // free lists + { + for (uint i = 0; i < 16; i++) { + Uint32 desc2 = RNIL; + Uint32 desc = cfreeTdList[i]; + while (desc != RNIL) { + const Uint32 size = (1 << i); + ndbrequire(size >= ZTD_FREE_SIZE); + ndbrequire(desc + size <= cnoOfTabDescrRec); + { Uint32 index = desc + ZTD_FL_HEADER; + ndbrequire(tableDescriptor[index].tabDescr == ZTD_TYPE_FREE); + } + { Uint32 index = desc + ZTD_FL_SIZE; + ndbrequire(tableDescriptor[index].tabDescr == size); + } + { Uint32 index = desc + size - ZTD_TR_TYPE; + ndbrequire(tableDescriptor[index].tabDescr == ZTD_TYPE_FREE); + } + { Uint32 index = desc + size - ZTD_TR_SIZE; + ndbrequire(tableDescriptor[index].tabDescr == size); + } + { Uint32 index = desc + ZTD_FL_PREV; + ndbrequire(tableDescriptor[index].tabDescr == desc2); + } + for (uint j = 0; j < size; j++) { + ndbrequire(wt[desc + j].fl == -1); + wt[desc + j].fl = i; + } + desc2 = desc; + desc = tableDescriptor[desc + ZTD_FL_NEXT].tabDescr; + free_frags++; + } + } + } + // tables + { + for (uint i = 0; i < cnoOfTablerec; i++) { + TablerecPtr ptr; + ptr.i = i; + ptrAss(ptr, tablerec); + if (ptr.p->tableStatus == DEFINED) { + Uint32 offset[10]; + const Uint32 alloc = getTabDescrOffsets(ptr.p, offset); + const Uint32 desc = ptr.p->readKeyArray - offset[3]; + Uint32 size = alloc; + if (size % ZTD_FREE_SIZE != 0) + size += ZTD_FREE_SIZE - size % ZTD_FREE_SIZE; + ndbrequire(desc + size <= cnoOfTabDescrRec); + { Uint32 index = desc + ZTD_FL_HEADER; + ndbrequire(tableDescriptor[index].tabDescr == ZTD_TYPE_NORMAL); + } + { Uint32 index = desc + ZTD_FL_SIZE; + ndbrequire(tableDescriptor[index].tabDescr == size); + } + { Uint32 index = desc + size - ZTD_TR_TYPE; + ndbrequire(tableDescriptor[index].tabDescr == ZTD_TYPE_NORMAL); + } + { Uint32 index = desc + size - ZTD_TR_SIZE; + ndbrequire(tableDescriptor[index].tabDescr == size); + } + for (uint j = 0; j < size; j++) { + ndbrequire(wt[desc + j].ti == -1); + wt[desc + j].ti = i; + } + } + } + } + // all words + { + for (uint i = 0; i < cnoOfTabDescrRec; i++) { + bool is_fl = wt[i].fl != -1; + bool is_ti = wt[i].ti != -1; + ndbrequire(is_fl != is_ti); + } + } + delete [] wt; + ndbout << "verifytabdes: frags=" << free_frags << endl; +} +#endif diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp index 176bab0d4bf..e6bb4d4f14f 100644 --- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp +++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp @@ -591,6 +591,13 @@ Ndbcntr::execCNTR_START_REP(Signal* signal){ Uint32 nodeId = signal->theData[0]; c_startedNodes.set(nodeId); c_start.m_starting.clear(nodeId); + + /** + * Inform all interested blocks that node has started + */ + for(Uint32 i = 0; i<ALL_BLOCKS_SZ; i++){ + sendSignal(ALL_BLOCKS[i].Ref, GSN_NODE_START_REP, signal, 1, JBB); + } if(!c_start.m_starting.isclear()){ jam(); @@ -1461,9 +1468,6 @@ void Ndbcntr::execNODE_FAILREP(Signal* signal) sendSignal(BACKUP_REF, GSN_NODE_FAILREP, signal, NodeFailRep::SignalLength, JBB); - sendSignal(SUMA_REF, GSN_NODE_FAILREP, signal, - NodeFailRep::SignalLength, JBB); - if (c_stopRec.stopReq.senderRef) { jam(); diff --git a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp index b9bf522f7c8..cc981f37987 100644 --- a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp +++ b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp @@ -438,6 +438,7 @@ void Qmgr::execCONNECT_REP(Signal* signal) void Qmgr::execREAD_NODESCONF(Signal* signal) { + jamEntry(); check_readnodes_reply(signal, refToNode(signal->getSendersBlockRef()), GSN_READ_NODESCONF); @@ -446,6 +447,7 @@ Qmgr::execREAD_NODESCONF(Signal* signal) void Qmgr::execREAD_NODESREF(Signal* signal) { + jamEntry(); check_readnodes_reply(signal, refToNode(signal->getSendersBlockRef()), GSN_READ_NODESREF); @@ -907,9 +909,9 @@ retry: char buf[255]; BaseString::snprintf(buf, sizeof(buf), - "Partitioned cluster! check StartPartialTimeout, " - " node %d thinks %d is president, " - " I think president is: %d", + "check StartPartialTimeout, " + "node %d thinks %d is president, " + "I think president is: %d", nodeId, president, cpresident); ndbout_c(buf); @@ -941,7 +943,7 @@ retry: CRASH_INSERTION(932); progError(__LINE__, - NDBD_EXIT_ARBIT_SHUTDOWN, + NDBD_EXIT_PARTITIONED_SHUTDOWN, buf); ndbrequire(false); @@ -2340,7 +2342,6 @@ void Qmgr::sendApiFailReq(Signal* signal, Uint16 failedNodeNo) failedNodePtr.p->failState = WAITING_FOR_FAILCONF1; sendSignal(DBTC_REF, GSN_API_FAILREQ, signal, 2, JBA); sendSignal(DBDICT_REF, GSN_API_FAILREQ, signal, 2, JBA); - sendSignal(SUMA_REF, GSN_API_FAILREQ, signal, 2, JBA); /**------------------------------------------------------------------------- * THE OTHER NODE WAS AN API NODE. THE COMMUNICATION LINK IS ALREADY @@ -2795,7 +2796,7 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode, break; case FailRep::ZPARTITIONED_CLUSTER: { - code = NDBD_EXIT_ARBIT_SHUTDOWN; + code = NDBD_EXIT_PARTITIONED_SHUTDOWN; char buf1[100], buf2[100]; c_clusterNodes.getText(buf1); if (signal->getLength()== FailRep::SignalLength + FailRep::ExtraLength && @@ -2806,16 +2807,14 @@ void Qmgr::failReportLab(Signal* signal, Uint16 aFailedNode, part.assign(NdbNodeBitmask::Size, rep->partition); part.getText(buf2); BaseString::snprintf(extra, sizeof(extra), - "Partitioned cluster!" - " Our cluster: %s other cluster: %s", + "Our cluster: %s other cluster: %s", buf1, buf2); } else { jam(); BaseString::snprintf(extra, sizeof(extra), - "Partitioned cluster!" - " Our cluster: %s ", buf1); + "Our cluster: %s", buf1); } msg = extra; break; diff --git a/ndb/src/kernel/blocks/suma/Suma.cpp b/ndb/src/kernel/blocks/suma/Suma.cpp index 3644bc0a03f..449436331e4 100644 --- a/ndb/src/kernel/blocks/suma/Suma.cpp +++ b/ndb/src/kernel/blocks/suma/Suma.cpp @@ -82,44 +82,6 @@ static const Uint32 SUMA_SEQUENCE = 0xBABEBABE; #define PRINT_ONLY 0 static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE; -void -Suma::getNodeGroupMembers(Signal* signal) { - jam(); - /** - * Ask DIH for nodeGroupMembers - */ - CheckNodeGroups * sd = (CheckNodeGroups*)signal->getDataPtrSend(); - sd->blockRef = reference(); - sd->requestType = - CheckNodeGroups::Direct | - CheckNodeGroups::GetNodeGroupMembers; - sd->nodeId = getOwnNodeId(); - EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal, - CheckNodeGroups::SignalLength); - jamEntry(); - - c_nodeGroup = sd->output; - c_noNodesInGroup = 0; - for (int i = 0; i < MAX_NDB_NODES; i++) { - if (sd->mask.get(i)) { - if (i == getOwnNodeId()) c_idInNodeGroup = c_noNodesInGroup; - c_nodesInGroup[c_noNodesInGroup] = i; - c_noNodesInGroup++; - } - } - - // ndbout_c("c_noNodesInGroup=%d", c_noNodesInGroup); - ndbrequire(c_noNodesInGroup > 0); // at least 1 node in the nodegroup - -#ifdef NODEFAIL_DEBUG - for (Uint32 i = 0; i < c_noNodesInGroup; i++) { - ndbout_c ("Suma: NodeGroup %u, me %u, me in group %u, member[%u] %u", - c_nodeGroup, getOwnNodeId(), c_idInNodeGroup, - i, c_nodesInGroup[i]); - } -#endif -} - void Suma::execREAD_CONFIG_REQ(Signal* signal) { @@ -188,11 +150,6 @@ Suma::execSTTOR(Signal* signal) { DBUG_PRINT("info",("startphase = %u, typeOfStart = %u", startphase, typeOfStart)); - if(startphase == 1){ - jam(); - c_restartLock = true; - } - if(startphase == 3){ jam(); g_TypeOfStart = typeOfStart; @@ -224,32 +181,7 @@ Suma::execSTTOR(Signal* signal) { DBUG_VOID_RETURN; } - if(startphase == 5) { - getNodeGroupMembers(signal); - if (g_TypeOfStart == NodeState::ST_NODE_RESTART) { - jam(); - for (Uint32 i = 0; i < c_noNodesInGroup; i++) { - Uint32 ref = calcSumaBlockRef(c_nodesInGroup[i]); - if (ref != reference()) - sendSignal(ref, GSN_SUMA_START_ME, signal, - 1 /*SumaStartMe::SignalLength*/, JBB); - } - } - } - if(startphase == 7) { - c_restartLock = false; // may be set false earlier with HANDOVER_REQ - - if (g_TypeOfStart != NodeState::ST_NODE_RESTART) { - for( int i = 0; i < NO_OF_BUCKETS; i++) { - if (getResponsibleSumaNodeId(i) == refToNode(reference())) { - // I'm running this bucket - DBUG_PRINT("info",("bucket %u set to true", i)); - c_buckets[i].active = true; - } - } - } - if(g_TypeOfStart == NodeState::ST_INITIAL_START && c_masterNodeId == getOwnNodeId()) { jam(); @@ -364,282 +296,6 @@ SumaParticipant::execCONTINUEB(Signal* signal) * *****************************************************************************/ -void Suma::execAPI_FAILREQ(Signal* signal) -{ - jamEntry(); - DBUG_ENTER("Suma::execAPI_FAILREQ"); - Uint32 failedApiNode = signal->theData[0]; - //BlockReference retRef = signal->theData[1]; - - c_failedApiNodes.set(failedApiNode); - bool found = removeSubscribersOnNode(signal, failedApiNode); - - if(!found){ - jam(); - c_failedApiNodes.clear(failedApiNode); - } - DBUG_VOID_RETURN; -}//execAPI_FAILREQ() - -bool -SumaParticipant::removeSubscribersOnNode(Signal *signal, Uint32 nodeId) -{ - DBUG_ENTER("SumaParticipant::removeSubscribersOnNode"); - bool found = false; - - SubscriberPtr i_subbPtr; - c_dataSubscribers.first(i_subbPtr); - while(!i_subbPtr.isNull()){ - SubscriberPtr subbPtr = i_subbPtr; - c_dataSubscribers.next(i_subbPtr); - jam(); - if (refToNode(subbPtr.p->m_subscriberRef) == nodeId) { - jam(); - c_dataSubscribers.remove(subbPtr); - c_removeDataSubscribers.add(subbPtr); - found = true; - } - } - if(found){ - jam(); - sendSubStopReq(signal); - } - DBUG_RETURN(found); -} - -void -SumaParticipant::sendSubStopReq(Signal *signal, bool unlock){ - DBUG_ENTER("SumaParticipant::sendSubStopReq"); - static bool remove_lock = false; - jam(); - - SubscriberPtr subbPtr; - c_removeDataSubscribers.first(subbPtr); - if (subbPtr.isNull()){ - jam(); -#if 0 - signal->theData[0] = failedApiNode; - signal->theData[1] = reference(); - sendSignal(retRef, GSN_API_FAILCONF, signal, 2, JBB); -#endif - c_failedApiNodes.clear(); - - remove_lock = false; - DBUG_VOID_RETURN; - } - - if(remove_lock && !unlock) { - jam(); - DBUG_VOID_RETURN; - } - remove_lock = true; - - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI); - - SubStopReq * const req = (SubStopReq*)signal->getDataPtrSend(); - req->senderRef = reference(); - req->senderData = subbPtr.i; - req->subscriberRef = subbPtr.p->m_subscriberRef; - req->subscriberData = subbPtr.p->m_subscriberData; - req->subscriptionId = subPtr.p->m_subscriptionId; - req->subscriptionKey = subPtr.p->m_subscriptionKey; - req->part = SubscriptionData::TableData; - - sendSignal(SUMA_REF, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB); - DBUG_VOID_RETURN; -} - -void -SumaParticipant::execSUB_STOP_CONF(Signal* signal){ - jamEntry(); - DBUG_ENTER("SumaParticipant::execSUB_STOP_CONF"); - - SubStopConf * const conf = (SubStopConf*)signal->getDataPtr(); - - // Uint32 subscriberData = conf->subscriberData; - // Uint32 subscriberRef = conf->subscriberRef; - - Subscription key; - key.m_subscriptionId = conf->subscriptionId; - key.m_subscriptionKey = conf->subscriptionKey; - - SubscriptionPtr subPtr; - if(c_subscriptions.find(subPtr, key)) { - jam(); - if (subPtr.p->m_markRemove) { - jam(); - ndbrequire(false); - ndbrequire(subPtr.p->m_nSubscribers > 0); - subPtr.p->m_nSubscribers--; - if (subPtr.p->m_nSubscribers == 0){ - jam(); - completeSubRemoveReq(signal, subPtr); - } - } - } - - sendSubStopReq(signal,true); - DBUG_VOID_RETURN; -} - -void -SumaParticipant::execSUB_STOP_REF(Signal* signal){ - jamEntry(); - DBUG_ENTER("SumaParticipant::execSUB_STOP_REF"); - - SubStopRef * const ref = (SubStopRef*)signal->getDataPtr(); - - Uint32 subscriptionId = ref->subscriptionId; - Uint32 subscriptionKey = ref->subscriptionKey; - Uint32 part = ref->part; - Uint32 subscriberData = ref->subscriberData; - Uint32 subscriberRef = ref->subscriberRef; - // Uint32 err = ref->err; - - if(!ref->isTemporary()){ - ndbrequire(false); - } - - SubStopReq * const req = (SubStopReq*)signal->getDataPtrSend(); - req->subscriberRef = subscriberRef; - req->subscriberData = subscriberData; - req->subscriptionId = subscriptionId; - req->subscriptionKey = subscriptionKey; - req->part = part; - - sendSignal(SUMA_REF, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB); - - DBUG_VOID_RETURN; -} - -void -Suma::execNODE_FAILREP(Signal* signal){ - jamEntry(); - DBUG_ENTER("Suma::execNODE_FAILREP"); - - NodeFailRep * const rep = (NodeFailRep*)signal->getDataPtr(); - - bool changed = false; - - NodePtr nodePtr; -#ifdef NODEFAIL_DEBUG - ndbout_c("Suma: nodefailrep"); -#endif - c_nodeFailGCI = getFirstGCI(signal); - - for(c_nodes.first(nodePtr); nodePtr.i != RNIL; c_nodes.next(nodePtr)){ - if(NodeBitmask::get(rep->theNodes, nodePtr.p->nodeId)){ - if(nodePtr.p->alive){ - ndbassert(c_aliveNodes.get(nodePtr.p->nodeId)); - changed = true; - jam(); - } else { - ndbassert(!c_aliveNodes.get(nodePtr.p->nodeId)); - jam(); - } - - if (c_preparingNodes.get(nodePtr.p->nodeId)) { - jam(); - // we are currently preparing this node that died - // it's ok just to clear and go back to waiting for it to start up - Restart.resetNode(calcSumaBlockRef(nodePtr.p->nodeId)); - c_preparingNodes.clear(nodePtr.p->nodeId); - } else if (c_handoverToDo) { - jam(); - // TODO what if I'm a SUMA that is currently restarting and the SUMA - // responsible for restarting me is the one that died? - - // a node has failed whilst handover is going on - // let's check if we're in the process of handover with that node - c_handoverToDo = false; - for( int i = 0; i < NO_OF_BUCKETS; i++) { - if (c_buckets[i].handover) { - // I'm doing handover, but is it with the dead node? - if (getResponsibleSumaNodeId(i) == nodePtr.p->nodeId) { - // so it was the dead node, has handover started? - if (c_buckets[i].handover_started) { - jam(); - // we're not ok and will have lost data! - // set not active to indicate this - - // this will generate takeover behaviour - c_buckets[i].active = false; - c_buckets[i].handover_started = false; - } // else we're ok to revert back to state before - c_buckets[i].handover = false; - } else { - jam(); - // ok, we're doing handover with a different node - c_handoverToDo = true; - } - } - } - } - - c_failoverBuffer.nodeFailRep(); - - nodePtr.p->alive = 0; - c_aliveNodes.clear(nodePtr.p->nodeId); // this has to be done after the loop above - } - } - DBUG_VOID_RETURN; -} - -void -Suma::execINCL_NODEREQ(Signal* signal){ - jamEntry(); - - //const Uint32 senderRef = signal->theData[0]; - const Uint32 inclNode = signal->theData[1]; - - NodePtr node; - for(c_nodes.first(node); node.i != RNIL; c_nodes.next(node)){ - jam(); - const Uint32 nodeId = node.p->nodeId; - if(inclNode == nodeId){ - jam(); - - ndbrequire(node.p->alive == 0); - ndbrequire(!c_aliveNodes.get(nodeId)); - - for (Uint32 j = 0; j < c_noNodesInGroup; j++) { - jam(); - if (c_nodesInGroup[j] == nodeId) { - // the starting node is part of my node group - jam(); - c_preparingNodes.set(nodeId); // set as being prepared - for (Uint32 i = 0; i < c_noNodesInGroup; i++) { - jam(); - if (i == c_idInNodeGroup) { - jam(); - // I'm responsible for restarting this SUMA - // ALL dict's should have meta data info so it is ok to start - Restart.startNode(signal, calcSumaBlockRef(nodeId)); - break; - }//if - if (c_aliveNodes.get(c_nodesInGroup[i])) { - jam(); - break; // another Suma takes care of this - }//if - }//for - break; - }//if - }//for - - node.p->alive = 1; - c_aliveNodes.set(nodeId); - - break; - }//if - }//for - -#if 0 // if we include this DIH's got to be prepared, later if needed... - signal->theData[0] = reference(); - - sendSignal(senderRef, GSN_INCL_NODECONF, signal, 1, JBB); -#endif -} - void Suma::execSIGNAL_DROPPED_REP(Signal* signal){ jamEntry(); @@ -685,10 +341,6 @@ Suma::execDUMP_STATE_ORD(Signal* signal){ syncPtr.p->startScan(signal); } - if(tCase == 8002){ - syncPtr.p->startTrigger(signal); - } - if(tCase == 8003){ subPtr.p->m_subscriptionType = SubCreateReq::SingleTableScan; LocalDataBuffer<15> attrs(c_dataBufferPool, syncPtr.p->m_attributeList); @@ -1154,26 +806,6 @@ SumaParticipant::sendSubCreateRef(Signal* signal, const SubCreateReq& req, Uint3 return; } - - - - - - - - - - - -Uint32 -SumaParticipant::getFirstGCI(Signal* signal) { - if (c_lastCompleteGCI == RNIL) { - ndbout_c("WARNING: c_lastCompleteGCI == RNIL"); - return 0; - } - return c_lastCompleteGCI+3; -} - /********************************************************** * * Setting upp trigger for subscription @@ -1219,27 +851,6 @@ SumaParticipant::execSUB_SYNC_REQ(Signal* signal) { case SubscriptionData::MetaData: ok = true; jam(); - if (subPtr.p->m_subscriptionType == SubCreateReq::DatabaseSnapshot) { - TableList::DataBufferIterator it; - syncPtr.p->m_tableList.first(it); - if(it.isNull()) { - /** - * Get all tables from dict - */ - ListTablesReq * req = (ListTablesReq*)signal->getDataPtrSend(); - req->senderRef = reference(); - req->senderData = syncPtr.i; - req->requestData = 0; - /** - * @todo: accomodate scan of index tables? - */ - req->setTableType(DictTabInfo::UserTable); - - sendSignal(DBDICT_REF, GSN_LIST_TABLES_REQ, signal, - ListTablesReq::SignalLength, JBB); - break; - } - } syncPtr.p->startMeta(signal); break; @@ -1274,16 +885,6 @@ SumaParticipant::sendSubSyncRef(Signal* signal, Uint32 errCode){ */ void -SumaParticipant::execLIST_TABLES_CONF(Signal* signal){ - jamEntry(); - CRASH_INSERTION(13005); - ListTablesConf* const conf = (ListTablesConf*)signal->getDataPtr(); - SyncRecord* tmp = c_syncPool.getPtr(conf->senderData); - tmp->runLIST_TABLES_CONF(signal); -} - - -void SumaParticipant::execGET_TABINFOREF(Signal* signal){ jamEntry(); GetTabInfoRef* const ref = (GetTabInfoRef*)signal->getDataPtr(); @@ -1491,113 +1092,12 @@ SumaParticipant::execDIGETPRIMCONF(Signal* signal){ tmp->runDIGETPRIMCONF(signal); } -void -SumaParticipant::execCREATE_TRIG_CONF(Signal* signal){ - jamEntry(); - DBUG_ENTER("SumaParticipant::execCREATE_TRIG_CONF"); - CRASH_INSERTION(13009); - - CreateTrigConf * const conf = (CreateTrigConf*)signal->getDataPtr(); - - const Uint32 senderData = conf->getConnectionPtr(); - SyncRecord* tmp = c_syncPool.getPtr(senderData); - tmp->runCREATE_TRIG_CONF(signal); - - /** - * dodido - * @todo: I (Johan) dont know what to do here. Jonas, what do you mean? - */ - DBUG_VOID_RETURN; -} - -void -SumaParticipant::execCREATE_TRIG_REF(Signal* signal){ - jamEntry(); - ndbrequire(false); -} - -void -SumaParticipant::execDROP_TRIG_CONF(Signal* signal){ - jamEntry(); - DBUG_ENTER("SumaParticipant::execDROP_TRIG_CONF"); - CRASH_INSERTION(13010); - - DropTrigConf * const conf = (DropTrigConf*)signal->getDataPtr(); - - const Uint32 senderData = conf->getConnectionPtr(); - SyncRecord* tmp = c_syncPool.getPtr(senderData); - tmp->runDROP_TRIG_CONF(signal); - DBUG_VOID_RETURN; -} - -void -SumaParticipant::execDROP_TRIG_REF(Signal* signal){ - jamEntry(); - DBUG_ENTER("SumaParticipant::execDROP_TRIG_CONF"); - DropTrigRef * const ref = (DropTrigRef*)signal->getDataPtr(); - - const Uint32 senderData = ref->getConnectionPtr(); - SyncRecord* tmp = c_syncPool.getPtr(senderData); - tmp->runDROP_TRIG_CONF(signal); - DBUG_VOID_RETURN; -} - /************************************************************************* * * */ void -SumaParticipant::SyncRecord::runLIST_TABLES_CONF(Signal* signal){ - jam(); - - ListTablesConf * const conf = (ListTablesConf*)signal->getDataPtr(); - const Uint32 len = signal->length() - ListTablesConf::HeaderLength; - - SubscriptionPtr subPtr; - suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI); - - for (unsigned i = 0; i < len; i++) { - subPtr.p->m_maxTables++; - suma.addTableId(ListTablesConf::getTableId(conf->tableData[i]), subPtr, this); - } - - // for (unsigned i = 0; i < len; i++) - // conf->tableData[i] = ListTablesConf::getTableId(conf->tableData[i]); - // m_tableList.append(&conf->tableData[0], len); - -#if 0 - TableList::DataBufferIterator it; - int i = 0; - for(m_tableList.first(it);!it.isNull();m_tableList.next(it)) { - ndbout_c("%u listtableconf tableid %d", i++, *it.data); - } -#endif - - if(len == ListTablesConf::DataLength){ - jam(); - // we expect more LIST_TABLE_CONF - return; - } - -#if 0 - subPtr.p->m_currentTable = 0; - subPtr.p->m_maxTables = 0; - - TableList::DataBufferIterator it; - for(m_tableList.first(it); !it.isNull(); m_tableList.next(it)) { - subPtr.p->m_maxTables++; - suma.addTableId(*it.data, subPtr, NULL); -#ifdef NODEFAIL_DEBUG - ndbout_c(" listtableconf tableid %d",*it.data); -#endif - } -#endif - - startMeta(signal); -} - -void SumaParticipant::SyncRecord::startMeta(Signal* signal){ jam(); m_currentTable = 0; @@ -1696,18 +1196,6 @@ SumaParticipant::SyncRecord::runGET_TABINFO_CONF(Signal* signal){ SegmentedSectionPtr ptr; signal->getSection(ptr, GetTabInfoConf::DICT_TAB_INFO); - SubMetaData * data = (SubMetaData*)signal->getDataPtrSend(); - /** - * sending lastCompleteGCI. Used by Lars in interval calculations - * incremenet by one, since last_CompleteGCI is the not the current gci. - */ - data->gci = suma.c_lastCompleteGCI + 1; - data->tableId = tableId; - data->senderData = subPtr.p->m_subscriberData; -#if PRINT_ONLY - ndbout_c("GSN_SUB_META_DATA Table %d", tableId); -#else - bool okToSend = m_doSendSyncData; /* @@ -1737,7 +1225,6 @@ SumaParticipant::SyncRecord::runGET_TABINFO_CONF(Signal* signal){ SubMetaData::SignalLength, JBB); } } -#endif TablePtr tabPtr; ndbrequire(suma.c_tables.find(tabPtr, tableId)); @@ -2113,513 +1600,6 @@ SumaParticipant::execSCAN_HBREP(Signal* signal){ } /********************************************************** - * - * Suma participant interface - * - * Creation of subscriber - * - */ - -void -SumaParticipant::execSUB_START_REQ(Signal* signal){ - jamEntry(); - DBUG_ENTER("SumaParticipant::execSUB_START_REQ"); - - CRASH_INSERTION(13013); - - if (c_restartLock) { - jam(); - // ndbout_c("c_restartLock"); - if (RtoI(signal->getSendersBlockRef(), false) == RNIL) { - jam(); - sendSubStartRef(signal, /** Error Code */ 0, true); - DBUG_VOID_RETURN; - } - // only allow other Suma's in the nodegroup to come through for restart purposes - } - - Subscription key; - - SubStartReq * const req = (SubStartReq*)signal->getDataPtr(); - - Uint32 senderRef = req->senderRef; - Uint32 senderData = req->senderData; - Uint32 subscriberData = req->subscriberData; - Uint32 subscriberRef = req->subscriberRef; - SubscriptionData::Part part = (SubscriptionData::Part)req->part; - key.m_subscriptionId = req->subscriptionId; - key.m_subscriptionKey = req->subscriptionKey; - - SubscriptionPtr subPtr; - if(!c_subscriptions.find(subPtr, key)){ - jam(); - sendSubStartRef(signal, /** Error Code */ 0); - DBUG_VOID_RETURN; - } - - Ptr<SyncRecord> syncPtr; - c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI); - if (syncPtr.p->m_locked) { - jam(); -#if 0 - ndbout_c("Locked"); -#endif - sendSubStartRef(signal, /** Error Code */ 0, true); - DBUG_VOID_RETURN; - } - syncPtr.p->m_locked = true; - - SubscriberPtr subbPtr; - if(!c_subscriberPool.seize(subbPtr)){ - jam(); - syncPtr.p->m_locked = false; - sendSubStartRef(signal, /** Error Code */ 0); - DBUG_VOID_RETURN; - } - - Uint32 type = subPtr.p->m_subscriptionType; - - subbPtr.p->m_senderRef = senderRef; - subbPtr.p->m_senderData = senderData; - - switch (type) { - case SubCreateReq::TableEvent: - jam(); - // we want the data to return to the API not DICT - subbPtr.p->m_subscriberRef = subscriberRef; - // ndbout_c("start ref = %u", signal->getSendersBlockRef()); - // ndbout_c("ref = %u", subbPtr.p->m_subscriberRef); - // we use the subscription id for now, should really be API choice - subbPtr.p->m_subscriberData = subscriberData; - -#if 0 - if (RtoI(signal->getSendersBlockRef(), false) == RNIL) { - jam(); - for (Uint32 i = 0; i < c_noNodesInGroup; i++) { - Uint32 ref = calcSumaBlockRef(c_nodesInGroup[i]); - if (ref != reference()) { - jam(); - sendSubStartReq(subPtr, subbPtr, signal, ref); - } else - jam(); - } - } -#endif - break; - case SubCreateReq::DatabaseSnapshot: - case SubCreateReq::SelectiveTableSnapshot: - jam(); - ndbrequire(false); - //subbPtr.p->m_subscriberRef = GREP_REF; - subbPtr.p->m_subscriberData = subPtr.p->m_subscriberData; - break; - case SubCreateReq::SingleTableScan: - jam(); - subbPtr.p->m_subscriberRef = subPtr.p->m_subscriberRef; - subbPtr.p->m_subscriberData = subPtr.p->m_subscriberData; - } - - subbPtr.p->m_subPtrI = subPtr.i; - subbPtr.p->m_firstGCI = RNIL; - if (type == SubCreateReq::TableEvent) - subbPtr.p->m_lastGCI = 0; - else - subbPtr.p->m_lastGCI = RNIL; // disable usage of m_lastGCI - bool ok = false; - - switch(part){ - case SubscriptionData::MetaData: - ok = true; - jam(); - c_metaSubscribers.add(subbPtr); - sendSubStartComplete(signal, subbPtr, 0, part); - break; - case SubscriptionData::TableData: - ok = true; - jam(); - c_prepDataSubscribers.add(subbPtr); - syncPtr.p->startTrigger(signal); - break; - } - ndbrequire(ok); - DBUG_VOID_RETURN; -} - -void -SumaParticipant::sendSubStartComplete(Signal* signal, - SubscriberPtr subbPtr, - Uint32 firstGCI, - SubscriptionData::Part part){ - jam(); - - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI); - - Ptr<SyncRecord> syncPtr; - c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI); - syncPtr.p->m_locked = false; - - SubStartConf * const conf = (SubStartConf*)signal->getDataPtrSend(); - - conf->senderRef = reference(); - conf->senderData = subbPtr.p->m_senderData; - conf->subscriptionId = subPtr.p->m_subscriptionId; - conf->subscriptionKey = subPtr.p->m_subscriptionKey; - conf->firstGCI = firstGCI; - conf->part = (Uint32) part; - - conf->subscriberData = subPtr.p->m_subscriberData; - sendSignal(subPtr.p->m_subscriberRef, GSN_SUB_START_CONF, signal, - SubStartConf::SignalLength, JBB); -} - -#if 0 -void -SumaParticipant::sendSubStartRef(SubscriptionPtr subPtr, - Signal* signal, Uint32 errCode, - bool temporary){ - jam(); - SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend(); - xxx ref->senderRef = reference(); - xxx ref->senderData = subPtr.p->m_senderData; - ref->subscriptionId = subPtr.p->m_subscriptionId; - ref->subscriptionKey = subPtr.p->m_subscriptionKey; - ref->part = (Uint32) subPtr.p->m_subscriptionType; - ref->subscriberData = subPtr.p->m_subscriberData; - ref->err = errCode; - if (temporary) { - jam(); - ref->setTemporary(); - } - releaseSections(signal); - sendSignal(subPtr.p->m_subscriberRef, GSN_SUB_START_REF, signal, - SubStartRef::SignalLength, JBB); -} -#endif -void -SumaParticipant::sendSubStartRef(Signal* signal, Uint32 errCode, - bool temporary){ - jam(); - SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend(); - ref->senderRef = reference(); - ref->err = errCode; - if (temporary) { - jam(); - ref->setTemporary(); - } - releaseSections(signal); - sendSignal(signal->getSendersBlockRef(), GSN_SUB_START_REF, signal, - SubStartRef::SignalLength, JBB); -} - -/********************************************************** - * - * Trigger admin interface - * - */ - -void -SumaParticipant::SyncRecord::startTrigger(Signal* signal){ - jam(); - m_currentTable = 0; - m_latestTriggerId = RNIL; - nextTrigger(signal); -} - -void -SumaParticipant::SyncRecord::nextTrigger(Signal* signal){ - jam(); - - TableList::DataBufferIterator it; - - if(!m_tableList.position(it, m_currentTable)){ - completeTrigger(signal); - return; - } - - SubscriptionPtr subPtr; - suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI); - ndbrequire(subPtr.p->m_syncPtrI == ptrI); - const Uint32 RT_BREAK = 48; - Uint32 latestTriggerId = 0; - for(Uint32 i = 0; i<RT_BREAK && !it.isNull(); i++, m_tableList.next(it)){ - TablePtr tabPtr; -#if 0 - ndbout_c("nextTrigger tableid %u", *it.data); -#endif - ndbrequire(suma.c_tables.find(tabPtr, *it.data)); - - AttributeMask attrMask; - createAttributeMask(attrMask, tabPtr.p); - - for(Uint32 j = 0; j<3; j++){ - i++; - latestTriggerId = (tabPtr.p->m_schemaVersion << 18) | - (j << 16) | tabPtr.p->m_tableId; - if(tabPtr.p->m_hasTriggerDefined[j] == 0) { - ndbrequire(tabPtr.p->m_triggerIds[j] == ILLEGAL_TRIGGER_ID); -#if 0 - ndbout_c("DEFINING trigger on table %u[%u]", tabPtr.p->m_tableId, j); -#endif - CreateTrigReq * const req = (CreateTrigReq*)signal->getDataPtrSend(); - req->setUserRef(SUMA_REF); - req->setConnectionPtr(ptrI); - req->setTriggerType(TriggerType::SUBSCRIPTION_BEFORE); - req->setTriggerActionTime(TriggerActionTime::TA_DETACHED); - req->setMonitorReplicas(true); - req->setMonitorAllAttributes(false); - req->setReceiverRef(SUMA_REF); - req->setTriggerId(latestTriggerId); - req->setTriggerEvent((TriggerEvent::Value)j); - req->setTableId(tabPtr.p->m_tableId); - req->setAttributeMask(attrMask); - suma.sendSignal(DBTUP_REF, GSN_CREATE_TRIG_REQ, - signal, CreateTrigReq::SignalLength, JBB); - - } else { - /** - * Faking that a trigger has been created in order to - * simulate the proper behaviour. - * Perhaps this should be a dummy signal instead of - * (ab)using CREATE_TRIG_CONF. - */ - CreateTrigConf * conf = (CreateTrigConf*)signal->getDataPtrSend(); - conf->setConnectionPtr(ptrI); - conf->setTableId(tabPtr.p->m_tableId); - conf->setTriggerId(latestTriggerId); - suma.sendSignal(SUMA_REF,GSN_CREATE_TRIG_CONF, - signal, CreateTrigConf::SignalLength, JBB); - - } - - } - m_currentTable++; - } - m_latestTriggerId = latestTriggerId; -} - -void -SumaParticipant::SyncRecord::createAttributeMask(AttributeMask& mask, - Table * table){ - jam(); - mask.clear(); - DataBuffer<15>::DataBufferIterator it; - LocalDataBuffer<15> attrBuf(suma.c_dataBufferPool, table->m_attributes); - for(attrBuf.first(it); !it.curr.isNull(); attrBuf.next(it)){ - mask.set(* it.data); - } -} - -void -SumaParticipant::SyncRecord::runCREATE_TRIG_CONF(Signal* signal){ - jam(); - - CreateTrigConf * const conf = (CreateTrigConf*)signal->getDataPtr(); - const Uint32 triggerId = conf->getTriggerId(); - Uint32 type = (triggerId >> 16) & 0x3; - Uint32 tableId = conf->getTableId(); - - TablePtr tabPtr; - ndbrequire(suma.c_tables.find(tabPtr, tableId)); - - ndbrequire(type < 3); - tabPtr.p->m_triggerIds[type] = triggerId; - tabPtr.p->m_hasTriggerDefined[type]++; - - if(triggerId == m_latestTriggerId){ - jam(); - nextTrigger(signal); - } -} - -void -SumaParticipant::SyncRecord::completeTrigger(Signal* signal){ - jam(); - SubscriptionPtr subPtr; - CRASH_INSERTION(13013); -#ifdef EVENT_PH3_DEBUG - ndbout_c("SumaParticipant: trigger completed"); -#endif - Uint32 gci; - suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI); - ndbrequire(subPtr.p->m_syncPtrI == ptrI); - - SubscriberPtr subbPtr; - { - bool found = false; - - for(suma.c_prepDataSubscribers.first(subbPtr); - !subbPtr.isNull(); suma.c_prepDataSubscribers.next(subbPtr)) { - jam(); - if(subbPtr.p->m_subPtrI == subPtr.i) { - jam(); - found = true; - break; - } - } - ndbrequire(found); - gci = suma.getFirstGCI(signal); - subbPtr.p->m_firstGCI = gci; - suma.c_prepDataSubscribers.remove(subbPtr); - suma.c_dataSubscribers.add(subbPtr); - } - suma.sendSubStartComplete(signal, subbPtr, gci, SubscriptionData::TableData); -} - -void -SumaParticipant::SyncRecord::startDropTrigger(Signal* signal){ - jam(); - m_currentTable = 0; - m_latestTriggerId = RNIL; - nextDropTrigger(signal); -} - -void -SumaParticipant::SyncRecord::nextDropTrigger(Signal* signal){ - jam(); - - TableList::DataBufferIterator it; - - if(!m_tableList.position(it, m_currentTable)){ - completeDropTrigger(signal); - return; - } - - SubscriptionPtr subPtr; - suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI); - ndbrequire(subPtr.p->m_syncPtrI == ptrI); - - const Uint32 RT_BREAK = 48; - Uint32 latestTriggerId = 0; - for(Uint32 i = 0; i<RT_BREAK && !it.isNull(); i++, m_tableList.next(it)){ - jam(); - TablePtr tabPtr; -#if 0 - ndbout_c("nextDropTrigger tableid %u", *it.data); -#endif - ndbrequire(suma.c_tables.find(tabPtr, * it.data)); - - for(Uint32 j = 0; j<3; j++){ - jam(); - ndbrequire(tabPtr.p->m_triggerIds[j] != ILLEGAL_TRIGGER_ID); - i++; - latestTriggerId = tabPtr.p->m_triggerIds[j]; - if(tabPtr.p->m_hasTriggerDefined[j] == 1) { - jam(); - - DropTrigReq * const req = (DropTrigReq*)signal->getDataPtrSend(); - req->setConnectionPtr(ptrI); - req->setUserRef(SUMA_REF); // Sending to myself - req->setRequestType(DropTrigReq::RT_USER); - req->setTriggerType(TriggerType::SUBSCRIPTION_BEFORE); - req->setTriggerActionTime(TriggerActionTime::TA_DETACHED); - req->setIndexId(RNIL); - - req->setTableId(tabPtr.p->m_tableId); - req->setTriggerId(latestTriggerId); - req->setTriggerEvent((TriggerEvent::Value)j); - -#if 0 - ndbout_c("DROPPING trigger %u = %u %u %u on table %u[%u]", - latestTriggerId,TriggerType::SUBSCRIPTION_BEFORE, - TriggerActionTime::TA_DETACHED, j, tabPtr.p->m_tableId, j); -#endif - suma.sendSignal(DBTUP_REF, GSN_DROP_TRIG_REQ, - signal, DropTrigReq::SignalLength, JBB); - } else { - jam(); - ndbrequire(tabPtr.p->m_hasTriggerDefined[j] > 1); - /** - * Faking that a trigger has been dropped in order to - * simulate the proper behaviour. - * Perhaps this should be a dummy signal instead of - * (ab)using DROP_TRIG_CONF. - */ - DropTrigConf * conf = (DropTrigConf*)signal->getDataPtrSend(); - conf->setConnectionPtr(ptrI); - conf->setTableId(tabPtr.p->m_tableId); - conf->setTriggerId(latestTriggerId); - suma.sendSignal(SUMA_REF,GSN_DROP_TRIG_CONF, - signal, DropTrigConf::SignalLength, JBB); - } - } - m_currentTable++; - } - m_latestTriggerId = latestTriggerId; -} - -void -SumaParticipant::SyncRecord::runDROP_TRIG_REF(Signal* signal){ - jam(); - DropTrigRef * const ref = (DropTrigRef*)signal->getDataPtr(); - if (ref->getErrorCode() != DropTrigRef::TriggerNotFound){ - ndbrequire(false); - } - const Uint32 triggerId = ref->getTriggerId(); - Uint32 tableId = ref->getTableId(); - runDropTrig(signal, triggerId, tableId); -} - -void -SumaParticipant::SyncRecord::runDROP_TRIG_CONF(Signal* signal){ - jam(); - - DropTrigConf * const conf = (DropTrigConf*)signal->getDataPtr(); - const Uint32 triggerId = conf->getTriggerId(); - Uint32 tableId = conf->getTableId(); - runDropTrig(signal, triggerId, tableId); -} - -void -SumaParticipant::SyncRecord::runDropTrig(Signal* signal, - Uint32 triggerId, - Uint32 tableId){ - Uint32 type = (triggerId >> 16) & 0x3; - - TablePtr tabPtr; - ndbrequire(suma.c_tables.find(tabPtr, tableId)); - - ndbrequire(type < 3); - ndbrequire(tabPtr.p->m_triggerIds[type] == triggerId); - tabPtr.p->m_hasTriggerDefined[type]--; - if (tabPtr.p->m_hasTriggerDefined[type] == 0) { - jam(); - tabPtr.p->m_triggerIds[type] = ILLEGAL_TRIGGER_ID; - } - if(triggerId == m_latestTriggerId){ - jam(); - nextDropTrigger(signal); - } -} - -void -SumaParticipant::SyncRecord::completeDropTrigger(Signal* signal){ - jam(); - SubscriptionPtr subPtr; - CRASH_INSERTION(13014); -#if 0 - ndbout_c("trigger completed"); -#endif - - suma.c_subscriptions.getPtr(subPtr, m_subscriptionPtrI); - ndbrequire(subPtr.p->m_syncPtrI == ptrI); - - bool found = false; - SubscriberPtr subbPtr; - for(suma.c_prepDataSubscribers.first(subbPtr); - !subbPtr.isNull(); suma.c_prepDataSubscribers.next(subbPtr)) { - jam(); - if(subbPtr.p->m_subPtrI == subPtr.i) { - jam(); - found = true; - break; - } - } - ndbrequire(found); - suma.sendSubStopComplete(signal, subbPtr); -} - -/********************************************************** * Scan data interface * * Assumption: one execTRANSID_AI contains all attr info @@ -2712,710 +1692,6 @@ SumaParticipant::execTRANSID_AI(Signal* signal){ f_bufferLock = 0; } -/********************************************************** - * - * Trigger data interface - * - */ - -void -SumaParticipant::execTRIG_ATTRINFO(Signal* signal){ - jamEntry(); - - CRASH_INSERTION(13016); - TrigAttrInfo* const trg = (TrigAttrInfo*)signal->getDataPtr(); - const Uint32 trigId = trg->getTriggerId(); - - const Uint32 dataLen = signal->length() - TrigAttrInfo::StaticLength; - - if(trg->getAttrInfoType() == TrigAttrInfo::BEFORE_VALUES){ - jam(); - - ndbrequire(b_bufferLock == trigId); - - memcpy(b_buffer + b_trigBufferSize, trg->getData(), 4 * dataLen); - b_trigBufferSize += dataLen; - // printf("before values %u %u %u\n",trigId, dataLen, b_trigBufferSize); - } else { - jam(); - - if(f_bufferLock == 0){ - f_bufferLock = trigId; - f_trigBufferSize = 0; - b_bufferLock = trigId; - b_trigBufferSize = 0; - } else { - ndbrequire(f_bufferLock == trigId); - } - - memcpy(f_buffer + f_trigBufferSize, trg->getData(), 4 * dataLen); - f_trigBufferSize += dataLen; - } -} - -#ifdef NODEFAIL_DEBUG2 -static int theCounts[64] = {0}; -#endif - -Uint32 -Suma::getStoreBucket(Uint32 v) -{ - // id will contain id to responsible suma or - // RNIL if we don't have nodegroup info yet - - const Uint32 N = NO_OF_BUCKETS; - const Uint32 D = v % N; // Distibution key - return D; -} - -Uint32 -Suma::getResponsibleSumaNodeId(Uint32 D) -{ - // id will contain id to responsible suma or - // RNIL if we don't have nodegroup info yet - - Uint32 id; - - if (c_restartLock) { - jam(); - // ndbout_c("c_restartLock"); - id = RNIL; - } else { - jam(); - id = RNIL; - const Uint32 n = c_noNodesInGroup; // Number nodes in node group - const Uint32 C1 = D / n; - const Uint32 C2 = D - C1*n; // = D % n; - const Uint32 C = C2 + C1 % n; - for (Uint32 i = 0; i < n; i++) { - jam(); - id = c_nodesInGroup[(C + i) % n]; - if (c_aliveNodes.get(id) && - !c_preparingNodes.get(id)) { - jam(); - break; - }//if - } -#ifdef NODEFAIL_DEBUG2 - theCounts[id]++; - ndbout_c("Suma:responsible n=%u, D=%u, id = %u, count=%u", - n,D, id, theCounts[id]); -#endif - } - return id; -} - -Uint32 -SumaParticipant::decideWhoToSend(Uint32 nBucket, Uint32 gci){ - bool replicaFlag = true; - Uint32 nId = RNIL; - - // bucket active/not active set by GCP_COMPLETE - if (c_buckets[nBucket].active) { - if (c_buckets[nBucket].handover && c_buckets[nBucket].handoverGCI <= gci) { - jam(); - replicaFlag = true; // let the other node send this - nId = RNIL; - // mark this as started, if we get a node failiure now we have some lost stuff - c_buckets[nBucket].handover_started = true; - } else { - jam(); - replicaFlag = false; - nId = refToNode(reference()); - } - } else { - nId = getResponsibleSumaNodeId(nBucket); - replicaFlag = !(nId == refToNode(reference())); - - if (!replicaFlag) { - if (!c_buckets[nBucket].handover) { - jam(); - // appearently a node has failed and we are taking over sending - // from that bucket. Now we need to go back to latest completed - // GCI. Handling will depend on Subscriber and Subscription - - // TODO, for now we make an easy takeover - if (gci < c_nodeFailGCI) - c_lastInconsistentGCI = gci; - - // we now have responsability for this bucket and we're actively - // sending from that - c_buckets[nBucket].active = true; -#ifdef HANDOVER_DEBUG - ndbout_c("Takeover Bucket %u", nBucket); -#endif - } else if (c_buckets[nBucket].handoverGCI > gci) { - jam(); - replicaFlag = true; // handover going on, but don't start sending yet - nId = RNIL; - } else { - jam(); -#ifdef HANDOVER_DEBUG - ndbout_c("Possible error: Will send from GCI = %u", gci); -#endif - } - } - } - -#ifdef NODEFAIL_DEBUG2 - ndbout_c("Suma:bucket %u, responsible id = %u, replicaFlag = %u", - nBucket, nId, (Uint32)replicaFlag); -#endif - return replicaFlag; -} - -void -SumaParticipant::execFIRE_TRIG_ORD(Signal* signal){ - jamEntry(); - DBUG_ENTER("SumaParticipant::execFIRE_TRIG_ORD"); - CRASH_INSERTION(13016); - FireTrigOrd* const trg = (FireTrigOrd*)signal->getDataPtr(); - const Uint32 trigId = trg->getTriggerId(); - const Uint32 hashValue = trg->getHashValue(); - const Uint32 gci = trg->getGCI(); - const Uint32 event = trg->getTriggerEvent(); - const Uint32 triggerId = trg->getTriggerId(); - Uint32 tableId = triggerId & 0xFFFF; - - ndbrequire(f_bufferLock == trigId); - -#ifdef EVENT_DEBUG2 - ndbout_c("SumaParticipant::execFIRE_TRIG_ORD"); -#endif - - Uint32 sz = trg->getNoOfPrimaryKeyWords()+trg->getNoOfAfterValueWords(); - ndbrequire(sz == f_trigBufferSize); - - /** - * Reformat as "all headers" + "all data" - */ - Uint32 dataLen = 0; - Uint32 noOfAttrs = 0; - Uint32 * src = f_buffer; - Uint32 * headers = signal->theData + 25; - Uint32 * dst = signal->theData + 25 + MAX_ATTRIBUTES_IN_TABLE; - - LinearSectionPtr ptr[3]; - int nptr; - - ptr[0].p = headers; - ptr[1].p = dst; - - while(sz > 0){ - jam(); - Uint32 tmp = * src ++; - * headers ++ = tmp; - Uint32 len = AttributeHeader::getDataSize(tmp); - memcpy(dst, src, 4 * len); - dst += len; - src += len; - - noOfAttrs++; - dataLen += len; - sz -= (1 + len); - } - ndbrequire(sz == 0); - - ptr[0].sz = noOfAttrs; - ptr[1].sz = dataLen; - - if (b_trigBufferSize > 0) { - jam(); - ptr[2].p = b_buffer; - ptr[2].sz = b_trigBufferSize; - nptr = 3; - } else { - jam(); - nptr = 2; - } - - // right now only for tableEvent - bool replicaFlag = decideWhoToSend(getStoreBucket(hashValue), gci); - - /** - * Signal to subscriber(s) - */ - SubTableData * data = (SubTableData*)signal->getDataPtrSend();//trg; - data->gci = gci; - data->tableId = tableId; - data->operation = event; - data->noOfAttributes = noOfAttrs; - data->dataSize = dataLen; - - SubscriberPtr subbPtr; - for(c_dataSubscribers.first(subbPtr); !subbPtr.isNull(); - c_dataSubscribers.next(subbPtr)){ - if (subbPtr.p->m_firstGCI > gci) { -#ifdef EVENT_DEBUG - ndbout_c("m_firstGCI = %u, gci = %u", subbPtr.p->m_firstGCI, gci); -#endif - jam(); - // we're either restarting or it's a newly created subscriber - // and waiting for the right gci - continue; - } - - jam(); - - const Uint32 ref = subbPtr.p->m_subscriberRef; - // ndbout_c("ref = %u", ref); - const Uint32 subdata = subbPtr.p->m_subscriberData; - data->senderData = subdata; - /* - * get subscription ptr for this subscriber - */ - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI); - - if(!subPtr.p->m_tables[tableId]) { - jam(); - continue; - //continue in for-loop if the table is not part of - //the subscription. Otherwise, send data to subscriber. - } - - if (subPtr.p->m_subscriptionType == SubCreateReq::TableEvent) { - if (replicaFlag) { - jam(); - c_failoverBuffer.subTableData(gci,NULL,0); - continue; - } - jam(); - Uint32 tmp = data->logType; - if (c_lastInconsistentGCI == data->gci) { - data->setGCINotConsistent(); - } - -#ifdef HANDOVER_DEBUG - { - static int aLongGCIName = 0; - if (data->gci != aLongGCIName) { - aLongGCIName = data->gci; - ndbout_c("sent from GCI = %u", aLongGCIName); - } - } -#endif - DBUG_PRINT("info",("GSN_SUB_TABLE_DATA to node %d", refToNode(ref))); - sendSignal(ref, GSN_SUB_TABLE_DATA, signal, - SubTableData::SignalLength, JBB, ptr, nptr); - data->logType = tmp; - } else { - ndbassert(refToNode(ref) == 0 || refToNode(ref) == getOwnNodeId()); - jam(); -#if PRINT_ONLY - ndbout_c("GSN_SUB_TABLE_DATA to %s: op: %d #attr: %d len: %d", - getBlockName(refToBlock(ref)), - noOfAttrs, dataLen); - -#else -#ifdef HANDOVER_DEBUG - { - static int aLongGCIName2 = 0; - if (data->gci != aLongGCIName2) { - aLongGCIName2 = data->gci; - ndbout_c("(EXECUTE_DIRECT) sent from GCI = %u to %u", aLongGCIName2, ref); - } - } -#endif - EXECUTE_DIRECT(refToBlock(ref), GSN_SUB_TABLE_DATA, signal, - SubTableData::SignalLength); - jamEntry(); -#endif - } - } - - /** - * Reset f_bufferLock - */ - f_bufferLock = 0; - b_bufferLock = 0; - - DBUG_VOID_RETURN; -} - -void -SumaParticipant::execSUB_GCP_COMPLETE_REP(Signal* signal){ - jamEntry(); - - SubGcpCompleteRep * rep = (SubGcpCompleteRep*)signal->getDataPtrSend(); - - Uint32 gci = rep->gci; - c_lastCompleteGCI = gci; - - /** - * Signal to subscriber(s) - */ - - SubscriberPtr subbPtr; - SubscriptionPtr subPtr; - c_dataSubscribers.first(subbPtr); - for(; !subbPtr.isNull(); c_dataSubscribers.next(subbPtr)){ - - if (subbPtr.p->m_firstGCI > gci) { - jam(); - // we don't send SUB_GCP_COMPLETE_REP for incomplete GCI's - continue; - } - - const Uint32 ref = subbPtr.p->m_subscriberRef; - rep->senderRef = ref; - rep->senderData = subbPtr.p->m_subscriberData; - - c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI); -#if PRINT_ONLY - ndbout_c("GSN_SUB_GCP_COMPLETE_REP to %s:", - getBlockName(refToBlock(ref))); -#else - - CRASH_INSERTION(13018); - - if (subPtr.p->m_subscriptionType == SubCreateReq::TableEvent) - { - jam(); - sendSignal(ref, GSN_SUB_GCP_COMPLETE_REP, signal, - SubGcpCompleteRep::SignalLength, JBB); - } - else - { - jam(); - ndbassert(refToNode(ref) == 0 || refToNode(ref) == getOwnNodeId()); - EXECUTE_DIRECT(refToBlock(ref), GSN_SUB_GCP_COMPLETE_REP, signal, - SubGcpCompleteRep::SignalLength); - jamEntry(); - } -#endif - } - - if (c_handoverToDo) { - jam(); - c_handoverToDo = false; - for( int i = 0; i < NO_OF_BUCKETS; i++) { - if (c_buckets[i].handover) { - if (c_buckets[i].handoverGCI > gci) { - jam(); - c_handoverToDo = true; // still waiting for the right GCI - break; /* since all handover should happen at the same time - * we can break here - */ - } else { - c_buckets[i].handover = false; -#ifdef HANDOVER_DEBUG - ndbout_c("Handover Bucket %u", i); -#endif - if (getResponsibleSumaNodeId(i) == refToNode(reference())) { - // my bucket to be handed over to me - ndbrequire(!c_buckets[i].active); - jam(); - c_buckets[i].active = true; - } else { - // someone else's bucket to handover to - ndbrequire(c_buckets[i].active); - jam(); - c_buckets[i].active = false; - } - } - } - } - } -} - -/*********************************************************** - * - * Embryo to syncronize the Suma's so as to know if a subscriber - * has received a GCP_COMPLETE from all suma's or not - * - */ - -void -SumaParticipant::runSUB_GCP_COMPLETE_ACC(Signal* signal){ - jam(); - - SubGcpCompleteAcc * const acc = (SubGcpCompleteAcc*)signal->getDataPtr(); - - Uint32 gci = acc->rep.gci; - -#ifdef EVENT_DEBUG - ndbout_c("SumaParticipant::runSUB_GCP_COMPLETE_ACC gci = %u", gci); -#endif - - c_failoverBuffer.subGcpCompleteRep(gci); -} - -void -Suma::execSUB_GCP_COMPLETE_ACC(Signal* signal){ - jamEntry(); - - if (RtoI(signal->getSendersBlockRef(), false) != RNIL) { - jam(); - // Ack from other SUMA - runSUB_GCP_COMPLETE_ACC(signal); - return; - } - - jam(); - // Ack from User and not an acc from other SUMA, redistribute in nodegroup - - SubGcpCompleteAcc * const acc = (SubGcpCompleteAcc*)signal->getDataPtr(); - Uint32 gci = acc->rep.gci; - Uint32 senderRef = acc->rep.senderRef; - Uint32 subscriberData = acc->rep.subscriberData; - -#ifdef EVENT_DEBUG - ndbout_c("Suma::execSUB_GCP_COMPLETE_ACC gci = %u", gci); -#endif - bool moreToCome = false; - - SubscriberPtr subbPtr; - for(c_dataSubscribers.first(subbPtr); - !subbPtr.isNull(); c_dataSubscribers.next(subbPtr)){ -#ifdef EVENT_DEBUG - ndbout_c("Suma::execSUB_GCP_COMPLETE_ACC %u == %u && %u == %u", - subbPtr.p->m_subscriberRef, - senderRef, - subbPtr.p->m_subscriberData, - subscriberData); -#endif - if (subbPtr.p->m_subscriberRef == senderRef && - subbPtr.p->m_subscriberData == subscriberData) { - jam(); -#ifdef EVENT_DEBUG - ndbout_c("Suma::execSUB_GCP_COMPLETE_ACC gci = FOUND SUBSCRIBER"); -#endif - subbPtr.p->m_lastGCI = gci; - } else if (subbPtr.p->m_lastGCI < gci) { - jam(); - if (subbPtr.p->m_firstGCI <= gci) - moreToCome = true; - } else - jam(); - } - - if (!moreToCome) { - // tell the other SUMA's that I'm done with this GCI - jam(); - for (Uint32 i = 0; i < c_noNodesInGroup; i++) { - Uint32 id = c_nodesInGroup[i]; - Uint32 ref = calcSumaBlockRef(id); - if ((ref != reference()) && c_aliveNodes.get(id)) { - jam(); - sendSignal(ref, GSN_SUB_GCP_COMPLETE_ACC, signal, - SubGcpCompleteAcc::SignalLength, JBB); - } else - jam(); - } - } -} - -static Uint32 tmpFailoverBuffer[512]; -//SumaParticipant::FailoverBuffer::FailoverBuffer(DataBuffer<15>::DataBufferPool & p) -// : m_dataList(p), -SumaParticipant::FailoverBuffer::FailoverBuffer() - : - c_gcis(tmpFailoverBuffer), c_sz(512), c_first(0), c_next(0), c_full(false) -{ -} - -bool SumaParticipant::FailoverBuffer::subTableData(Uint32 gci, Uint32 *src, int sz) -{ - bool ok = true; - - if (c_full) { - ok = false; -#ifdef EVENT_DEBUG - ndbout_c("Suma::FailoverBuffer::SubTableData buffer full gci=%u"); -#endif - } else { - c_gcis[c_next] = gci; - c_next++; - if (c_next == c_sz) c_next = 0; - if (c_next == c_first) - c_full = true; - // ndbout_c("%u %u %u",c_first,c_next,c_sz); - } - return ok; -} -bool SumaParticipant::FailoverBuffer::subGcpCompleteRep(Uint32 gci) -{ - bool ok = true; - - // ndbout_c("Empty"); - while (true) { - if (c_first == c_next && !c_full) - break; - if (c_gcis[c_first] > gci) - break; - c_full = false; - c_first++; - if (c_first == c_sz) c_first = 0; - // ndbout_c("%u %u %u : ",c_first,c_next,c_sz); - } - - return ok; -} -bool SumaParticipant::FailoverBuffer::nodeFailRep() -{ - bool ok = true; - while (true) { - if (c_first == c_next && !c_full) - break; - -#ifdef EVENT_DEBUG - ndbout_c("Suma::FailoverBuffer::NodeFailRep resending gci=%u", c_gcis[c_first]); -#endif - c_full = false; - c_first++; - if (c_first == c_sz) c_first = 0; - } - return ok; -} - -/********************************************************** - * Suma participant interface - * - * Stopping and removing of subscriber - * - */ - -void -SumaParticipant::execSUB_STOP_REQ(Signal* signal){ - jamEntry(); - DBUG_ENTER("SumaParticipant::execSUB_STOP_REQ"); - - CRASH_INSERTION(13019); - - SubStopReq * const req = (SubStopReq*)signal->getDataPtr(); - Uint32 senderRef = signal->getSendersBlockRef(); - Uint32 senderData = req->senderData; - Uint32 subscriberRef = req->subscriberRef; - Uint32 subscriberData = req->subscriberData; - SubscriptionPtr subPtr; - Subscription key; - key.m_subscriptionId = req->subscriptionId; - key.m_subscriptionKey = req->subscriptionKey; - Uint32 part = req->part; - - if (key.m_subscriptionKey == 0 && - key.m_subscriptionId == 0 && - subscriberData == 0) { - SubStopConf* conf = (SubStopConf*)signal->getDataPtrSend(); - - conf->senderRef = reference(); - conf->senderData = senderData; - conf->subscriptionId = key.m_subscriptionId; - conf->subscriptionKey = key.m_subscriptionKey; - conf->subscriberData = subscriberData; - - sendSignal(senderRef, GSN_SUB_STOP_CONF, signal, - SubStopConf::SignalLength, JBB); - - removeSubscribersOnNode(signal, refToNode(subscriberRef)); - DBUG_VOID_RETURN; - } - - if(!c_subscriptions.find(subPtr, key)){ - jam(); - sendSubStopRef(signal, GrepError::SUBSCRIPTION_ID_NOT_FOUND); - return; - } - - ndbrequire(part == SubscriptionData::TableData); - - SubscriberPtr subbPtr; - if (senderRef == reference()){ - jam(); - c_subscriberPool.getPtr(subbPtr, senderData); - ndbrequire(subbPtr.p->m_subPtrI == subPtr.i && - subbPtr.p->m_subscriberRef == subscriberRef && - subbPtr.p->m_subscriberData == subscriberData); - c_removeDataSubscribers.remove(subbPtr); - } else { - bool found = false; - jam(); - c_dataSubscribers.first(subbPtr); - for (;!subbPtr.isNull(); c_dataSubscribers.next(subbPtr)){ - jam(); - if (subbPtr.p->m_subPtrI == subPtr.i && - refToNode(subbPtr.p->m_subscriberRef) == refToNode(subscriberRef) && - subbPtr.p->m_subscriberData == subscriberData){ - // ndbout_c("STOP_REQ: before c_dataSubscribers.release"); - jam(); - c_dataSubscribers.remove(subbPtr); - found = true; - break; - } - } - /** - * If we didn't find anyone, send ref - */ - if (!found) { - jam(); - sendSubStopRef(signal, GrepError::SUBSCRIBER_NOT_FOUND); - DBUG_VOID_RETURN; - } - } - - subbPtr.p->m_senderRef = senderRef; // store ref to requestor - subbPtr.p->m_senderData = senderData; // store ref to requestor - c_prepDataSubscribers.add(subbPtr); - - Ptr<SyncRecord> syncPtr; - c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI); - if (syncPtr.p->m_locked) { - jam(); - sendSubStopRef(signal, /** Error Code */ 0, true); - DBUG_VOID_RETURN; - } - syncPtr.p->m_locked = true; - - syncPtr.p->startDropTrigger(signal); - DBUG_VOID_RETURN; -} - -void -SumaParticipant::sendSubStopComplete(Signal* signal, SubscriberPtr subbPtr){ - jam(); - - CRASH_INSERTION(13020); - - SubscriptionPtr subPtr; - c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI); - - Ptr<SyncRecord> syncPtr; - c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI); - syncPtr.p->m_locked = false; - - SubStopConf * const conf = (SubStopConf*)signal->getDataPtrSend(); - - conf->senderRef = reference(); - conf->senderData = subbPtr.p->m_senderData; - conf->subscriptionId = subPtr.p->m_subscriptionId; - conf->subscriptionKey = subPtr.p->m_subscriptionKey; - conf->subscriberData = subbPtr.p->m_subscriberData; - Uint32 senderRef = subbPtr.p->m_senderRef; - - c_prepDataSubscribers.release(subbPtr); - sendSignal(senderRef, GSN_SUB_STOP_CONF, signal, - SubStopConf::SignalLength, JBB); -} - -void -SumaParticipant::sendSubStopRef(Signal* signal, Uint32 errCode, - bool temporary){ - jam(); - SubStopRef * ref = (SubStopRef *)signal->getDataPtrSend(); - ref->senderRef = reference(); - ref->errorCode = errCode; - if (temporary) { - ref->setTemporary(); - } - sendSignal(signal->getSendersBlockRef(), - GSN_SUB_STOP_REF, - signal, - SubStopRef::SignalLength, - JBB); - return; -} - /************************************************************** * * Removing subscription @@ -3446,36 +1722,6 @@ SumaParticipant::execSUB_REMOVE_REQ(Signal* signal) { { jam(); SubscriberPtr i_subbPtr; - for(c_prepDataSubscribers.first(i_subbPtr); - !i_subbPtr.isNull(); c_prepDataSubscribers.next(i_subbPtr)){ - jam(); - if( i_subbPtr.p->m_subPtrI == subPtr.i ) { - jam(); - sendSubRemoveRef(signal, req, /* ErrorCode */ 0, true); - return; - // c_prepDataSubscribers.release(subbPtr); - } - } - c_dataSubscribers.first(i_subbPtr); - while(!i_subbPtr.isNull()){ - jam(); - SubscriberPtr subbPtr = i_subbPtr; - c_dataSubscribers.next(i_subbPtr); - if( subbPtr.p->m_subPtrI == subPtr.i ) { - jam(); - sendSubRemoveRef(signal, req, /* ErrorCode */ 0, true); - return; - /* Unfinished/untested code. If remove should be possible - * even if subscribers are left these have to be stopped - * first. See m_markRemove, m_nSubscribers. We need also to - * block remove for this subscription so that multiple - * removes is not possible... - */ - c_dataSubscribers.remove(subbPtr); - c_removeDataSubscribers.add(subbPtr); - count++; - } - } c_metaSubscribers.first(i_subbPtr); while(!i_subbPtr.isNull()){ jam(); @@ -3491,15 +1737,7 @@ SumaParticipant::execSUB_REMOVE_REQ(Signal* signal) { subPtr.p->m_senderRef = senderRef; subPtr.p->m_senderData = req.senderData; - if (count > 0){ - jam(); - ndbrequire(false); // code not finalized - subPtr.p->m_markRemove = true; - subPtr.p->m_nSubscribers = count; - sendSubStopReq(signal); - } else { - completeSubRemoveReq(signal, subPtr); - } + completeSubRemoveReq(signal, subPtr); } void @@ -3596,486 +1834,5 @@ SumaParticipant::SyncRecord::release(){ attrBuf.release(); } - -/************************************************************** - * - * Restarting remote node functions, master functionality - * (slave does nothing special) - * - triggered on INCL_NODEREQ calling startNode - * - included node will issue START_ME when it's ready to start - * the subscribers - * - */ - -Suma::Restart::Restart(Suma& s) : suma(s) { - for (int i = 0; i < MAX_REPLICAS; i++) { - c_okToStart[i] = false; - c_waitingToStart[i] = false; - } -} - -void -Suma::Restart::resetNode(Uint32 sumaRef) -{ - jam(); - int I = suma.RtoI(sumaRef); - c_okToStart[I] = false; - c_waitingToStart[I] = false; -} - -void -Suma::Restart::startNode(Signal* signal, Uint32 sumaRef) -{ - jam(); - resetNode(sumaRef); - - // right now we can only handle restarting one node - // at a time in a node group - - createSubscription(signal, sumaRef); -} - -void -Suma::Restart::createSubscription(Signal* signal, Uint32 sumaRef) { - jam(); - suma.c_subscriptions.first(c_subPtr); - nextSubscription(signal, sumaRef); -} - -void -Suma::Restart::nextSubscription(Signal* signal, Uint32 sumaRef) { - jam(); - if (c_subPtr.isNull()) { - jam(); - completeSubscription(signal, sumaRef); - return; - } - SubscriptionPtr subPtr; - subPtr.i = c_subPtr.curr.i; - subPtr.p = suma.c_subscriptions.getPtr(subPtr.i); - - suma.c_subscriptions.next(c_subPtr); - - SubCreateReq * req = (SubCreateReq *)signal->getDataPtrSend(); - - req->subscriberRef = suma.reference(); - req->subscriberData = subPtr.i; - req->subscriptionId = subPtr.p->m_subscriptionId; - req->subscriptionKey = subPtr.p->m_subscriptionKey; - req->subscriptionType = subPtr.p->m_subscriptionType | - SubCreateReq::RestartFlag; - - switch (subPtr.p->m_subscriptionType) { - case SubCreateReq::TableEvent: - case SubCreateReq::SelectiveTableSnapshot: - case SubCreateReq::DatabaseSnapshot: { - jam(); - - Ptr<SyncRecord> syncPtr; - suma.c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI); - syncPtr.p->m_tableList.first(syncPtr.p->m_tableList_it); - - ndbrequire(!syncPtr.p->m_tableList_it.isNull()); - - req->tableId = *syncPtr.p->m_tableList_it.data; - -#if 0 - for (int i = 0; i < MAX_TABLES; i++) - if (subPtr.p->m_tables[i]) { - req->tableId = i; - break; - } -#endif - - suma.sendSignal(sumaRef, GSN_SUB_CREATE_REQ, signal, - SubCreateReq::SignalLength+1 /*to get table Id*/, JBB); - return; - } - case SubCreateReq::SingleTableScan : - // TODO - jam(); - return; - } - ndbrequire(false); -} - -void -Suma::execSUB_CREATE_CONF(Signal* signal) { - jamEntry(); -#ifdef NODEFAIL_DEBUG - ndbout_c("Suma::execSUB_CREATE_CONF"); -#endif - - const Uint32 senderRef = signal->senderBlockRef(); - - SubCreateConf * const conf = (SubCreateConf *)signal->getDataPtr(); - - Subscription key; - const Uint32 subscriberData = conf->subscriberData; - key.m_subscriptionId = conf->subscriptionId; - key.m_subscriptionKey = conf->subscriptionKey; - - SubscriptionPtr subPtr; - ndbrequire(c_subscriptions.find(subPtr, key)); - - switch(subPtr.p->m_subscriptionType) { - case SubCreateReq::TableEvent: - case SubCreateReq::SelectiveTableSnapshot: - case SubCreateReq::DatabaseSnapshot: - { - Ptr<SyncRecord> syncPtr; - c_syncPool.getPtr(syncPtr, subPtr.p->m_syncPtrI); - - syncPtr.p->m_tableList.next(syncPtr.p->m_tableList_it); - if (syncPtr.p->m_tableList_it.isNull()) { - jam(); - SubSyncReq *req = (SubSyncReq *)signal->getDataPtrSend(); - - req->subscriptionId = key.m_subscriptionId; - req->subscriptionKey = key.m_subscriptionKey; - req->subscriberData = subscriberData; - req->part = (Uint32) SubscriptionData::MetaData; - - sendSignal(senderRef, GSN_SUB_SYNC_REQ, signal, - SubSyncReq::SignalLength, JBB); - } else { - jam(); - SubCreateReq * req = (SubCreateReq *)signal->getDataPtrSend(); - - req->subscriberRef = reference(); - req->subscriberData = subPtr.i; - req->subscriptionId = subPtr.p->m_subscriptionId; - req->subscriptionKey = subPtr.p->m_subscriptionKey; - req->subscriptionType = subPtr.p->m_subscriptionType | - SubCreateReq::RestartFlag | - SubCreateReq::AddTableFlag; - - req->tableId = *syncPtr.p->m_tableList_it.data; - - sendSignal(senderRef, GSN_SUB_CREATE_REQ, signal, - SubCreateReq::SignalLength+1 /*to get table Id*/, JBB); - } - } - return; - case SubCreateReq::SingleTableScan: - ndbrequire(false); - } - ndbrequire(false); -} - -void -Suma::execSUB_CREATE_REF(Signal* signal) { - jamEntry(); -#ifdef NODEFAIL_DEBUG - ndbout_c("Suma::execSUB_CREATE_REF"); -#endif - //ndbrequire(false); -} - -void -Suma::execSUB_SYNC_CONF(Signal* signal) { - jamEntry(); -#ifdef NODEFAIL_DEBUG - ndbout_c("Suma::execSUB_SYNC_CONF"); -#endif - Uint32 sumaRef = signal->getSendersBlockRef(); - - SubSyncConf *conf = (SubSyncConf *)signal->getDataPtr(); - Subscription key; - - key.m_subscriptionId = conf->subscriptionId; - key.m_subscriptionKey = conf->subscriptionKey; - // SubscriptionData::Part part = (SubscriptionData::Part)conf->part; - // const Uint32 subscriberData = conf->subscriberData; - - SubscriptionPtr subPtr; - c_subscriptions.find(subPtr, key); - - switch(subPtr.p->m_subscriptionType) { - case SubCreateReq::TableEvent: - case SubCreateReq::SelectiveTableSnapshot: - case SubCreateReq::DatabaseSnapshot: - jam(); - Restart.nextSubscription(signal, sumaRef); - return; - case SubCreateReq::SingleTableScan: - ndbrequire(false); - return; - } - ndbrequire(false); -} - -void -Suma::execSUB_SYNC_REF(Signal* signal) { - jamEntry(); -#ifdef NODEFAIL_DEBUG - ndbout_c("Suma::execSUB_SYNC_REF"); -#endif - //ndbrequire(false); -} - -void -Suma::execSUMA_START_ME(Signal* signal) { - jamEntry(); -#ifdef NODEFAIL_DEBUG - ndbout_c("Suma::execSUMA_START_ME"); -#endif - - Restart.runSUMA_START_ME(signal, signal->getSendersBlockRef()); -} - -void -Suma::Restart::runSUMA_START_ME(Signal* signal, Uint32 sumaRef) { - int I = suma.RtoI(sumaRef); - - // restarting Suma is ready for SUB_START_REQ - if (c_waitingToStart[I]) { - // we've waited with startSubscriber since restarting suma was not ready - c_waitingToStart[I] = false; - startSubscriber(signal, sumaRef); - } else { - // do startSubscriber as soon as its time - c_okToStart[I] = true; - } -} - -void -Suma::Restart::completeSubscription(Signal* signal, Uint32 sumaRef) { - jam(); - int I = suma.RtoI(sumaRef); - - if (c_okToStart[I]) {// otherwise will start when START_ME comes - c_okToStart[I] = false; - startSubscriber(signal, sumaRef); - } else { - c_waitingToStart[I] = true; - } -} - -void -Suma::Restart::startSubscriber(Signal* signal, Uint32 sumaRef) { - jam(); - suma.c_dataSubscribers.first(c_subbPtr); - nextSubscriber(signal, sumaRef); -} - -void -Suma::Restart::sendSubStartReq(SubscriptionPtr subPtr, SubscriberPtr subbPtr, - Signal* signal, Uint32 sumaRef) -{ - jam(); - SubStartReq * req = (SubStartReq *)signal->getDataPtrSend(); - - req->senderRef = suma.reference(); - req->senderData = subbPtr.p->m_senderData; - req->subscriptionId = subPtr.p->m_subscriptionId; - req->subscriptionKey = subPtr.p->m_subscriptionKey; - req->part = SubscriptionData::TableData; - req->subscriberData = subbPtr.p->m_subscriberData; - req->subscriberRef = subbPtr.p->m_subscriberRef; - - // restarting suma will not respond to this until startphase 5 - // since it is not until then data copying has been completed -#ifdef NODEFAIL_DEBUG - ndbout_c("Suma::Restart::sendSubStartReq sending GSN_SUB_START_REQ id=%u key=%u", - req->subscriptionId, req->subscriptionKey); -#endif - suma.sendSignal(sumaRef, GSN_SUB_START_REQ, - signal, SubStartReq::SignalLength2, JBB); -} - -void -Suma::execSUB_START_CONF(Signal* signal) { - jamEntry(); -#ifdef NODEFAIL_DEBUG - ndbout_c("Suma::execSUB_START_CONF"); -#endif - Uint32 sumaRef = signal->getSendersBlockRef(); - Restart.nextSubscriber(signal, sumaRef); -} - -void -Suma::execSUB_START_REF(Signal* signal) { - jamEntry(); -#ifdef NODEFAIL_DEBUG - ndbout_c("Suma::execSUB_START_REF"); -#endif - //ndbrequire(false); -} - -void -Suma::Restart::nextSubscriber(Signal* signal, Uint32 sumaRef) { - jam(); - if (c_subbPtr.isNull()) { - jam(); - completeSubscriber(signal, sumaRef); - return; - } - - SubscriberPtr subbPtr = c_subbPtr; - suma.c_dataSubscribers.next(c_subbPtr); - - /* - * get subscription ptr for this subscriber - */ - - SubscriptionPtr subPtr; - suma.c_subscriptions.getPtr(subPtr, subbPtr.p->m_subPtrI); - switch (subPtr.p->m_subscriptionType) { - case SubCreateReq::TableEvent: - case SubCreateReq::SelectiveTableSnapshot: - case SubCreateReq::DatabaseSnapshot: - { - jam(); - sendSubStartReq(subPtr, subbPtr, signal, sumaRef); -#if 0 - SubStartReq * req = (SubStartReq *)signal->getDataPtrSend(); - - req->senderRef = reference(); - req->senderData = subbPtr.p->m_senderData; - req->subscriptionId = subPtr.p->m_subscriptionId; - req->subscriptionKey = subPtr.p->m_subscriptionKey; - req->part = SubscriptionData::TableData; - req->subscriberData = subbPtr.p->m_subscriberData; - req->subscriberRef = subbPtr.p->m_subscriberRef; - - // restarting suma will not respond to this until startphase 5 - // since it is not until then data copying has been completed -#ifdef NODEFAIL_DEBUG - ndbout_c("Suma::nextSubscriber sending GSN_SUB_START_REQ id=%u key=%u", - req->subscriptionId, req->subscriptionKey); -#endif - suma.sendSignal(sumaRef, GSN_SUB_START_REQ, - signal, SubStartReq::SignalLength2, JBB); -#endif - } - return; - case SubCreateReq::SingleTableScan: - ndbrequire(false); - return; - } - ndbrequire(false); -} - -void -Suma::Restart::completeSubscriber(Signal* signal, Uint32 sumaRef) { - completeRestartingNode(signal, sumaRef); -} - -void -Suma::Restart::completeRestartingNode(Signal* signal, Uint32 sumaRef) { - jam(); - SumaHandoverReq * req = (SumaHandoverReq *)signal->getDataPtrSend(); - - req->gci = suma.getFirstGCI(signal); - - suma.sendSignal(sumaRef, GSN_SUMA_HANDOVER_REQ, signal, - SumaHandoverReq::SignalLength, JBB); -} - -// only run on restarting suma - -void -Suma::execSUMA_HANDOVER_REQ(Signal* signal) -{ - jamEntry(); - // Uint32 sumaRef = signal->getSendersBlockRef(); - SumaHandoverReq const * req = (SumaHandoverReq *)signal->getDataPtr(); - - Uint32 gci = req->gci; - Uint32 new_gci = getFirstGCI(signal); - - if (new_gci > gci) { - gci = new_gci; - } - - { // all recreated subscribers at restarting SUMA start at same GCI - SubscriberPtr subbPtr; - for(c_dataSubscribers.first(subbPtr); - !subbPtr.isNull(); - c_dataSubscribers.next(subbPtr)){ - subbPtr.p->m_firstGCI = gci; - } - } - -#ifdef NODEFAIL_DEBUG - ndbout_c("Suma::execSUMA_HANDOVER_REQ, gci = %u", gci); -#endif - - c_handoverToDo = false; - c_restartLock = false; - { -#ifdef HANDOVER_DEBUG - int c = 0; -#endif - for( int i = 0; i < NO_OF_BUCKETS; i++) { - jam(); - if (getResponsibleSumaNodeId(i) == refToNode(reference())) { -#ifdef HANDOVER_DEBUG - c++; -#endif - jam(); - c_buckets[i].active = false; - c_buckets[i].handoverGCI = gci; - c_buckets[i].handover = true; - c_buckets[i].handover_started = false; - c_handoverToDo = true; - } - } -#ifdef HANDOVER_DEBUG - ndbout_c("prepared handover of bucket %u buckets", c); -#endif - } - - for (Uint32 i = 0; i < c_noNodesInGroup; i++) { - jam(); - Uint32 ref = calcSumaBlockRef(c_nodesInGroup[i]); - if (ref != reference()) { - jam(); - sendSignal(ref, GSN_SUMA_HANDOVER_CONF, signal, - SumaHandoverConf::SignalLength, JBB); - }//if - } -} - -// only run on all but restarting suma -void -Suma::execSUMA_HANDOVER_CONF(Signal* signal) { - jamEntry(); - Uint32 sumaRef = signal->getSendersBlockRef(); - SumaHandoverConf const * conf = (SumaHandoverConf *)signal->getDataPtr(); - - Uint32 gci = conf->gci; - -#ifdef HANDOVER_DEBUG - ndbout_c("Suma::execSUMA_HANDOVER_CONF, gci = %u", gci); -#endif - - /* TODO, if we are restarting several SUMA's (>2 in a nodegroup) - * we have to collect all these conf's before proceding - */ - - // restarting node is now prepared and ready - c_preparingNodes.clear(refToNode(sumaRef)); /* !! important to do before - * below since it affects - * getResponsibleSumaNodeId() - */ - - c_handoverToDo = false; - // mark all active buckets really belonging to restarting SUMA - for( int i = 0; i < NO_OF_BUCKETS; i++) { - if (c_buckets[i].active) { - // I'm running this bucket - if (getResponsibleSumaNodeId(i) == refToNode(sumaRef)) { - // but it should really be the restarted node - c_buckets[i].handoverGCI = gci; - c_buckets[i].handover = true; - c_buckets[i].handover_started = false; - c_handoverToDo = true; - } - } - } -} - template void append(DataBuffer<11>&,SegmentedSectionPtr,SectionSegmentPool&); diff --git a/ndb/src/kernel/blocks/suma/Suma.hpp b/ndb/src/kernel/blocks/suma/Suma.hpp index 3508c5b0e0f..5cf1c4d543f 100644 --- a/ndb/src/kernel/blocks/suma/Suma.hpp +++ b/ndb/src/kernel/blocks/suma/Suma.hpp @@ -77,14 +77,6 @@ protected: void execSUB_SYNC_CONTINUE_CONF(Signal* signal); /** - * Trigger logging - */ - void execTRIG_ATTRINFO(Signal* signal); - void execFIRE_TRIG_ORD(Signal* signal); - void execSUB_GCP_COMPLETE_REP(Signal* signal); - void runSUB_GCP_COMPLETE_ACC(Signal* signal); - - /** * DIH signals */ void execDI_FCOUNTREF(Signal* signal); @@ -93,14 +85,6 @@ protected: void execDIGETPRIMCONF(Signal* signal); /** - * Trigger administration - */ - void execCREATE_TRIG_REF(Signal* signal); - void execCREATE_TRIG_CONF(Signal* signal); - void execDROP_TRIG_REF(Signal* signal); - void execDROP_TRIG_CONF(Signal* signal); - - /** * continueb */ void execCONTINUEB(Signal* signal); @@ -190,22 +174,6 @@ public: void completeMeta(Signal*); /** - * Create triggers - */ - Uint32 m_latestTriggerId; - void startTrigger(Signal* signal); - void nextTrigger(Signal* signal); - void completeTrigger(Signal* signal); - void createAttributeMask(AttributeMask&, Table*); - - /** - * Drop triggers - */ - void startDropTrigger(Signal* signal); - void nextDropTrigger(Signal* signal); - void completeDropTrigger(Signal* signal); - - /** * Sync data */ Uint32 m_currentTable; // Index in m_tableList @@ -229,18 +197,12 @@ public: suma.progError(line, cause, extra); } - void runLIST_TABLES_CONF(Signal* signal); void runGET_TABINFO_CONF(Signal* signal); void runGET_TABINFOREF(Signal* signal); void runDI_FCOUNTCONF(Signal* signal); void runDIGETPRIMCONF(Signal* signal); - void runCREATE_TRIG_CONF(Signal* signal); - void runDROP_TRIG_CONF(Signal* signal); - void runDROP_TRIG_REF(Signal* signal); - void runDropTrig(Signal* signal, Uint32 triggerId, Uint32 tableId); - Uint32 ptrI; union { Uint32 nextPool; Uint32 nextList; }; }; @@ -294,24 +256,11 @@ public: Uint32 m_subscriberRef; Uint32 m_subscriberData; Uint32 m_subPtrI; //reference to subscription - Uint32 m_firstGCI; // first GCI to send - Uint32 m_lastGCI; // last acnowledged GCI Uint32 nextList; union { Uint32 nextPool; Uint32 prevList; }; }; typedef Ptr<Subscriber> SubscriberPtr; - struct Bucket { - bool active; - bool handover; - bool handover_started; - Uint32 handoverGCI; - }; -#define NO_OF_BUCKETS 24 - struct Bucket c_buckets[NO_OF_BUCKETS]; - bool c_handoverToDo; - Uint32 c_lastCompleteGCI; - /** * */ @@ -336,25 +285,8 @@ public: DataBuffer<15>::DataBufferPool c_dataBufferPool; /** - * for restarting Suma not to start sending data too early - */ - bool c_restartLock; - - /** - * for flagging that a GCI containg inconsistent data - * typically due to node failiure - */ - - Uint32 c_lastInconsistentGCI; - Uint32 c_nodeFailGCI; - - NodeBitmask c_failedApiNodes; - - /** * Functions */ - bool removeSubscribersOnNode(Signal *signal, Uint32 nodeId); - bool parseTable(Signal* signal, class GetTabInfoConf* conf, Uint32 tableId, SyncRecord* syncPtr_p); bool checkTableTriggers(SegmentedSectionPtr ptr); @@ -365,52 +297,11 @@ public: void sendSubIdRef(Signal* signal, Uint32 errorCode); void sendSubCreateConf(Signal* signal, Uint32 sender, SubscriptionPtr subPtr); void sendSubCreateRef(Signal* signal, const SubCreateReq& req, Uint32 errorCode); - void sendSubStartRef(SubscriptionPtr subPtr, Signal* signal, - Uint32 errorCode, bool temporary = false); - void sendSubStartRef(Signal* signal, - Uint32 errorCode, bool temporary = false); - void sendSubStopRef(Signal* signal, - Uint32 errorCode, bool temporary = false); void sendSubSyncRef(Signal* signal, Uint32 errorCode); void sendSubRemoveRef(Signal* signal, const SubRemoveReq& ref, Uint32 errorCode, bool temporary = false); - void sendSubStartComplete(Signal*, SubscriberPtr, Uint32, - SubscriptionData::Part); - void sendSubStopComplete(Signal*, SubscriberPtr); - void sendSubStopReq(Signal* signal, bool unlock= false); - void completeSubRemoveReq(Signal* signal, SubscriptionPtr subPtr); - Uint32 getFirstGCI(Signal* signal); - Uint32 decideWhoToSend(Uint32 nBucket, Uint32 gci); - - virtual Uint32 getStoreBucket(Uint32 v) = 0; - virtual Uint32 getResponsibleSumaNodeId(Uint32 D) = 0; - virtual Uint32 RtoI(Uint32 sumaRef, bool dieOnNotFound = true) = 0; - - struct FailoverBuffer { - // FailoverBuffer(DataBuffer<15>::DataBufferPool & p); - FailoverBuffer(); - - bool subTableData(Uint32 gci, Uint32 *src, int sz); - bool subGcpCompleteRep(Uint32 gci); - bool nodeFailRep(); - - // typedef DataBuffer<15> GCIDataBuffer; - // GCIDataBuffer m_GCIDataBuffer; - // GCIDataBuffer::DataBufferIterator m_GCIDataBuffer_it; - - Uint32 *c_gcis; - int c_sz; - - // Uint32 *c_buf; - // int c_buf_sz; - - int c_first; - int c_next; - bool c_full; - } c_failoverBuffer; - /** * Table admin */ @@ -441,8 +332,6 @@ private: * Framework signals */ - void getNodeGroupMembers(Signal* signal); - void execREAD_CONFIG_REQ(Signal* signal); void execSTTOR(Signal* signal); @@ -454,35 +343,13 @@ private: void execINCL_NODEREQ(Signal* signal); void execCONTINUEB(Signal* signal); void execSIGNAL_DROPPED_REP(Signal* signal); - void execAPI_FAILREQ(Signal* signal) ; - - void execSUB_GCP_COMPLETE_ACC(Signal* signal); /** * Controller interface */ - void execSUB_CREATE_REF(Signal* signal); - void execSUB_CREATE_CONF(Signal* signal); - - void execSUB_DROP_REF(Signal* signal); - void execSUB_DROP_CONF(Signal* signal); - - void execSUB_START_REF(Signal* signal); - void execSUB_START_CONF(Signal* signal); - - void execSUB_STOP_REF(Signal* signal); - void execSUB_STOP_CONF(Signal* signal); - - void execSUB_SYNC_REF(Signal* signal); - void execSUB_SYNC_CONF(Signal* signal); - void execSUB_ABORT_SYNC_REF(Signal* signal); void execSUB_ABORT_SYNC_CONF(Signal* signal); - void execSUMA_START_ME(Signal* signal); - void execSUMA_HANDOVER_REQ(Signal* signal); - void execSUMA_HANDOVER_CONF(Signal* signal); - /** * Subscription generation interface */ @@ -494,49 +361,6 @@ private: void execUTIL_SEQUENCE_REF(Signal* signal); void execCREATE_SUBID_REQ(Signal* signal); - Uint32 getStoreBucket(Uint32 v); - Uint32 getResponsibleSumaNodeId(Uint32 D); - - /** - * for Suma that is restarting another - */ - - struct Restart { - Restart(Suma& s); - - Suma & suma; - - bool c_okToStart[MAX_REPLICAS]; - bool c_waitingToStart[MAX_REPLICAS]; - - DLHashTable<SumaParticipant::Subscription>::Iterator c_subPtr; // TODO [MAX_REPLICAS] - SubscriberPtr c_subbPtr; // TODO [MAX_REPLICAS] - - void progError(int line, int cause, const char * extra) { - suma.progError(line, cause, extra); - } - - void resetNode(Uint32 sumaRef); - void runSUMA_START_ME(Signal*, Uint32 sumaRef); - void startNode(Signal*, Uint32 sumaRef); - - void createSubscription(Signal* signal, Uint32 sumaRef); - void nextSubscription(Signal* signal, Uint32 sumaRef); - void completeSubscription(Signal* signal, Uint32 sumaRef); - - void startSync(Signal* signal, Uint32 sumaRef); - void nextSync(Signal* signal, Uint32 sumaRef); - void completeSync(Signal* signal, Uint32 sumaRef); - - void sendSubStartReq(SubscriptionPtr subPtr, SubscriberPtr subbPtr, - Signal* signal, Uint32 sumaRef); - void startSubscriber(Signal* signal, Uint32 sumaRef); - void nextSubscriber(Signal* signal, Uint32 sumaRef); - void completeSubscriber(Signal* signal, Uint32 sumaRef); - - void completeRestartingNode(Signal* signal, Uint32 sumaRef); - } Restart; - private: friend class Restart; struct SubCoordinator { @@ -590,14 +414,4 @@ private: DLList<SubCoordinator> c_runningSubscriptions; }; -inline Uint32 -Suma::RtoI(Uint32 sumaRef, bool dieOnNotFound) { - for (Uint32 i = 0; i < c_noNodesInGroup; i++) { - if (sumaRef == calcSumaBlockRef(c_nodesInGroup[i])) - return i; - } - ndbrequire(!dieOnNotFound); - return RNIL; -} - #endif diff --git a/ndb/src/kernel/blocks/suma/SumaInit.cpp b/ndb/src/kernel/blocks/suma/SumaInit.cpp index ad8493ff908..ae7425da4bf 100644 --- a/ndb/src/kernel/blocks/suma/SumaInit.cpp +++ b/ndb/src/kernel/blocks/suma/SumaInit.cpp @@ -35,19 +35,11 @@ SumaParticipant::SumaParticipant(const Configuration & conf) : */ addRecSignal(GSN_SUB_CREATE_REQ, &SumaParticipant::execSUB_CREATE_REQ); addRecSignal(GSN_SUB_REMOVE_REQ, &SumaParticipant::execSUB_REMOVE_REQ); - addRecSignal(GSN_SUB_START_REQ, &SumaParticipant::execSUB_START_REQ); - addRecSignal(GSN_SUB_STOP_REQ, &SumaParticipant::execSUB_STOP_REQ); addRecSignal(GSN_SUB_SYNC_REQ, &SumaParticipant::execSUB_SYNC_REQ); - addRecSignal(GSN_SUB_STOP_CONF, &SumaParticipant::execSUB_STOP_CONF); - addRecSignal(GSN_SUB_STOP_REF, &SumaParticipant::execSUB_STOP_REF); - /** * Dict interface */ - //addRecSignal(GSN_LIST_TABLES_REF, &SumaParticipant::execLIST_TABLES_REF); - addRecSignal(GSN_LIST_TABLES_CONF, &SumaParticipant::execLIST_TABLES_CONF); - //addRecSignal(GSN_GET_TABINFOREF, &SumaParticipant::execGET_TABINFO_REF); addRecSignal(GSN_GET_TABINFO_CONF, &SumaParticipant::execGET_TABINFO_CONF); addRecSignal(GSN_GET_TABINFOREF, &SumaParticipant::execGET_TABINFOREF); #if 0 @@ -76,32 +68,6 @@ SumaParticipant::SumaParticipant(const Configuration & conf) : addRecSignal(GSN_SUB_SYNC_CONTINUE_CONF, &SumaParticipant::execSUB_SYNC_CONTINUE_CONF); - /** - * Trigger stuff - */ - addRecSignal(GSN_TRIG_ATTRINFO, &SumaParticipant::execTRIG_ATTRINFO); - addRecSignal(GSN_FIRE_TRIG_ORD, &SumaParticipant::execFIRE_TRIG_ORD); - - addRecSignal(GSN_CREATE_TRIG_REF, &Suma::execCREATE_TRIG_REF); - addRecSignal(GSN_CREATE_TRIG_CONF, &Suma::execCREATE_TRIG_CONF); - addRecSignal(GSN_DROP_TRIG_REF, &Suma::execDROP_TRIG_REF); - addRecSignal(GSN_DROP_TRIG_CONF, &Suma::execDROP_TRIG_CONF); - - addRecSignal(GSN_SUB_GCP_COMPLETE_REP, - &SumaParticipant::execSUB_GCP_COMPLETE_REP); - - for( int i = 0; i < NO_OF_BUCKETS; i++) { - c_buckets[i].active = false; - c_buckets[i].handover = false; - c_buckets[i].handover_started = false; - c_buckets[i].handoverGCI = 0; - } - c_handoverToDo = false; - c_lastInconsistentGCI = RNIL; - c_lastCompleteGCI = RNIL; - c_nodeFailGCI = 0; - - c_failedApiNodes.clear(); } SumaParticipant::~SumaParticipant() @@ -110,7 +76,6 @@ SumaParticipant::~SumaParticipant() Suma::Suma(const Configuration & conf) : SumaParticipant(conf), - Restart(*this), c_nodes(c_nodePool), c_runningSubscriptions(c_subCoordinatorPool) { @@ -120,29 +85,12 @@ Suma::Suma(const Configuration & conf) : addRecSignal(GSN_NDB_STTOR, &Suma::execNDB_STTOR); addRecSignal(GSN_DUMP_STATE_ORD, &Suma::execDUMP_STATE_ORD); addRecSignal(GSN_READ_NODESCONF, &Suma::execREAD_NODESCONF); - addRecSignal(GSN_API_FAILREQ, &Suma::execAPI_FAILREQ); - addRecSignal(GSN_NODE_FAILREP, &Suma::execNODE_FAILREP); - addRecSignal(GSN_INCL_NODEREQ, &Suma::execINCL_NODEREQ); addRecSignal(GSN_CONTINUEB, &Suma::execCONTINUEB); addRecSignal(GSN_SIGNAL_DROPPED_REP, &Suma::execSIGNAL_DROPPED_REP, true); addRecSignal(GSN_UTIL_SEQUENCE_CONF, &Suma::execUTIL_SEQUENCE_CONF); addRecSignal(GSN_UTIL_SEQUENCE_REF, &Suma::execUTIL_SEQUENCE_REF); addRecSignal(GSN_CREATE_SUBID_REQ, &Suma::execCREATE_SUBID_REQ); - - addRecSignal(GSN_SUB_CREATE_CONF, &Suma::execSUB_CREATE_CONF); - addRecSignal(GSN_SUB_CREATE_REF, &Suma::execSUB_CREATE_REF); - addRecSignal(GSN_SUB_SYNC_CONF, &Suma::execSUB_SYNC_CONF); - addRecSignal(GSN_SUB_SYNC_REF, &Suma::execSUB_SYNC_REF); - addRecSignal(GSN_SUB_START_CONF, &Suma::execSUB_START_CONF); - addRecSignal(GSN_SUB_START_REF, &Suma::execSUB_START_REF); - - addRecSignal(GSN_SUMA_START_ME, &Suma::execSUMA_START_ME); - addRecSignal(GSN_SUMA_HANDOVER_REQ, &Suma::execSUMA_HANDOVER_REQ); - addRecSignal(GSN_SUMA_HANDOVER_CONF, &Suma::execSUMA_HANDOVER_CONF); - - addRecSignal(GSN_SUB_GCP_COMPLETE_ACC, - &Suma::execSUB_GCP_COMPLETE_ACC); } Suma::~Suma() diff --git a/ndb/src/kernel/error/ndbd_exit_codes.c b/ndb/src/kernel/error/ndbd_exit_codes.c index 257af4c5b1b..07b276346a0 100644 --- a/ndb/src/kernel/error/ndbd_exit_codes.c +++ b/ndb/src/kernel/error/ndbd_exit_codes.c @@ -54,6 +54,8 @@ static const ErrStruct errArray[] = {NDBD_EXIT_ARBIT_SHUTDOWN, XAE, "Node lost connection to other nodes and " "can not form a unpartitioned cluster, please investigate if there are " "error(s) on other node(s)"}, + {NDBD_EXIT_PARTITIONED_SHUTDOWN, XAE, "Partitioned cluster detected. " + "Please check if cluster is already running"}, {NDBD_EXIT_POINTER_NOTINRANGE, XIE, "Pointer too large"}, {NDBD_EXIT_SR_OTHERNODEFAILED, XRE, "Another node failed during system " "restart, please investigate error(s) on other node(s)"}, diff --git a/ndb/src/kernel/vm/RequestTracker.hpp b/ndb/src/kernel/vm/RequestTracker.hpp index 5fd1ae7255a..ac9ed85ae4b 100644 --- a/ndb/src/kernel/vm/RequestTracker.hpp +++ b/ndb/src/kernel/vm/RequestTracker.hpp @@ -26,12 +26,12 @@ public: void init() { m_confs.clear(); m_nRefs = 0; } template<typename SignalClass> - void init(SafeCounterManager& mgr, + bool init(SafeCounterManager& mgr, NodeReceiverGroup rg, Uint16 GSN, Uint32 senderData) { init(); SafeCounter tmp(mgr, m_sc); - tmp.init<SignalClass>(rg, GSN, senderData); + return tmp.init<SignalClass>(rg, GSN, senderData); } bool ignoreRef(SafeCounterManager& mgr, Uint32 nodeId) diff --git a/ndb/src/kernel/vm/SafeCounter.hpp b/ndb/src/kernel/vm/SafeCounter.hpp index 3ee5e076ab8..917a67f2508 100644 --- a/ndb/src/kernel/vm/SafeCounter.hpp +++ b/ndb/src/kernel/vm/SafeCounter.hpp @@ -230,10 +230,13 @@ inline bool SafeCounter::init(NodeReceiverGroup rg, Uint16 GSN, Uint32 senderData){ - bool b = init<Ref>(rg.m_block, GSN, senderData); - m_nodes = rg.m_nodes; - m_count = m_nodes.count(); - return b; + if (init<Ref>(rg.m_block, GSN, senderData)) + { + m_nodes = rg.m_nodes; + m_count = m_nodes.count(); + return true; + } + return false; } template<typename Ref> @@ -241,10 +244,13 @@ inline bool SafeCounter::init(NodeReceiverGroup rg, Uint32 senderData){ - bool b = init<Ref>(rg.m_block, Ref::GSN, senderData); - m_nodes = rg.m_nodes; - m_count = m_nodes.count(); - return b; + if (init<Ref>(rg.m_block, Ref::GSN, senderData)) + { + m_nodes = rg.m_nodes; + m_count = m_nodes.count(); + return true; + } + return false; } inline diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp index 3fe76e45322..b4787209d55 100644 --- a/ndb/src/kernel/vm/SimulatedBlock.cpp +++ b/ndb/src/kernel/vm/SimulatedBlock.cpp @@ -148,6 +148,7 @@ SimulatedBlock::installSimulatedBlockFunctions(){ a[GSN_FSREMOVEREF] = &SimulatedBlock::execFSREMOVEREF; a[GSN_FSSYNCREF] = &SimulatedBlock::execFSSYNCREF; a[GSN_FSAPPENDREF] = &SimulatedBlock::execFSAPPENDREF; + a[GSN_NODE_START_REP] = &SimulatedBlock::execNODE_START_REP; } void @@ -913,6 +914,20 @@ SimulatedBlock::execCONTINUE_FRAGMENTED(Signal * signal){ sendSignal(reference(), GSN_CONTINUE_FRAGMENTED, signal, 1, JBB); } +void +SimulatedBlock::execNODE_START_REP(Signal* signal) +{ + // common stuff for all blocks + + // block specific stuff by virtual method override (default empty) + exec_node_start_rep(signal); +} + +void +SimulatedBlock::exec_node_start_rep(Signal* signal) +{ +} + #ifdef VM_TRACE_TIME void SimulatedBlock::clearTimes() { diff --git a/ndb/src/kernel/vm/SimulatedBlock.hpp b/ndb/src/kernel/vm/SimulatedBlock.hpp index b7bd8c57ee8..4a3620a00ab 100644 --- a/ndb/src/kernel/vm/SimulatedBlock.hpp +++ b/ndb/src/kernel/vm/SimulatedBlock.hpp @@ -423,6 +423,8 @@ private: void execSIGNAL_DROPPED_REP(Signal* signal); void execCONTINUE_FRAGMENTED(Signal* signal); + void execNODE_START_REP(Signal* signal); + virtual void exec_node_start_rep(Signal* signal); Uint32 c_fragmentIdCounter; ArrayPool<FragmentInfo> c_fragmentInfoPool; diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp index 629ddf7a655..ab4f2b413b3 100644 --- a/ndb/src/mgmsrv/ConfigInfo.cpp +++ b/ndb/src/mgmsrv/ConfigInfo.cpp @@ -30,6 +30,7 @@ extern my_bool opt_core; #define MAX_LINE_LENGTH 255 #define KEY_INTERNAL 0 #define MAX_INT_RNIL 0xfffffeff +#define MAX_PORT_NO 65535 #define _STR_VALUE(x) #x #define STR_VALUE(x) _STR_VALUE(x) @@ -422,7 +423,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, UNDEFINED, "1", - STR_VALUE(MAX_INT_RNIL) }, + STR_VALUE(MAX_PORT_NO) }, { CFG_DB_NO_REPLICAS, @@ -1462,7 +1463,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, NDB_PORT, "0", - STR_VALUE(MAX_INT_RNIL) }, + STR_VALUE(MAX_PORT_NO) }, { KEY_INTERNAL, @@ -1474,7 +1475,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, UNDEFINED, "0", - STR_VALUE(MAX_INT_RNIL) }, + STR_VALUE(MAX_PORT_NO) }, { CFG_NODE_ARBIT_RANK, @@ -1616,7 +1617,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "0", - STR_VALUE(MAX_INT_RNIL) }, + STR_VALUE(MAX_PORT_NO) }, { CFG_TCP_SEND_BUFFER_SIZE, @@ -1722,7 +1723,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "0", - STR_VALUE(MAX_INT_RNIL) }, + STR_VALUE(MAX_PORT_NO) }, { CFG_SHM_SIGNUM, @@ -1944,7 +1945,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = { ConfigInfo::CI_INT, MANDATORY, "0", - STR_VALUE(MAX_INT_RNIL) }, + STR_VALUE(MAX_PORT_NO) }, { CFG_SCI_HOST1_ID_0, diff --git a/ndb/src/ndbapi/DictCache.cpp b/ndb/src/ndbapi/DictCache.cpp index a6a90fe3039..bb59c16fb7c 100644 --- a/ndb/src/ndbapi/DictCache.cpp +++ b/ndb/src/ndbapi/DictCache.cpp @@ -325,12 +325,15 @@ GlobalDictCache::invalidate_all() if (vers->size()) { TableVersion * ver = & vers->back(); - ver->m_impl->m_status = NdbDictionary::Object::Invalid; - ver->m_status = DROPPED; - if (ver->m_refCount == 0) + if (ver->m_status != RETREIVING) { - delete ver->m_impl; - vers->erase(vers->size() - 1); + ver->m_impl->m_status = NdbDictionary::Object::Invalid; + ver->m_status = DROPPED; + if (ver->m_refCount == 0) + { + delete ver->m_impl; + vers->erase(vers->size() - 1); + } } } curr = m_tableHash.getNext(curr); diff --git a/ndb/src/ndbapi/Makefile.am b/ndb/src/ndbapi/Makefile.am index 99b75ffbd53..522e78dd6e0 100644 --- a/ndb/src/ndbapi/Makefile.am +++ b/ndb/src/ndbapi/Makefile.am @@ -24,8 +24,6 @@ libndbapi_la_SOURCES = \ NdbOperationExec.cpp \ NdbScanOperation.cpp NdbScanFilter.cpp \ NdbIndexOperation.cpp \ - NdbEventOperation.cpp \ - NdbEventOperationImpl.cpp \ NdbApiSignal.cpp \ NdbRecAttr.cpp \ NdbUtil.cpp \ diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp index 56d68503825..9d1c78a5972 100644 --- a/ndb/src/ndbapi/Ndb.cpp +++ b/ndb/src/ndbapi/Ndb.cpp @@ -28,7 +28,6 @@ Name: Ndb.cpp #include "NdbImpl.hpp" #include <NdbOperation.hpp> #include <NdbTransaction.hpp> -#include <NdbEventOperation.hpp> #include <NdbRecAttr.hpp> #include <md5_hash.hpp> #include <NdbSleep.h> @@ -1300,51 +1299,6 @@ Ndb::getSchemaFromInternalName(const char * internalName) return ret; } -NdbEventOperation* Ndb::createEventOperation(const char* eventName, - const int bufferLength) -{ - NdbEventOperation* tOp; - - tOp = new NdbEventOperation(this, eventName, bufferLength); - - if (tOp == 0) - { - theError.code= 4000; - return NULL; - } - - if (tOp->getState() != NdbEventOperation::EO_CREATED) { - theError.code= tOp->getNdbError().code; - delete tOp; - tOp = NULL; - } - - //now we have to look up this event in dict - - return tOp; -} - -int Ndb::dropEventOperation(NdbEventOperation* op) { - delete op; - return 0; -} - -NdbGlobalEventBufferHandle* Ndb::getGlobalEventBufferHandle() -{ - return theGlobalEventBufferHandle; -} - -//void Ndb::monitorEvent(NdbEventOperation *op, NdbEventCallback cb, void* rs) -//{ -//} - -int -Ndb::pollEvents(int aMillisecondNumber) -{ - return NdbEventOperation::wait(theGlobalEventBufferHandle, - aMillisecondNumber); -} - #ifdef VM_TRACE #include <NdbMutex.h> extern NdbMutex *ndb_print_state_mutex; diff --git a/ndb/src/ndbapi/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp index a0a3dd431b8..6c721b76ba0 100644 --- a/ndb/src/ndbapi/NdbDictionary.cpp +++ b/ndb/src/ndbapi/NdbDictionary.cpp @@ -611,132 +611,6 @@ NdbDictionary::Index::getObjectVersion() const { } /***************************************************************** - * Event facade - */ -NdbDictionary::Event::Event(const char * name) - : m_impl(* new NdbEventImpl(* this)) -{ - setName(name); -} - -NdbDictionary::Event::Event(const char * name, const Table& table) - : m_impl(* new NdbEventImpl(* this)) -{ - setName(name); - setTable(table); -} - -NdbDictionary::Event::Event(NdbEventImpl & impl) - : m_impl(impl) -{ -} - -NdbDictionary::Event::~Event() -{ - NdbEventImpl * tmp = &m_impl; - if(this != tmp){ - delete tmp; - } -} - -void -NdbDictionary::Event::setName(const char * name) -{ - m_impl.setName(name); -} - -const char * -NdbDictionary::Event::getName() const -{ - return m_impl.getName(); -} - -void -NdbDictionary::Event::setTable(const Table& table) -{ - m_impl.setTable(table); -} - -void -NdbDictionary::Event::setTable(const char * table) -{ - m_impl.setTable(table); -} - -const char* -NdbDictionary::Event::getTableName() const -{ - return m_impl.getTableName(); -} - -void -NdbDictionary::Event::addTableEvent(const TableEvent t) -{ - m_impl.addTableEvent(t); -} - -void -NdbDictionary::Event::setDurability(EventDurability d) -{ - m_impl.setDurability(d); -} - -NdbDictionary::Event::EventDurability -NdbDictionary::Event::getDurability() const -{ - return m_impl.getDurability(); -} - -void -NdbDictionary::Event::addColumn(const Column & c){ - NdbColumnImpl* col = new NdbColumnImpl; - (* col) = NdbColumnImpl::getImpl(c); - m_impl.m_columns.push_back(col); -} - -void -NdbDictionary::Event::addEventColumn(unsigned attrId) -{ - m_impl.m_attrIds.push_back(attrId); -} - -void -NdbDictionary::Event::addEventColumn(const char * name) -{ - const Column c(name); - addColumn(c); -} - -void -NdbDictionary::Event::addEventColumns(int n, const char ** names) -{ - for (int i = 0; i < n; i++) - addEventColumn(names[i]); -} - -int NdbDictionary::Event::getNoOfEventColumns() const -{ - return m_impl.getNoOfEventColumns(); -} - -NdbDictionary::Object::Status -NdbDictionary::Event::getObjectStatus() const -{ - return m_impl.m_status; -} - -int -NdbDictionary::Event::getObjectVersion() const -{ - return m_impl.m_version; -} - -void NdbDictionary::Event::print() -{ - m_impl.print(); -} - -/***************************************************************** * Dictionary facade */ NdbDictionary::Dictionary::Dictionary(Ndb & ndb) @@ -885,28 +759,6 @@ NdbDictionary::Dictionary::getIndexTable(const char * indexName, return 0; } - -int -NdbDictionary::Dictionary::createEvent(const Event & ev) -{ - return m_impl.createEvent(NdbEventImpl::getImpl(ev)); -} - -int -NdbDictionary::Dictionary::dropEvent(const char * eventName) -{ - return m_impl.dropEvent(eventName); -} - -const NdbDictionary::Event * -NdbDictionary::Dictionary::getEvent(const char * eventName) -{ - NdbEventImpl * t = m_impl.getEvent(eventName); - if(t) - return t->m_facade; - return 0; -} - int NdbDictionary::Dictionary::listObjects(List& list, Object::Type type) { diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index ce348b616c9..b91df24d8d7 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -32,8 +32,6 @@ #include <SimpleProperties.hpp> #include <Bitmask.hpp> #include <AttributeList.hpp> -#include <NdbEventOperation.hpp> -#include "NdbEventOperationImpl.hpp" #include <NdbBlob.hpp> #include "NdbBlobImpl.hpp" #include <AttributeHeader.hpp> @@ -586,99 +584,6 @@ NdbIndexImpl::getIndexTable() const } /** - * NdbEventImpl - */ - -NdbEventImpl::NdbEventImpl() : - NdbDictionary::Event(* this), - m_facade(this) -{ - init(); -} - -NdbEventImpl::NdbEventImpl(NdbDictionary::Event & f) : - NdbDictionary::Event(* this), - m_facade(&f) -{ - init(); -} - -void NdbEventImpl::init() -{ - m_eventId= RNIL; - m_eventKey= RNIL; - m_tableId= RNIL; - mi_type= 0; - m_dur= NdbDictionary::Event::ED_UNDEFINED; - m_tableImpl= NULL; - m_bufferId= RNIL; - eventOp= NULL; -} - -NdbEventImpl::~NdbEventImpl() -{ - for (unsigned i = 0; i < m_columns.size(); i++) - delete m_columns[i]; -} - -void NdbEventImpl::setName(const char * name) -{ - m_externalName.assign(name); -} - -const char *NdbEventImpl::getName() const -{ - return m_externalName.c_str(); -} - -void -NdbEventImpl::setTable(const NdbDictionary::Table& table) -{ - m_tableImpl= &NdbTableImpl::getImpl(table); - m_tableName.assign(m_tableImpl->getName()); -} - -void -NdbEventImpl::setTable(const char * table) -{ - m_tableName.assign(table); -} - -const char * -NdbEventImpl::getTableName() const -{ - return m_tableName.c_str(); -} - -void -NdbEventImpl::addTableEvent(const NdbDictionary::Event::TableEvent t = NdbDictionary::Event::TE_ALL) -{ - switch (t) { - case NdbDictionary::Event::TE_INSERT : mi_type |= 1; break; - case NdbDictionary::Event::TE_DELETE : mi_type |= 2; break; - case NdbDictionary::Event::TE_UPDATE : mi_type |= 4; break; - default: mi_type = 4 | 2 | 1; // all types - } -} - -void -NdbEventImpl::setDurability(NdbDictionary::Event::EventDurability d) -{ - m_dur = d; -} - -NdbDictionary::Event::EventDurability -NdbEventImpl::getDurability() const -{ - return m_dur; -} - -int NdbEventImpl::getNoOfEventColumns() const -{ - return m_attrIds.size() + m_columns.size(); -} - -/** * NdbDictionaryImpl */ @@ -901,36 +806,6 @@ NdbDictInterface::execSignal(void* dictImpl, case GSN_DROP_INDX_CONF: tmp->execDROP_INDX_CONF(signal, ptr); break; - case GSN_CREATE_EVNT_REF: - tmp->execCREATE_EVNT_REF(signal, ptr); - break; - case GSN_CREATE_EVNT_CONF: - tmp->execCREATE_EVNT_CONF(signal, ptr); - break; - case GSN_SUB_START_CONF: - tmp->execSUB_START_CONF(signal, ptr); - break; - case GSN_SUB_START_REF: - tmp->execSUB_START_REF(signal, ptr); - break; - case GSN_SUB_TABLE_DATA: - tmp->execSUB_TABLE_DATA(signal, ptr); - break; - case GSN_SUB_GCP_COMPLETE_REP: - tmp->execSUB_GCP_COMPLETE_REP(signal, ptr); - break; - case GSN_SUB_STOP_CONF: - tmp->execSUB_STOP_CONF(signal, ptr); - break; - case GSN_SUB_STOP_REF: - tmp->execSUB_STOP_REF(signal, ptr); - break; - case GSN_DROP_EVNT_REF: - tmp->execDROP_EVNT_REF(signal, ptr); - break; - case GSN_DROP_EVNT_CONF: - tmp->execDROP_EVNT_CONF(signal, ptr); - break; case GSN_LIST_TABLES_CONF: tmp->execLIST_TABLES_CONF(signal, ptr); break; @@ -2385,616 +2260,6 @@ NdbDictInterface::execDROP_INDX_REF(NdbApiSignal * signal, } /***************************************************************** - * Create event - */ - -int -NdbDictionaryImpl::createEvent(NdbEventImpl & evnt) -{ - int i; - NdbTableImpl* tab = getTable(evnt.getTableName()); - - if(tab == 0){ -#ifdef EVENT_DEBUG - ndbout_c("NdbDictionaryImpl::createEvent: table not found: %s", - evnt.getTableName()); -#endif - return -1; - } - - evnt.m_tableId = tab->m_tableId; - evnt.m_tableImpl = tab; -#ifdef EVENT_DEBUG - ndbout_c("Event on tableId=%d", evnt.m_tableId); -#endif - - NdbTableImpl &table = *evnt.m_tableImpl; - - - int attributeList_sz = evnt.m_attrIds.size(); - - for (i = 0; i < attributeList_sz; i++) { - NdbColumnImpl *col_impl = table.getColumn(evnt.m_attrIds[i]); - if (col_impl) { - evnt.m_facade->addColumn(*(col_impl->m_facade)); - } else { - ndbout_c("Attr id %u in table %s not found", evnt.m_attrIds[i], - evnt.getTableName()); - m_error.code= 4713; - return -1; - } - } - - evnt.m_attrIds.clear(); - - attributeList_sz = evnt.m_columns.size(); -#ifdef EVENT_DEBUG - ndbout_c("creating event %s", evnt.m_externalName.c_str()); - ndbout_c("no of columns %d", evnt.m_columns.size()); -#endif - int pk_count = 0; - evnt.m_attrListBitmask.clear(); - - for(i = 0; i<attributeList_sz; i++){ - const NdbColumnImpl* col = - table.getColumn(evnt.m_columns[i]->m_name.c_str()); - if(col == 0){ - m_error.code= 4247; - return -1; - } - // Copy column definition - *evnt.m_columns[i] = *col; - - if(col->m_pk){ - pk_count++; - } - - evnt.m_attrListBitmask.set(col->m_attrId); - } - - // Sort index attributes according to primary table (using insertion sort) - for(i = 1; i < attributeList_sz; i++) { - NdbColumnImpl* temp = evnt.m_columns[i]; - unsigned int j = i; - while((j > 0) && (evnt.m_columns[j - 1]->m_attrId > temp->m_attrId)) { - evnt.m_columns[j] = evnt.m_columns[j - 1]; - j--; - } - evnt.m_columns[j] = temp; - } - // Check for illegal duplicate attributes - for(i = 1; i<attributeList_sz; i++) { - if (evnt.m_columns[i-1]->m_attrId == evnt.m_columns[i]->m_attrId) { - m_error.code= 4258; - return -1; - } - } - -#ifdef EVENT_DEBUG - char buf[128] = {0}; - evnt.m_attrListBitmask.getText(buf); - ndbout_c("createEvent: mask = %s", buf); -#endif - - // NdbDictInterface m_receiver; - return m_receiver.createEvent(m_ndb, evnt, 0 /* getFlag unset */); -} - -int -NdbDictInterface::createEvent(class Ndb & ndb, - NdbEventImpl & evnt, - int getFlag) -{ - NdbApiSignal tSignal(m_reference); - tSignal.theReceiversBlockNumber = DBDICT; - tSignal.theVerId_signalNumber = GSN_CREATE_EVNT_REQ; - if (getFlag) - tSignal.theLength = CreateEvntReq::SignalLengthGet; - else - tSignal.theLength = CreateEvntReq::SignalLengthCreate; - - CreateEvntReq * const req = CAST_PTR(CreateEvntReq, tSignal.getDataPtrSend()); - - req->setUserRef(m_reference); - req->setUserData(0); - - if (getFlag) { - // getting event from Dictionary - req->setRequestType(CreateEvntReq::RT_USER_GET); - } else { - // creating event in Dictionary - req->setRequestType(CreateEvntReq::RT_USER_CREATE); - req->setTableId(evnt.m_tableId); - req->setAttrListBitmask(evnt.m_attrListBitmask); - req->setEventType(evnt.mi_type); - } - - UtilBufferWriter w(m_buffer); - - const size_t len = strlen(evnt.m_externalName.c_str()) + 1; - if(len > MAX_TAB_NAME_SIZE) { - m_error.code= 4241; - return -1; - } - - w.add(SimpleProperties::StringValue, evnt.m_externalName.c_str()); - - if (getFlag == 0) - { - const BaseString internal_tabname( - ndb.internalize_table_name(evnt.m_tableName.c_str())); - w.add(SimpleProperties::StringValue, - internal_tabname.c_str()); - } - - LinearSectionPtr ptr[1]; - ptr[0].p = (Uint32*)m_buffer.get_data(); - ptr[0].sz = (m_buffer.length()+3) >> 2; - - int ret = createEvent(&tSignal, ptr, 1); - - if (ret) { - return ret; - } - - char *dataPtr = (char *)m_buffer.get_data(); - unsigned int lenCreateEvntConf = *((unsigned int *)dataPtr); - dataPtr += sizeof(lenCreateEvntConf); - CreateEvntConf const * evntConf = (CreateEvntConf *)dataPtr; - dataPtr += lenCreateEvntConf; - - // NdbEventImpl *evntImpl = (NdbEventImpl *)evntConf->getUserData(); - - if (getFlag) { - evnt.m_tableId = evntConf->getTableId(); - evnt.m_attrListBitmask = evntConf->getAttrListBitmask(); - evnt.mi_type = evntConf->getEventType(); - evnt.setTable(dataPtr); - } else { - if (evnt.m_tableId != evntConf->getTableId() || - //evnt.m_attrListBitmask != evntConf->getAttrListBitmask() || - evnt.mi_type != evntConf->getEventType()) { - ndbout_c("ERROR*************"); - return 1; - } - } - - evnt.m_eventId = evntConf->getEventId(); - evnt.m_eventKey = evntConf->getEventKey(); - - return ret; -} - -int -NdbDictInterface::createEvent(NdbApiSignal* signal, - LinearSectionPtr ptr[3], int noLSP) -{ - const int noErrCodes = 1; - int errCodes[noErrCodes] = {CreateEvntRef::Busy}; - return dictSignal(signal,ptr,noLSP, - 1 /*use masternode id*/, - 100, - WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/, - -1, - errCodes,noErrCodes, CreateEvntRef::Temporary); -} - -int -NdbDictionaryImpl::executeSubscribeEvent(NdbEventImpl & ev) -{ - // NdbDictInterface m_receiver; - return m_receiver.executeSubscribeEvent(m_ndb, ev); -} - -int -NdbDictInterface::executeSubscribeEvent(class Ndb & ndb, - NdbEventImpl & evnt) -{ - DBUG_ENTER("NdbDictInterface::executeSubscribeEvent"); - NdbApiSignal tSignal(m_reference); - // tSignal.theReceiversBlockNumber = SUMA; - tSignal.theReceiversBlockNumber = DBDICT; - tSignal.theVerId_signalNumber = GSN_SUB_START_REQ; - tSignal.theLength = SubStartReq::SignalLength2; - - SubStartReq * sumaStart = CAST_PTR(SubStartReq, tSignal.getDataPtrSend()); - - sumaStart->subscriptionId = evnt.m_eventId; - sumaStart->subscriptionKey = evnt.m_eventKey; - sumaStart->part = SubscriptionData::TableData; - sumaStart->subscriberData = evnt.m_bufferId & 0xFF; - sumaStart->subscriberRef = m_reference; - - DBUG_RETURN(executeSubscribeEvent(&tSignal, NULL)); -} - -int -NdbDictInterface::executeSubscribeEvent(NdbApiSignal* signal, - LinearSectionPtr ptr[3]) -{ - return dictSignal(signal,NULL,0, - 1 /*use masternode id*/, - 100, - WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/, - -1, - NULL,0); -} - -int -NdbDictionaryImpl::stopSubscribeEvent(NdbEventImpl & ev) -{ - // NdbDictInterface m_receiver; - return m_receiver.stopSubscribeEvent(m_ndb, ev); -} - -int -NdbDictInterface::stopSubscribeEvent(class Ndb & ndb, - NdbEventImpl & evnt) -{ - DBUG_ENTER("NdbDictInterface::stopSubscribeEvent"); - - NdbApiSignal tSignal(m_reference); - // tSignal.theReceiversBlockNumber = SUMA; - tSignal.theReceiversBlockNumber = DBDICT; - tSignal.theVerId_signalNumber = GSN_SUB_STOP_REQ; - tSignal.theLength = SubStopReq::SignalLength; - - SubStopReq * sumaStop = CAST_PTR(SubStopReq, tSignal.getDataPtrSend()); - - sumaStop->subscriptionId = evnt.m_eventId; - sumaStop->subscriptionKey = evnt.m_eventKey; - sumaStop->subscriberData = evnt.m_bufferId & 0xFF; - sumaStop->part = (Uint32) SubscriptionData::TableData; - sumaStop->subscriberRef = m_reference; - - DBUG_RETURN(stopSubscribeEvent(&tSignal, NULL)); -} - -int -NdbDictInterface::stopSubscribeEvent(NdbApiSignal* signal, - LinearSectionPtr ptr[3]) -{ - return dictSignal(signal,NULL,0, - 1 /*use masternode id*/, - 100, - WAIT_CREATE_INDX_REQ /*WAIT_SUB_STOP__REQ*/, - -1, - NULL,0); -} - -NdbEventImpl * -NdbDictionaryImpl::getEvent(const char * eventName) -{ - NdbEventImpl *ev = new NdbEventImpl(); - - if (ev == NULL) { - return NULL; - } - - ev->setName(eventName); - - int ret = m_receiver.createEvent(m_ndb, *ev, 1 /* getFlag set */); - - if (ret) { - delete ev; - return NULL; - } - - // We only have the table name with internal name - ev->setTable(m_ndb.externalizeTableName(ev->getTableName())); - ev->m_tableImpl = getTable(ev->getTableName()); - - // get the columns from the attrListBitmask - - NdbTableImpl &table = *ev->m_tableImpl; - AttributeMask & mask = ev->m_attrListBitmask; - int attributeList_sz = mask.count(); - int id = -1; - -#ifdef EVENT_DEBUG - ndbout_c("NdbDictionaryImpl::getEvent attributeList_sz = %d", - attributeList_sz); - char buf[128] = {0}; - mask.getText(buf); - ndbout_c("mask = %s", buf); -#endif - - for(int i = 0; i < attributeList_sz; i++) { - id++; while (!mask.get(id)) id++; - - const NdbColumnImpl* col = table.getColumn(id); - if(col == 0) { -#ifdef EVENT_DEBUG - ndbout_c("NdbDictionaryImpl::getEvent could not find column id %d", id); -#endif - m_error.code= 4247; - delete ev; - return NULL; - } - NdbColumnImpl* new_col = new NdbColumnImpl; - // Copy column definition - *new_col = *col; - - ev->m_columns.push_back(new_col); - } - - return ev; -} - -void -NdbDictInterface::execCREATE_EVNT_CONF(NdbApiSignal * signal, - LinearSectionPtr ptr[3]) -{ - DBUG_ENTER("NdbDictInterface::execCREATE_EVNT_CONF"); - - m_buffer.clear(); - unsigned int len = signal->getLength() << 2; - m_buffer.append((char *)&len, sizeof(len)); - m_buffer.append(signal->getDataPtr(), len); - - if (signal->m_noOfSections > 0) { - m_buffer.append((char *)ptr[0].p, strlen((char *)ptr[0].p)+1); - } - - const CreateEvntConf * const createEvntConf= - CAST_CONSTPTR(CreateEvntConf, signal->getDataPtr()); - - Uint32 subscriptionId = createEvntConf->getEventId(); - Uint32 subscriptionKey = createEvntConf->getEventKey(); - - DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d", - subscriptionId,subscriptionKey)); - m_waiter.signal(NO_WAIT); - DBUG_VOID_RETURN; -} - -void -NdbDictInterface::execCREATE_EVNT_REF(NdbApiSignal * signal, - LinearSectionPtr ptr[3]) -{ - DBUG_ENTER("NdbDictInterface::execCREATE_EVNT_REF"); - - const CreateEvntRef* const ref= - CAST_CONSTPTR(CreateEvntRef, signal->getDataPtr()); - m_error.code= ref->getErrorCode(); - DBUG_PRINT("error",("error=%d,line=%d,node=%d",ref->getErrorCode(), - ref->getErrorLine(),ref->getErrorNode())); - m_waiter.signal(NO_WAIT); - DBUG_VOID_RETURN; -} - -void -NdbDictInterface::execSUB_STOP_CONF(NdbApiSignal * signal, - LinearSectionPtr ptr[3]) -{ - DBUG_ENTER("NdbDictInterface::execSUB_STOP_CONF"); - const SubStopConf * const subStopConf= - CAST_CONSTPTR(SubStopConf, signal->getDataPtr()); - - Uint32 subscriptionId = subStopConf->subscriptionId; - Uint32 subscriptionKey = subStopConf->subscriptionKey; - Uint32 subscriberData = subStopConf->subscriberData; - - DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d", - subscriptionId,subscriptionKey,subscriberData)); - m_waiter.signal(NO_WAIT); - DBUG_VOID_RETURN; -} - -void -NdbDictInterface::execSUB_STOP_REF(NdbApiSignal * signal, - LinearSectionPtr ptr[3]) -{ - DBUG_ENTER("NdbDictInterface::execSUB_STOP_REF"); - const SubStopRef * const subStopRef= - CAST_CONSTPTR(SubStopRef, signal->getDataPtr()); - - Uint32 subscriptionId = subStopRef->subscriptionId; - Uint32 subscriptionKey = subStopRef->subscriptionKey; - Uint32 subscriberData = subStopRef->subscriberData; - m_error.code= subStopRef->errorCode; - - DBUG_PRINT("error",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d,error=%d", - subscriptionId,subscriptionKey,subscriberData,m_error.code)); - m_waiter.signal(NO_WAIT); - DBUG_VOID_RETURN; -} - -void -NdbDictInterface::execSUB_START_CONF(NdbApiSignal * signal, - LinearSectionPtr ptr[3]) -{ - DBUG_ENTER("NdbDictInterface::execSUB_START_CONF"); - const SubStartConf * const subStartConf= - CAST_CONSTPTR(SubStartConf, signal->getDataPtr()); - - Uint32 subscriptionId = subStartConf->subscriptionId; - Uint32 subscriptionKey = subStartConf->subscriptionKey; - SubscriptionData::Part part = - (SubscriptionData::Part)subStartConf->part; - Uint32 subscriberData = subStartConf->subscriberData; - - switch(part) { - case SubscriptionData::MetaData: { - DBUG_PRINT("error",("SubscriptionData::MetaData")); - m_error.code= 1; - break; - } - case SubscriptionData::TableData: { - DBUG_PRINT("info",("SubscriptionData::TableData")); - break; - } - default: { - DBUG_PRINT("error",("wrong data")); - m_error.code= 2; - break; - } - } - DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d", - subscriptionId,subscriptionKey,subscriberData)); - m_waiter.signal(NO_WAIT); - DBUG_VOID_RETURN; -} - -void -NdbDictInterface::execSUB_START_REF(NdbApiSignal * signal, - LinearSectionPtr ptr[3]) -{ - DBUG_ENTER("NdbDictInterface::execSUB_START_REF"); - const SubStartRef * const subStartRef= - CAST_CONSTPTR(SubStartRef, signal->getDataPtr()); - m_error.code= subStartRef->errorCode; - m_waiter.signal(NO_WAIT); - DBUG_VOID_RETURN; -} -void -NdbDictInterface::execSUB_GCP_COMPLETE_REP(NdbApiSignal * signal, - LinearSectionPtr ptr[3]) -{ - const SubGcpCompleteRep * const rep= - CAST_CONSTPTR(SubGcpCompleteRep, signal->getDataPtr()); - - const Uint32 gci = rep->gci; - // const Uint32 senderRef = rep->senderRef; - const Uint32 subscriberData = rep->subscriberData; - - const Uint32 bufferId = subscriberData; - - const Uint32 ref = signal->theSendersBlockRef; - - NdbApiSignal tSignal(m_reference); - SubGcpCompleteAcc * acc= - CAST_PTR(SubGcpCompleteAcc, tSignal.getDataPtrSend()); - - acc->rep = *rep; - - tSignal.theReceiversBlockNumber = refToBlock(ref); - tSignal.theVerId_signalNumber = GSN_SUB_GCP_COMPLETE_ACC; - tSignal.theLength = SubGcpCompleteAcc::SignalLength; - - Uint32 aNodeId = refToNode(ref); - - // m_transporter->lock_mutex(); - int r; - r = m_transporter->sendSignal(&tSignal, aNodeId); - // m_transporter->unlock_mutex(); - - NdbGlobalEventBufferHandle::latestGCI(bufferId, gci); -} - -void -NdbDictInterface::execSUB_TABLE_DATA(NdbApiSignal * signal, - LinearSectionPtr ptr[3]) -{ -#ifdef EVENT_DEBUG - const char * FNAME = "NdbDictInterface::execSUB_TABLE_DATA"; -#endif - //TODO - const SubTableData * const sdata = CAST_CONSTPTR(SubTableData, signal->getDataPtr()); - - // const Uint32 gci = sdata->gci; - // const Uint32 operation = sdata->operation; - // const Uint32 tableId = sdata->tableId; - // const Uint32 noOfAttrs = sdata->noOfAttributes; - // const Uint32 dataLen = sdata->dataSize; - const Uint32 subscriberData = sdata->subscriberData; - // const Uint32 logType = sdata->logType; - - for (int i=signal->m_noOfSections;i < 3; i++) { - ptr[i].p = NULL; - ptr[i].sz = 0; - } -#ifdef EVENT_DEBUG - ndbout_c("%s: senderData %d, gci %d, operation %d, tableId %d, noOfAttrs %d, dataLen %d", - FNAME, subscriberData, gci, operation, tableId, noOfAttrs, dataLen); - ndbout_c("ptr[0] %u %u ptr[1] %u %u ptr[2] %u %u\n", - ptr[0].p,ptr[0].sz,ptr[1].p,ptr[1].sz,ptr[2].p,ptr[2].sz); -#endif - const Uint32 bufferId = subscriberData; - - NdbGlobalEventBufferHandle::insertDataL(bufferId, - sdata, ptr); -} - -/***************************************************************** - * Drop event - */ -int -NdbDictionaryImpl::dropEvent(const char * eventName) -{ - NdbEventImpl *ev= new NdbEventImpl(); - ev->setName(eventName); - int ret= m_receiver.dropEvent(*ev); - delete ev; - - // printf("__________________RET %u\n", ret); - return ret; -} - -int -NdbDictInterface::dropEvent(const NdbEventImpl &evnt) -{ - NdbApiSignal tSignal(m_reference); - tSignal.theReceiversBlockNumber = DBDICT; - tSignal.theVerId_signalNumber = GSN_DROP_EVNT_REQ; - tSignal.theLength = DropEvntReq::SignalLength; - - DropEvntReq * const req = CAST_PTR(DropEvntReq, tSignal.getDataPtrSend()); - - req->setUserRef(m_reference); - req->setUserData(0); - - UtilBufferWriter w(m_buffer); - - w.add(SimpleProperties::StringValue, evnt.m_externalName.c_str()); - - LinearSectionPtr ptr[1]; - ptr[0].p = (Uint32*)m_buffer.get_data(); - ptr[0].sz = (m_buffer.length()+3) >> 2; - - return dropEvent(&tSignal, ptr, 1); -} - -int -NdbDictInterface::dropEvent(NdbApiSignal* signal, - LinearSectionPtr ptr[3], int noLSP) -{ - //TODO - const int noErrCodes = 1; - int errCodes[noErrCodes] = {DropEvntRef::Busy}; - return dictSignal(signal,ptr,noLSP, - 1 /*use masternode id*/, - 100, - WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/, - -1, - errCodes,noErrCodes, DropEvntRef::Temporary); -} -void -NdbDictInterface::execDROP_EVNT_CONF(NdbApiSignal * signal, - LinearSectionPtr ptr[3]) -{ - DBUG_ENTER("NdbDictInterface::execDROP_EVNT_CONF"); - m_waiter.signal(NO_WAIT); - DBUG_VOID_RETURN; -} - -void -NdbDictInterface::execDROP_EVNT_REF(NdbApiSignal * signal, - LinearSectionPtr ptr[3]) -{ - DBUG_ENTER("NdbDictInterface::execDROP_EVNT_REF"); - const DropEvntRef* const ref= - CAST_CONSTPTR(DropEvntRef, signal->getDataPtr()); - m_error.code= ref->getErrorCode(); - - DBUG_PRINT("info",("ErrorCode=%u Errorline=%u ErrorNode=%u", - ref->getErrorCode(), ref->getErrorLine(), ref->getErrorNode())); - - m_waiter.signal(NO_WAIT); - DBUG_VOID_RETURN; -} - -/***************************************************************** * List objects or indexes */ int diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp index dfccf120228..6a86ee44bfb 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp @@ -208,55 +208,6 @@ public: NdbDictionary::Index * m_facade; }; -class NdbEventImpl : public NdbDictionary::Event, public NdbDictObjectImpl { -public: - NdbEventImpl(); - NdbEventImpl(NdbDictionary::Event &); - ~NdbEventImpl(); - - void init(); - void setName(const char * name); - const char * getName() const; - void setTable(const NdbDictionary::Table& table); - void setTable(const char * table); - const char * getTableName() const; - void addTableEvent(const NdbDictionary::Event::TableEvent t); - void setDurability(NdbDictionary::Event::EventDurability d); - NdbDictionary::Event::EventDurability getDurability() const; - void addEventColumn(const NdbColumnImpl &c); - int getNoOfEventColumns() const; - - void print() { - ndbout_c("NdbEventImpl: id=%d, key=%d", - m_eventId, - m_eventKey); - }; - - Uint32 m_eventId; - Uint32 m_eventKey; - Uint32 m_tableId; - AttributeMask m_attrListBitmask; - //BaseString m_internalName; - BaseString m_externalName; - Uint32 mi_type; - NdbDictionary::Event::EventDurability m_dur; - - - NdbTableImpl *m_tableImpl; - BaseString m_tableName; - Vector<NdbColumnImpl *> m_columns; - Vector<unsigned> m_attrIds; - - int m_bufferId; - - NdbEventOperation *eventOp; - - static NdbEventImpl & getImpl(NdbDictionary::Event & t); - static NdbEventImpl & getImpl(const NdbDictionary::Event & t); - NdbDictionary::Event * m_facade; -}; - - class NdbDictInterface { public: NdbDictInterface(NdbError& err) : m_error(err) { @@ -294,24 +245,12 @@ public: const NdbTableImpl &); int createIndex(NdbApiSignal* signal, LinearSectionPtr ptr[3]); - int createEvent(class Ndb & ndb, NdbEventImpl &, int getFlag); - int createEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3], int noLSP); - int dropTable(const NdbTableImpl &); int dropTable(NdbApiSignal* signal, LinearSectionPtr ptr[3]); int dropIndex(const NdbIndexImpl &, const NdbTableImpl &); int dropIndex(NdbApiSignal* signal, LinearSectionPtr ptr[3]); - int dropEvent(const NdbEventImpl &); - int dropEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3], int noLSP); - - int executeSubscribeEvent(class Ndb & ndb, NdbEventImpl &); - int executeSubscribeEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3]); - - int stopSubscribeEvent(class Ndb & ndb, NdbEventImpl &); - int stopSubscribeEvent(NdbApiSignal* signal, LinearSectionPtr ptr[3]); - int listObjects(NdbDictionary::Dictionary::List& list, Uint32 requestData, bool fullyQualifiedNames); int listObjects(NdbApiSignal* signal); @@ -357,17 +296,6 @@ private: void execDROP_INDX_REF(NdbApiSignal *, LinearSectionPtr ptr[3]); void execDROP_INDX_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]); - void execCREATE_EVNT_REF(NdbApiSignal *, LinearSectionPtr ptr[3]); - void execCREATE_EVNT_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]); - void execSUB_START_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]); - void execSUB_START_REF(NdbApiSignal *, LinearSectionPtr ptr[3]); - void execSUB_TABLE_DATA(NdbApiSignal *, LinearSectionPtr ptr[3]); - void execSUB_GCP_COMPLETE_REP(NdbApiSignal *, LinearSectionPtr ptr[3]); - void execSUB_STOP_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]); - void execSUB_STOP_REF(NdbApiSignal *, LinearSectionPtr ptr[3]); - void execDROP_EVNT_REF(NdbApiSignal *, LinearSectionPtr ptr[3]); - void execDROP_EVNT_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]); - void execDROP_TABLE_REF(NdbApiSignal *, LinearSectionPtr ptr[3]); void execDROP_TABLE_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]); void execLIST_TABLES_CONF(NdbApiSignal *, LinearSectionPtr ptr[3]); @@ -402,12 +330,6 @@ public: NdbTableImpl * getIndexTable(NdbIndexImpl * index, NdbTableImpl * table); - int createEvent(NdbEventImpl &); - int dropEvent(const char * eventName); - - int executeSubscribeEvent(NdbEventImpl &); - int stopSubscribeEvent(NdbEventImpl &); - int listObjects(List& list, NdbDictionary::Object::Type type); int listIndexes(List& list, Uint32 indexId); @@ -418,8 +340,6 @@ public: const char * tableName); NdbIndexImpl * getIndex(const char * indexName, NdbTableImpl * table); - NdbEventImpl * getEvent(const char * eventName); - NdbEventImpl * getEventImpl(const char * internalName); const NdbError & getNdbError() const; NdbError m_error; @@ -441,18 +361,6 @@ private: }; inline -NdbEventImpl & -NdbEventImpl::getImpl(const NdbDictionary::Event & t){ - return t.m_impl; -} - -inline -NdbEventImpl & -NdbEventImpl::getImpl(NdbDictionary::Event & t){ - return t.m_impl; -} - -inline NdbColumnImpl & NdbColumnImpl::getImpl(NdbDictionary::Column & t){ return t.m_impl; diff --git a/ndb/src/ndbapi/NdbReceiver.cpp b/ndb/src/ndbapi/NdbReceiver.cpp index df16ae66915..62119880076 100644 --- a/ndb/src/ndbapi/NdbReceiver.cpp +++ b/ndb/src/ndbapi/NdbReceiver.cpp @@ -121,7 +121,15 @@ NdbReceiver::calculate_batch_size(Uint32 key_size, * no more than MAX_SCAN_BATCH_SIZE is sent from all nodes in total per * batch. */ - batch_byte_size= max_batch_byte_size; + if (batch_size == 0) + { + batch_byte_size= max_batch_byte_size; + } + else + { + batch_byte_size= batch_size * tot_size; + } + if (batch_byte_size * parallelism > max_scan_batch_size) { batch_byte_size= max_scan_batch_size / parallelism; } diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index 7d0712e117d..90e3a63c53d 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -117,7 +117,8 @@ NdbScanOperation::init(const NdbTableImpl* tab, NdbTransaction* myConnection) int NdbScanOperation::readTuples(NdbScanOperation::LockMode lm, Uint32 scan_flags, - Uint32 parallel) + Uint32 parallel, + Uint32 batch) { m_ordered = m_descending = false; Uint32 fragCount = m_currentTable->m_fragmentCount; @@ -181,9 +182,12 @@ NdbScanOperation::readTuples(NdbScanOperation::LockMode lm, bool tupScan = (scan_flags & SF_TupScan); if (tupScan && rangeScan) tupScan = false; - - theParallelism = parallel; + if (rangeScan && (scan_flags & SF_OrderBy)) + parallel = fragCount; + + theParallelism = parallel; + if(fix_receivers(parallel) == -1){ setErrorCodeAbort(4000); return -1; @@ -202,6 +206,7 @@ NdbScanOperation::readTuples(NdbScanOperation::LockMode lm, req->tableSchemaVersion = m_accessTable->m_version; req->storedProcId = 0xFFFF; req->buddyConPtr = theNdbCon->theBuddyConPtr; + req->first_batch_size = batch; // Save user specified batch size Uint32 reqInfo = 0; ScanTabReq::setParallelism(reqInfo, parallel); @@ -750,13 +755,14 @@ int NdbScanOperation::prepareSendScan(Uint32 aTC_ConnectPtr, * The number of records sent by each LQH is calculated and the kernel * is informed of this number by updating the SCAN_TABREQ signal */ - Uint32 batch_size, batch_byte_size, first_batch_size; + ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend()); + Uint32 batch_size = req->first_batch_size; // User specified + Uint32 batch_byte_size, first_batch_size; theReceiver.calculate_batch_size(key_size, theParallelism, batch_size, batch_byte_size, first_batch_size); - ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend()); ScanTabReq::setScanBatch(req->requestInfo, batch_size); req->batch_byte_size= batch_byte_size; req->first_batch_size= first_batch_size; @@ -1216,13 +1222,14 @@ error: int NdbIndexScanOperation::readTuples(LockMode lm, Uint32 scan_flags, - Uint32 parallel) + Uint32 parallel, + Uint32 batch) { const bool order_by = scan_flags & SF_OrderBy; const bool order_desc = scan_flags & SF_Descending; const bool read_range_no = scan_flags & SF_ReadRangeNo; - - int res = NdbScanOperation::readTuples(lm, scan_flags, 0); + + int res = NdbScanOperation::readTuples(lm, scan_flags, parallel, batch); if(!res && read_range_no) { m_read_range_no = 1; diff --git a/ndb/src/ndbapi/Ndberr.cpp b/ndb/src/ndbapi/Ndberr.cpp index b05818de6f1..ad0b4eafcb4 100644 --- a/ndb/src/ndbapi/Ndberr.cpp +++ b/ndb/src/ndbapi/Ndberr.cpp @@ -21,7 +21,6 @@ #include <NdbOperation.hpp> #include <NdbTransaction.hpp> #include <NdbBlob.hpp> -#include "NdbEventOperationImpl.hpp" static void update(const NdbError & _err){ @@ -73,10 +72,3 @@ NdbBlob::getNdbError() const { update(theError); return theError; } - -const -NdbError & -NdbEventOperationImpl::getNdbError() const { - update(m_error); - return m_error; -} diff --git a/ndb/src/ndbapi/Ndbif.cpp b/ndb/src/ndbapi/Ndbif.cpp index 4af070638d4..6aaf44d0168 100644 --- a/ndb/src/ndbapi/Ndbif.cpp +++ b/ndb/src/ndbapi/Ndbif.cpp @@ -661,29 +661,11 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) case GSN_CREATE_INDX_REF: case GSN_DROP_INDX_CONF: case GSN_DROP_INDX_REF: - case GSN_CREATE_EVNT_CONF: - case GSN_CREATE_EVNT_REF: - case GSN_DROP_EVNT_CONF: - case GSN_DROP_EVNT_REF: case GSN_LIST_TABLES_CONF: NdbDictInterface::execSignal(&theDictionary->m_receiver, aSignal, ptr); break; - case GSN_SUB_META_DATA: - case GSN_SUB_REMOVE_CONF: - case GSN_SUB_REMOVE_REF: - break; // ignore these signals - case GSN_SUB_GCP_COMPLETE_REP: - case GSN_SUB_START_CONF: - case GSN_SUB_START_REF: - case GSN_SUB_TABLE_DATA: - case GSN_SUB_STOP_CONF: - case GSN_SUB_STOP_REF: - NdbDictInterface::execSignal(&theDictionary->m_receiver, - aSignal, ptr); - break; - case GSN_DIHNDBTAMPER: { tFirstDataPtr = int2void(tFirstData); diff --git a/ndb/src/ndbapi/Ndbinit.cpp b/ndb/src/ndbapi/Ndbinit.cpp index d5ad7066273..40cac675b21 100644 --- a/ndb/src/ndbapi/Ndbinit.cpp +++ b/ndb/src/ndbapi/Ndbinit.cpp @@ -34,10 +34,6 @@ #include "NdbUtil.hpp" #include <NdbBlob.hpp> -class NdbGlobalEventBufferHandle; -NdbGlobalEventBufferHandle *NdbGlobalEventBuffer_init(int); -void NdbGlobalEventBuffer_drop(NdbGlobalEventBufferHandle *); - Ndb::Ndb( Ndb_cluster_connection *ndb_cluster_connection, const char* aDataBase , const char* aSchema) : theImpl(NULL) @@ -107,16 +103,6 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection, if (theInitState == NotConstructed) theInitState = NotInitialised; - { - NdbGlobalEventBufferHandle *h= - NdbGlobalEventBuffer_init(NDB_MAX_ACTIVE_EVENTS); - if (h == NULL) { - ndbout_c("Failed NdbGlobalEventBuffer_init(%d)",NDB_MAX_ACTIVE_EVENTS); - exit(-1); - } - theGlobalEventBufferHandle = h; - } - DBUG_VOID_RETURN; } @@ -132,8 +118,6 @@ Ndb::~Ndb() DBUG_PRINT("enter",("Ndb::~Ndb this=0x%x",this)); doDisconnect(); - NdbGlobalEventBuffer_drop(theGlobalEventBufferHandle); - if (TransporterFacade::instance() != NULL && theNdbBlockNumber > 0){ TransporterFacade::instance()->close(theNdbBlockNumber, theFirstTransId); } diff --git a/ndb/test/include/HugoTransactions.hpp b/ndb/test/include/HugoTransactions.hpp index 5795bbc94c9..7a15a2f977d 100644 --- a/ndb/test/include/HugoTransactions.hpp +++ b/ndb/test/include/HugoTransactions.hpp @@ -28,9 +28,6 @@ public: HugoTransactions(const NdbDictionary::Table&, const NdbDictionary::Index* idx = 0); ~HugoTransactions(); - int createEvent(Ndb*); - int eventOperation(Ndb*, void* stats, - int records); int loadTable(Ndb*, int records, int batch = 512, diff --git a/ndb/test/ndbapi/Makefile.am b/ndb/test/ndbapi/Makefile.am index 7dfa239cb66..b639c71d07a 100644 --- a/ndb/test/ndbapi/Makefile.am +++ b/ndb/test/ndbapi/Makefile.am @@ -31,14 +31,16 @@ testSystemRestart \ testTimeout \ testTransactions \ testDeadlock \ -test_event ndbapi_slow_select testReadPerf testLcp \ +ndbapi_slow_select testReadPerf testLcp \ testPartitioning \ testBitfield \ DbCreate DbAsyncGenerator \ -test_event_multi_table \ -testSRBank \ -test_event_merge +testSRBank +EXTRA_PROGRAMS = \ + test_event \ + test_event_merge \ + test_event_multi_table #flexTimedAsynch #testBlobs #flex_bench_mysql diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp index 397f41b3d4e..b992d492ad6 100644 --- a/ndb/test/ndbapi/testDict.cpp +++ b/ndb/test/ndbapi/testDict.cpp @@ -233,6 +233,101 @@ int runCreateAndDrop(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int runCreateAndDropAtRandom(NDBT_Context* ctx, NDBT_Step* step) +{ + myRandom48Init(NdbTick_CurrentMillisecond()); + Ndb* pNdb = GETNDB(step); + NdbDictionary::Dictionary* pDic = pNdb->getDictionary(); + int loops = ctx->getNumLoops(); + int numTables = NDBT_Tables::getNumTables(); + bool* tabList = new bool [ numTables ]; + int tabCount; + + { + for (int num = 0; num < numTables; num++) { + (void)pDic->dropTable(NDBT_Tables::getTable(num)->getName()); + tabList[num] = false; + } + tabCount = 0; + } + + NdbRestarter restarter; + int result = NDBT_OK; + int bias = 1; // 0-less 1-more + int i = 0; + + while (i < loops) { + g_info << "loop " << i << " tabs " << tabCount << "/" << numTables << endl; + int num = myRandom48(numTables); + const NdbDictionary::Table* pTab = NDBT_Tables::getTable(num); + char tabName[200]; + strcpy(tabName, pTab->getName()); + + if (tabList[num] == false) { + if (bias == 0 && myRandom48(100) < 80) + continue; + g_info << tabName << ": create" << endl; + if (pDic->createTable(*pTab) != 0) { + const NdbError err = pDic->getNdbError(); + g_err << tabName << ": create failed: " << err << endl; + result = NDBT_FAILED; + break; + } + const NdbDictionary::Table* pTab2 = pDic->getTable(tabName); + if (pTab2 == NULL) { + const NdbError err = pDic->getNdbError(); + g_err << tabName << ": verify create: " << err << endl; + result = NDBT_FAILED; + break; + } + tabList[num] = true; + assert(tabCount < numTables); + tabCount++; + if (tabCount == numTables) + bias = 0; + } + else { + if (bias == 1 && myRandom48(100) < 80) + continue; + g_info << tabName << ": drop" << endl; + if (restarter.insertErrorInAllNodes(4013) != 0) { + g_err << "error insert failed" << endl; + result = NDBT_FAILED; + break; + } + if (pDic->dropTable(tabName) != 0) { + const NdbError err = pDic->getNdbError(); + g_err << tabName << ": drop failed: " << err << endl; + result = NDBT_FAILED; + break; + } + const NdbDictionary::Table* pTab2 = pDic->getTable(tabName); + if (pTab2 != NULL) { + g_err << tabName << ": verify drop: table exists" << endl; + result = NDBT_FAILED; + break; + } + if (pDic->getNdbError().code != 709 && + pDic->getNdbError().code != 723) { + const NdbError err = pDic->getNdbError(); + g_err << tabName << ": verify drop: " << err << endl; + result = NDBT_FAILED; + break; + } + tabList[num] = false; + assert(tabCount > 0); + tabCount--; + if (tabCount == 0) + bias = 1; + } + i++; + } + + delete [] tabList; + return result; +} + + int runCreateAndDropWithData(NDBT_Context* ctx, NDBT_Step* step){ Ndb* pNdb = GETNDB(step); int loops = ctx->getNumLoops(); @@ -1849,6 +1944,12 @@ TESTCASE("CreateAndDrop", "Try to create and drop the table loop number of times\n"){ INITIALIZER(runCreateAndDrop); } +TESTCASE("CreateAndDropAtRandom", + "Try to create and drop table at random loop number of times\n" + "Uses all available tables\n" + "Uses error insert 4013 to make TUP verify table descriptor"){ + INITIALIZER(runCreateAndDropAtRandom); +} TESTCASE("CreateAndDropWithData", "Try to create and drop the table when it's filled with data\n" "do this loop number of times\n"){ diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp index 754b3edc269..c1502940655 100644 --- a/ndb/test/ndbapi/testNodeRestart.cpp +++ b/ndb/test/ndbapi/testNodeRestart.cpp @@ -294,6 +294,7 @@ int runRestarts(NDBT_Context* ctx, NDBT_Step* step){ } i++; } + ctx->stopTest(); return result; } diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt index 6077c9fb536..cbb8a9a2574 100644 --- a/ndb/test/run-test/daily-basic-tests.txt +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -466,6 +466,10 @@ args: -n CreateAndDrop max-time: 1500 cmd: testDict +args: -n CreateAndDropAtRandom -l 200 T1 + +max-time: 1500 +cmd: testDict args: -n CreateAndDropWithData max-time: 1500 @@ -500,6 +504,10 @@ max-time: 1500 cmd: testDict args: -n TemporaryTables T1 T6 T7 T8 +max-time: 1500 +cmd: testDict +args: -n Restart_NR2 T1 + # # TEST NDBAPI # diff --git a/ndb/test/src/HugoTransactions.cpp b/ndb/test/src/HugoTransactions.cpp index 3260b921985..7616c93c9e3 100644 --- a/ndb/test/src/HugoTransactions.cpp +++ b/ndb/test/src/HugoTransactions.cpp @@ -768,285 +768,6 @@ HugoTransactions::fillTable(Ndb* pNdb, } int -HugoTransactions::createEvent(Ndb* pNdb){ - - char eventName[1024]; - sprintf(eventName,"%s_EVENT",tab.getName()); - - NdbDictionary::Dictionary *myDict = pNdb->getDictionary(); - - if (!myDict) { - g_err << "Dictionary not found " - << pNdb->getNdbError().code << " " - << pNdb->getNdbError().message << endl; - return NDBT_FAILED; - } - - NdbDictionary::Event myEvent(eventName); - myEvent.setTable(tab.getName()); - myEvent.addTableEvent(NdbDictionary::Event::TE_ALL); - // myEvent.addTableEvent(NdbDictionary::Event::TE_INSERT); - // myEvent.addTableEvent(NdbDictionary::Event::TE_UPDATE); - // myEvent.addTableEvent(NdbDictionary::Event::TE_DELETE); - - // const NdbDictionary::Table *_table = myDict->getTable(tab.getName()); - for(int a = 0; a < tab.getNoOfColumns(); a++){ - // myEvent.addEventColumn(_table->getColumn(a)->getName()); - myEvent.addEventColumn(a); - } - - int res = myDict->createEvent(myEvent); // Add event to database - - if (res == 0) - myEvent.print(); - else if (myDict->getNdbError().classification == - NdbError::SchemaObjectExists) - { - g_info << "Event creation failed event exists\n"; - res = myDict->dropEvent(eventName); - if (res) { - g_err << "Failed to drop event: " - << myDict->getNdbError().code << " : " - << myDict->getNdbError().message << endl; - return NDBT_FAILED; - } - // try again - res = myDict->createEvent(myEvent); // Add event to database - if (res) { - g_err << "Failed to create event (1): " - << myDict->getNdbError().code << " : " - << myDict->getNdbError().message << endl; - return NDBT_FAILED; - } - } - else - { - g_err << "Failed to create event (2): " - << myDict->getNdbError().code << " : " - << myDict->getNdbError().message << endl; - return NDBT_FAILED; - } - - return NDBT_OK; -} - -#include <NdbEventOperation.hpp> -#include "TestNdbEventOperation.hpp" -#include <NdbAutoPtr.hpp> - -struct receivedEvent { - Uint32 pk; - Uint32 count; - Uint32 event; -}; - -int XXXXX = 0; - -int -HugoTransactions::eventOperation(Ndb* pNdb, void* pstats, - int records) { - int myXXXXX = XXXXX++; - Uint32 i; - const char function[] = "HugoTransactions::eventOperation: "; - struct receivedEvent* recInsertEvent; - NdbAutoObjArrayPtr<struct receivedEvent> - p00( recInsertEvent = new struct receivedEvent[3*records] ); - struct receivedEvent* recUpdateEvent = &recInsertEvent[records]; - struct receivedEvent* recDeleteEvent = &recInsertEvent[2*records]; - - EventOperationStats &stats = *(EventOperationStats*)pstats; - - stats.n_inserts = 0; - stats.n_deletes = 0; - stats.n_updates = 0; - stats.n_consecutive = 0; - stats.n_duplicates = 0; - stats.n_inconsistent_gcis = 0; - - for (i = 0; i < records; i++) { - recInsertEvent[i].pk = 0xFFFFFFFF; - recInsertEvent[i].count = 0; - recInsertEvent[i].event = 0xFFFFFFFF; - - recUpdateEvent[i].pk = 0xFFFFFFFF; - recUpdateEvent[i].count = 0; - recUpdateEvent[i].event = 0xFFFFFFFF; - - recDeleteEvent[i].pk = 0xFFFFFFFF; - recDeleteEvent[i].count = 0; - recDeleteEvent[i].event = 0xFFFFFFFF; - } - - NdbDictionary::Dictionary *myDict = pNdb->getDictionary(); - - if (!myDict) { - g_err << function << "Event Creation failedDictionary not found\n"; - return NDBT_FAILED; - } - - int r = 0; - NdbEventOperation *pOp; - - char eventName[1024]; - sprintf(eventName,"%s_EVENT",tab.getName()); - int noEventColumnName = tab.getNoOfColumns(); - - g_info << function << "create EventOperation\n"; - pOp = pNdb->createEventOperation(eventName, 100); - if ( pOp == NULL ) { - g_err << function << "Event operation creation failed\n"; - return NDBT_FAILED; - } - - g_info << function << "get values\n"; - NdbRecAttr* recAttr[1024]; - NdbRecAttr* recAttrPre[1024]; - - const NdbDictionary::Table *_table = myDict->getTable(tab.getName()); - - for (int a = 0; a < noEventColumnName; a++) { - recAttr[a] = pOp->getValue(_table->getColumn(a)->getName()); - recAttrPre[a] = pOp->getPreValue(_table->getColumn(a)->getName()); - } - - // set up the callbacks - g_info << function << "execute\n"; - if (pOp->execute()) { // This starts changes to "start flowing" - g_err << function << "operation execution failed: \n"; - g_err << pOp->getNdbError().code << " " - << pOp->getNdbError().message << endl; - return NDBT_FAILED; - } - - g_info << function << "ok\n"; - - int count = 0; - Uint32 last_inconsitant_gci = 0xEFFFFFF0; - - while (r < records){ - //printf("now waiting for event...\n"); - int res = pNdb->pollEvents(1000); // wait for event or 1000 ms - - if (res > 0) { - //printf("got data! %d\n", r); - int overrun; - while (pOp->next(&overrun) > 0) { - r++; - r += overrun; - count++; - - Uint32 gci = pOp->getGCI(); - Uint32 pk = recAttr[0]->u_32_value(); - - if (!pOp->isConsistent()) { - if (last_inconsitant_gci != gci) { - last_inconsitant_gci = gci; - stats.n_inconsistent_gcis++; - } - g_warning << "A node failure has occured and events might be missing\n"; - } - g_info << function << "GCI " << gci << ": " << count; - struct receivedEvent* recEvent; - switch (pOp->getEventType()) { - case NdbDictionary::Event::TE_INSERT: - stats.n_inserts++; - g_info << " INSERT: "; - recEvent = recInsertEvent; - break; - case NdbDictionary::Event::TE_DELETE: - stats.n_deletes++; - g_info << " DELETE: "; - recEvent = recDeleteEvent; - break; - case NdbDictionary::Event::TE_UPDATE: - stats.n_updates++; - g_info << " UPDATE: "; - recEvent = recUpdateEvent; - break; - case NdbDictionary::Event::TE_ALL: - abort(); - } - - if ((int)pk < records) { - recEvent[pk].pk = pk; - recEvent[pk].count++; - } - - g_info << "overrun " << overrun << " pk " << pk; - for (i = 1; i < noEventColumnName; i++) { - if (recAttr[i]->isNULL() >= 0) { // we have a value - g_info << " post[" << i << "]="; - if (recAttr[i]->isNULL() == 0) // we have a non-null value - g_info << recAttr[i]->u_32_value(); - else // we have a null value - g_info << "NULL"; - } - if (recAttrPre[i]->isNULL() >= 0) { // we have a value - g_info << " pre[" << i << "]="; - if (recAttrPre[i]->isNULL() == 0) // we have a non-null value - g_info << recAttrPre[i]->u_32_value(); - else // we have a null value - g_info << "NULL"; - } - } - g_info << endl; - } - } else - ;//printf("timed out\n"); - } - - // sleep ((XXXXX-myXXXXX)*2); - - g_info << myXXXXX << "dropping event operation" << endl; - - int res = pNdb->dropEventOperation(pOp); - if (res != 0) { - g_err << "operation execution failed\n"; - return NDBT_FAILED; - } - - g_info << myXXXXX << " ok" << endl; - - if (stats.n_inserts > 0) { - stats.n_consecutive++; - } - if (stats.n_deletes > 0) { - stats.n_consecutive++; - } - if (stats.n_updates > 0) { - stats.n_consecutive++; - } - for (i = 0; i < (Uint32)records/3; i++) { - if (recInsertEvent[i].pk != i) { - stats.n_consecutive ++; - ndbout << "missing insert pk " << i << endl; - } else if (recInsertEvent[i].count > 1) { - ndbout << "duplicates insert pk " << i - << " count " << recInsertEvent[i].count << endl; - stats.n_duplicates += recInsertEvent[i].count-1; - } - if (recUpdateEvent[i].pk != i) { - stats.n_consecutive ++; - ndbout << "missing update pk " << i << endl; - } else if (recUpdateEvent[i].count > 1) { - ndbout << "duplicates update pk " << i - << " count " << recUpdateEvent[i].count << endl; - stats.n_duplicates += recUpdateEvent[i].count-1; - } - if (recDeleteEvent[i].pk != i) { - stats.n_consecutive ++; - ndbout << "missing delete pk " << i << endl; - } else if (recDeleteEvent[i].count > 1) { - ndbout << "duplicates delete pk " << i - << " count " << recDeleteEvent[i].count << endl; - stats.n_duplicates += recDeleteEvent[i].count-1; - } - } - - return NDBT_OK; -} - -int HugoTransactions::pkReadRecords(Ndb* pNdb, int records, int batch, diff --git a/ndb/tools/restore/consumer_restore.cpp b/ndb/tools/restore/consumer_restore.cpp index bff63c28716..dc1399e73b2 100644 --- a/ndb/tools/restore/consumer_restore.cpp +++ b/ndb/tools/restore/consumer_restore.cpp @@ -145,17 +145,38 @@ BackupRestore::finalize_table(const TableS & table){ bool ret= true; if (!m_restore && !m_restore_meta) return ret; - if (table.have_auto_inc()) + if (!table.have_auto_inc()) + return ret; + + Uint64 max_val= table.get_max_auto_val(); + do { - Uint64 max_val= table.get_max_auto_val(); - Uint64 auto_val; + Uint64 auto_val = ~(Uint64)0; int r= m_ndb->readAutoIncrementValue(get_table(table.m_dictTable), auto_val); - if (r == -1 && m_ndb->getNdbError().code != 626) + if (r == -1 && m_ndb->getNdbError().status == NdbError::TemporaryError) + { + NdbSleep_MilliSleep(50); + continue; // retry + } + else if (r == -1 && m_ndb->getNdbError().code != 626) + { ret= false; - else if (r == -1 || max_val+1 > auto_val) - ret= m_ndb->setAutoIncrementValue(get_table(table.m_dictTable), max_val+1, false) != -1; - } - return ret; + } + else if ((r == -1 && m_ndb->getNdbError().code == 626) || + max_val+1 > auto_val || auto_val == ~(Uint64)0) + { + r= m_ndb->setAutoIncrementValue(get_table(table.m_dictTable), + max_val+1, false); + if (r == -1 && + m_ndb->getNdbError().status == NdbError::TemporaryError) + { + NdbSleep_MilliSleep(50); + continue; // retry + } + ret = (r == 0); + } + return (ret); + } while (1); } bool @@ -217,9 +238,6 @@ BackupRestore::table(const TableS & table){ err << "Unable to find table: " << split[2].c_str() << endl; return false; } - if(m_restore_meta){ - m_ndb->setAutoIncrementValue(tab, ~(Uint64)0, false); - } const NdbDictionary::Table* null = 0; m_new_tables.fill(table.m_dictTable->getTableId(), null); m_new_tables[table.m_dictTable->getTableId()] = tab; diff --git a/netware/BUILD/mwasmnlm b/netware/BUILD/mwasmnlm index 381f84ec0c8..11fc2bc3842 100755 --- a/netware/BUILD/mwasmnlm +++ b/netware/BUILD/mwasmnlm @@ -5,4 +5,7 @@ set -e args=" $*" -wine --debugmsg -all -- mwasmnlm $args +# NOTE: Option 'pipefail' is not standard sh +set -o pipefail +wine --debugmsg -all -- mwasmnlm $args | \ +perl -pe 's/\r//g; s/^\e.*\e(\[J|>)?//; s/[[^:print:]]//g' diff --git a/netware/BUILD/mwccnlm b/netware/BUILD/mwccnlm index cb2d62fe8cf..e6840e781f8 100755 --- a/netware/BUILD/mwccnlm +++ b/netware/BUILD/mwccnlm @@ -7,4 +7,7 @@ set -e # convert it to "-I../include" args=" "`echo $* | sed -e 's/-I.\/../-I../g'` -wine --debugmsg -all -- mwccnlm $args +# NOTE: Option 'pipefail' is not standard sh +set -o pipefail +wine --debugmsg -all -- mwccnlm $args | \ +perl -pe 's/\r//g; s/^\e.*\e(\[J|>)?//; s/[[^:print:]]//g' diff --git a/netware/BUILD/mwldnlm b/netware/BUILD/mwldnlm index 28566fc5cb1..cc8c9e63c6e 100755 --- a/netware/BUILD/mwldnlm +++ b/netware/BUILD/mwldnlm @@ -5,4 +5,7 @@ set -e args=" $*" -wine --debugmsg -all -- mwldnlm $args +# NOTE: Option 'pipefail' is not standard sh +set -o pipefail +wine --debugmsg -all -- mwldnlm $args | \ +perl -pe 's/\r//g; s/^\e.*\e(\[J|>)?//; s/[[^:print:]]//g' diff --git a/scripts/mysqld_safe-watch.sh b/scripts/mysqld_safe-watch.sh index c59b3b2614d..c837ba9a118 100644 --- a/scripts/mysqld_safe-watch.sh +++ b/scripts/mysqld_safe-watch.sh @@ -93,10 +93,10 @@ do if test "$#" -eq 0 then nohup $ledir/mysqld --basedir=$MY_BASEDIR_VERSION --datadir=$DATADIR \ - --skip-locking >> $err 2>&1 & + --skip-external-locking >> $err 2>&1 & else nohup $ledir/mysqld --basedir=$MY_BASEDIR_VERSION --datadir=$DATADIR \ - --skip-locking "$@" >> $err 2>&1 & + --skip-external-locking "$@" >> $err 2>&1 & fi pid=$! rm -f $lockfile diff --git a/server-tools/instance-manager/mysqlmanager.vcproj b/server-tools/instance-manager/mysqlmanager.vcproj index ef8b2dd017e..bbcb94fa221 100644 --- a/server-tools/instance-manager/mysqlmanager.vcproj +++ b/server-tools/instance-manager/mysqlmanager.vcproj @@ -34,7 +34,7 @@ <Tool Name="VCLinkerTool" AdditionalDependencies="wsock32.lib" - OutputFile="$(OutDir)/mysqlmanager.exe" + OutputFile="../../client_debug/mysqlmanager.exe" LinkIncremental="2" GenerateDebugInformation="TRUE" ProgramDatabaseFile="$(OutDir)/mysqlmanager.pdb" @@ -82,7 +82,7 @@ <Tool Name="VCLinkerTool" AdditionalDependencies="wsock32.lib" - OutputFile="$(OutDir)/mysqlmanager.exe" + OutputFile="../../client_release/mysqlmanager.exe" LinkIncremental="1" GenerateDebugInformation="TRUE" SubSystem="1" diff --git a/sql-common/client.c b/sql-common/client.c index 56a5862c90e..31e85475f08 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1514,6 +1514,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , */ #ifdef HAVE_OPENSSL + static void mysql_ssl_free(MYSQL *mysql __attribute__((unused))) { @@ -1538,6 +1539,7 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused))) DBUG_VOID_RETURN; } +#endif /* HAVE_OPENSSL */ /* Return the SSL cipher (if any) used for current @@ -1553,8 +1555,10 @@ const char * STDCALL mysql_get_ssl_cipher(MYSQL *mysql) { DBUG_ENTER("mysql_get_ssl_cipher"); +#ifdef HAVE_OPENSSL if (mysql->net.vio && mysql->net.vio->ssl_arg) DBUG_RETURN(SSL_get_cipher_name((SSL*)mysql->net.vio->ssl_arg)); +#endif /* HAVE_OPENSSL */ DBUG_RETURN(NULL); } @@ -1573,6 +1577,9 @@ mysql_get_ssl_cipher(MYSQL *mysql) 1 Failed to validate server */ + +#ifdef HAVE_OPENSSL + static int ssl_verify_server_cert(Vio *vio, const char* server_hostname) { SSL *ssl; diff --git a/sql/Makefile.am b/sql/Makefile.am index 453e50a3b0b..416f0faf1a6 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -79,7 +79,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ mysqld.cc password.c hash_filo.cc hostname.cc \ set_var.cc sql_parse.cc sql_yacc.yy \ sql_base.cc table.cc sql_select.cc sql_insert.cc \ - sql_prepare.cc sql_error.cc \ + sql_prepare.cc sql_error.cc sql_locale.cc \ sql_update.cc sql_delete.cc uniques.cc sql_do.cc \ procedure.cc item_uniq.cc sql_test.cc \ log.cc log_event.cc init.cc derror.cc sql_acl.cc \ diff --git a/sql/field.cc b/sql/field.cc index 7c25e4ad9f7..946351efe36 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1515,7 +1515,8 @@ bool Field::optimize_range(uint idx, uint part) } -Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table) +Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table, + bool keep_type __attribute__((unused))) { Field *tmp; if (!(tmp= (Field*) memdup_root(root,(char*) this,size_of()))) @@ -1540,7 +1541,7 @@ Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table, uint new_null_bit) { Field *tmp; - if ((tmp= new_field(root, new_table))) + if ((tmp= new_field(root, new_table, table == new_table))) { tmp->ptr= new_ptr; tmp->null_ptr= new_null_ptr; @@ -6227,29 +6228,21 @@ uint Field_string::max_packed_col_length(uint max_length) } -Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table) +Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table, + bool keep_type) { Field *new_field; - if (type() != MYSQL_TYPE_VAR_STRING || table == new_table) - return Field::new_field(root, new_table); + if (type() != MYSQL_TYPE_VAR_STRING || keep_type) + return Field::new_field(root, new_table, keep_type); /* Old VARCHAR field which should be modified to a VARCHAR on copy This is done to ensure that ALTER TABLE will convert old VARCHAR fields to now VARCHAR fields. */ - if ((new_field= new Field_varstring(field_length, maybe_null(), - field_name, new_table, charset()))) - { - /* - delayed_insert::get_local_table() needs a ptr copied from old table. - This is what other new_field() methods do too. The above method of - Field_varstring sets ptr to NULL. - */ - new_field->ptr= ptr; - } - return new_field; + return new Field_varstring(field_length, maybe_null(), + field_name, new_table, charset()); } /**************************************************************************** @@ -6741,9 +6734,11 @@ int Field_varstring::cmp_binary(const char *a_ptr, const char *b_ptr, } -Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table) +Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table, + bool keep_type) { - Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table); + Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table, + keep_type); if (res) res->length_bytes= length_bytes; return res; diff --git a/sql/field.h b/sql/field.h index ed13372df71..3b33d3651e3 100644 --- a/sql/field.h +++ b/sql/field.h @@ -211,7 +211,8 @@ public: */ virtual bool can_be_compared_as_longlong() const { return FALSE; } virtual void free() {} - virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table); + virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table, + bool keep_type); virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, char *new_ptr, uchar *new_null_ptr, uint new_null_bit); @@ -1033,7 +1034,7 @@ public: enum_field_types real_type() const { return FIELD_TYPE_STRING; } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } - Field *new_field(MEM_ROOT *root, struct st_table *new_table); + Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type); }; @@ -1105,7 +1106,7 @@ public: enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } - Field *new_field(MEM_ROOT *root, struct st_table *new_table); + Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type); Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, char *new_ptr, uchar *new_null_ptr, uint new_null_bit); diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 4e977c06180..3200f2ca9b2 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -675,9 +675,14 @@ void field_conv(Field *to,Field *from) { // Be sure the value is stored Field_blob *blob=(Field_blob*) to; from->val_str(&blob->value); - if (!blob->value.is_alloced() && - from->real_type() != MYSQL_TYPE_STRING && - from->real_type() != MYSQL_TYPE_VARCHAR) + /* + Copy value if copy_blobs is set, or source is not a string and + we have a pointer to its internal string conversion buffer. + */ + if (to->table->copy_blobs || + (!blob->value.is_alloced() && + from->real_type() != MYSQL_TYPE_STRING && + from->real_type() != MYSQL_TYPE_VARCHAR)) blob->value.copy(); blob->store(blob->value.ptr(),blob->value.length(),from->charset()); return; diff --git a/sql/ha_blackhole.cc b/sql/ha_blackhole.cc index 7632ed59949..2505919af39 100644 --- a/sql/ha_blackhole.cc +++ b/sql/ha_blackhole.cc @@ -47,7 +47,7 @@ handlerton blackhole_hton= { NULL, /* create_cursor_read_view */ NULL, /* set_cursor_read_view */ NULL, /* close_cursor_read_view */ - HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE + HTON_CAN_RECREATE }; /***************************************************************************** diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 11f676d9cf6..e2988df1619 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -1810,19 +1810,13 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) /* buffers for following strings */ - char old_field_value_buffer[STRING_BUFFER_USUAL_SIZE]; - char new_field_value_buffer[STRING_BUFFER_USUAL_SIZE]; + char field_value_buffer[STRING_BUFFER_USUAL_SIZE]; char update_buffer[FEDERATED_QUERY_BUFFER_SIZE]; char where_buffer[FEDERATED_QUERY_BUFFER_SIZE]; - /* stores the value to be replaced of the field were are updating */ - String old_field_value(old_field_value_buffer, - sizeof(old_field_value_buffer), - &my_charset_bin); - /* stores the new value of the field */ - String new_field_value(new_field_value_buffer, - sizeof(new_field_value_buffer), - &my_charset_bin); + /* Work area for field values */ + String field_value(field_value_buffer, sizeof(field_value_buffer), + &my_charset_bin); /* stores the update query */ String update_string(update_buffer, sizeof(update_buffer), @@ -1835,8 +1829,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) /* set string lengths to 0 to avoid misc chars in string */ - old_field_value.length(0); - new_field_value.length(0); + field_value.length(0); update_string.length(0); where_string.length(0); @@ -1850,8 +1843,8 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) In this loop, we want to match column names to values being inserted (while building INSERT statement). - Iterate through table->field (new data) and share->old_filed (old_data) - using the same index to created an SQL UPDATE statement, new data is + Iterate through table->field (new data) and share->old_field (old_data) + using the same index to create an SQL UPDATE statement. New data is used to create SET field=value and old data is used to create WHERE field=oldvalue */ @@ -1863,30 +1856,28 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) update_string.append(FEDERATED_EQ); if ((*field)->is_null()) - new_field_value.append(FEDERATED_NULL); + update_string.append(FEDERATED_NULL); else { /* otherwise = */ - (*field)->val_str(&new_field_value); - (*field)->quote_data(&new_field_value); - - if (!field_in_record_is_null(table, *field, (char*) old_data)) - where_string.append(FEDERATED_EQ); + (*field)->val_str(&field_value); + (*field)->quote_data(&field_value); + update_string.append(field_value); + field_value.length(0); } if (field_in_record_is_null(table, *field, (char*) old_data)) where_string.append(FEDERATED_ISNULL); else { - (*field)->val_str(&old_field_value, + where_string.append(FEDERATED_EQ); + (*field)->val_str(&field_value, (char*) (old_data + (*field)->offset())); - (*field)->quote_data(&old_field_value); - where_string.append(old_field_value); + (*field)->quote_data(&field_value); + where_string.append(field_value); + field_value.length(0); } - update_string.append(new_field_value); - new_field_value.length(0); - /* Only append conjunctions if we have another field in which to iterate @@ -1896,7 +1887,6 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) update_string.append(FEDERATED_COMMA); where_string.append(FEDERATED_AND); } - old_field_value.length(0); } update_string.append(FEDERATED_WHERE); update_string.append(where_string); diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index d2fd1a9e28a..9780f163634 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -55,7 +55,7 @@ handlerton myisammrg_hton= { NULL, /* create_cursor_read_view */ NULL, /* set_cursor_read_view */ NULL, /* close_cursor_read_view */ - HTON_CAN_RECREATE | HTON_ALTER_CANNOT_CREATE + HTON_CAN_RECREATE }; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index b36099cf25c..1af677fa754 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2254,9 +2254,10 @@ int ha_ndbcluster::write_row(byte *record) { Ndb *ndb= get_ndb(); Uint64 next_val= (Uint64) table->next_number_field->val_int() + 1; + char buff[22]; DBUG_PRINT("info", - ("Trying to set next auto increment value to %llu", - (ulonglong) next_val)); + ("Trying to set next auto increment value to %s", + llstr(next_val, buff))); if (ndb->setAutoIncrementValue((const NDBTAB *) m_table, next_val, TRUE) == -1) ERR_RETURN(ndb->getNdbError()); @@ -2582,13 +2583,15 @@ void ha_ndbcluster::unpack_record(byte* buf) { // Table with hidden primary key int hidden_no= table->s->fields; + char buff[22]; const NDBTAB *tab= (const NDBTAB *) m_table; const NDBCOL *hidden_col= tab->getColumn(hidden_no); const NdbRecAttr* rec= m_value[hidden_no].rec; DBUG_ASSERT(rec); - DBUG_PRINT("hidden", ("%d: %s \"%llu\"", hidden_no, - hidden_col->getName(), rec->u_64_value())); - } + DBUG_PRINT("hidden", ("%d: %s \"%s\"", hidden_no, + hidden_col->getName(), + llstr(rec->u_64_value(), buff))); + } print_results(); #endif DBUG_VOID_RETURN; @@ -3214,20 +3217,11 @@ int ha_ndbcluster::extra(enum ha_extra_function operation) break; case HA_EXTRA_IGNORE_DUP_KEY: /* Dup keys don't rollback everything*/ DBUG_PRINT("info", ("HA_EXTRA_IGNORE_DUP_KEY")); - if (current_thd->lex->sql_command == SQLCOM_REPLACE && !m_has_unique_index) - { - DBUG_PRINT("info", ("Turning ON use of write instead of insert")); - m_use_write= TRUE; - } else - { - DBUG_PRINT("info", ("Ignoring duplicate key")); - m_ignore_dup_key= TRUE; - } + DBUG_PRINT("info", ("Ignoring duplicate key")); + m_ignore_dup_key= TRUE; break; case HA_EXTRA_NO_IGNORE_DUP_KEY: DBUG_PRINT("info", ("HA_EXTRA_NO_IGNORE_DUP_KEY")); - DBUG_PRINT("info", ("Turning OFF use of write instead of insert")); - m_use_write= FALSE; m_ignore_dup_key= FALSE; break; case HA_EXTRA_RETRIEVE_ALL_COLS: /* Retrieve all columns, not just those @@ -3257,7 +3251,19 @@ int ha_ndbcluster::extra(enum ha_extra_function operation) case HA_EXTRA_KEYREAD_PRESERVE_FIELDS: DBUG_PRINT("info", ("HA_EXTRA_KEYREAD_PRESERVE_FIELDS")); break; - + case HA_EXTRA_WRITE_CAN_REPLACE: + DBUG_PRINT("info", ("HA_EXTRA_WRITE_CAN_REPLACE")); + if (!m_has_unique_index) + { + DBUG_PRINT("info", ("Turning ON use of write instead of insert")); + m_use_write= TRUE; + } + break; + case HA_EXTRA_WRITE_CANNOT_REPLACE: + DBUG_PRINT("info", ("HA_EXTRA_WRITE_CANNOT_REPLACE")); + DBUG_PRINT("info", ("Turning OFF use of write instead of insert")); + m_use_write= FALSE; + break; } DBUG_RETURN(0); @@ -4101,10 +4107,11 @@ static int create_ndb_column(NDBCOL &col, // Set autoincrement if (field->flags & AUTO_INCREMENT_FLAG) { + char buff[22]; col.setAutoIncrement(TRUE); ulonglong value= info->auto_increment_value ? info->auto_increment_value : (ulonglong) 1; - DBUG_PRINT("info", ("Autoincrement key, initial: %llu", value)); + DBUG_PRINT("info", ("Autoincrement key, initial: %s", llstr(value, buff))); col.setAutoIncrementInitialValue(value); } else @@ -4580,7 +4587,8 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg): HA_NO_PREFIX_CHAR_KEYS | HA_NEED_READ_RANGE_BUFFER | HA_CAN_GEOMETRY | - HA_CAN_BIT_FIELD), + HA_CAN_BIT_FIELD | + HA_PARTIAL_COLUMN_READ), m_share(0), m_use_write(FALSE), m_ignore_dup_key(FALSE), @@ -5493,8 +5501,9 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, if (share->commit_count != 0) { *commit_count= share->commit_count; - DBUG_PRINT("info", ("Getting commit_count: %llu from share", - share->commit_count)); + char buff[22]; + DBUG_PRINT("info", ("Getting commit_count: %s from share", + llstr(share->commit_count, buff))); pthread_mutex_unlock(&share->mutex); free_share(share); DBUG_RETURN(0); @@ -5518,7 +5527,9 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, pthread_mutex_lock(&share->mutex); if (share->commit_count_lock == lock) { - DBUG_PRINT("info", ("Setting commit_count to %llu", stat.commit_count)); + char buff[22]; + DBUG_PRINT("info", ("Setting commit_count to %s", + llstr(stat.commit_count, buff))); share->commit_count= stat.commit_count; *commit_count= stat.commit_count; } @@ -5568,13 +5579,12 @@ ndbcluster_cache_retrieval_allowed(THD *thd, char *full_name, uint full_name_len, ulonglong *engine_data) { - DBUG_ENTER("ndbcluster_cache_retrieval_allowed"); - Uint64 commit_count; bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); char *dbname= full_name; char *tabname= dbname+strlen(dbname)+1; - + char buff[22], buff2[22]; + DBUG_ENTER("ndbcluster_cache_retrieval_allowed"); DBUG_PRINT("enter", ("dbname: %s, tabname: %s, is_autocommit: %d", dbname, tabname, is_autocommit)); @@ -5590,8 +5600,8 @@ ndbcluster_cache_retrieval_allowed(THD *thd, DBUG_PRINT("exit", ("No, could not retrieve commit_count")); DBUG_RETURN(FALSE); } - DBUG_PRINT("info", ("*engine_data: %llu, commit_count: %llu", - *engine_data, commit_count)); + DBUG_PRINT("info", ("*engine_data: %s, commit_count: %s", + llstr(*engine_data, buff), llstr(commit_count, buff2))); if (commit_count == 0) { *engine_data= 0; /* invalidate */ @@ -5605,7 +5615,8 @@ ndbcluster_cache_retrieval_allowed(THD *thd, DBUG_RETURN(FALSE); } - DBUG_PRINT("exit", ("OK to use cache, engine_data: %llu", *engine_data)); + DBUG_PRINT("exit", ("OK to use cache, engine_data: %s", + llstr(*engine_data, buff))); DBUG_RETURN(TRUE); } @@ -5638,10 +5649,10 @@ ha_ndbcluster::register_query_cache_table(THD *thd, qc_engine_callback *engine_callback, ulonglong *engine_data) { - DBUG_ENTER("ha_ndbcluster::register_query_cache_table"); - + Uint64 commit_count; + char buff[22]; bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); - + DBUG_ENTER("ha_ndbcluster::register_query_cache_table"); DBUG_PRINT("enter",("dbname: %s, tabname: %s, is_autocommit: %d", m_dbname, m_tabname, is_autocommit)); @@ -5651,7 +5662,6 @@ ha_ndbcluster::register_query_cache_table(THD *thd, DBUG_RETURN(FALSE); } - Uint64 commit_count; if (ndb_get_commitcount(thd, m_dbname, m_tabname, &commit_count)) { *engine_data= 0; @@ -5660,7 +5670,7 @@ ha_ndbcluster::register_query_cache_table(THD *thd, } *engine_data= commit_count; *engine_callback= ndbcluster_cache_retrieval_allowed; - DBUG_PRINT("exit", ("commit_count: %llu", commit_count)); + DBUG_PRINT("exit", ("commit_count: %s", llstr(commit_count, buff))); DBUG_RETURN(commit_count > 0); } @@ -5841,12 +5851,13 @@ int ndb_get_table_statistics(Ndb* ndb, const char * table, struct Ndb_statistics * ndbstat) { - DBUG_ENTER("ndb_get_table_statistics"); - DBUG_PRINT("enter", ("table: %s", table)); NdbTransaction* pTrans; NdbError error; int retries= 10; int retry_sleep= 30 * 1000; /* 30 milliseconds */ + char buff[22], buff2[22], buff3[22], buff4[22]; + DBUG_ENTER("ndb_get_table_statistics"); + DBUG_PRINT("enter", ("table: %s", table)); do { @@ -5923,10 +5934,13 @@ ndb_get_table_statistics(Ndb* ndb, const char * table, ndbstat->row_size= sum_row_size; ndbstat->fragment_memory= sum_mem; - DBUG_PRINT("exit", ("records: %llu commits: %llu " - "row_size: %llu mem: %llu count: %u", - sum_rows, sum_commits, sum_row_size, - sum_mem, count)); + DBUG_PRINT("exit", ("records: %s commits: %s " + "row_size: %s mem: %s count: %u", + llstr(sum_rows, buff), + llstr(sum_commits, buff2), + llstr(sum_row_size, buff3), + llstr(sum_mem, buff4), + count)); DBUG_RETURN(0); retry: @@ -6461,9 +6475,12 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) if (ndb_get_table_statistics(ndb, tabname, &stat) == 0) { + char buff[22], buff2[22]; DBUG_PRINT("ndb_util_thread", - ("Table: %s, commit_count: %llu, rows: %llu", - share->table_name, stat.commit_count, stat.row_count)); + ("Table: %s commit_count: %s rows: %s", + share->table_name, + llstr(stat.commit_count, buff), + llstr(stat.row_count, buff2))); } else { diff --git a/sql/handler.cc b/sql/handler.cc index b40934ea194..9c03a9ef88f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1471,6 +1471,66 @@ next_insert_id(ulonglong nr,struct system_variables *variables) } +void handler::adjust_next_insert_id_after_explicit_value(ulonglong nr) +{ + /* + If we have set THD::next_insert_id previously and plan to insert an + explicitely-specified value larger than this, we need to increase + THD::next_insert_id to be greater than the explicit value. + */ + THD *thd= table->in_use; + if (thd->clear_next_insert_id && (nr >= thd->next_insert_id)) + { + if (thd->variables.auto_increment_increment != 1) + nr= next_insert_id(nr, &thd->variables); + else + nr++; + thd->next_insert_id= nr; + DBUG_PRINT("info",("next_insert_id: %lu", (ulong) nr)); + } +} + + +/* + Computes the largest number X: + - smaller than or equal to "nr" + - of the form: auto_increment_offset + N * auto_increment_increment + where N>=0. + + SYNOPSIS + prev_insert_id + nr Number to "round down" + variables variables struct containing auto_increment_increment and + auto_increment_offset + + RETURN + The number X if it exists, "nr" otherwise. +*/ + +inline ulonglong +prev_insert_id(ulonglong nr, struct system_variables *variables) +{ + if (unlikely(nr < variables->auto_increment_offset)) + { + /* + There's nothing good we can do here. That is a pathological case, where + the offset is larger than the column's max possible value, i.e. not even + the first sequence value may be inserted. User will receive warning. + */ + DBUG_PRINT("info",("auto_increment: nr: %lu cannot honour " + "auto_increment_offset: %lu", + nr, variables->auto_increment_offset)); + return nr; + } + if (variables->auto_increment_increment == 1) + return nr; // optimization of the formula below + nr= (((nr - variables->auto_increment_offset)) / + (ulonglong) variables->auto_increment_increment); + return (nr * (ulonglong) variables->auto_increment_increment + + variables->auto_increment_offset); +} + + /* Update the auto_increment field if necessary @@ -1547,17 +1607,7 @@ bool handler::update_auto_increment() /* Clear flag for next row */ /* Mark that we didn't generate a new value **/ auto_increment_column_changed=0; - - /* Update next_insert_id if we have already generated a value */ - if (thd->clear_next_insert_id && nr >= thd->next_insert_id) - { - if (variables->auto_increment_increment != 1) - nr= next_insert_id(nr, variables); - else - nr++; - thd->next_insert_id= nr; - DBUG_PRINT("info",("next_insert_id: %lu", (ulong) nr)); - } + adjust_next_insert_id_after_explicit_value(nr); DBUG_RETURN(0); } if (!(nr= thd->next_insert_id)) @@ -1580,10 +1630,19 @@ bool handler::update_auto_increment() /* Mark that we should clear next_insert_id before next stmt */ thd->clear_next_insert_id= 1; - if (!table->next_number_field->store((longlong) nr, TRUE)) + if (likely(!table->next_number_field->store((longlong) nr, TRUE))) thd->insert_id((ulonglong) nr); else - thd->insert_id(table->next_number_field->val_int()); + { + /* + overflow of the field; we'll use the max value, however we try to + decrease it to honour auto_increment_* variables: + */ + nr= prev_insert_id(table->next_number_field->val_int(), variables); + thd->insert_id(nr); + if (unlikely(table->next_number_field->store((longlong) nr, TRUE))) + thd->insert_id(nr= table->next_number_field->val_int()); + } /* We can't set next_insert_id if the auto-increment key is not the diff --git a/sql/handler.h b/sql/handler.h index 31aac075a5e..44de0cc715a 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -57,6 +57,7 @@ see mi_rsame/heap_rsame/myrg_rsame */ #define HA_READ_RND_SAME (1 << 0) +#define HA_PARTIAL_COLUMN_READ (1 << 1) /* read may not return all columns */ #define HA_TABLE_SCAN_ON_INDEX (1 << 2) /* No separate data/index file */ #define HA_REC_NOT_IN_SEQ (1 << 3) /* ha_info don't return recnumber; It returns a position to ha_r_rnd */ @@ -409,7 +410,6 @@ struct show_table_alias_st { #define HTON_ALTER_NOT_SUPPORTED (1 << 1) //Engine does not support alter #define HTON_CAN_RECREATE (1 << 2) //Delete all is used fro truncate #define HTON_HIDDEN (1 << 3) //Engine does not appear in lists -#define HTON_ALTER_CANNOT_CREATE (1 << 4) //Cannot use alter to create typedef struct st_thd_trans { @@ -428,7 +428,8 @@ typedef struct st_ha_create_information { CHARSET_INFO *table_charset, *default_table_charset; LEX_STRING connect_string; - const char *comment,*password; + LEX_STRING comment; + const char *password; const char *data_file_name, *index_file_name; const char *alias; ulonglong max_rows,min_rows; @@ -563,6 +564,7 @@ public: {} virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ } int ha_open(const char *name, int mode, int test_if_locked); + void adjust_next_insert_id_after_explicit_value(ulonglong nr); bool update_auto_increment(); virtual void print_error(int error, myf errflag); virtual bool get_error_message(int error, String *buf); diff --git a/sql/item.cc b/sql/item.cc index 24efc1f106f..511ea1ffb44 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1315,35 +1315,37 @@ void my_coll_agg_error(DTCollation &c1, DTCollation &c2, DTCollation &c3, static -void my_coll_agg_error(Item** args, uint count, const char *fname) +void my_coll_agg_error(Item** args, uint count, const char *fname, + int item_sep) { if (count == 2) - my_coll_agg_error(args[0]->collation, args[1]->collation, fname); + my_coll_agg_error(args[0]->collation, args[item_sep]->collation, fname); else if (count == 3) - my_coll_agg_error(args[0]->collation, args[1]->collation, - args[2]->collation, fname); + my_coll_agg_error(args[0]->collation, args[item_sep]->collation, + args[2*item_sep]->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) + Item **av, uint count, uint flags, int item_sep) { uint i; + Item **arg; c.set(av[0]->collation); - for (i= 1; i < count; i++) + for (i= 1, arg= &av[item_sep]; i < count; i++, arg++) { - if (c.aggregate(av[i]->collation, flags)) + if (c.aggregate((*arg)->collation, flags)) { - my_coll_agg_error(av, count, fname); + my_coll_agg_error(av, count, fname, item_sep); return TRUE; } } if ((flags & MY_COLL_DISALLOW_NONE) && c.derivation == DERIVATION_NONE) { - my_coll_agg_error(av, count, fname); + my_coll_agg_error(av, count, fname, item_sep); return TRUE; } return FALSE; @@ -1354,7 +1356,7 @@ 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)); + flags | MY_COLL_DISALLOW_NONE, 1)); } @@ -1377,13 +1379,22 @@ bool agg_item_collations_for_comparison(DTCollation &c, const char *fname, For functions with more than two arguments: collect(A,B,C) ::= collect(collect(A,B),C) + + Since this function calls THD::change_item_tree() on the passed Item ** + pointers, it is necessary to pass the original Item **'s, not copies. + Otherwise their values will not be properly restored (see BUG#20769). + If the items are not consecutive (eg. args[2] and args[5]), use the + item_sep argument, ie. + + agg_item_charsets(coll, fname, &args[2], 2, flags, 3) + */ bool agg_item_charsets(DTCollation &coll, const char *fname, - Item **args, uint nargs, uint flags) + Item **args, uint nargs, uint flags, int item_sep) { - Item **arg, **last, *safe_args[2]; - if (agg_item_collations(coll, fname, args, nargs, flags)) + Item **arg, *safe_args[2]; + if (agg_item_collations(coll, fname, args, nargs, flags, item_sep)) return TRUE; /* @@ -1396,19 +1407,20 @@ bool agg_item_charsets(DTCollation &coll, const char *fname, if (nargs >=2 && nargs <= 3) { safe_args[0]= args[0]; - safe_args[1]= args[1]; + safe_args[1]= args[item_sep]; } THD *thd= current_thd; Query_arena *arena, backup; bool res= FALSE; + uint i; /* In case we're in statement prepare, create conversion item in its memory: it will be reused on each execute. */ arena= thd->activate_stmt_arena_if_needed(&backup); - for (arg= args, last= args + nargs; arg < last; arg++) + for (i= 0, arg= args; i < nargs; i++, arg+= item_sep) { Item* conv; uint32 dummy_offset; @@ -1423,9 +1435,9 @@ bool agg_item_charsets(DTCollation &coll, const char *fname, { /* restore the original arguments for better error message */ args[0]= safe_args[0]; - args[1]= safe_args[1]; + args[item_sep]= safe_args[1]; } - my_coll_agg_error(args, nargs, fname); + my_coll_agg_error(args, nargs, fname, item_sep); res= TRUE; break; // we cannot return here, we need to restore "arena". } @@ -1457,7 +1469,18 @@ bool agg_item_charsets(DTCollation &coll, const char *fname, } - +void Item_ident_for_show::make_field(Send_field *tmp_field) +{ + tmp_field->table_name= tmp_field->org_table_name= table_name; + tmp_field->db_name= db_name; + tmp_field->col_name= tmp_field->org_col_name= field->field_name; + tmp_field->charsetnr= field->charset()->number; + tmp_field->length=field->field_length; + tmp_field->type=field->type(); + tmp_field->flags= field->table->maybe_null ? + (field->flags & ~NOT_NULL_FLAG) : field->flags; + tmp_field->decimals= 0; +} /**********************************************/ @@ -5350,9 +5373,14 @@ void Item_insert_value::print(String *str) void Item_trigger_field::setup_field(THD *thd, TABLE *table, GRANT_INFO *table_grant_info) { + /* + There is no sense in marking fields used by trigger with current value + of THD::query_id since it is completely unrelated to the THD::query_id + value for statements which will invoke trigger. So instead we use + Table_triggers_list::mark_fields_used() method which is called during + execution of these statements. + */ bool save_set_query_id= thd->set_query_id; - - /* TODO: Think more about consequences of this step. */ thd->set_query_id= 0; /* Try to find field by its name and if it will be found diff --git a/sql/item.h b/sql/item.h index 2cadfda6895..0f49145082f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -697,9 +697,16 @@ public: Any new item which can be NULL must implement this call. */ virtual bool is_null() { return 0; } + /* - it is "top level" item of WHERE clause and we do not need correct NULL - handling + Inform the item that there will be no distinction between its result + being FALSE or NULL. + + NOTE + This function will be called for eg. Items that are top-level AND-parts + of the WHERE clause. Items implementing this function (currently + Item_cond_and and subquery-related item) enable special optimizations + when they are "top level". */ virtual void top_level_item() {} /* @@ -827,13 +834,6 @@ protected: public: LEX_STRING m_name; - /* - Buffer, pointing to the string value of the item. We need it to - protect internal buffer from changes. See comment to analogous - member in Item_param for more details. - */ - String str_value_ptr; - public: #ifndef DBUG_OFF /* @@ -1075,12 +1075,11 @@ public: }; bool agg_item_collations(DTCollation &c, const char *name, - Item **items, uint nitems, uint flags= 0); + Item **items, uint nitems, uint flags, int item_sep); bool agg_item_collations_for_comparison(DTCollation &c, const char *name, - Item **items, uint nitems, - uint flags= 0); + Item **items, uint nitems, uint flags); bool agg_item_charsets(DTCollation &c, const char *name, - Item **items, uint nitems, uint flags= 0); + Item **items, uint nitems, uint flags, int item_sep); class Item_num: public Item @@ -1142,6 +1141,28 @@ public: bool any_privileges); }; + +class Item_ident_for_show :public Item +{ +public: + Field *field; + const char *db_name; + const char *table_name; + + Item_ident_for_show(Field *par_field, const char *db_arg, + const char *table_name_arg) + :field(par_field), db_name(db_arg), table_name(table_name_arg) + {} + + enum Type type() const { return FIELD_ITEM; } + double val_real() { return field->val_real(); } + longlong val_int() { return field->val_int(); } + String *val_str(String *str) { return field->val_str(str); } + my_decimal *val_decimal(my_decimal *dec) { return field->val_decimal(dec); } + void make_field(Send_field *tmp_field); +}; + + class Item_equal; class COND_EQUAL; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 80cf756d852..98453899375 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -394,7 +394,7 @@ void Item_bool_func2::fix_length_and_dec() DTCollation coll; if (args[0]->result_type() == STRING_RESULT && args[1]->result_type() == STRING_RESULT && - agg_arg_charsets(coll, args, 2, MY_COLL_CMP_CONV)) + agg_arg_charsets(coll, args, 2, MY_COLL_CMP_CONV, 1)) return; @@ -1211,7 +1211,7 @@ void Item_func_between::fix_length_and_dec() agg_cmp_type(thd, &cmp_type, args, 3); if (cmp_type == STRING_RESULT) - agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV); + agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1); } @@ -1331,7 +1331,7 @@ Item_func_ifnull::fix_length_and_dec() switch (hybrid_type) { case STRING_RESULT: - agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV); + agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1); break; case DECIMAL_RESULT: case REAL_RESULT: @@ -1503,7 +1503,7 @@ Item_func_if::fix_length_and_dec() agg_result_type(&cached_result_type, args+1, 2); if (cached_result_type == STRING_RESULT) { - if (agg_arg_charsets(collation, args+1, 2, MY_COLL_ALLOW_CONV)) + if (agg_arg_charsets(collation, args+1, 2, MY_COLL_ALLOW_CONV, 1)) return; } else @@ -1584,7 +1584,7 @@ Item_func_nullif::fix_length_and_dec() unsigned_flag= args[0]->unsigned_flag; cached_result_type= args[0]->result_type(); if (cached_result_type == STRING_RESULT && - agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV)) + agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1)) return; } } @@ -1876,7 +1876,7 @@ void Item_func_case::fix_length_and_dec() agg_result_type(&cached_result_type, agg, nagg); if ((cached_result_type == STRING_RESULT) && - agg_arg_charsets(collation, agg, nagg, MY_COLL_ALLOW_CONV)) + agg_arg_charsets(collation, agg, nagg, MY_COLL_ALLOW_CONV, 1)) return; @@ -1892,7 +1892,7 @@ void Item_func_case::fix_length_and_dec() nagg++; agg_cmp_type(thd, &cmp_type, agg, nagg); if ((cmp_type == STRING_RESULT) && - agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV)) + agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV, 1)) return; } @@ -2022,7 +2022,7 @@ void Item_func_coalesce::fix_length_and_dec() case STRING_RESULT: count_only_length(); decimals= NOT_FIXED_DEC; - agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV); + agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1); break; case DECIMAL_RESULT: count_decimal_length(); @@ -2486,7 +2486,7 @@ void Item_func_in::fix_length_and_dec() agg_cmp_type(thd, &cmp_type, args, arg_count); if (cmp_type == STRING_RESULT && - agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV)) + agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1)) return; for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++) @@ -3219,7 +3219,7 @@ Item_func_regex::fix_fields(THD *thd, Item **ref) max_length= 1; decimals= 0; - if (agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV)) + if (agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1)) return TRUE; used_tables_cache=args[0]->used_tables() | args[1]->used_tables(); @@ -3303,7 +3303,7 @@ longlong Item_func_regex::val_int() } } null_value=0; - return my_regexec(&preg,res->c_ptr(),0,(my_regmatch_t*) 0,0) ? 0 : 1; + return my_regexec(&preg,res->c_ptr_safe(),0,(my_regmatch_t*) 0,0) ? 0 : 1; } diff --git a/sql/item_create.cc b/sql/item_create.cc index bfcb2101d60..7d57757432e 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -296,12 +296,6 @@ Item *create_func_pow(Item* a, Item *b) return new Item_func_pow(a,b); } -Item *create_func_current_user() -{ - current_thd->lex->safe_to_cache_query= 0; - return new Item_func_user(TRUE); -} - Item *create_func_radians(Item *a) { return new Item_func_units((char*) "radians",a,M_PI/180,0.0); diff --git a/sql/item_create.h b/sql/item_create.h index 35db9be3c89..cf61f90f91d 100644 --- a/sql/item_create.h +++ b/sql/item_create.h @@ -73,7 +73,6 @@ Item *create_func_period_add(Item* a, Item *b); Item *create_func_period_diff(Item* a, Item *b); Item *create_func_pi(void); Item *create_func_pow(Item* a, Item *b); -Item *create_func_current_user(void); Item *create_func_radians(Item *a); Item *create_func_release_lock(Item* a); Item *create_func_repeat(Item* a, Item *b); diff --git a/sql/item_func.cc b/sql/item_func.cc index 194d62b1183..1d906b300b6 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2038,7 +2038,7 @@ void Item_func_min_max::fix_length_and_dec() cmp_type=item_cmp_type(cmp_type,args[i]->result_type()); } if (cmp_type == STRING_RESULT) - agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV); + agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1); else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT)) max_length= my_decimal_precision_to_length(max_int_part+decimals, decimals, unsigned_flag); @@ -2227,7 +2227,7 @@ longlong Item_func_coercibility::val_int() void Item_func_locate::fix_length_and_dec() { maybe_null=0; max_length=11; - agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV); + agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1); } @@ -2344,7 +2344,7 @@ void Item_func_field::fix_length_and_dec() for (uint i=1; i < arg_count ; i++) cmp_type= item_cmp_type(cmp_type, args[i]->result_type()); if (cmp_type == STRING_RESULT) - agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV); + agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1); } @@ -2411,7 +2411,7 @@ void Item_func_find_in_set::fix_length_and_dec() } } } - agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV); + agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1); } static const char separator=','; @@ -2510,8 +2510,7 @@ void udf_handler::cleanup() { if (u_d->func_deinit != NULL) { - void (*deinit)(UDF_INIT *) = (void (*)(UDF_INIT*)) - u_d->func_deinit; + Udf_func_deinit deinit= u_d->func_deinit; (*deinit)(&initid); } free_udf(u_d); @@ -2656,9 +2655,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, } } thd->net.last_error[0]=0; - my_bool (*init)(UDF_INIT *, UDF_ARGS *, char *)= - (my_bool (*)(UDF_INIT *, UDF_ARGS *, char *)) - u_d->func_init; + Udf_func_init init= u_d->func_init; if ((error=(uchar) init(&initid, &f_args, thd->net.last_error))) { my_error(ER_CANT_INITIALIZE_UDF, MYF(0), @@ -4401,7 +4398,8 @@ bool Item_func_match::fix_fields(THD *thd, Item **ref) return 1; } table->fulltext_searched=1; - return agg_arg_collations_for_comparison(cmp_collation, args+1, arg_count-1); + return agg_arg_collations_for_comparison(cmp_collation, + args+1, arg_count-1, 0); } bool Item_func_match::fix_index() diff --git a/sql/item_func.h b/sql/item_func.h index 1d8a1bd5e22..2ca4be9f3f2 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -166,21 +166,21 @@ public: my_decimal *val_decimal(my_decimal *); bool agg_arg_collations(DTCollation &c, Item **items, uint nitems, - uint flags= 0) + uint flags) { - return agg_item_collations(c, func_name(), items, nitems, flags); + return agg_item_collations(c, func_name(), items, nitems, flags, 1); } bool agg_arg_collations_for_comparison(DTCollation &c, Item **items, uint nitems, - uint flags= 0) + uint flags) { 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, int item_sep) { - return agg_item_charsets(c, func_name(), items, nitems, flags); + return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep); } bool walk(Item_processor processor, byte *arg); Item *transform(Item_transformer transformer, byte *arg); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 7a35dedc08a..c03f360271f 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -405,7 +405,7 @@ void Item_func_concat::fix_length_and_dec() { ulonglong max_result_length= 0; - if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV)) + if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1)) return; for (uint i=0 ; i < arg_count ; i++) @@ -727,7 +727,7 @@ void Item_func_concat_ws::fix_length_and_dec() { ulonglong max_result_length; - if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV)) + if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1)) return; /* @@ -752,44 +752,47 @@ String *Item_func_reverse::val_str(String *str) { DBUG_ASSERT(fixed == 1); String *res = args[0]->val_str(str); - char *ptr,*end; + char *ptr, *end, *tmp; if ((null_value=args[0]->null_value)) return 0; /* An empty string is a special case as the string pointer may be null */ if (!res->length()) return &my_empty_string; - res=copy_if_not_alloced(str,res,res->length()); - ptr = (char *) res->ptr(); - end=ptr+res->length(); + if (tmp_value.alloced_length() < res->length() && + tmp_value.realloc(res->length())) + { + null_value= 1; + return 0; + } + tmp_value.length(res->length()); + tmp_value.set_charset(res->charset()); + ptr= (char *) res->ptr(); + end= ptr + res->length(); + tmp= (char *) tmp_value.ptr() + tmp_value.length(); #ifdef USE_MB if (use_mb(res->charset())) { - String tmpstr; - tmpstr.copy(*res); - char *tmp = (char *) tmpstr.ptr() + tmpstr.length(); register uint32 l; while (ptr < end) { - if ((l=my_ismbchar(res->charset(), ptr,end))) - tmp-=l, memcpy(tmp,ptr,l), ptr+=l; + if ((l= my_ismbchar(res->charset(),ptr,end))) + { + tmp-= l; + memcpy(tmp,ptr,l); + ptr+= l; + } else - *--tmp=*ptr++; + *--tmp= *ptr++; } - memcpy((char *) res->ptr(),(char *) tmpstr.ptr(), res->length()); } else #endif /* USE_MB */ { - char tmp; while (ptr < end) - { - tmp=*ptr; - *ptr++=*--end; - *end=tmp; - } + *--tmp= *ptr++; } - return res; + return &tmp_value; } @@ -937,7 +940,7 @@ void Item_func_replace::fix_length_and_dec() } max_length= (ulong) max_result_length; - if (agg_arg_charsets(collation, args, 3, MY_COLL_CMP_CONV)) + if (agg_arg_charsets(collation, args, 3, MY_COLL_CMP_CONV, 1)) return; } @@ -982,15 +985,11 @@ null: void Item_func_insert::fix_length_and_dec() { - Item *cargs[2]; ulonglong max_result_length; - cargs[0]= args[0]; - cargs[1]= args[3]; - if (agg_arg_charsets(collation, cargs, 2, MY_COLL_ALLOW_CONV)) + // Handle character set for args[0] and args[3]. + if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 3)) return; - args[0]= cargs[0]; - args[3]= cargs[1]; max_result_length= ((ulonglong) args[0]->max_length+ (ulonglong) args[3]->max_length); if (max_result_length >= MAX_BLOB_WIDTH) @@ -1161,7 +1160,7 @@ void Item_func_substr_index::fix_length_and_dec() { max_length= args[0]->max_length; - if (agg_arg_charsets(collation, args, 2, MY_COLL_CMP_CONV)) + if (agg_arg_charsets(collation, args, 2, MY_COLL_CMP_CONV, 1)) return; } @@ -1497,13 +1496,10 @@ void Item_func_trim::fix_length_and_dec() } else { - Item *cargs[2]; - cargs[0]= args[1]; - cargs[1]= args[0]; - if (agg_arg_charsets(collation, cargs, 2, MY_COLL_CMP_CONV)) + // Handle character set for args[1] and args[0]. + // Note that we pass args[1] as the first item, and args[0] as the second. + if (agg_arg_charsets(collation, &args[1], 2, MY_COLL_CMP_CONV, -1)) return; - args[0]= cargs[1]; - args[1]= cargs[0]; } } @@ -1677,42 +1673,51 @@ String *Item_func_database::val_str(String *str) return str; } -// TODO: make USER() replicate properly (currently it is replicated to "") -String *Item_func_user::val_str(String *str) +/* + TODO: make USER() replicate properly (currently it is replicated to "") +*/ +bool Item_func_user::init(const char *user, const char *host) { DBUG_ASSERT(fixed == 1); - THD *thd=current_thd; - CHARSET_INFO *cs= system_charset_info; - const char *host, *user; - uint res_length; - if (is_current) - { - user= thd->security_ctx->priv_user; - host= thd->security_ctx->priv_host; - } - else + // For system threads (e.g. replication SQL thread) user may be empty + if (user) { - user= thd->main_security_ctx.user; - host= thd->main_security_ctx.host_or_ip; - } + CHARSET_INFO *cs= str_value.charset(); + uint res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen; - // For system threads (e.g. replication SQL thread) user may be empty - if (!user) - return &my_empty_string; - res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen; + if (str_value.alloc(res_length)) + { + null_value=1; + return TRUE; + } - if (str->alloc(res_length)) - { - null_value=1; - return 0; + res_length=cs->cset->snprintf(cs, (char*)str_value.ptr(), res_length, + "%s@%s", user, host); + str_value.length(res_length); + str_value.mark_as_const(); } - res_length=cs->cset->snprintf(cs, (char*)str->ptr(), res_length, "%s@%s", - user, host); - str->length(res_length); - str->set_charset(cs); - return str; + return FALSE; +} + + +bool Item_func_user::fix_fields(THD *thd, Item **ref) +{ + return (Item_func_sysconst::fix_fields(thd, ref) || + init(thd->main_security_ctx.user, + thd->main_security_ctx.host_or_ip)); +} + + +bool Item_func_current_user::fix_fields(THD *thd, Item **ref) +{ + if (Item_func_sysconst::fix_fields(thd, ref)) + return TRUE; + + Security_context *ctx= (context->security_ctx + ? context->security_ctx : thd->security_ctx); + return init(ctx->priv_user, ctx->priv_host); } @@ -1887,7 +1892,7 @@ void Item_func_elt::fix_length_and_dec() max_length=0; decimals=0; - if (agg_arg_charsets(collation, args+1, arg_count-1, MY_COLL_ALLOW_CONV)) + if (agg_arg_charsets(collation, args+1, arg_count-1, MY_COLL_ALLOW_CONV, 1)) return; for (uint i= 1 ; i < arg_count ; i++) @@ -1954,7 +1959,7 @@ void Item_func_make_set::fix_length_and_dec() { max_length=arg_count-1; - if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV)) + if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1)) return; for (uint i=0 ; i < arg_count ; i++) @@ -2162,14 +2167,9 @@ err: void Item_func_rpad::fix_length_and_dec() { - Item *cargs[2]; - - cargs[0]= args[0]; - cargs[1]= args[2]; - if (agg_arg_charsets(collation, cargs, 2, MY_COLL_ALLOW_CONV)) + // Handle character set for args[0] and args[2]. + if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 2)) return; - args[0]= cargs[0]; - args[2]= cargs[1]; if (args[1]->const_item()) { ulonglong length= ((ulonglong) args[1]->val_int() * @@ -2249,13 +2249,9 @@ String *Item_func_rpad::val_str(String *str) void Item_func_lpad::fix_length_and_dec() { - Item *cargs[2]; - cargs[0]= args[0]; - cargs[1]= args[2]; - if (agg_arg_charsets(collation, cargs, 2, MY_COLL_ALLOW_CONV)) + // Handle character set for args[0] and args[2]. + if (agg_arg_charsets(collation, &args[0], 2, MY_COLL_ALLOW_CONV, 2)) return; - args[0]= cargs[0]; - args[2]= cargs[1]; if (args[1]->const_item()) { @@ -2712,8 +2708,8 @@ void Item_func_export_set::fix_length_and_dec() uint sep_length=(arg_count > 3 ? args[3]->max_length : 1); max_length=length*64+sep_length*63; - if (agg_arg_charsets(collation, args+1, min(4,arg_count)-1), - MY_COLL_ALLOW_CONV) + if (agg_arg_charsets(collation, args+1, min(4,arg_count)-1, + MY_COLL_ALLOW_CONV, 1)) return; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index af59b8d740b..46b1b2fc248 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -102,6 +102,7 @@ public: class Item_func_reverse :public Item_str_func { + String tmp_value; public: Item_func_reverse(Item *a) :Item_str_func(a) {} String *val_str(String *); @@ -385,21 +386,40 @@ public: class Item_func_user :public Item_func_sysconst { - bool is_current; +protected: + bool init (const char *user, const char *host); public: - Item_func_user(bool is_current_arg) - :Item_func_sysconst(), is_current(is_current_arg) {} - String *val_str(String *); + Item_func_user() + { + str_value.set("", 0, system_charset_info); + } + String *val_str(String *) + { + DBUG_ASSERT(fixed == 1); + return (null_value ? 0 : &str_value); + } + bool fix_fields(THD *thd, Item **ref); void fix_length_and_dec() { max_length= ((USERNAME_LENGTH + HOSTNAME_LENGTH + 1) * system_charset_info->mbmaxlen); } - const char *func_name() const - { return is_current ? "current_user" : "user"; } - const char *fully_qualified_func_name() const - { return is_current ? "current_user()" : "user()"; } + const char *func_name() const { return "user"; } + const char *fully_qualified_func_name() const { return "user()"; } +}; + + +class Item_func_current_user :public Item_func_user +{ + Name_resolution_context *context; + +public: + Item_func_current_user(Name_resolution_context *context_arg) + : context(context_arg) {} + bool fix_fields(THD *thd, Item **ref); + const char *func_name() const { return "current_user"; } + const char *fully_qualified_func_name() const { return "current_user()"; } }; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index dda1b46ab10..5404021a348 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -802,7 +802,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, if (!select_lex->group_list.elements && !select_lex->having && !select_lex->with_sum_func && - !(select_lex->next_select())) + !(select_lex->next_select()) && + select_lex->table_list.elements) { Item_sum_hybrid *item; nesting_map save_allow_sum_func; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 877eb908d27..4d70debb966 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3228,7 +3228,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) args, /* skip charset aggregation for order columns */ arg_count - arg_count_order, - MY_COLL_ALLOW_CONV)) + MY_COLL_ALLOW_CONV, 1)) return 1; result.set_charset(collation.collation); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index f741984e05f..9e1962835c8 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -30,25 +30,6 @@ /* Day number for Dec 31st, 9999 */ #define MAX_DAY_NUMBER 3652424L -static const char *month_names[]= -{ - "January", "February", "March", "April", "May", "June", "July", "August", - "September", "October", "November", "December", NullS -}; - -TYPELIB month_names_typelib= -{ array_elements(month_names)-1,"", month_names, NULL }; - -static const char *day_names[]= -{ - "Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturday" ,"Sunday", NullS -}; - -TYPELIB day_names_typelib= -{ array_elements(day_names)-1,"", day_names, NULL}; - - /* OPTIMIZATION TODO: - Replace the switch with a function that should be called for each @@ -223,8 +204,12 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, val= tmp; break; case 'M': + if ((l_time->month= check_word(my_locale_en_US.month_names, + val, val_end, &val)) <= 0) + goto err; + break; case 'b': - if ((l_time->month= check_word(&month_names_typelib, + if ((l_time->month= check_word(my_locale_en_US.ab_month_names, val, val_end, &val)) <= 0) goto err; break; @@ -299,8 +284,11 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, /* Exotic things */ case 'W': + if ((weekday= check_word(my_locale_en_US.day_names, val, val_end, &val)) <= 0) + goto err; + break; case 'a': - if ((weekday= check_word(&day_names_typelib, val, val_end, &val)) <= 0) + if ((weekday= check_word(my_locale_en_US.ab_day_names, val, val_end, &val)) <= 0) goto err; break; case 'w': @@ -502,9 +490,16 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, uint weekday; ulong length; const char *ptr, *end; + MY_LOCALE *locale; + THD *thd= current_thd; + char buf[STRING_BUFFER_USUAL_SIZE]; + String tmp(buf, sizeof(buf), thd->variables.character_set_results); + uint errors= 0; + tmp.length(0); str->length(0); str->set_charset(&my_charset_bin); + locale = thd->variables.lc_time_names; if (l_time->neg) str->append('-'); @@ -520,26 +515,38 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, case 'M': if (!l_time->month) return 1; - str->append(month_names[l_time->month-1]); + tmp.copy(locale->month_names->type_names[l_time->month-1], + strlen(locale->month_names->type_names[l_time->month-1]), + system_charset_info, tmp.charset(), &errors); + str->append(tmp.ptr(), tmp.length()); break; case 'b': if (!l_time->month) return 1; - str->append(month_names[l_time->month-1],3); + tmp.copy(locale->ab_month_names->type_names[l_time->month-1], + strlen(locale->ab_month_names->type_names[l_time->month-1]), + system_charset_info, tmp.charset(), &errors); + str->append(tmp.ptr(), tmp.length()); break; case 'W': if (type == MYSQL_TIMESTAMP_TIME) return 1; weekday= calc_weekday(calc_daynr(l_time->year,l_time->month, l_time->day),0); - str->append(day_names[weekday]); + tmp.copy(locale->day_names->type_names[weekday], + strlen(locale->day_names->type_names[weekday]), + system_charset_info, tmp.charset(), &errors); + str->append(tmp.ptr(), tmp.length()); break; case 'a': if (type == MYSQL_TIMESTAMP_TIME) return 1; weekday=calc_weekday(calc_daynr(l_time->year,l_time->month, l_time->day),0); - str->append(day_names[weekday],3); + tmp.copy(locale->ab_day_names->type_names[weekday], + strlen(locale->ab_day_names->type_names[weekday]), + system_charset_info, tmp.charset(), &errors); + str->append(tmp.ptr(), tmp.length()); break; case 'D': if (type == MYSQL_TIMESTAMP_TIME) @@ -919,6 +926,7 @@ String* Item_func_monthname::val_str(String* str) DBUG_ASSERT(fixed == 1); const char *month_name; uint month= (uint) val_int(); + THD *thd= current_thd; if (null_value || !month) { @@ -926,7 +934,7 @@ String* Item_func_monthname::val_str(String* str) return (String*) 0; } null_value=0; - month_name= month_names[month-1]; + month_name= thd->variables.lc_time_names->month_names->type_names[month-1]; str->set(month_name, strlen(month_name), system_charset_info); return str; } @@ -1051,11 +1059,12 @@ String* Item_func_dayname::val_str(String* str) DBUG_ASSERT(fixed == 1); uint weekday=(uint) val_int(); // Always Item_func_daynr() const char *name; + THD *thd= current_thd; if (null_value) return (String*) 0; - name= day_names[weekday]; + name= thd->variables.lc_time_names->day_names->type_names[weekday]; str->set(name, strlen(name), system_charset_info); return str; } @@ -1676,7 +1685,7 @@ uint Item_func_date_format::format_length(const String *format) switch(*++ptr) { case 'M': /* month, textual */ case 'W': /* day (of the week), textual */ - size += 9; + size += 64; /* large for UTF8 locale data */ break; case 'D': /* day (of the month), numeric plus english suffix */ case 'Y': /* year, numeric, 4 digits */ @@ -1686,6 +1695,8 @@ uint Item_func_date_format::format_length(const String *format) break; case 'a': /* locale's abbreviated weekday name (Sun..Sat) */ case 'b': /* locale's abbreviated month name (Jan.Dec) */ + size += 32; /* large for UTF8 locale data */ + break; case 'j': /* day of year (001..366) */ size += 3; break; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3c58f2cbc6b..c9ae743addd 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -95,6 +95,23 @@ char* query_table_status(THD *thd,const char *db,const char *table_name); extern CHARSET_INFO *system_charset_info, *files_charset_info ; extern CHARSET_INFO *national_charset_info, *table_alias_charset; + +typedef struct my_locale_st +{ + const char *name; + const char *description; + const bool is_ascii; + TYPELIB *month_names; + TYPELIB *ab_month_names; + TYPELIB *day_names; + TYPELIB *ab_day_names; +} MY_LOCALE; + +extern MY_LOCALE my_locale_en_US; +extern MY_LOCALE *my_locales[]; + +MY_LOCALE *my_locale_by_name(const char *name); + /*************************************************************************** Configuration parameters ****************************************************************************/ @@ -537,6 +554,7 @@ int append_query_string(CHARSET_INFO *csinfo, void get_default_definer(THD *thd, LEX_USER *definer); LEX_USER *create_default_definer(THD *thd); LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name); +LEX_USER *get_current_user(THD *thd, LEX_USER *user); enum enum_mysql_completiontype { ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7, @@ -566,6 +584,7 @@ struct Query_cache_query_flags ulong sql_mode; ulong max_sort_length; ulong group_concat_max_len; + MY_LOCALE *lc_time_names; }; #define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags) #include "sql_cache.h" @@ -726,9 +745,7 @@ bool mysql_alter_table(THD *thd, char *new_db, char *new_name, TABLE_LIST *table_list, List<create_field> &fields, List<Key> &keys, - uint order_num, ORDER *order, - enum enum_duplicates handle_duplicates, - bool ignore, + uint order_num, ORDER *order, bool ignore, ALTER_INFO *alter_info, bool do_send_ok); bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok); bool mysql_create_like_table(THD *thd, TABLE_LIST *table, @@ -764,6 +781,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields, bool ignore); int check_that_all_fields_are_given_values(THD *thd, TABLE *entry, TABLE_LIST *table_list); +void mark_fields_used_by_triggers_for_insert_stmt(THD *thd, TABLE *table, + enum_duplicates duplic); bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds); bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order, ha_rows rows, ulonglong options, diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 72ead07059b..3b77d1b419e 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -59,18 +59,119 @@ static int sel_cmp(Field *f,char *a,char *b,uint8 a_flag,uint8 b_flag); static char is_null_string[2]= {1,0}; + +/* + A construction block of the SEL_ARG-graph. + + The following description only covers graphs of SEL_ARG objects with + sel_arg->type==KEY_RANGE: + + One SEL_ARG object represents an "elementary interval" in form + + min_value <=? table.keypartX <=? max_value + + The interval is a non-empty interval of any kind: with[out] minimum/maximum + bound, [half]open/closed, single-point interval, etc. + + 1. SEL_ARG GRAPH STRUCTURE + + SEL_ARG objects are linked together in a graph. The meaning of the graph + is better demostrated by an example: + + tree->keys[i] + | + | $ $ + | part=1 $ part=2 $ part=3 + | $ $ + | +-------+ $ +-------+ $ +--------+ + | | kp1<1 |--$-->| kp2=5 |--$-->| kp3=10 | + | +-------+ $ +-------+ $ +--------+ + | | $ $ | + | | $ $ +--------+ + | | $ $ | kp3=12 | + | | $ $ +--------+ + | +-------+ $ $ + \->| kp1=2 |--$--------------$-+ + +-------+ $ $ | +--------+ + | $ $ ==>| kp3=11 | + +-------+ $ $ | +--------+ + | kp1=3 |--$--------------$-+ | + +-------+ $ $ +--------+ + | $ $ | kp3=14 | + ... $ $ +--------+ + + The entire graph is partitioned into "interval lists". + + An interval list is a sequence of ordered disjoint intervals over the same + key part. SEL_ARG are linked via "next" and "prev" pointers. Additionally, + all intervals in the list form an RB-tree, linked via left/right/parent + pointers. The RB-tree root SEL_ARG object will be further called "root of the + interval list". + + In the example pic, there are 4 interval lists: + "kp<1 OR kp1=2 OR kp1=3", "kp2=5", "kp3=10 OR kp3=12", "kp3=11 OR kp3=13". + The vertical lines represent SEL_ARG::next/prev pointers. + + In an interval list, each member X may have SEL_ARG::next_key_part pointer + pointing to the root of another interval list Y. The pointed interval list + must cover a key part with greater number (i.e. Y->part > X->part). + + In the example pic, the next_key_part pointers are represented by + horisontal lines. + + 2. SEL_ARG GRAPH SEMANTICS + + It represents a condition in a special form (we don't have a name for it ATM) + The SEL_ARG::next/prev is "OR", and next_key_part is "AND". + + For example, the picture represents the condition in form: + (kp1 < 1 AND kp2=5 AND (kp3=10 OR kp3=12)) OR + (kp1=2 AND (kp3=11 OR kp3=14)) OR + (kp1=3 AND (kp3=11 OR kp3=14)) + + + 3. SEL_ARG GRAPH USE + + Use get_mm_tree() to construct SEL_ARG graph from WHERE condition. + Then walk the SEL_ARG graph and get a list of dijsoint ordered key + intervals (i.e. intervals in form + + (constA1, .., const1_K) < (keypart1,.., keypartK) < (constB1, .., constB_K) + + Those intervals can be used to access the index. The uses are in: + - check_quick_select() - Walk the SEL_ARG graph and find an estimate of + how many table records are contained within all + intervals. + - get_quick_select() - Walk the SEL_ARG, materialize the key intervals, + and create QUICK_RANGE_SELECT object that will + read records within these intervals. +*/ + class SEL_ARG :public Sql_alloc { public: uint8 min_flag,max_flag,maybe_flag; uint8 part; // Which key part uint8 maybe_null; - uint16 elements; // Elements in tree - ulong use_count; // use of this sub_tree + /* + Number of children of this element in the RB-tree, plus 1 for this + element itself. + */ + uint16 elements; + /* + Valid only for elements which are RB-tree roots: Number of times this + RB-tree is referred to (it is referred by SEL_ARG::next_key_part or by + SEL_TREE::keys[i] or by a temporary SEL_ARG* variable) + */ + ulong use_count; + Field *field; char *min_value,*max_value; // Pointer to range - SEL_ARG *left,*right,*next,*prev,*parent,*next_key_part; + SEL_ARG *left,*right; /* R-B tree children */ + SEL_ARG *next,*prev; /* Links for bi-directional interval list */ + SEL_ARG *parent; /* R-B tree parent */ + SEL_ARG *next_key_part; enum leaf_color { BLACK,RED } color; enum Type { IMPOSSIBLE, MAYBE, MAYBE_KEY, KEY_RANGE } type; @@ -1278,6 +1379,7 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg) } increment_use_count(1); tmp->color= color; + tmp->elements= this->elements; return tmp; } @@ -4457,8 +4559,21 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag) } +/* + Produce a SEL_ARG graph that represents "key1 AND key2" + + SYNOPSIS + key_and() + key1 First argument, root of its RB-tree + key2 Second argument, root of its RB-tree + + RETURN + RB-tree root of the resulting SEL_ARG graph. + NULL if the result of AND operation is an empty interval {0}. +*/ + static SEL_ARG * -key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag) +key_and(SEL_ARG *key1, SEL_ARG *key2, uint clone_flag) { if (!key1) return key2; @@ -4521,6 +4636,7 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag) if ((key1->min_flag | key2->min_flag) & GEOM_FLAG) { + /* TODO: why not leave one of the trees? */ key1->free_tree(); key2->free_tree(); return 0; // Can't optimize this @@ -5242,6 +5358,51 @@ int test_rb_tree(SEL_ARG *element,SEL_ARG *parent) return -1; // Error, no more warnings } + +/* + Count how many times SEL_ARG graph "root" refers to its part "key" + + SYNOPSIS + count_key_part_usage() + root An RB-Root node in a SEL_ARG graph. + key Another RB-Root node in that SEL_ARG graph. + + DESCRIPTION + The passed "root" node may refer to "key" node via root->next_key_part, + root->next->n + + This function counts how many times the node "key" is referred (via + SEL_ARG::next_key_part) by + - intervals of RB-tree pointed by "root", + - intervals of RB-trees that are pointed by SEL_ARG::next_key_part from + intervals of RB-tree pointed by "root", + - and so on. + + Here is an example (horizontal links represent next_key_part pointers, + vertical links - next/prev prev pointers): + + +----+ $ + |root|-----------------+ + +----+ $ | + | $ | + | $ | + +----+ +---+ $ | +---+ Here the return value + | |- ... -| |---$-+--+->|key| will be 4. + +----+ +---+ $ | | +---+ + | $ | | + ... $ | | + | $ | | + +----+ +---+ $ | | + | |---| |---------+ | + +----+ +---+ $ | + | | $ | + ... +---+ $ | + | |------------+ + +---+ $ + RETURN + Number of links to "key" from nodes reachable from "root". +*/ + static ulong count_key_part_usage(SEL_ARG *root, SEL_ARG *key) { ulong count= 0; @@ -5259,6 +5420,20 @@ static ulong count_key_part_usage(SEL_ARG *root, SEL_ARG *key) } +/* + Check if SEL_ARG::use_count value is correct + + SYNOPSIS + SEL_ARG::test_use_count() + root The root node of the SEL_ARG graph (an RB-tree root node that + has the least value of sel_arg->part in the entire graph, and + thus is the "origin" of the graph) + + DESCRIPTION + Check if SEL_ARG::use_count value is correct. See the definition of + use_count for what is "correct". +*/ + void SEL_ARG::test_use_count(SEL_ARG *root) { uint e_count=0; diff --git a/sql/set_var.cc b/sql/set_var.cc index 1cb3878ac70..8e3fda0a164 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -58,6 +58,7 @@ #include <my_getopt.h> #include <thr_alarm.h> #include <myisam.h> + #ifdef HAVE_BERKELEY_DB #include "ha_berkeley.h" #endif @@ -553,6 +554,9 @@ static sys_var_thd_ha_rows sys_select_limit("sql_select_limit", static sys_var_timestamp sys_timestamp("timestamp"); static sys_var_last_insert_id sys_last_insert_id("last_insert_id"); static sys_var_last_insert_id sys_identity("identity"); + +static sys_var_thd_lc_time_names sys_lc_time_names("lc_time_names"); + static sys_var_insert_id sys_insert_id("insert_id"); static sys_var_readonly sys_error_count("error_count", OPT_SESSION, @@ -651,6 +655,7 @@ sys_var *sys_variables[]= &sys_key_cache_division_limit, &sys_key_cache_age_threshold, &sys_last_insert_id, + &sys_lc_time_names, &sys_license, &sys_local_infile, &sys_log_binlog, @@ -921,6 +926,7 @@ struct show_var_st init_vars[]= { {"large_files_support", (char*) &opt_large_files, SHOW_BOOL}, {"large_page_size", (char*) &opt_large_page_size, SHOW_INT}, {"large_pages", (char*) &opt_large_pages, SHOW_MY_BOOL}, + {sys_lc_time_names.name, (char*) &sys_lc_time_names, SHOW_SYS}, {sys_license.name, (char*) &sys_license, SHOW_SYS}, {sys_local_infile.name, (char*) &sys_local_infile, SHOW_SYS}, #ifdef HAVE_MLOCKALL @@ -2764,6 +2770,40 @@ byte *sys_var_max_user_conn::value_ptr(THD *thd, enum_var_type type, return (byte*) &(max_user_connections); } +bool sys_var_thd_lc_time_names::check(THD *thd, set_var *var) +{ + char *locale_str =var->value->str_value.c_ptr(); + MY_LOCALE *locale_match= my_locale_by_name(locale_str); + + if (locale_match == NULL) + { + my_printf_error(ER_UNKNOWN_ERROR, + "Unknown locale: '%s'", MYF(0), locale_str); + return 1; + } + var->save_result.locale_value= locale_match; + return 0; +} + + +bool sys_var_thd_lc_time_names::update(THD *thd, set_var *var) +{ + thd->variables.lc_time_names= var->save_result.locale_value; + return 0; +} + + +byte *sys_var_thd_lc_time_names::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) +{ + return (byte *)(thd->variables.lc_time_names->name); +} + + +void sys_var_thd_lc_time_names::set_default(THD *thd, enum_var_type type) +{ + thd->variables.lc_time_names = &my_locale_en_US; +} /* Functions to update thd->options bits diff --git a/sql/set_var.h b/sql/set_var.h index b048428219d..11de6ceafe5 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -28,6 +28,8 @@ class sys_var; class set_var; typedef struct system_variables SV; +typedef struct my_locale_st MY_LOCALE; + extern TYPELIB bool_typelib, delay_key_write_typelib, sql_mode_typelib; typedef int (*sys_check_func)(THD *, set_var *); @@ -812,6 +814,25 @@ public: bool update(THD *thd, set_var *var); }; + +class sys_var_thd_lc_time_names :public sys_var_thd +{ +public: + sys_var_thd_lc_time_names(const char *name_arg): + sys_var_thd(name_arg) + {} + bool check(THD *thd, set_var *var); + SHOW_TYPE type() { return SHOW_CHAR; } + bool check_update_type(Item_result type) + { + return type != STRING_RESULT; /* Only accept strings */ + } + bool check_default(enum_var_type type) { return 0; } + bool update(THD *thd, set_var *var); + byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + virtual void set_default(THD *thd, enum_var_type type); +}; + /**************************************************************************** Classes for parsing of the SET command ****************************************************************************/ @@ -844,6 +865,7 @@ public: ulonglong ulonglong_value; DATE_TIME_FORMAT *date_time_format; Time_zone *time_zone; + MY_LOCALE *locale_value; } save_result; LEX_STRING base; /* for structs */ diff --git a/sql/sp_head.cc b/sql/sp_head.cc index b3b99557b63..9965c48935a 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1869,8 +1869,11 @@ sp_head::show_create_procedure(THD *thd) field_list.push_back(new Item_empty_string("Procedure", NAME_LEN)); field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len)); // 1024 is for not to confuse old clients - field_list.push_back(new Item_empty_string("Create Procedure", - max(buffer.length(), 1024))); + Item_empty_string *definition= + new Item_empty_string("Create Procedure", max(buffer.length(),1024)); + definition->maybe_null= TRUE; + field_list.push_back(definition); + if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(1); @@ -1879,6 +1882,8 @@ sp_head::show_create_procedure(THD *thd) protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info); if (full_access) protocol->store(m_defstr.str, m_defstr.length, system_charset_info); + else + protocol->store_null(); res= protocol->write(); send_eof(thd); @@ -1934,8 +1939,11 @@ sp_head::show_create_function(THD *thd) &sql_mode_len); field_list.push_back(new Item_empty_string("Function",NAME_LEN)); field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len)); - field_list.push_back(new Item_empty_string("Create Function", - max(buffer.length(),1024))); + Item_empty_string *definition= + new Item_empty_string("Create Function", max(buffer.length(),1024)); + definition->maybe_null= TRUE; + field_list.push_back(definition); + if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(1); @@ -1944,6 +1952,8 @@ sp_head::show_create_function(THD *thd) protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info); if (full_access) protocol->store(m_defstr.str, m_defstr.length, system_charset_info); + else + protocol->store_null(); res= protocol->write(); send_eof(thd); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 124d3566b19..f7dac349d8a 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2766,7 +2766,7 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, { ulong column_priv= 0; List_iterator <LEX_USER> str_list (user_list); - LEX_USER *Str; + LEX_USER *Str, *tmp_Str; TABLE_LIST tables[3]; bool create_new_users=0; char *db_name, *table_name; @@ -2891,10 +2891,15 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, thd->mem_root= &memex; grant_version++; - while ((Str = str_list++)) + while ((tmp_Str = str_list++)) { int error; GRANT_TABLE *grant_table; + if (!(Str= get_current_user(thd, tmp_Str))) + { + result= TRUE; + continue; + } if (Str->host.length > HOSTNAME_LENGTH || Str->user.length > USERNAME_LENGTH) { @@ -3030,7 +3035,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, bool revoke_grant, bool no_error) { List_iterator <LEX_USER> str_list (user_list); - LEX_USER *Str; + LEX_USER *Str, *tmp_Str; TABLE_LIST tables[2]; bool create_new_users=0, result=0; char *db_name, *table_name; @@ -3098,10 +3103,15 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, DBUG_PRINT("info",("now time to iterate and add users")); - while ((Str= str_list++)) + while ((tmp_Str= str_list++)) { int error; GRANT_NAME *grant_name; + if (!(Str= get_current_user(thd, tmp_Str))) + { + result= TRUE; + continue; + } if (Str->host.length > HOSTNAME_LENGTH || Str->user.length > USERNAME_LENGTH) { @@ -3170,7 +3180,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, ulong rights, bool revoke_grant) { List_iterator <LEX_USER> str_list (list); - LEX_USER *Str; + LEX_USER *Str, *tmp_Str; char tmp_db[NAME_LEN+1]; bool create_new_users=0; TABLE_LIST tables[2]; @@ -3229,8 +3239,13 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, grant_version++; int result=0; - while ((Str = str_list++)) + while ((tmp_Str = str_list++)) { + if (!(Str= get_current_user(thd, tmp_Str))) + { + result= TRUE; + continue; + } if (Str->host.length > HOSTNAME_LENGTH || Str->user.length > USERNAME_LENGTH) { @@ -5187,7 +5202,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) int result; String wrong_users; ulong sql_mode; - LEX_USER *user_name; + LEX_USER *user_name, *tmp_user_name; List_iterator <LEX_USER> user_list(list); TABLE_LIST tables[GRANT_TABLES]; DBUG_ENTER("mysql_create_user"); @@ -5199,8 +5214,13 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - while ((user_name= user_list++)) + while ((tmp_user_name= user_list++)) { + if (!(user_name= get_current_user(thd, tmp_user_name))) + { + result= TRUE; + continue; + } /* Search all in-memory structures and grant tables for a mention of the new user name. @@ -5246,7 +5266,7 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) { int result; String wrong_users; - LEX_USER *user_name; + LEX_USER *user_name, *tmp_user_name; List_iterator <LEX_USER> user_list(list); TABLE_LIST tables[GRANT_TABLES]; DBUG_ENTER("mysql_drop_user"); @@ -5258,8 +5278,14 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - while ((user_name= user_list++)) + while ((tmp_user_name= user_list++)) { + user_name= get_current_user(thd, tmp_user_name); + if (!(user_name= get_current_user(thd, tmp_user_name))) + { + result= TRUE; + continue; + } if (handle_grant_data(tables, 1, user_name, NULL) <= 0) { append_user(&wrong_users, user_name); @@ -5296,8 +5322,8 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) { int result; String wrong_users; - LEX_USER *user_from; - LEX_USER *user_to; + LEX_USER *user_from, *tmp_user_from; + LEX_USER *user_to, *tmp_user_to; List_iterator <LEX_USER> user_list(list); TABLE_LIST tables[GRANT_TABLES]; DBUG_ENTER("mysql_rename_user"); @@ -5309,9 +5335,19 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - while ((user_from= user_list++)) + while ((tmp_user_from= user_list++)) { - user_to= user_list++; + if (!(user_from= get_current_user(thd, tmp_user_from))) + { + result= TRUE; + continue; + } + tmp_user_to= user_list++; + if (!(user_to= get_current_user(thd, tmp_user_to))) + { + result= TRUE; + continue; + } DBUG_ASSERT(user_to != 0); /* Syntax enforces pairs of users. */ /* @@ -5366,10 +5402,15 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) rw_wrlock(&LOCK_grant); VOID(pthread_mutex_lock(&acl_cache->lock)); - LEX_USER *lex_user; + LEX_USER *lex_user, *tmp_lex_user; List_iterator <LEX_USER> user_list(list); - while ((lex_user=user_list++)) + while ((tmp_lex_user= user_list++)) { + if (!(lex_user= get_current_user(thd, tmp_lex_user))) + { + result= -1; + continue; + } if (!find_acl_user(lex_user->host.str, lex_user->user.str, TRUE)) { sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' does not " diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 5904e13d710..5383bb52aaa 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -624,8 +624,10 @@ void close_temporary_tables(THD *thd) if (!mysql_bin_log.is_open()) { - for (table= thd->temporary_tables; table; table= table->next) + TABLE *next; + for (table= thd->temporary_tables; table; table= next) { + next= table->next; close_temporary(table, 1); } thd->temporary_tables= 0; @@ -648,7 +650,6 @@ void close_temporary_tables(THD *thd) insertion sort of temp tables by pseudo_thread_id to build ordered list of sublists of equal pseudo_thread_id */ - for (prev_table= thd->temporary_tables, table= prev_table->next; table; prev_table= table, table= table->next) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 31201474c05..f8f7bde3a62 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -814,6 +814,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) flags.time_zone= thd->variables.time_zone; flags.sql_mode= thd->variables.sql_mode; flags.max_sort_length= thd->variables.max_sort_length; + flags.lc_time_names= thd->variables.lc_time_names; flags.group_concat_max_len= thd->variables.group_concat_max_len; DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \ CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \ @@ -1048,6 +1049,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) flags.sql_mode= thd->variables.sql_mode; flags.max_sort_length= thd->variables.max_sort_length; flags.group_concat_max_len= thd->variables.group_concat_max_len; + flags.lc_time_names= thd->variables.lc_time_names; DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \ CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \ sql mode: 0x%lx, sort len: %lu, conncat len: %lu", diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 06082a57964..87a515641de 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -269,6 +269,7 @@ THD::THD() tablespace_op=FALSE; ulong tmp=sql_rnd_with_mutex(); randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id); + substitute_null_with_insert_id = FALSE; thr_lock_info_init(&lock_info); /* safety: will be reset after start */ thr_lock_owner_init(&main_lock_id, &lock_info); } @@ -306,6 +307,7 @@ void THD::init(void) total_warn_count= 0; update_charset(); bzero((char *) &status_var, sizeof(status_var)); + variables.lc_time_names = &my_locale_en_US; } @@ -930,7 +932,7 @@ bool select_send::send_data(List<Item> &items) Protocol *protocol= thd->protocol; char buff[MAX_FIELD_WIDTH]; String buffer(buff, sizeof(buff), &my_charset_bin); - DBUG_ENTER("send_data"); + DBUG_ENTER("select_send::send_data"); protocol->prepare_for_resend(); Item *item; @@ -1140,7 +1142,7 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u) bool select_export::send_data(List<Item> &items) { - DBUG_ENTER("send_data"); + DBUG_ENTER("select_export::send_data"); char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH]; bool space_inited=0; String tmp(buff,sizeof(buff),&my_charset_bin),*res; @@ -1297,7 +1299,7 @@ bool select_dump::send_data(List<Item> &items) String tmp(buff,sizeof(buff),&my_charset_bin),*res; tmp.length(0); Item *item; - DBUG_ENTER("send_data"); + DBUG_ENTER("select_dump::send_data"); if (unit->offset_limit_cnt) { // using limit offset,count @@ -1946,6 +1948,7 @@ void Security_context::init() { host= user= priv_user= ip= 0; host_or_ip= "connecting host"; + priv_host[0]= '\0'; #ifndef NO_EMBEDDED_ACCESS_CHECKS db_access= NO_ACCESS; #endif diff --git a/sql/sql_class.h b/sql/sql_class.h index eb075dd54bb..5ed5e68adb9 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -575,6 +575,9 @@ struct system_variables CHARSET_INFO *collation_database; CHARSET_INFO *collation_connection; + /* Locale Support */ + MY_LOCALE *lc_time_names; + Time_zone *time_zone; /* DATE, DATETIME and TIME formats */ @@ -1321,6 +1324,8 @@ public: bool no_errors, password, is_fatal_error; bool query_start_used, rand_used, time_zone_used; bool last_insert_id_used,insert_id_used, clear_next_insert_id; + /* for IS NULL => = last_insert_id() fix in remove_eq_conds() */ + bool substitute_null_with_insert_id; bool in_lock_tables; bool query_error, bootstrap, cleanup_done; bool tmp_table_used; @@ -1452,6 +1457,7 @@ public: { last_insert_id= id_arg; insert_id_used=1; + substitute_null_with_insert_id= TRUE; } inline ulonglong insert_id(void) { diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index af20b770c56..381d1a71e31 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -194,6 +194,10 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, deleted=0L; init_ftfuncs(thd, select_lex, 1); thd->proc_info="updating"; + + if (table->triggers) + table->triggers->mark_fields_used(thd, TRG_EVENT_DELETE); + while (!(error=info.read_record(&info)) && !thd->killed && !thd->net.report_error) { @@ -387,7 +391,7 @@ extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b) bool mysql_multi_delete_prepare(THD *thd) { LEX *lex= thd->lex; - TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxilliary_table_list.first; + TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxiliary_table_list.first; TABLE_LIST *target_tbl; DBUG_ENTER("mysql_multi_delete_prepare"); @@ -507,6 +511,8 @@ multi_delete::initialize_tables(JOIN *join) transactional_tables= 1; else normal_tables= 1; + if (tbl->triggers) + tbl->triggers->mark_fields_used(thd, TRG_EVENT_DELETE); } else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) && walk == delete_tables) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index ba0d2d00f2c..7274d38a7cc 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -17,6 +17,44 @@ /* Insert of records */ +/* + INSERT DELAYED + + Insert delayed is distinguished from a normal insert by lock_type == + TL_WRITE_DELAYED instead of TL_WRITE. It first tries to open a + "delayed" table (delayed_get_table()), but falls back to + open_and_lock_tables() on error and proceeds as normal insert then. + + Opening a "delayed" table means to find a delayed insert thread that + has the table open already. If this fails, a new thread is created and + waited for to open and lock the table. + + If accessing the thread succeeded, in + delayed_insert::get_local_table() the table of the thread is copied + for local use. A copy is required because the normal insert logic + works on a target table, but the other threads table object must not + be used. The insert logic uses the record buffer to create a record. + And the delayed insert thread uses the record buffer to pass the + record to the table handler. So there must be different objects. Also + the copied table is not included in the lock, so that the statement + can proceed even if the real table cannot be accessed at this moment. + + Copying a table object is not a trivial operation. Besides the TABLE + object there are the field pointer array, the field objects and the + record buffer. After copying the field objects, their pointers into + the record must be "moved" to point to the new record buffer. + + After this setup the normal insert logic is used. Only that for + delayed inserts write_delayed() is called instead of write_record(). + It inserts the rows into a queue and signals the delayed insert thread + instead of writing directly to the table. + + The delayed insert thread awakes from the signal. It locks the table, + inserts the rows from the queue, unlocks the table, and waits for the + next signal. It does normally live until a FLUSH TABLES or SHUTDOWN. + +*/ + #include "mysql_priv.h" #include "sp_head.h" #include "sql_trigger.h" @@ -241,6 +279,33 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list, } +/* + Mark fields used by triggers for INSERT-like statement. + + SYNOPSIS + mark_fields_used_by_triggers_for_insert_stmt() + thd The current thread + table Table to which insert will happen + duplic Type of duplicate handling for insert which will happen + + NOTE + For REPLACE there is no sense in marking particular fields + used by ON DELETE trigger as to execute it properly we have + to retrieve and store values for all table columns anyway. +*/ + +void mark_fields_used_by_triggers_for_insert_stmt(THD *thd, TABLE *table, + enum_duplicates duplic) +{ + if (table->triggers) + { + table->triggers->mark_fields_used(thd, TRG_EVENT_INSERT); + if (duplic == DUP_UPDATE) + table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE); + } +} + + bool mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, List<List_item> &values_list, @@ -400,6 +465,17 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, thd->proc_info="update"; if (duplic != DUP_ERROR || ignore) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + if (duplic == DUP_REPLACE) + { + if (!table->triggers || !table->triggers->has_delete_triggers()) + table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); + /* + REPLACE should change values of all columns so we should mark + all columns as columns to be set. As nice side effect we will + retrieve columns which values are needed for ON DELETE triggers. + */ + table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); + } /* let's *try* to start bulk inserts. It won't necessary start them as values_list.elements should be greater than @@ -428,6 +504,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, error= 1; } + mark_fields_used_by_triggers_for_insert_stmt(thd, table, duplic); + if (table_list->prepare_where(thd, 0, TRUE) || table_list->prepare_check_option(thd)) error= 1; @@ -598,6 +676,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, thd->next_insert_id=0; // Reset this if wrongly used if (duplic != DUP_ERROR || ignore) table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); + if (duplic == DUP_REPLACE && + (!table->triggers || !table->triggers->has_delete_triggers())) + table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); /* Reset value of LAST_INSERT_ID if no rows where inserted */ if (!info.copied && thd->insert_id_used) @@ -674,6 +755,7 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view) 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; + bool save_set_query_id= thd->set_query_id; DBUG_ENTER("check_key_in_view"); if (!used_fields_buff) @@ -686,15 +768,26 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view) bitmap_clear_all(&used_fields); view->contain_auto_increment= 0; + /* + we must not set query_id for fields as they're not + really used in this context + */ + thd->set_query_id= 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; + { + thd->set_query_id= save_set_query_id; + DBUG_RETURN(TRUE); + } Item_field *field; /* simple SELECT list entry (field without expression) */ if (!(field= trans->item->filed_for_view_update())) + { + thd->set_query_id= save_set_query_id; DBUG_RETURN(TRUE); + } if (field->field->unireg_check == Field::NEXT_NUMBER) view->contain_auto_increment= 1; /* prepare unique test */ @@ -704,6 +797,7 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view) */ trans->item= field; } + thd->set_query_id= save_set_query_id; /* unique test */ for (trans= trans_start; trans != trans_end; trans++) { @@ -954,7 +1048,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) uint key_nr; if (error != HA_WRITE_SKIP) goto err; - table->file->restore_auto_increment(); if ((int) (key_nr = table->file->get_dup_key(error)) < 0) { error=HA_WRITE_SKIP; /* Database can't find key */ @@ -1027,20 +1120,20 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) if (res == VIEW_CHECK_ERROR) goto before_trg_err; - if (thd->clear_next_insert_id) - { - /* Reset auto-increment cacheing if we do an update */ - thd->clear_next_insert_id= 0; - thd->next_insert_id= 0; - } if ((error=table->file->update_row(table->record[1],table->record[0]))) { if ((error == HA_ERR_FOUND_DUPP_KEY) && info->ignore) + { + table->file->restore_auto_increment(); goto ok_or_after_trg_err; + } goto err; } info->updated++; + if (table->next_number_field) + table->file->adjust_next_insert_id_after_explicit_value(table->next_number_field->val_int()); + trg_error= (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE)); @@ -1069,12 +1162,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH) && (!table->triggers || !table->triggers->has_delete_triggers())) { - if (thd->clear_next_insert_id) - { - /* Reset auto-increment cacheing if we do an update */ - thd->clear_next_insert_id= 0; - thd->next_insert_id= 0; - } if ((error=table->file->update_row(table->record[1], table->record[0]))) goto err; @@ -1138,6 +1225,7 @@ err: table->file->print_error(error,MYF(0)); before_trg_err: + table->file->restore_auto_increment(); if (key) my_safe_afree(key, table->s->max_unique_length, MAX_KEY_LENGTH); DBUG_RETURN(1); @@ -1441,6 +1529,7 @@ TABLE *delayed_insert::get_local_table(THD* client_thd) my_ptrdiff_t adjust_ptrs; Field **field,**org_field, *found_next_number_field; TABLE *copy; + DBUG_ENTER("delayed_insert::get_local_table"); /* First request insert thread to get a lock */ status=1; @@ -1464,31 +1553,47 @@ TABLE *delayed_insert::get_local_table(THD* client_thd) } } + /* + Allocate memory for the TABLE object, the field pointers array, and + one record buffer of reclength size. Normally a table has three + record buffers of rec_buff_length size, which includes alignment + bytes. Since the table copy is used for creating one record only, + the other record buffers and alignment are unnecessary. + */ client_thd->proc_info="allocating local table"; copy= (TABLE*) client_thd->alloc(sizeof(*copy)+ (table->s->fields+1)*sizeof(Field**)+ table->s->reclength); if (!copy) goto error; + + /* Copy the TABLE object. */ *copy= *table; copy->s= ©->share_not_to_be_used; // No name hashing bzero((char*) ©->s->name_hash,sizeof(copy->s->name_hash)); /* We don't need to change the file handler here */ - field=copy->field=(Field**) (copy+1); - copy->record[0]=(byte*) (field+table->s->fields+1); - memcpy((char*) copy->record[0],(char*) table->record[0],table->s->reclength); + /* Assign the pointers for the field pointers array and the record. */ + field= copy->field= (Field**) (copy + 1); + copy->record[0]= (byte*) (field + table->s->fields + 1); + memcpy((char*) copy->record[0], (char*) table->record[0], + table->s->reclength); - /* Make a copy of all fields */ - - adjust_ptrs=PTR_BYTE_DIFF(copy->record[0],table->record[0]); + /* + Make a copy of all fields. + The copied fields need to point into the copied record. This is done + by copying the field objects with their old pointer values and then + "move" the pointers by the distance between the original and copied + records. That way we preserve the relative positions in the records. + */ + adjust_ptrs= PTR_BYTE_DIFF(copy->record[0], table->record[0]); - found_next_number_field=table->found_next_number_field; - for (org_field=table->field ; *org_field ; org_field++,field++) + found_next_number_field= table->found_next_number_field; + for (org_field= table->field; *org_field; org_field++, field++) { - if (!(*field= (*org_field)->new_field(client_thd->mem_root,copy))) - return 0; + if (!(*field= (*org_field)->new_field(client_thd->mem_root, copy, 1))) + DBUG_RETURN(0); (*field)->orig_table= copy; // Remove connection (*field)->move_field(adjust_ptrs); // Point at copy->record[0] if (*org_field == found_next_number_field) @@ -1515,14 +1620,14 @@ TABLE *delayed_insert::get_local_table(THD* client_thd) /* Adjust lock_count. This table object is not part of a lock. */ copy->lock_count= 0; - return copy; + DBUG_RETURN(copy); /* Got fatal error */ error: tables_in_use--; status=1; pthread_cond_signal(&cond); // Inform thread about abort - return 0; + DBUG_RETURN(0); } @@ -1879,7 +1984,8 @@ bool delayed_insert::handle_inserts(void) { int error; ulong max_rows; - bool using_ignore=0, using_bin_log=mysql_bin_log.is_open(); + bool using_ignore= 0, using_opt_replace= 0; + bool using_bin_log= mysql_bin_log.is_open(); delayed_row *row; DBUG_ENTER("handle_inserts"); @@ -1941,6 +2047,13 @@ bool delayed_insert::handle_inserts(void) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); using_ignore=1; } + if (info.handle_duplicates == DUP_REPLACE && + (!table->triggers || + !table->triggers->has_delete_triggers())) + { + table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); + using_opt_replace= 1; + } thd.clear_error(); // reset error for binlog if (write_record(&thd, table, &info)) { @@ -1953,6 +2066,11 @@ bool delayed_insert::handle_inserts(void) using_ignore=0; table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); } + if (using_opt_replace) + { + using_opt_replace= 0; + table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); + } if (row->query && row->log_query && using_bin_log) { Query_log_event qinfo(&thd, row->query, row->query_length, 0, FALSE); @@ -2198,6 +2316,12 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) thd->cuted_fields=0; if (info.ignore || info.handle_duplicates != DUP_ERROR) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + if (info.handle_duplicates == DUP_REPLACE) + { + if (!table->triggers || !table->triggers->has_delete_triggers()) + table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); + table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); + } thd->no_trans_update= 0; thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & @@ -2207,6 +2331,10 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) check_that_all_fields_are_given_values(thd, table, table_list)) || table_list->prepare_where(thd, 0, TRUE) || table_list->prepare_check_option(thd)); + + if (!res) + mark_fields_used_by_triggers_for_insert_stmt(thd, table, + info.handle_duplicates); DBUG_RETURN(res); } @@ -2372,6 +2500,7 @@ bool select_insert::send_eof() error= (!thd->prelocked_mode) ? table->file->end_bulk_insert():0; table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); + table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); /* We must invalidate the table in the query cache before binlog writing @@ -2601,6 +2730,12 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) thd->cuted_fields=0; if (info.ignore || info.handle_duplicates != DUP_ERROR) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + if (info.handle_duplicates == DUP_REPLACE) + { + if (!table->triggers || !table->triggers->has_delete_triggers()) + table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); + table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); + } if (!thd->prelocked_mode) table->file->start_bulk_insert((ha_rows) 0); thd->no_trans_update= 0; @@ -2640,6 +2775,7 @@ bool select_create::send_eof() else { table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); + table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); VOID(pthread_mutex_lock(&LOCK_open)); mysql_unlock_tables(thd, lock); /* @@ -2673,6 +2809,7 @@ void select_create::abort() if (table) { table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); + table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); enum db_type table_type=table->s->db_type; if (!table->s->tmp_table) { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 47af816f41d..7d4dca15608 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -41,8 +41,6 @@ sys_var_long_ptr trg_new_row_fake_var(0, 0); #define yySkip() lex->ptr++ #define yyLength() ((uint) (lex->ptr - lex->tok_start)-1) -pthread_key(LEX*,THR_LEX); - /* Longest standard keyword name */ #define TOCK_NAME_LENGTH 24 @@ -91,8 +89,6 @@ void lex_init(void) for (i=0 ; i < array_elements(sql_functions) ; i++) sql_functions[i].length=(uchar) strlen(sql_functions[i].name); - VOID(pthread_key_create(&THR_LEX,NULL)); - DBUG_VOID_RETURN; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 285e1d6d5a6..e5b087fc72a 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -873,7 +873,7 @@ typedef struct st_lex : public Query_tables_list */ List<Name_resolution_context> context_stack; - SQL_LIST proc_list, auxilliary_table_list, save_list; + SQL_LIST proc_list, auxiliary_table_list, save_list; create_field *last_field; Item_sum *in_sum_func; udf_func udf; @@ -1116,6 +1116,3 @@ extern void lex_start(THD *thd, uchar *buf,uint length); extern void lex_end(LEX *lex); extern int MYSQLlex(void *arg, void *yythd); -extern pthread_key(LEX*,THR_LEX); - -#define current_lex (current_thd->lex) diff --git a/sql/sql_load.cc b/sql/sql_load.cc index eaee5edf9f1..40e1e6b07aa 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -225,6 +225,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, DBUG_RETURN(TRUE); } + mark_fields_used_by_triggers_for_insert_stmt(thd, table, handle_duplicates); + uint tot_length=0; bool use_blobs= 0, use_vars= 0; List_iterator_fast<Item> it(fields_vars); @@ -357,6 +359,13 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, if (ignore || handle_duplicates == DUP_REPLACE) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + if (handle_duplicates == DUP_REPLACE) + { + if (!table->triggers || + !table->triggers->has_delete_triggers()) + table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); + table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); + } if (!thd->prelocked_mode) table->file->start_bulk_insert((ha_rows) 0); table->copy_blobs=1; @@ -381,6 +390,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, error= 1; } table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); + table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); table->next_number_field=0; } ha_enable_transaction(thd, TRUE); diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc new file mode 100644 index 00000000000..9dae55e4508 --- /dev/null +++ b/sql/sql_locale.cc @@ -0,0 +1,1607 @@ +/* Copyright (C) 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 */ + +/* + The beginnings of locale(7) support. + Sponsored for subset of LC_TIME support, WorkLog entry 2928, -- Josh Chamas + + !! This file is built from my_locale.pl !! +*/ + +#include "mysql_priv.h" + + +MY_LOCALE *my_locale_by_name(const char *name) +{ + MY_LOCALE **locale; + for( locale= my_locales; *locale != NULL; locale++) + { + if(!strcmp((*locale)->name, name)) + return *locale; + } + return NULL; +} + +/***** LOCALE BEGIN ar_AE: Arabic - United Arab Emirates *****/ +static const char *my_locale_month_names_ar_AE[13] = + {"يناير","Ùبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوÙمبر","ديسمبر", NullS }; +static const char *my_locale_ab_month_names_ar_AE[13] = + {"ينا","Ùبر","مار","أبر","ماي","يون","يول","أغس","سبت","أكت","نوÙ","ديس", NullS }; +static const char *my_locale_day_names_ar_AE[8] = + {"الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت ","الأØد", NullS }; +static const char *my_locale_ab_day_names_ar_AE[8] = + {"Ù†","Ø«","ر","Ø®","ج","س","Ø", NullS }; +static TYPELIB my_locale_typelib_month_names_ar_AE = + { array_elements(my_locale_month_names_ar_AE)-1, "", my_locale_month_names_ar_AE, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ar_AE = + { array_elements(my_locale_ab_month_names_ar_AE)-1, "", my_locale_ab_month_names_ar_AE, NULL }; +static TYPELIB my_locale_typelib_day_names_ar_AE = + { array_elements(my_locale_day_names_ar_AE)-1, "", my_locale_day_names_ar_AE, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ar_AE = + { array_elements(my_locale_ab_day_names_ar_AE)-1, "", my_locale_ab_day_names_ar_AE, NULL }; +MY_LOCALE my_locale_ar_AE= + { "ar_AE", "Arabic - United Arab Emirates", FALSE, &my_locale_typelib_month_names_ar_AE, &my_locale_typelib_ab_month_names_ar_AE, &my_locale_typelib_day_names_ar_AE, &my_locale_typelib_ab_day_names_ar_AE }; +/***** LOCALE END ar_AE *****/ + +/***** LOCALE BEGIN ar_BH: Arabic - Bahrain *****/ +static const char *my_locale_month_names_ar_BH[13] = + {"يناير","Ùبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوÙمبر","ديسمبر", NullS }; +static const char *my_locale_ab_month_names_ar_BH[13] = + {"ينا","Ùبر","مار","أبر","ماي","يون","يول","أغس","سبت","أكت","نوÙ","ديس", NullS }; +static const char *my_locale_day_names_ar_BH[8] = + {"الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأØد", NullS }; +static const char *my_locale_ab_day_names_ar_BH[8] = + {"Ù†","Ø«","ر","Ø®","ج","س","Ø", NullS }; +static TYPELIB my_locale_typelib_month_names_ar_BH = + { array_elements(my_locale_month_names_ar_BH)-1, "", my_locale_month_names_ar_BH, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ar_BH = + { array_elements(my_locale_ab_month_names_ar_BH)-1, "", my_locale_ab_month_names_ar_BH, NULL }; +static TYPELIB my_locale_typelib_day_names_ar_BH = + { array_elements(my_locale_day_names_ar_BH)-1, "", my_locale_day_names_ar_BH, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ar_BH = + { array_elements(my_locale_ab_day_names_ar_BH)-1, "", my_locale_ab_day_names_ar_BH, NULL }; +MY_LOCALE my_locale_ar_BH= + { "ar_BH", "Arabic - Bahrain", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH }; +/***** LOCALE END ar_BH *****/ + +/***** LOCALE BEGIN ar_JO: Arabic - Jordan *****/ +static const char *my_locale_month_names_ar_JO[13] = + {"كانون الثاني","شباط","آذار","نيسان","نوار","Øزيران","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول", NullS }; +static const char *my_locale_ab_month_names_ar_JO[13] = + {"كانون الثاني","شباط","آذار","نيسان","نوار","Øزيران","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول", NullS }; +static const char *my_locale_day_names_ar_JO[8] = + {"الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأØد", NullS }; +static const char *my_locale_ab_day_names_ar_JO[8] = + {"الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأØد", NullS }; +static TYPELIB my_locale_typelib_month_names_ar_JO = + { array_elements(my_locale_month_names_ar_JO)-1, "", my_locale_month_names_ar_JO, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ar_JO = + { array_elements(my_locale_ab_month_names_ar_JO)-1, "", my_locale_ab_month_names_ar_JO, NULL }; +static TYPELIB my_locale_typelib_day_names_ar_JO = + { array_elements(my_locale_day_names_ar_JO)-1, "", my_locale_day_names_ar_JO, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ar_JO = + { array_elements(my_locale_ab_day_names_ar_JO)-1, "", my_locale_ab_day_names_ar_JO, NULL }; +MY_LOCALE my_locale_ar_JO= + { "ar_JO", "Arabic - Jordan", FALSE, &my_locale_typelib_month_names_ar_JO, &my_locale_typelib_ab_month_names_ar_JO, &my_locale_typelib_day_names_ar_JO, &my_locale_typelib_ab_day_names_ar_JO }; +/***** LOCALE END ar_JO *****/ + +/***** LOCALE BEGIN ar_SA: Arabic - Saudi Arabia *****/ +static const char *my_locale_month_names_ar_SA[13] = + {"كانون الثاني","شباط","آذار","نيسـان","أيار","Øزيران","تـمـوز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول", NullS }; +static const char *my_locale_ab_month_names_ar_SA[13] = + {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec", NullS }; +static const char *my_locale_day_names_ar_SA[8] = + {"الإثنين","الثلاثاء","الأربعاء","الخميس","الجمعـة","السبت","الأØد", NullS }; +static const char *my_locale_ab_day_names_ar_SA[8] = + {"Mon","Tue","Wed","Thu","Fri","Sat","Sun", NullS }; +static TYPELIB my_locale_typelib_month_names_ar_SA = + { array_elements(my_locale_month_names_ar_SA)-1, "", my_locale_month_names_ar_SA, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ar_SA = + { array_elements(my_locale_ab_month_names_ar_SA)-1, "", my_locale_ab_month_names_ar_SA, NULL }; +static TYPELIB my_locale_typelib_day_names_ar_SA = + { array_elements(my_locale_day_names_ar_SA)-1, "", my_locale_day_names_ar_SA, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ar_SA = + { array_elements(my_locale_ab_day_names_ar_SA)-1, "", my_locale_ab_day_names_ar_SA, NULL }; +MY_LOCALE my_locale_ar_SA= + { "ar_SA", "Arabic - Saudi Arabia", FALSE, &my_locale_typelib_month_names_ar_SA, &my_locale_typelib_ab_month_names_ar_SA, &my_locale_typelib_day_names_ar_SA, &my_locale_typelib_ab_day_names_ar_SA }; +/***** LOCALE END ar_SA *****/ + +/***** LOCALE BEGIN ar_SY: Arabic - Syria *****/ +static const char *my_locale_month_names_ar_SY[13] = + {"كانون الثاني","شباط","آذار","نيسان","نواران","Øزير","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول", NullS }; +static const char *my_locale_ab_month_names_ar_SY[13] = + {"كانون الثاني","شباط","آذار","نيسان","نوار","Øزيران","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول", NullS }; +static const char *my_locale_day_names_ar_SY[8] = + {"الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأØد", NullS }; +static const char *my_locale_ab_day_names_ar_SY[8] = + {"الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأØد", NullS }; +static TYPELIB my_locale_typelib_month_names_ar_SY = + { array_elements(my_locale_month_names_ar_SY)-1, "", my_locale_month_names_ar_SY, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ar_SY = + { array_elements(my_locale_ab_month_names_ar_SY)-1, "", my_locale_ab_month_names_ar_SY, NULL }; +static TYPELIB my_locale_typelib_day_names_ar_SY = + { array_elements(my_locale_day_names_ar_SY)-1, "", my_locale_day_names_ar_SY, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ar_SY = + { array_elements(my_locale_ab_day_names_ar_SY)-1, "", my_locale_ab_day_names_ar_SY, NULL }; +MY_LOCALE my_locale_ar_SY= + { "ar_SY", "Arabic - Syria", FALSE, &my_locale_typelib_month_names_ar_SY, &my_locale_typelib_ab_month_names_ar_SY, &my_locale_typelib_day_names_ar_SY, &my_locale_typelib_ab_day_names_ar_SY }; +/***** LOCALE END ar_SY *****/ + +/***** LOCALE BEGIN be_BY: Belarusian - Belarus *****/ +static const char *my_locale_month_names_be_BY[13] = + {"Студзень","Люты","Сакавік","КраÑавік","Травень","ЧÑрвень","Ліпень","Жнівень","ВераÑень","КаÑтрычнік","ЛіÑтапад","Снежань", NullS }; +static const char *my_locale_ab_month_names_be_BY[13] = + {"Стд","Лют","Сак","КрÑ","Тра","ЧÑÑ€","Ліп","Жнв","Ð’Ñ€Ñ","КÑÑ‚","ЛіÑ","Снж", NullS }; +static const char *my_locale_day_names_be_BY[8] = + {"ПанÑдзелак","Ðўторак","Серада","Чацвер","ПÑтніца","Субота","ÐÑдзелÑ", NullS }; +static const char *my_locale_ab_day_names_be_BY[8] = + {"Пан","Ðўт","Срд","Чцв","ПÑÑ‚","Суб","ÐÑд", NullS }; +static TYPELIB my_locale_typelib_month_names_be_BY = + { array_elements(my_locale_month_names_be_BY)-1, "", my_locale_month_names_be_BY, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_be_BY = + { array_elements(my_locale_ab_month_names_be_BY)-1, "", my_locale_ab_month_names_be_BY, NULL }; +static TYPELIB my_locale_typelib_day_names_be_BY = + { array_elements(my_locale_day_names_be_BY)-1, "", my_locale_day_names_be_BY, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_be_BY = + { array_elements(my_locale_ab_day_names_be_BY)-1, "", my_locale_ab_day_names_be_BY, NULL }; +MY_LOCALE my_locale_be_BY= + { "be_BY", "Belarusian - Belarus", FALSE, &my_locale_typelib_month_names_be_BY, &my_locale_typelib_ab_month_names_be_BY, &my_locale_typelib_day_names_be_BY, &my_locale_typelib_ab_day_names_be_BY }; +/***** LOCALE END be_BY *****/ + +/***** LOCALE BEGIN bg_BG: Bulgarian - Bulgaria *****/ +static const char *my_locale_month_names_bg_BG[13] = + {"Ñнуари","февруари","март","април","май","юни","юли","авгуÑÑ‚","Ñептември","октомври","ноември","декември", NullS }; +static const char *my_locale_ab_month_names_bg_BG[13] = + {"Ñну","фев","мар","апр","май","юни","юли","авг","Ñеп","окт","ное","дек", NullS }; +static const char *my_locale_day_names_bg_BG[8] = + {"понеделник","вторник","ÑÑ€Ñда","четвъртък","петък","Ñъбота","неделÑ", NullS }; +static const char *my_locale_ab_day_names_bg_BG[8] = + {"пн","вт","ÑÑ€","чт","пт","Ñб","нд", NullS }; +static TYPELIB my_locale_typelib_month_names_bg_BG = + { array_elements(my_locale_month_names_bg_BG)-1, "", my_locale_month_names_bg_BG, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_bg_BG = + { array_elements(my_locale_ab_month_names_bg_BG)-1, "", my_locale_ab_month_names_bg_BG, NULL }; +static TYPELIB my_locale_typelib_day_names_bg_BG = + { array_elements(my_locale_day_names_bg_BG)-1, "", my_locale_day_names_bg_BG, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_bg_BG = + { array_elements(my_locale_ab_day_names_bg_BG)-1, "", my_locale_ab_day_names_bg_BG, NULL }; +MY_LOCALE my_locale_bg_BG= + { "bg_BG", "Bulgarian - Bulgaria", FALSE, &my_locale_typelib_month_names_bg_BG, &my_locale_typelib_ab_month_names_bg_BG, &my_locale_typelib_day_names_bg_BG, &my_locale_typelib_ab_day_names_bg_BG }; +/***** LOCALE END bg_BG *****/ + +/***** LOCALE BEGIN ca_ES: Catalan - Catalan *****/ +static const char *my_locale_month_names_ca_ES[13] = + {"gener","febrer","març","abril","maig","juny","juliol","agost","setembre","octubre","novembre","desembre", NullS }; +static const char *my_locale_ab_month_names_ca_ES[13] = + {"gen","feb","mar","abr","mai","jun","jul","ago","set","oct","nov","des", NullS }; +static const char *my_locale_day_names_ca_ES[8] = + {"dilluns","dimarts","dimecres","dijous","divendres","dissabte","diumenge", NullS }; +static const char *my_locale_ab_day_names_ca_ES[8] = + {"dl","dt","dc","dj","dv","ds","dg", NullS }; +static TYPELIB my_locale_typelib_month_names_ca_ES = + { array_elements(my_locale_month_names_ca_ES)-1, "", my_locale_month_names_ca_ES, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ca_ES = + { array_elements(my_locale_ab_month_names_ca_ES)-1, "", my_locale_ab_month_names_ca_ES, NULL }; +static TYPELIB my_locale_typelib_day_names_ca_ES = + { array_elements(my_locale_day_names_ca_ES)-1, "", my_locale_day_names_ca_ES, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ca_ES = + { array_elements(my_locale_ab_day_names_ca_ES)-1, "", my_locale_ab_day_names_ca_ES, NULL }; +MY_LOCALE my_locale_ca_ES= + { "ca_ES", "Catalan - Catalan", FALSE, &my_locale_typelib_month_names_ca_ES, &my_locale_typelib_ab_month_names_ca_ES, &my_locale_typelib_day_names_ca_ES, &my_locale_typelib_ab_day_names_ca_ES }; +/***** LOCALE END ca_ES *****/ + +/***** LOCALE BEGIN cs_CZ: Czech - Czech Republic *****/ +static const char *my_locale_month_names_cs_CZ[13] = + {"leden","únor","bÅ™ezen","duben","kvÄ›ten","Äerven","Äervenec","srpen","zářÃ","Å™Ãjen","listopad","prosinec", NullS }; +static const char *my_locale_ab_month_names_cs_CZ[13] = + {"led","úno","bÅ™e","dub","kvÄ›","Äen","Äec","srp","zář","Å™Ãj","lis","pro", NullS }; +static const char *my_locale_day_names_cs_CZ[8] = + {"PondÄ›lÃ","Úterý","StÅ™eda","ÄŒtvrtek","Pátek","Sobota","NedÄ›le", NullS }; +static const char *my_locale_ab_day_names_cs_CZ[8] = + {"Po","Út","St","ÄŒt","Pá","So","Ne", NullS }; +static TYPELIB my_locale_typelib_month_names_cs_CZ = + { array_elements(my_locale_month_names_cs_CZ)-1, "", my_locale_month_names_cs_CZ, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_cs_CZ = + { array_elements(my_locale_ab_month_names_cs_CZ)-1, "", my_locale_ab_month_names_cs_CZ, NULL }; +static TYPELIB my_locale_typelib_day_names_cs_CZ = + { array_elements(my_locale_day_names_cs_CZ)-1, "", my_locale_day_names_cs_CZ, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_cs_CZ = + { array_elements(my_locale_ab_day_names_cs_CZ)-1, "", my_locale_ab_day_names_cs_CZ, NULL }; +MY_LOCALE my_locale_cs_CZ= + { "cs_CZ", "Czech - Czech Republic", FALSE, &my_locale_typelib_month_names_cs_CZ, &my_locale_typelib_ab_month_names_cs_CZ, &my_locale_typelib_day_names_cs_CZ, &my_locale_typelib_ab_day_names_cs_CZ }; +/***** LOCALE END cs_CZ *****/ + +/***** LOCALE BEGIN da_DK: Danish - Denmark *****/ +static const char *my_locale_month_names_da_DK[13] = + {"januar","februar","marts","april","maj","juni","juli","august","september","oktober","november","december", NullS }; +static const char *my_locale_ab_month_names_da_DK[13] = + {"jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec", NullS }; +static const char *my_locale_day_names_da_DK[8] = + {"mandag","tirsdag","onsdag","torsdag","fredag","lørdag","søndag", NullS }; +static const char *my_locale_ab_day_names_da_DK[8] = + {"man","tir","ons","tor","fre","lør","søn", NullS }; +static TYPELIB my_locale_typelib_month_names_da_DK = + { array_elements(my_locale_month_names_da_DK)-1, "", my_locale_month_names_da_DK, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_da_DK = + { array_elements(my_locale_ab_month_names_da_DK)-1, "", my_locale_ab_month_names_da_DK, NULL }; +static TYPELIB my_locale_typelib_day_names_da_DK = + { array_elements(my_locale_day_names_da_DK)-1, "", my_locale_day_names_da_DK, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_da_DK = + { array_elements(my_locale_ab_day_names_da_DK)-1, "", my_locale_ab_day_names_da_DK, NULL }; +MY_LOCALE my_locale_da_DK= + { "da_DK", "Danish - Denmark", FALSE, &my_locale_typelib_month_names_da_DK, &my_locale_typelib_ab_month_names_da_DK, &my_locale_typelib_day_names_da_DK, &my_locale_typelib_ab_day_names_da_DK }; +/***** LOCALE END da_DK *****/ + +/***** LOCALE BEGIN de_AT: German - Austria *****/ +static const char *my_locale_month_names_de_AT[13] = + {"Jänner","Feber","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS }; +static const char *my_locale_ab_month_names_de_AT[13] = + {"Jän","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez", NullS }; +static const char *my_locale_day_names_de_AT[8] = + {"Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag","Sonntag", NullS }; +static const char *my_locale_ab_day_names_de_AT[8] = + {"Mon","Die","Mit","Don","Fre","Sam","Son", NullS }; +static TYPELIB my_locale_typelib_month_names_de_AT = + { array_elements(my_locale_month_names_de_AT)-1, "", my_locale_month_names_de_AT, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_de_AT = + { array_elements(my_locale_ab_month_names_de_AT)-1, "", my_locale_ab_month_names_de_AT, NULL }; +static TYPELIB my_locale_typelib_day_names_de_AT = + { array_elements(my_locale_day_names_de_AT)-1, "", my_locale_day_names_de_AT, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_de_AT = + { array_elements(my_locale_ab_day_names_de_AT)-1, "", my_locale_ab_day_names_de_AT, NULL }; +MY_LOCALE my_locale_de_AT= + { "de_AT", "German - Austria", FALSE, &my_locale_typelib_month_names_de_AT, &my_locale_typelib_ab_month_names_de_AT, &my_locale_typelib_day_names_de_AT, &my_locale_typelib_ab_day_names_de_AT }; +/***** LOCALE END de_AT *****/ + +/***** LOCALE BEGIN de_DE: German - Germany *****/ +static const char *my_locale_month_names_de_DE[13] = + {"Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS }; +static const char *my_locale_ab_month_names_de_DE[13] = + {"Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez", NullS }; +static const char *my_locale_day_names_de_DE[8] = + {"Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag","Sonntag", NullS }; +static const char *my_locale_ab_day_names_de_DE[8] = + {"Mo","Di","Mi","Do","Fr","Sa","So", NullS }; +static TYPELIB my_locale_typelib_month_names_de_DE = + { array_elements(my_locale_month_names_de_DE)-1, "", my_locale_month_names_de_DE, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_de_DE = + { array_elements(my_locale_ab_month_names_de_DE)-1, "", my_locale_ab_month_names_de_DE, NULL }; +static TYPELIB my_locale_typelib_day_names_de_DE = + { array_elements(my_locale_day_names_de_DE)-1, "", my_locale_day_names_de_DE, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_de_DE = + { array_elements(my_locale_ab_day_names_de_DE)-1, "", my_locale_ab_day_names_de_DE, NULL }; +MY_LOCALE my_locale_de_DE= + { "de_DE", "German - Germany", FALSE, &my_locale_typelib_month_names_de_DE, &my_locale_typelib_ab_month_names_de_DE, &my_locale_typelib_day_names_de_DE, &my_locale_typelib_ab_day_names_de_DE }; +/***** LOCALE END de_DE *****/ + +/***** LOCALE BEGIN en_US: English - United States *****/ +static const char *my_locale_month_names_en_US[13] = + {"January","February","March","April","May","June","July","August","September","October","November","December", NullS }; +static const char *my_locale_ab_month_names_en_US[13] = + {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec", NullS }; +static const char *my_locale_day_names_en_US[8] = + {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday", NullS }; +static const char *my_locale_ab_day_names_en_US[8] = + {"Mon","Tue","Wed","Thu","Fri","Sat","Sun", NullS }; +static TYPELIB my_locale_typelib_month_names_en_US = + { array_elements(my_locale_month_names_en_US)-1, "", my_locale_month_names_en_US, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_en_US = + { array_elements(my_locale_ab_month_names_en_US)-1, "", my_locale_ab_month_names_en_US, NULL }; +static TYPELIB my_locale_typelib_day_names_en_US = + { array_elements(my_locale_day_names_en_US)-1, "", my_locale_day_names_en_US, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_en_US = + { array_elements(my_locale_ab_day_names_en_US)-1, "", my_locale_ab_day_names_en_US, NULL }; +MY_LOCALE my_locale_en_US= + { "en_US", "English - United States", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US }; +/***** LOCALE END en_US *****/ + +/***** LOCALE BEGIN es_ES: Spanish - Spain *****/ +static const char *my_locale_month_names_es_ES[13] = + {"enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre", NullS }; +static const char *my_locale_ab_month_names_es_ES[13] = + {"ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic", NullS }; +static const char *my_locale_day_names_es_ES[8] = + {"lunes","martes","miércoles","jueves","viernes","sábado","domingo", NullS }; +static const char *my_locale_ab_day_names_es_ES[8] = + {"lun","mar","mié","jue","vie","sáb","dom", NullS }; +static TYPELIB my_locale_typelib_month_names_es_ES = + { array_elements(my_locale_month_names_es_ES)-1, "", my_locale_month_names_es_ES, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_es_ES = + { array_elements(my_locale_ab_month_names_es_ES)-1, "", my_locale_ab_month_names_es_ES, NULL }; +static TYPELIB my_locale_typelib_day_names_es_ES = + { array_elements(my_locale_day_names_es_ES)-1, "", my_locale_day_names_es_ES, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_es_ES = + { array_elements(my_locale_ab_day_names_es_ES)-1, "", my_locale_ab_day_names_es_ES, NULL }; +MY_LOCALE my_locale_es_ES= + { "es_ES", "Spanish - Spain", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_ES *****/ + +/***** LOCALE BEGIN et_EE: Estonian - Estonia *****/ +static const char *my_locale_month_names_et_EE[13] = + {"jaanuar","veebruar","märts","aprill","mai","juuni","juuli","august","september","oktoober","november","detsember", NullS }; +static const char *my_locale_ab_month_names_et_EE[13] = + {"jaan ","veebr","märts","apr ","mai ","juuni","juuli","aug ","sept ","okt ","nov ","dets ", NullS }; +static const char *my_locale_day_names_et_EE[8] = + {"esmaspäev","teisipäev","kolmapäev","neljapäev","reede","laupäev","pühapäev", NullS }; +static const char *my_locale_ab_day_names_et_EE[8] = + {"E","T","K","N","R","L","P", NullS }; +static TYPELIB my_locale_typelib_month_names_et_EE = + { array_elements(my_locale_month_names_et_EE)-1, "", my_locale_month_names_et_EE, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_et_EE = + { array_elements(my_locale_ab_month_names_et_EE)-1, "", my_locale_ab_month_names_et_EE, NULL }; +static TYPELIB my_locale_typelib_day_names_et_EE = + { array_elements(my_locale_day_names_et_EE)-1, "", my_locale_day_names_et_EE, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_et_EE = + { array_elements(my_locale_ab_day_names_et_EE)-1, "", my_locale_ab_day_names_et_EE, NULL }; +MY_LOCALE my_locale_et_EE= + { "et_EE", "Estonian - Estonia", FALSE, &my_locale_typelib_month_names_et_EE, &my_locale_typelib_ab_month_names_et_EE, &my_locale_typelib_day_names_et_EE, &my_locale_typelib_ab_day_names_et_EE }; +/***** LOCALE END et_EE *****/ + +/***** LOCALE BEGIN eu_ES: Basque - Basque *****/ +static const char *my_locale_month_names_eu_ES[13] = + {"urtarrila","otsaila","martxoa","apirila","maiatza","ekaina","uztaila","abuztua","iraila","urria","azaroa","abendua", NullS }; +static const char *my_locale_ab_month_names_eu_ES[13] = + {"urt","ots","mar","api","mai","eka","uzt","abu","ira","urr","aza","abe", NullS }; +static const char *my_locale_day_names_eu_ES[8] = + {"astelehena","asteartea","asteazkena","osteguna","ostirala","larunbata","igandea", NullS }; +static const char *my_locale_ab_day_names_eu_ES[8] = + {"al.","ar.","az.","og.","or.","lr.","ig.", NullS }; +static TYPELIB my_locale_typelib_month_names_eu_ES = + { array_elements(my_locale_month_names_eu_ES)-1, "", my_locale_month_names_eu_ES, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_eu_ES = + { array_elements(my_locale_ab_month_names_eu_ES)-1, "", my_locale_ab_month_names_eu_ES, NULL }; +static TYPELIB my_locale_typelib_day_names_eu_ES = + { array_elements(my_locale_day_names_eu_ES)-1, "", my_locale_day_names_eu_ES, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_eu_ES = + { array_elements(my_locale_ab_day_names_eu_ES)-1, "", my_locale_ab_day_names_eu_ES, NULL }; +MY_LOCALE my_locale_eu_ES= + { "eu_ES", "Basque - Basque", TRUE, &my_locale_typelib_month_names_eu_ES, &my_locale_typelib_ab_month_names_eu_ES, &my_locale_typelib_day_names_eu_ES, &my_locale_typelib_ab_day_names_eu_ES }; +/***** LOCALE END eu_ES *****/ + +/***** LOCALE BEGIN fi_FI: Finnish - Finland *****/ +static const char *my_locale_month_names_fi_FI[13] = + {"tammikuu","helmikuu","maaliskuu","huhtikuu","toukokuu","kesäkuu","heinäkuu","elokuu","syyskuu","lokakuu","marraskuu","joulukuu", NullS }; +static const char *my_locale_ab_month_names_fi_FI[13] = + {"tammi ","helmi ","maalis","huhti ","touko ","kesä  ","heinä ","elo   ","syys  ","loka  ","marras","joulu ", NullS }; +static const char *my_locale_day_names_fi_FI[8] = + {"maanantai","tiistai","keskiviikko","torstai","perjantai","lauantai","sunnuntai", NullS }; +static const char *my_locale_ab_day_names_fi_FI[8] = + {"ma","ti","ke","to","pe","la","su", NullS }; +static TYPELIB my_locale_typelib_month_names_fi_FI = + { array_elements(my_locale_month_names_fi_FI)-1, "", my_locale_month_names_fi_FI, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_fi_FI = + { array_elements(my_locale_ab_month_names_fi_FI)-1, "", my_locale_ab_month_names_fi_FI, NULL }; +static TYPELIB my_locale_typelib_day_names_fi_FI = + { array_elements(my_locale_day_names_fi_FI)-1, "", my_locale_day_names_fi_FI, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_fi_FI = + { array_elements(my_locale_ab_day_names_fi_FI)-1, "", my_locale_ab_day_names_fi_FI, NULL }; +MY_LOCALE my_locale_fi_FI= + { "fi_FI", "Finnish - Finland", FALSE, &my_locale_typelib_month_names_fi_FI, &my_locale_typelib_ab_month_names_fi_FI, &my_locale_typelib_day_names_fi_FI, &my_locale_typelib_ab_day_names_fi_FI }; +/***** LOCALE END fi_FI *****/ + +/***** LOCALE BEGIN fo_FO: Faroese - Faroe Islands *****/ +static const char *my_locale_month_names_fo_FO[13] = + {"januar","februar","mars","aprÃl","mai","juni","juli","august","september","oktober","november","desember", NullS }; +static const char *my_locale_ab_month_names_fo_FO[13] = + {"jan","feb","mar","apr","mai","jun","jul","aug","sep","okt","nov","des", NullS }; +static const char *my_locale_day_names_fo_FO[8] = + {"mánadagur","týsdagur","mikudagur","hósdagur","frÃggjadagur","leygardagur","sunnudagur", NullS }; +static const char *my_locale_ab_day_names_fo_FO[8] = + {"mán","týs","mik","hós","frÃ","ley","sun", NullS }; +static TYPELIB my_locale_typelib_month_names_fo_FO = + { array_elements(my_locale_month_names_fo_FO)-1, "", my_locale_month_names_fo_FO, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_fo_FO = + { array_elements(my_locale_ab_month_names_fo_FO)-1, "", my_locale_ab_month_names_fo_FO, NULL }; +static TYPELIB my_locale_typelib_day_names_fo_FO = + { array_elements(my_locale_day_names_fo_FO)-1, "", my_locale_day_names_fo_FO, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_fo_FO = + { array_elements(my_locale_ab_day_names_fo_FO)-1, "", my_locale_ab_day_names_fo_FO, NULL }; +MY_LOCALE my_locale_fo_FO= + { "fo_FO", "Faroese - Faroe Islands", FALSE, &my_locale_typelib_month_names_fo_FO, &my_locale_typelib_ab_month_names_fo_FO, &my_locale_typelib_day_names_fo_FO, &my_locale_typelib_ab_day_names_fo_FO }; +/***** LOCALE END fo_FO *****/ + +/***** LOCALE BEGIN fr_FR: French - France *****/ +static const char *my_locale_month_names_fr_FR[13] = + {"janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre", NullS }; +static const char *my_locale_ab_month_names_fr_FR[13] = + {"jan","fév","mar","avr","mai","jun","jui","aoû","sep","oct","nov","déc", NullS }; +static const char *my_locale_day_names_fr_FR[8] = + {"lundi","mardi","mercredi","jeudi","vendredi","samedi","dimanche", NullS }; +static const char *my_locale_ab_day_names_fr_FR[8] = + {"lun","mar","mer","jeu","ven","sam","dim", NullS }; +static TYPELIB my_locale_typelib_month_names_fr_FR = + { array_elements(my_locale_month_names_fr_FR)-1, "", my_locale_month_names_fr_FR, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_fr_FR = + { array_elements(my_locale_ab_month_names_fr_FR)-1, "", my_locale_ab_month_names_fr_FR, NULL }; +static TYPELIB my_locale_typelib_day_names_fr_FR = + { array_elements(my_locale_day_names_fr_FR)-1, "", my_locale_day_names_fr_FR, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_fr_FR = + { array_elements(my_locale_ab_day_names_fr_FR)-1, "", my_locale_ab_day_names_fr_FR, NULL }; +MY_LOCALE my_locale_fr_FR= + { "fr_FR", "French - France", FALSE, &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, &my_locale_typelib_ab_day_names_fr_FR }; +/***** LOCALE END fr_FR *****/ + +/***** LOCALE BEGIN gl_ES: Galician - Galician *****/ +static const char *my_locale_month_names_gl_ES[13] = + {"Xaneiro","Febreiro","Marzo","Abril","Maio","Xuño","Xullo","Agosto","Setembro","Outubro","Novembro","Decembro", NullS }; +static const char *my_locale_ab_month_names_gl_ES[13] = + {"Xan","Feb","Mar","Abr","Mai","Xuñ","Xul","Ago","Set","Out","Nov","Dec", NullS }; +static const char *my_locale_day_names_gl_ES[8] = + {"Luns","Martes","Mércores","Xoves","Venres","Sábado","Domingo", NullS }; +static const char *my_locale_ab_day_names_gl_ES[8] = + {"Lun","Mar","Mér","Xov","Ven","Sáb","Dom", NullS }; +static TYPELIB my_locale_typelib_month_names_gl_ES = + { array_elements(my_locale_month_names_gl_ES)-1, "", my_locale_month_names_gl_ES, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_gl_ES = + { array_elements(my_locale_ab_month_names_gl_ES)-1, "", my_locale_ab_month_names_gl_ES, NULL }; +static TYPELIB my_locale_typelib_day_names_gl_ES = + { array_elements(my_locale_day_names_gl_ES)-1, "", my_locale_day_names_gl_ES, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_gl_ES = + { array_elements(my_locale_ab_day_names_gl_ES)-1, "", my_locale_ab_day_names_gl_ES, NULL }; +MY_LOCALE my_locale_gl_ES= + { "gl_ES", "Galician - Galician", FALSE, &my_locale_typelib_month_names_gl_ES, &my_locale_typelib_ab_month_names_gl_ES, &my_locale_typelib_day_names_gl_ES, &my_locale_typelib_ab_day_names_gl_ES }; +/***** LOCALE END gl_ES *****/ + +/***** LOCALE BEGIN gu_IN: Gujarati - India *****/ +static const char *my_locale_month_names_gu_IN[13] = + {"જાનà«àª¯à«àª†àª°à«€","ફેબà«àª°à«àª†àª°à«€","મારà«àªš","àªàªªà«àª°àª¿àª²","મે","જà«àª¨","જà«àª²àª¾àª‡","ઓગસà«àªŸ","સેપà«àªŸà«‡àª®à«àª¬àª°","ઓકà«àªŸà«‹àª¬àª°","નવેમà«àª¬àª°","ડિસેમà«àª¬àª°", NullS }; +static const char *my_locale_ab_month_names_gu_IN[13] = + {"જાન","ફેબ","માર","àªàªªà«àª°","મે","જà«àª¨","જà«àª²","ઓગ","સેપà«àªŸ","ઓકà«àªŸ","નોવ","ડિસ", NullS }; +static const char *my_locale_day_names_gu_IN[8] = + {"સોમવાર","મનà«àª—ળવાર","બà«àª§àªµàª¾àª°","ગà«àª°à«àªµàª¾àª°","શà«àª•à«àª°àªµàª¾àª°","શનિવાર","રવિવાર", NullS }; +static const char *my_locale_ab_day_names_gu_IN[8] = + {"સોમ","મનà«àª—ળ","બà«àª§","ગà«àª°à«","શà«àª•à«àª°","શનિ","રવિ", NullS }; +static TYPELIB my_locale_typelib_month_names_gu_IN = + { array_elements(my_locale_month_names_gu_IN)-1, "", my_locale_month_names_gu_IN, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_gu_IN = + { array_elements(my_locale_ab_month_names_gu_IN)-1, "", my_locale_ab_month_names_gu_IN, NULL }; +static TYPELIB my_locale_typelib_day_names_gu_IN = + { array_elements(my_locale_day_names_gu_IN)-1, "", my_locale_day_names_gu_IN, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_gu_IN = + { array_elements(my_locale_ab_day_names_gu_IN)-1, "", my_locale_ab_day_names_gu_IN, NULL }; +MY_LOCALE my_locale_gu_IN= + { "gu_IN", "Gujarati - India", FALSE, &my_locale_typelib_month_names_gu_IN, &my_locale_typelib_ab_month_names_gu_IN, &my_locale_typelib_day_names_gu_IN, &my_locale_typelib_ab_day_names_gu_IN }; +/***** LOCALE END gu_IN *****/ + +/***** LOCALE BEGIN he_IL: Hebrew - Israel *****/ +static const char *my_locale_month_names_he_IL[13] = + {"×™× ×•×ר","פברו×ר","מרץ","×פריל","מ××™","×™×•× ×™","יולי","×וגוסט","ספטמבר","×וקטובר","× ×•×‘×ž×‘×¨","דצמבר", NullS }; +static const char *my_locale_ab_month_names_he_IL[13] = + {"×™× ×•","פבר","מרץ","×פר","מ××™","×™×•× ","יול","×וג","ספט","×וק","× ×•×‘","דצמ", NullS }; +static const char *my_locale_day_names_he_IL[8] = + {"×©× ×™","שלישי","רביעי","חמישי","שישי","שבת","ר×שון", NullS }; +static const char *my_locale_ab_day_names_he_IL[8] = + {"ב'","×’'","ד'","×”'","ו'","ש'","×'", NullS }; +static TYPELIB my_locale_typelib_month_names_he_IL = + { array_elements(my_locale_month_names_he_IL)-1, "", my_locale_month_names_he_IL, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_he_IL = + { array_elements(my_locale_ab_month_names_he_IL)-1, "", my_locale_ab_month_names_he_IL, NULL }; +static TYPELIB my_locale_typelib_day_names_he_IL = + { array_elements(my_locale_day_names_he_IL)-1, "", my_locale_day_names_he_IL, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_he_IL = + { array_elements(my_locale_ab_day_names_he_IL)-1, "", my_locale_ab_day_names_he_IL, NULL }; +MY_LOCALE my_locale_he_IL= + { "he_IL", "Hebrew - Israel", FALSE, &my_locale_typelib_month_names_he_IL, &my_locale_typelib_ab_month_names_he_IL, &my_locale_typelib_day_names_he_IL, &my_locale_typelib_ab_day_names_he_IL }; +/***** LOCALE END he_IL *****/ + +/***** LOCALE BEGIN hi_IN: Hindi - India *****/ +static const char *my_locale_month_names_hi_IN[13] = + {"जनवरी","फ़रवरी","मारà¥à¤š","अपà¥à¤°à¥‡à¤²","मई","जून","जà¥à¤²à¤¾à¤ˆ","अगसà¥à¤¤","सितमà¥à¤¬à¤°","अकà¥à¤Ÿà¥‚बर","नवमà¥à¤¬à¤°","दिसमà¥à¤¬à¤°", NullS }; +static const char *my_locale_ab_month_names_hi_IN[13] = + {"जनवरी","फ़रवरी","मारà¥à¤š","अपà¥à¤°à¥‡à¤²","मई","जून","जà¥à¤²à¤¾à¤ˆ","अगसà¥à¤¤","सितमà¥à¤¬à¤°","अकà¥à¤Ÿà¥‚बर","नवमà¥à¤¬à¤°","दिसमà¥à¤¬à¤°", NullS }; +static const char *my_locale_day_names_hi_IN[8] = + {"सोमवार ","मंगलवार ","बà¥à¤§à¤µà¤¾à¤° ","गà¥à¤°à¥à¤µà¤¾à¤° ","शà¥à¤•à¥à¤°à¤µà¤¾à¤° ","शनिवार ","रविवार ", NullS }; +static const char *my_locale_ab_day_names_hi_IN[8] = + {"सोम ","मंगल ","बà¥à¤§ ","गà¥à¤°à¥ ","शà¥à¤•à¥à¤° ","शनि ","रवि ", NullS }; +static TYPELIB my_locale_typelib_month_names_hi_IN = + { array_elements(my_locale_month_names_hi_IN)-1, "", my_locale_month_names_hi_IN, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_hi_IN = + { array_elements(my_locale_ab_month_names_hi_IN)-1, "", my_locale_ab_month_names_hi_IN, NULL }; +static TYPELIB my_locale_typelib_day_names_hi_IN = + { array_elements(my_locale_day_names_hi_IN)-1, "", my_locale_day_names_hi_IN, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_hi_IN = + { array_elements(my_locale_ab_day_names_hi_IN)-1, "", my_locale_ab_day_names_hi_IN, NULL }; +MY_LOCALE my_locale_hi_IN= + { "hi_IN", "Hindi - India", FALSE, &my_locale_typelib_month_names_hi_IN, &my_locale_typelib_ab_month_names_hi_IN, &my_locale_typelib_day_names_hi_IN, &my_locale_typelib_ab_day_names_hi_IN }; +/***** LOCALE END hi_IN *****/ + +/***** LOCALE BEGIN hr_HR: Croatian - Croatia *****/ +static const char *my_locale_month_names_hr_HR[13] = + {"SijeÄanj","VeljaÄa","Ožujak","Travanj","Svibanj","Lipanj","Srpanj","Kolovoz","Rujan","Listopad","Studeni","Prosinac", NullS }; +static const char *my_locale_ab_month_names_hr_HR[13] = + {"Sij","Vel","Ožu","Tra","Svi","Lip","Srp","Kol","Ruj","Lis","Stu","Pro", NullS }; +static const char *my_locale_day_names_hr_HR[8] = + {"Ponedjeljak","Utorak","Srijeda","ÄŒetvrtak","Petak","Subota","Nedjelja", NullS }; +static const char *my_locale_ab_day_names_hr_HR[8] = + {"Pon","Uto","Sri","ÄŒet","Pet","Sub","Ned", NullS }; +static TYPELIB my_locale_typelib_month_names_hr_HR = + { array_elements(my_locale_month_names_hr_HR)-1, "", my_locale_month_names_hr_HR, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_hr_HR = + { array_elements(my_locale_ab_month_names_hr_HR)-1, "", my_locale_ab_month_names_hr_HR, NULL }; +static TYPELIB my_locale_typelib_day_names_hr_HR = + { array_elements(my_locale_day_names_hr_HR)-1, "", my_locale_day_names_hr_HR, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_hr_HR = + { array_elements(my_locale_ab_day_names_hr_HR)-1, "", my_locale_ab_day_names_hr_HR, NULL }; +MY_LOCALE my_locale_hr_HR= + { "hr_HR", "Croatian - Croatia", FALSE, &my_locale_typelib_month_names_hr_HR, &my_locale_typelib_ab_month_names_hr_HR, &my_locale_typelib_day_names_hr_HR, &my_locale_typelib_ab_day_names_hr_HR }; +/***** LOCALE END hr_HR *****/ + +/***** LOCALE BEGIN hu_HU: Hungarian - Hungary *****/ +static const char *my_locale_month_names_hu_HU[13] = + {"január","február","március","április","május","június","július","augusztus","szeptember","október","november","december", NullS }; +static const char *my_locale_ab_month_names_hu_HU[13] = + {"jan","feb","már","ápr","máj","jún","júl","aug","sze","okt","nov","dec", NullS }; +static const char *my_locale_day_names_hu_HU[8] = + {"hétfÅ‘","kedd","szerda","csütörtök","péntek","szombat","vasárnap", NullS }; +static const char *my_locale_ab_day_names_hu_HU[8] = + {"h","k","sze","cs","p","szo","v", NullS }; +static TYPELIB my_locale_typelib_month_names_hu_HU = + { array_elements(my_locale_month_names_hu_HU)-1, "", my_locale_month_names_hu_HU, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_hu_HU = + { array_elements(my_locale_ab_month_names_hu_HU)-1, "", my_locale_ab_month_names_hu_HU, NULL }; +static TYPELIB my_locale_typelib_day_names_hu_HU = + { array_elements(my_locale_day_names_hu_HU)-1, "", my_locale_day_names_hu_HU, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_hu_HU = + { array_elements(my_locale_ab_day_names_hu_HU)-1, "", my_locale_ab_day_names_hu_HU, NULL }; +MY_LOCALE my_locale_hu_HU= + { "hu_HU", "Hungarian - Hungary", FALSE, &my_locale_typelib_month_names_hu_HU, &my_locale_typelib_ab_month_names_hu_HU, &my_locale_typelib_day_names_hu_HU, &my_locale_typelib_ab_day_names_hu_HU }; +/***** LOCALE END hu_HU *****/ + +/***** LOCALE BEGIN id_ID: Indonesian - Indonesia *****/ +static const char *my_locale_month_names_id_ID[13] = + {"Januari","Pebruari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember", NullS }; +static const char *my_locale_ab_month_names_id_ID[13] = + {"Jan","Peb","Mar","Apr","Mei","Jun","Jul","Agu","Sep","Okt","Nov","Des", NullS }; +static const char *my_locale_day_names_id_ID[8] = + {"Senin","Selasa","Rabu","Kamis","Jumat","Sabtu","Minggu", NullS }; +static const char *my_locale_ab_day_names_id_ID[8] = + {"Sen","Sel","Rab","Kam","Jum","Sab","Min", NullS }; +static TYPELIB my_locale_typelib_month_names_id_ID = + { array_elements(my_locale_month_names_id_ID)-1, "", my_locale_month_names_id_ID, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_id_ID = + { array_elements(my_locale_ab_month_names_id_ID)-1, "", my_locale_ab_month_names_id_ID, NULL }; +static TYPELIB my_locale_typelib_day_names_id_ID = + { array_elements(my_locale_day_names_id_ID)-1, "", my_locale_day_names_id_ID, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_id_ID = + { array_elements(my_locale_ab_day_names_id_ID)-1, "", my_locale_ab_day_names_id_ID, NULL }; +MY_LOCALE my_locale_id_ID= + { "id_ID", "Indonesian - Indonesia", TRUE, &my_locale_typelib_month_names_id_ID, &my_locale_typelib_ab_month_names_id_ID, &my_locale_typelib_day_names_id_ID, &my_locale_typelib_ab_day_names_id_ID }; +/***** LOCALE END id_ID *****/ + +/***** LOCALE BEGIN is_IS: Icelandic - Iceland *****/ +static const char *my_locale_month_names_is_IS[13] = + {"janúar","febrúar","mars","aprÃl","maÃ","júnÃ","júlÃ","ágúst","september","október","nóvember","desember", NullS }; +static const char *my_locale_ab_month_names_is_IS[13] = + {"jan","feb","mar","apr","maÃ","jún","júl","ágú","sep","okt","nóv","des", NullS }; +static const char *my_locale_day_names_is_IS[8] = + {"mánudagur","þriðjudagur","miðvikudagur","fimmtudagur","föstudagur","laugardagur","sunnudagur", NullS }; +static const char *my_locale_ab_day_names_is_IS[8] = + {"mán","þri","mið","fim","fös","lau","sun", NullS }; +static TYPELIB my_locale_typelib_month_names_is_IS = + { array_elements(my_locale_month_names_is_IS)-1, "", my_locale_month_names_is_IS, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_is_IS = + { array_elements(my_locale_ab_month_names_is_IS)-1, "", my_locale_ab_month_names_is_IS, NULL }; +static TYPELIB my_locale_typelib_day_names_is_IS = + { array_elements(my_locale_day_names_is_IS)-1, "", my_locale_day_names_is_IS, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_is_IS = + { array_elements(my_locale_ab_day_names_is_IS)-1, "", my_locale_ab_day_names_is_IS, NULL }; +MY_LOCALE my_locale_is_IS= + { "is_IS", "Icelandic - Iceland", FALSE, &my_locale_typelib_month_names_is_IS, &my_locale_typelib_ab_month_names_is_IS, &my_locale_typelib_day_names_is_IS, &my_locale_typelib_ab_day_names_is_IS }; +/***** LOCALE END is_IS *****/ + +/***** LOCALE BEGIN it_CH: Italian - Switzerland *****/ +static const char *my_locale_month_names_it_CH[13] = + {"gennaio","febbraio","marzo","aprile","maggio","giugno","luglio","agosto","settembre","ottobre","novembre","dicembre", NullS }; +static const char *my_locale_ab_month_names_it_CH[13] = + {"gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic", NullS }; +static const char *my_locale_day_names_it_CH[8] = + {"lunedì","martedì","mercoledì","giovedì","venerdì","sabato","domenica", NullS }; +static const char *my_locale_ab_day_names_it_CH[8] = + {"lun","mar","mer","gio","ven","sab","dom", NullS }; +static TYPELIB my_locale_typelib_month_names_it_CH = + { array_elements(my_locale_month_names_it_CH)-1, "", my_locale_month_names_it_CH, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_it_CH = + { array_elements(my_locale_ab_month_names_it_CH)-1, "", my_locale_ab_month_names_it_CH, NULL }; +static TYPELIB my_locale_typelib_day_names_it_CH = + { array_elements(my_locale_day_names_it_CH)-1, "", my_locale_day_names_it_CH, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_it_CH = + { array_elements(my_locale_ab_day_names_it_CH)-1, "", my_locale_ab_day_names_it_CH, NULL }; +MY_LOCALE my_locale_it_CH= + { "it_CH", "Italian - Switzerland", FALSE, &my_locale_typelib_month_names_it_CH, &my_locale_typelib_ab_month_names_it_CH, &my_locale_typelib_day_names_it_CH, &my_locale_typelib_ab_day_names_it_CH }; +/***** LOCALE END it_CH *****/ + +/***** LOCALE BEGIN ja_JP: Japanese - Japan *****/ +static const char *my_locale_month_names_ja_JP[13] = + {"1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月", NullS }; +static const char *my_locale_ab_month_names_ja_JP[13] = + {" 1月"," 2月"," 3月"," 4月"," 5月"," 6月"," 7月"," 8月"," 9月","10月","11月","12月", NullS }; +static const char *my_locale_day_names_ja_JP[8] = + {"月曜日","ç«æ›œæ—¥","水曜日","木曜日","金曜日","土曜日","日曜日", NullS }; +static const char *my_locale_ab_day_names_ja_JP[8] = + {"月","ç«","æ°´","木","金","土","æ—¥", NullS }; +static TYPELIB my_locale_typelib_month_names_ja_JP = + { array_elements(my_locale_month_names_ja_JP)-1, "", my_locale_month_names_ja_JP, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ja_JP = + { array_elements(my_locale_ab_month_names_ja_JP)-1, "", my_locale_ab_month_names_ja_JP, NULL }; +static TYPELIB my_locale_typelib_day_names_ja_JP = + { array_elements(my_locale_day_names_ja_JP)-1, "", my_locale_day_names_ja_JP, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ja_JP = + { array_elements(my_locale_ab_day_names_ja_JP)-1, "", my_locale_ab_day_names_ja_JP, NULL }; +MY_LOCALE my_locale_ja_JP= + { "ja_JP", "Japanese - Japan", FALSE, &my_locale_typelib_month_names_ja_JP, &my_locale_typelib_ab_month_names_ja_JP, &my_locale_typelib_day_names_ja_JP, &my_locale_typelib_ab_day_names_ja_JP }; +/***** LOCALE END ja_JP *****/ + +/***** LOCALE BEGIN ko_KR: Korean - Korea *****/ +static const char *my_locale_month_names_ko_KR[13] = + {"ì¼ì›”","ì´ì›”","삼월","사월","오월","ìœ ì›”","ì¹ ì›”","팔월","구월","시월","ì‹ì¼ì›”","ì‹ì´ì›”", NullS }; +static const char *my_locale_ab_month_names_ko_KR[13] = + {" 1ì›”"," 2ì›”"," 3ì›”"," 4ì›”"," 5ì›”"," 6ì›”"," 7ì›”"," 8ì›”"," 9ì›”","10ì›”","11ì›”","12ì›”", NullS }; +static const char *my_locale_day_names_ko_KR[8] = + {"월요ì¼","화요ì¼","수요ì¼","목요ì¼","금요ì¼","í† ìš”ì¼","ì¼ìš”ì¼", NullS }; +static const char *my_locale_ab_day_names_ko_KR[8] = + {"ì›”","í™”","수","목","금","í† ","ì¼", NullS }; +static TYPELIB my_locale_typelib_month_names_ko_KR = + { array_elements(my_locale_month_names_ko_KR)-1, "", my_locale_month_names_ko_KR, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ko_KR = + { array_elements(my_locale_ab_month_names_ko_KR)-1, "", my_locale_ab_month_names_ko_KR, NULL }; +static TYPELIB my_locale_typelib_day_names_ko_KR = + { array_elements(my_locale_day_names_ko_KR)-1, "", my_locale_day_names_ko_KR, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ko_KR = + { array_elements(my_locale_ab_day_names_ko_KR)-1, "", my_locale_ab_day_names_ko_KR, NULL }; +MY_LOCALE my_locale_ko_KR= + { "ko_KR", "Korean - Korea", FALSE, &my_locale_typelib_month_names_ko_KR, &my_locale_typelib_ab_month_names_ko_KR, &my_locale_typelib_day_names_ko_KR, &my_locale_typelib_ab_day_names_ko_KR }; +/***** LOCALE END ko_KR *****/ + +/***** LOCALE BEGIN lt_LT: Lithuanian - Lithuania *****/ +static const char *my_locale_month_names_lt_LT[13] = + {"sausio","vasario","kovo","balandžio","gegužės","birželio","liepos","rugpjÅ«Äio","rugsÄ—jo","spalio","lapkriÄio","gruodžio", NullS }; +static const char *my_locale_ab_month_names_lt_LT[13] = + {"Sau","Vas","Kov","Bal","Geg","Bir","Lie","Rgp","Rgs","Spa","Lap","Grd", NullS }; +static const char *my_locale_day_names_lt_LT[8] = + {"Pirmadienis","Antradienis","TreÄiadienis","Ketvirtadienis","Penktadienis","Å eÅ¡tadienis","Sekmadienis", NullS }; +static const char *my_locale_ab_day_names_lt_LT[8] = + {"Pr","An","Tr","Kt","Pn","Å t","Sk", NullS }; +static TYPELIB my_locale_typelib_month_names_lt_LT = + { array_elements(my_locale_month_names_lt_LT)-1, "", my_locale_month_names_lt_LT, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_lt_LT = + { array_elements(my_locale_ab_month_names_lt_LT)-1, "", my_locale_ab_month_names_lt_LT, NULL }; +static TYPELIB my_locale_typelib_day_names_lt_LT = + { array_elements(my_locale_day_names_lt_LT)-1, "", my_locale_day_names_lt_LT, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_lt_LT = + { array_elements(my_locale_ab_day_names_lt_LT)-1, "", my_locale_ab_day_names_lt_LT, NULL }; +MY_LOCALE my_locale_lt_LT= + { "lt_LT", "Lithuanian - Lithuania", FALSE, &my_locale_typelib_month_names_lt_LT, &my_locale_typelib_ab_month_names_lt_LT, &my_locale_typelib_day_names_lt_LT, &my_locale_typelib_ab_day_names_lt_LT }; +/***** LOCALE END lt_LT *****/ + +/***** LOCALE BEGIN lv_LV: Latvian - Latvia *****/ +static const char *my_locale_month_names_lv_LV[13] = + {"janvÄris","februÄris","marts","aprÄ«lis","maijs","jÅ«nijs","jÅ«lijs","augusts","septembris","oktobris","novembris","decembris", NullS }; +static const char *my_locale_ab_month_names_lv_LV[13] = + {"jan","feb","mar","apr","mai","jÅ«n","jÅ«l","aug","sep","okt","nov","dec", NullS }; +static const char *my_locale_day_names_lv_LV[8] = + {"pirmdiena","otrdiena","treÅ¡diena","ceturtdiena","piektdiena","sestdiena","svÄ“tdiena", NullS }; +static const char *my_locale_ab_day_names_lv_LV[8] = + {"P ","O ","T ","C ","Pk","S ","Sv", NullS }; +static TYPELIB my_locale_typelib_month_names_lv_LV = + { array_elements(my_locale_month_names_lv_LV)-1, "", my_locale_month_names_lv_LV, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_lv_LV = + { array_elements(my_locale_ab_month_names_lv_LV)-1, "", my_locale_ab_month_names_lv_LV, NULL }; +static TYPELIB my_locale_typelib_day_names_lv_LV = + { array_elements(my_locale_day_names_lv_LV)-1, "", my_locale_day_names_lv_LV, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_lv_LV = + { array_elements(my_locale_ab_day_names_lv_LV)-1, "", my_locale_ab_day_names_lv_LV, NULL }; +MY_LOCALE my_locale_lv_LV= + { "lv_LV", "Latvian - Latvia", FALSE, &my_locale_typelib_month_names_lv_LV, &my_locale_typelib_ab_month_names_lv_LV, &my_locale_typelib_day_names_lv_LV, &my_locale_typelib_ab_day_names_lv_LV }; +/***** LOCALE END lv_LV *****/ + +/***** LOCALE BEGIN mk_MK: Macedonian - FYROM *****/ +static const char *my_locale_month_names_mk_MK[13] = + {"јануари","февруари","март","април","мај","јуни","јули","авгуÑÑ‚","Ñептември","октомври","ноември","декември", NullS }; +static const char *my_locale_ab_month_names_mk_MK[13] = + {"јан","фев","мар","апр","мај","јун","јул","авг","Ñеп","окт","ное","дек", NullS }; +static const char *my_locale_day_names_mk_MK[8] = + {"понеделник","вторник","Ñреда","четврток","петок","Ñабота","недела", NullS }; +static const char *my_locale_ab_day_names_mk_MK[8] = + {"пон","вто","Ñре","чет","пет","Ñаб","нед", NullS }; +static TYPELIB my_locale_typelib_month_names_mk_MK = + { array_elements(my_locale_month_names_mk_MK)-1, "", my_locale_month_names_mk_MK, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_mk_MK = + { array_elements(my_locale_ab_month_names_mk_MK)-1, "", my_locale_ab_month_names_mk_MK, NULL }; +static TYPELIB my_locale_typelib_day_names_mk_MK = + { array_elements(my_locale_day_names_mk_MK)-1, "", my_locale_day_names_mk_MK, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_mk_MK = + { array_elements(my_locale_ab_day_names_mk_MK)-1, "", my_locale_ab_day_names_mk_MK, NULL }; +MY_LOCALE my_locale_mk_MK= + { "mk_MK", "Macedonian - FYROM", FALSE, &my_locale_typelib_month_names_mk_MK, &my_locale_typelib_ab_month_names_mk_MK, &my_locale_typelib_day_names_mk_MK, &my_locale_typelib_ab_day_names_mk_MK }; +/***** LOCALE END mk_MK *****/ + +/***** LOCALE BEGIN mn_MN: Mongolia - Mongolian *****/ +static const char *my_locale_month_names_mn_MN[13] = + {"ÐÑгдүгÑÑÑ€ Ñар","Хоёрдугаар Ñар","Гуравдугаар Ñар","ДөрөвдүгÑÑÑ€ Ñар","Тавдугаар Ñар","Зургаадугар Ñар","Долоодугаар Ñар","Ðаймдугаар Ñар","ЕÑдүгÑÑÑ€ Ñар","Ðравдугаар Ñар","ÐрваннÑгдүгÑÑÑ€ Ñар","Ðрванхоёрдгаар Ñар", NullS }; +static const char *my_locale_ab_month_names_mn_MN[13] = + {"1-Ñ€","2-Ñ€","3-Ñ€","4-Ñ€","5-Ñ€","6-Ñ€","7-Ñ€","8-Ñ€","9-Ñ€","10-Ñ€","11-Ñ€","12-Ñ€", NullS }; +static const char *my_locale_day_names_mn_MN[8] = + {"Даваа","ÐœÑгмар","Лхагва","ПүрÑв","БааÑан","БÑмба","ÐÑм", NullS }; +static const char *my_locale_ab_day_names_mn_MN[8] = + {"Да","ÐœÑ","Лх","Пү","Ба","БÑ","ÐÑ", NullS }; +static TYPELIB my_locale_typelib_month_names_mn_MN = + { array_elements(my_locale_month_names_mn_MN)-1, "", my_locale_month_names_mn_MN, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_mn_MN = + { array_elements(my_locale_ab_month_names_mn_MN)-1, "", my_locale_ab_month_names_mn_MN, NULL }; +static TYPELIB my_locale_typelib_day_names_mn_MN = + { array_elements(my_locale_day_names_mn_MN)-1, "", my_locale_day_names_mn_MN, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_mn_MN = + { array_elements(my_locale_ab_day_names_mn_MN)-1, "", my_locale_ab_day_names_mn_MN, NULL }; +MY_LOCALE my_locale_mn_MN= + { "mn_MN", "Mongolia - Mongolian", FALSE, &my_locale_typelib_month_names_mn_MN, &my_locale_typelib_ab_month_names_mn_MN, &my_locale_typelib_day_names_mn_MN, &my_locale_typelib_ab_day_names_mn_MN }; +/***** LOCALE END mn_MN *****/ + +/***** LOCALE BEGIN ms_MY: Malay - Malaysia *****/ +static const char *my_locale_month_names_ms_MY[13] = + {"Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember", NullS }; +static const char *my_locale_ab_month_names_ms_MY[13] = + {"Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ogos","Sep","Okt","Nov","Dis", NullS }; +static const char *my_locale_day_names_ms_MY[8] = + {"Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu","Ahad", NullS }; +static const char *my_locale_ab_day_names_ms_MY[8] = + {"Isn","Sel","Rab","Kha","Jum","Sab","Ahd", NullS }; +static TYPELIB my_locale_typelib_month_names_ms_MY = + { array_elements(my_locale_month_names_ms_MY)-1, "", my_locale_month_names_ms_MY, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ms_MY = + { array_elements(my_locale_ab_month_names_ms_MY)-1, "", my_locale_ab_month_names_ms_MY, NULL }; +static TYPELIB my_locale_typelib_day_names_ms_MY = + { array_elements(my_locale_day_names_ms_MY)-1, "", my_locale_day_names_ms_MY, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ms_MY = + { array_elements(my_locale_ab_day_names_ms_MY)-1, "", my_locale_ab_day_names_ms_MY, NULL }; +MY_LOCALE my_locale_ms_MY= + { "ms_MY", "Malay - Malaysia", TRUE, &my_locale_typelib_month_names_ms_MY, &my_locale_typelib_ab_month_names_ms_MY, &my_locale_typelib_day_names_ms_MY, &my_locale_typelib_ab_day_names_ms_MY }; +/***** LOCALE END ms_MY *****/ + +/***** LOCALE BEGIN nb_NO: Norwegian(Bokml) - Norway *****/ +static const char *my_locale_month_names_nb_NO[13] = + {"januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember", NullS }; +static const char *my_locale_ab_month_names_nb_NO[13] = + {"jan","feb","mar","apr","mai","jun","jul","aug","sep","okt","nov","des", NullS }; +static const char *my_locale_day_names_nb_NO[8] = + {"mandag","tirsdag","onsdag","torsdag","fredag","lørdag","søndag", NullS }; +static const char *my_locale_ab_day_names_nb_NO[8] = + {"man","tir","ons","tor","fre","lør","søn", NullS }; +static TYPELIB my_locale_typelib_month_names_nb_NO = + { array_elements(my_locale_month_names_nb_NO)-1, "", my_locale_month_names_nb_NO, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_nb_NO = + { array_elements(my_locale_ab_month_names_nb_NO)-1, "", my_locale_ab_month_names_nb_NO, NULL }; +static TYPELIB my_locale_typelib_day_names_nb_NO = + { array_elements(my_locale_day_names_nb_NO)-1, "", my_locale_day_names_nb_NO, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_nb_NO = + { array_elements(my_locale_ab_day_names_nb_NO)-1, "", my_locale_ab_day_names_nb_NO, NULL }; +MY_LOCALE my_locale_nb_NO= + { "nb_NO", "Norwegian(Bokml) - Norway", FALSE, &my_locale_typelib_month_names_nb_NO, &my_locale_typelib_ab_month_names_nb_NO, &my_locale_typelib_day_names_nb_NO, &my_locale_typelib_ab_day_names_nb_NO }; +/***** LOCALE END nb_NO *****/ + +/***** LOCALE BEGIN nl_NL: Dutch - The Netherlands *****/ +static const char *my_locale_month_names_nl_NL[13] = + {"januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december", NullS }; +static const char *my_locale_ab_month_names_nl_NL[13] = + {"jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec", NullS }; +static const char *my_locale_day_names_nl_NL[8] = + {"maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag","zondag", NullS }; +static const char *my_locale_ab_day_names_nl_NL[8] = + {"ma","di","wo","do","vr","za","zo", NullS }; +static TYPELIB my_locale_typelib_month_names_nl_NL = + { array_elements(my_locale_month_names_nl_NL)-1, "", my_locale_month_names_nl_NL, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_nl_NL = + { array_elements(my_locale_ab_month_names_nl_NL)-1, "", my_locale_ab_month_names_nl_NL, NULL }; +static TYPELIB my_locale_typelib_day_names_nl_NL = + { array_elements(my_locale_day_names_nl_NL)-1, "", my_locale_day_names_nl_NL, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_nl_NL = + { array_elements(my_locale_ab_day_names_nl_NL)-1, "", my_locale_ab_day_names_nl_NL, NULL }; +MY_LOCALE my_locale_nl_NL= + { "nl_NL", "Dutch - The Netherlands", TRUE, &my_locale_typelib_month_names_nl_NL, &my_locale_typelib_ab_month_names_nl_NL, &my_locale_typelib_day_names_nl_NL, &my_locale_typelib_ab_day_names_nl_NL }; +/***** LOCALE END nl_NL *****/ + +/***** LOCALE BEGIN pl_PL: Polish - Poland *****/ +static const char *my_locale_month_names_pl_PL[13] = + {"styczeÅ„","luty","marzec","kwiecieÅ„","maj","czerwiec","lipiec","sierpieÅ„","wrzesieÅ„","październik","listopad","grudzieÅ„", NullS }; +static const char *my_locale_ab_month_names_pl_PL[13] = + {"sty","lut","mar","kwi","maj","cze","lip","sie","wrz","paź","lis","gru", NullS }; +static const char *my_locale_day_names_pl_PL[8] = + {"poniedziaÅ‚ek","wtorek","Å›roda","czwartek","piÄ…tek","sobota","niedziela", NullS }; +static const char *my_locale_ab_day_names_pl_PL[8] = + {"pon","wto","Å›ro","czw","piÄ…","sob","nie", NullS }; +static TYPELIB my_locale_typelib_month_names_pl_PL = + { array_elements(my_locale_month_names_pl_PL)-1, "", my_locale_month_names_pl_PL, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_pl_PL = + { array_elements(my_locale_ab_month_names_pl_PL)-1, "", my_locale_ab_month_names_pl_PL, NULL }; +static TYPELIB my_locale_typelib_day_names_pl_PL = + { array_elements(my_locale_day_names_pl_PL)-1, "", my_locale_day_names_pl_PL, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_pl_PL = + { array_elements(my_locale_ab_day_names_pl_PL)-1, "", my_locale_ab_day_names_pl_PL, NULL }; +MY_LOCALE my_locale_pl_PL= + { "pl_PL", "Polish - Poland", FALSE, &my_locale_typelib_month_names_pl_PL, &my_locale_typelib_ab_month_names_pl_PL, &my_locale_typelib_day_names_pl_PL, &my_locale_typelib_ab_day_names_pl_PL }; +/***** LOCALE END pl_PL *****/ + +/***** LOCALE BEGIN pt_BR: Portugese - Brazil *****/ +static const char *my_locale_month_names_pt_BR[13] = + {"janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro", NullS }; +static const char *my_locale_ab_month_names_pt_BR[13] = + {"Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez", NullS }; +static const char *my_locale_day_names_pt_BR[8] = + {"segunda","terça","quarta","quinta","sexta","sábado","domingo", NullS }; +static const char *my_locale_ab_day_names_pt_BR[8] = + {"Seg","Ter","Qua","Qui","Sex","Sáb","Dom", NullS }; +static TYPELIB my_locale_typelib_month_names_pt_BR = + { array_elements(my_locale_month_names_pt_BR)-1, "", my_locale_month_names_pt_BR, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_pt_BR = + { array_elements(my_locale_ab_month_names_pt_BR)-1, "", my_locale_ab_month_names_pt_BR, NULL }; +static TYPELIB my_locale_typelib_day_names_pt_BR = + { array_elements(my_locale_day_names_pt_BR)-1, "", my_locale_day_names_pt_BR, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_pt_BR = + { array_elements(my_locale_ab_day_names_pt_BR)-1, "", my_locale_ab_day_names_pt_BR, NULL }; +MY_LOCALE my_locale_pt_BR= + { "pt_BR", "Portugese - Brazil", FALSE, &my_locale_typelib_month_names_pt_BR, &my_locale_typelib_ab_month_names_pt_BR, &my_locale_typelib_day_names_pt_BR, &my_locale_typelib_ab_day_names_pt_BR }; +/***** LOCALE END pt_BR *****/ + +/***** LOCALE BEGIN pt_PT: Portugese - Portugal *****/ +static const char *my_locale_month_names_pt_PT[13] = + {"Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro", NullS }; +static const char *my_locale_ab_month_names_pt_PT[13] = + {"Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez", NullS }; +static const char *my_locale_day_names_pt_PT[8] = + {"Segunda","Terça","Quarta","Quinta","Sexta","Sábado","Domingo", NullS }; +static const char *my_locale_ab_day_names_pt_PT[8] = + {"Seg","Ter","Qua","Qui","Sex","Sáb","Dom", NullS }; +static TYPELIB my_locale_typelib_month_names_pt_PT = + { array_elements(my_locale_month_names_pt_PT)-1, "", my_locale_month_names_pt_PT, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_pt_PT = + { array_elements(my_locale_ab_month_names_pt_PT)-1, "", my_locale_ab_month_names_pt_PT, NULL }; +static TYPELIB my_locale_typelib_day_names_pt_PT = + { array_elements(my_locale_day_names_pt_PT)-1, "", my_locale_day_names_pt_PT, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_pt_PT = + { array_elements(my_locale_ab_day_names_pt_PT)-1, "", my_locale_ab_day_names_pt_PT, NULL }; +MY_LOCALE my_locale_pt_PT= + { "pt_PT", "Portugese - Portugal", FALSE, &my_locale_typelib_month_names_pt_PT, &my_locale_typelib_ab_month_names_pt_PT, &my_locale_typelib_day_names_pt_PT, &my_locale_typelib_ab_day_names_pt_PT }; +/***** LOCALE END pt_PT *****/ + +/***** LOCALE BEGIN ro_RO: Romanian - Romania *****/ +static const char *my_locale_month_names_ro_RO[13] = + {"Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie","Iulie","August","Septembrie","Octombrie","Noiembrie","Decembrie", NullS }; +static const char *my_locale_ab_month_names_ro_RO[13] = + {"ian","feb","mar","apr","mai","iun","iul","aug","sep","oct","nov","dec", NullS }; +static const char *my_locale_day_names_ro_RO[8] = + {"Luni","MarÅ£i","Miercuri","Joi","Vineri","SîmbÄ‚tÄ‚","DuminicÄ‚", NullS }; +static const char *my_locale_ab_day_names_ro_RO[8] = + {"Lu","Ma","Mi","Jo","Vi","Sî","Du", NullS }; +static TYPELIB my_locale_typelib_month_names_ro_RO = + { array_elements(my_locale_month_names_ro_RO)-1, "", my_locale_month_names_ro_RO, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ro_RO = + { array_elements(my_locale_ab_month_names_ro_RO)-1, "", my_locale_ab_month_names_ro_RO, NULL }; +static TYPELIB my_locale_typelib_day_names_ro_RO = + { array_elements(my_locale_day_names_ro_RO)-1, "", my_locale_day_names_ro_RO, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ro_RO = + { array_elements(my_locale_ab_day_names_ro_RO)-1, "", my_locale_ab_day_names_ro_RO, NULL }; +MY_LOCALE my_locale_ro_RO= + { "ro_RO", "Romanian - Romania", FALSE, &my_locale_typelib_month_names_ro_RO, &my_locale_typelib_ab_month_names_ro_RO, &my_locale_typelib_day_names_ro_RO, &my_locale_typelib_ab_day_names_ro_RO }; +/***** LOCALE END ro_RO *****/ + +/***** LOCALE BEGIN ru_RU: Russian - Russia *****/ +static const char *my_locale_month_names_ru_RU[13] = + {"ЯнварÑ","ФевралÑ","Марта","ÐпрелÑ","МаÑ","ИюнÑ","ИюлÑ","ÐвгуÑта","СентÑбрÑ","ОктÑбрÑ","ÐоÑбрÑ","ДекабрÑ", NullS }; +static const char *my_locale_ab_month_names_ru_RU[13] = + {"Янв","Фев","Мар","Ðпр","Май","Июн","Июл","Ðвг","Сен","Окт","ÐоÑ","Дек", NullS }; +static const char *my_locale_day_names_ru_RU[8] = + {"Понедельник","Вторник","Среда","Четверг","ПÑтница","Суббота","ВоÑкреÑенье", NullS }; +static const char *my_locale_ab_day_names_ru_RU[8] = + {"Пнд","Ð’Ñ‚Ñ€","Срд","Чтв","Птн","Сбт","Ð’Ñк", NullS }; +static TYPELIB my_locale_typelib_month_names_ru_RU = + { array_elements(my_locale_month_names_ru_RU)-1, "", my_locale_month_names_ru_RU, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ru_RU = + { array_elements(my_locale_ab_month_names_ru_RU)-1, "", my_locale_ab_month_names_ru_RU, NULL }; +static TYPELIB my_locale_typelib_day_names_ru_RU = + { array_elements(my_locale_day_names_ru_RU)-1, "", my_locale_day_names_ru_RU, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ru_RU = + { array_elements(my_locale_ab_day_names_ru_RU)-1, "", my_locale_ab_day_names_ru_RU, NULL }; +MY_LOCALE my_locale_ru_RU= + { "ru_RU", "Russian - Russia", FALSE, &my_locale_typelib_month_names_ru_RU, &my_locale_typelib_ab_month_names_ru_RU, &my_locale_typelib_day_names_ru_RU, &my_locale_typelib_ab_day_names_ru_RU }; +/***** LOCALE END ru_RU *****/ + +/***** LOCALE BEGIN ru_UA: Russian - Ukraine *****/ +static const char *my_locale_month_names_ru_UA[13] = + {"Январь","Февраль","Март","Ðпрель","Май","Июнь","Июль","ÐвгуÑÑ‚","СентÑбрь","ОктÑбрь","ÐоÑбрь","Декабрь", NullS }; +static const char *my_locale_ab_month_names_ru_UA[13] = + {"Янв","Фев","Мар","Ðпр","Май","Июн","Июл","Ðвг","Сен","Окт","ÐоÑ","Дек", NullS }; +static const char *my_locale_day_names_ru_UA[8] = + {"Понедельник","Вторник","Среда","Четверг","ПÑтница","Суббота","ВоÑкреÑенье", NullS }; +static const char *my_locale_ab_day_names_ru_UA[8] = + {"Пнд","Вто","Срд","Чтв","Птн","Суб","Ð’Ñк", NullS }; +static TYPELIB my_locale_typelib_month_names_ru_UA = + { array_elements(my_locale_month_names_ru_UA)-1, "", my_locale_month_names_ru_UA, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ru_UA = + { array_elements(my_locale_ab_month_names_ru_UA)-1, "", my_locale_ab_month_names_ru_UA, NULL }; +static TYPELIB my_locale_typelib_day_names_ru_UA = + { array_elements(my_locale_day_names_ru_UA)-1, "", my_locale_day_names_ru_UA, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ru_UA = + { array_elements(my_locale_ab_day_names_ru_UA)-1, "", my_locale_ab_day_names_ru_UA, NULL }; +MY_LOCALE my_locale_ru_UA= + { "ru_UA", "Russian - Ukraine", FALSE, &my_locale_typelib_month_names_ru_UA, &my_locale_typelib_ab_month_names_ru_UA, &my_locale_typelib_day_names_ru_UA, &my_locale_typelib_ab_day_names_ru_UA }; +/***** LOCALE END ru_UA *****/ + +/***** LOCALE BEGIN sk_SK: Slovak - Slovakia *****/ +static const char *my_locale_month_names_sk_SK[13] = + {"január","február","marec","aprÃl","máj","jún","júl","august","september","október","november","december", NullS }; +static const char *my_locale_ab_month_names_sk_SK[13] = + {"jan","feb","mar","apr","máj","jún","júl","aug","sep","okt","nov","dec", NullS }; +static const char *my_locale_day_names_sk_SK[8] = + {"Pondelok","Utorok","Streda","Å tvrtok","Piatok","Sobota","Nedeľa", NullS }; +static const char *my_locale_ab_day_names_sk_SK[8] = + {"Po","Ut","St","Å t","Pi","So","Ne", NullS }; +static TYPELIB my_locale_typelib_month_names_sk_SK = + { array_elements(my_locale_month_names_sk_SK)-1, "", my_locale_month_names_sk_SK, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_sk_SK = + { array_elements(my_locale_ab_month_names_sk_SK)-1, "", my_locale_ab_month_names_sk_SK, NULL }; +static TYPELIB my_locale_typelib_day_names_sk_SK = + { array_elements(my_locale_day_names_sk_SK)-1, "", my_locale_day_names_sk_SK, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_sk_SK = + { array_elements(my_locale_ab_day_names_sk_SK)-1, "", my_locale_ab_day_names_sk_SK, NULL }; +MY_LOCALE my_locale_sk_SK= + { "sk_SK", "Slovak - Slovakia", FALSE, &my_locale_typelib_month_names_sk_SK, &my_locale_typelib_ab_month_names_sk_SK, &my_locale_typelib_day_names_sk_SK, &my_locale_typelib_ab_day_names_sk_SK }; +/***** LOCALE END sk_SK *****/ + +/***** LOCALE BEGIN sl_SI: Slovenian - Slovenia *****/ +static const char *my_locale_month_names_sl_SI[13] = + {"januar","februar","marec","april","maj","junij","julij","avgust","september","oktober","november","december", NullS }; +static const char *my_locale_ab_month_names_sl_SI[13] = + {"jan","feb","mar","apr","maj","jun","jul","avg","sep","okt","nov","dec", NullS }; +static const char *my_locale_day_names_sl_SI[8] = + {"ponedeljek","torek","sreda","Äetrtek","petek","sobota","nedelja", NullS }; +static const char *my_locale_ab_day_names_sl_SI[8] = + {"pon","tor","sre","Äet","pet","sob","ned", NullS }; +static TYPELIB my_locale_typelib_month_names_sl_SI = + { array_elements(my_locale_month_names_sl_SI)-1, "", my_locale_month_names_sl_SI, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_sl_SI = + { array_elements(my_locale_ab_month_names_sl_SI)-1, "", my_locale_ab_month_names_sl_SI, NULL }; +static TYPELIB my_locale_typelib_day_names_sl_SI = + { array_elements(my_locale_day_names_sl_SI)-1, "", my_locale_day_names_sl_SI, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_sl_SI = + { array_elements(my_locale_ab_day_names_sl_SI)-1, "", my_locale_ab_day_names_sl_SI, NULL }; +MY_LOCALE my_locale_sl_SI= + { "sl_SI", "Slovenian - Slovenia", FALSE, &my_locale_typelib_month_names_sl_SI, &my_locale_typelib_ab_month_names_sl_SI, &my_locale_typelib_day_names_sl_SI, &my_locale_typelib_ab_day_names_sl_SI }; +/***** LOCALE END sl_SI *****/ + +/***** LOCALE BEGIN sq_AL: Albanian - Albania *****/ +static const char *my_locale_month_names_sq_AL[13] = + {"janar","shkurt","mars","prill","maj","qershor","korrik","gusht","shtator","tetor","nëntor","dhjetor", NullS }; +static const char *my_locale_ab_month_names_sq_AL[13] = + {"Jan","Shk","Mar","Pri","Maj","Qer","Kor","Gsh","Sht","Tet","Nën","Dhj", NullS }; +static const char *my_locale_day_names_sq_AL[8] = + {"e hënë ","e martë ","e mërkurë ","e enjte ","e premte ","e shtunë ","e diel ", NullS }; +static const char *my_locale_ab_day_names_sq_AL[8] = + {"Hën ","Mar ","Mër ","Enj ","Pre ","Sht ","Die ", NullS }; +static TYPELIB my_locale_typelib_month_names_sq_AL = + { array_elements(my_locale_month_names_sq_AL)-1, "", my_locale_month_names_sq_AL, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_sq_AL = + { array_elements(my_locale_ab_month_names_sq_AL)-1, "", my_locale_ab_month_names_sq_AL, NULL }; +static TYPELIB my_locale_typelib_day_names_sq_AL = + { array_elements(my_locale_day_names_sq_AL)-1, "", my_locale_day_names_sq_AL, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_sq_AL = + { array_elements(my_locale_ab_day_names_sq_AL)-1, "", my_locale_ab_day_names_sq_AL, NULL }; +MY_LOCALE my_locale_sq_AL= + { "sq_AL", "Albanian - Albania", FALSE, &my_locale_typelib_month_names_sq_AL, &my_locale_typelib_ab_month_names_sq_AL, &my_locale_typelib_day_names_sq_AL, &my_locale_typelib_ab_day_names_sq_AL }; +/***** LOCALE END sq_AL *****/ + +/***** LOCALE BEGIN sr_YU: Servian - Yugoslavia *****/ +static const char *my_locale_month_names_sr_YU[13] = + {"januar","februar","mart","april","maj","juni","juli","avgust","septembar","oktobar","novembar","decembar", NullS }; +static const char *my_locale_ab_month_names_sr_YU[13] = + {"jan","feb","mar","apr","maj","jun","jul","avg","sep","okt","nov","dec", NullS }; +static const char *my_locale_day_names_sr_YU[8] = + {"ponedeljak","utorak","sreda","Äetvrtak","petak","subota","nedelja", NullS }; +static const char *my_locale_ab_day_names_sr_YU[8] = + {"pon","uto","sre","Äet","pet","sub","ned", NullS }; +static TYPELIB my_locale_typelib_month_names_sr_YU = + { array_elements(my_locale_month_names_sr_YU)-1, "", my_locale_month_names_sr_YU, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_sr_YU = + { array_elements(my_locale_ab_month_names_sr_YU)-1, "", my_locale_ab_month_names_sr_YU, NULL }; +static TYPELIB my_locale_typelib_day_names_sr_YU = + { array_elements(my_locale_day_names_sr_YU)-1, "", my_locale_day_names_sr_YU, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_sr_YU = + { array_elements(my_locale_ab_day_names_sr_YU)-1, "", my_locale_ab_day_names_sr_YU, NULL }; +MY_LOCALE my_locale_sr_YU= + { "sr_YU", "Servian - Yugoslavia", FALSE, &my_locale_typelib_month_names_sr_YU, &my_locale_typelib_ab_month_names_sr_YU, &my_locale_typelib_day_names_sr_YU, &my_locale_typelib_ab_day_names_sr_YU }; +/***** LOCALE END sr_YU *****/ + +/***** LOCALE BEGIN sv_SE: Swedish - Sweden *****/ +static const char *my_locale_month_names_sv_SE[13] = + {"januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december", NullS }; +static const char *my_locale_ab_month_names_sv_SE[13] = + {"jan","feb","mar","apr","maj","jun","jul","aug","sep","okt","nov","dec", NullS }; +static const char *my_locale_day_names_sv_SE[8] = + {"mÃ¥ndag","tisdag","onsdag","torsdag","fredag","lördag","söndag", NullS }; +static const char *my_locale_ab_day_names_sv_SE[8] = + {"mÃ¥n","tis","ons","tor","fre","lör","sön", NullS }; +static TYPELIB my_locale_typelib_month_names_sv_SE = + { array_elements(my_locale_month_names_sv_SE)-1, "", my_locale_month_names_sv_SE, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_sv_SE = + { array_elements(my_locale_ab_month_names_sv_SE)-1, "", my_locale_ab_month_names_sv_SE, NULL }; +static TYPELIB my_locale_typelib_day_names_sv_SE = + { array_elements(my_locale_day_names_sv_SE)-1, "", my_locale_day_names_sv_SE, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_sv_SE = + { array_elements(my_locale_ab_day_names_sv_SE)-1, "", my_locale_ab_day_names_sv_SE, NULL }; +MY_LOCALE my_locale_sv_SE= + { "sv_SE", "Swedish - Sweden", FALSE, &my_locale_typelib_month_names_sv_SE, &my_locale_typelib_ab_month_names_sv_SE, &my_locale_typelib_day_names_sv_SE, &my_locale_typelib_ab_day_names_sv_SE }; +/***** LOCALE END sv_SE *****/ + +/***** LOCALE BEGIN ta_IN: Tamil - India *****/ +static const char *my_locale_month_names_ta_IN[13] = + {"ஜனவரி","பெபà¯à®°à®µà®°à®¿","மாரà¯à®šà¯","à®à®ªà¯à®°à®²à¯","மே","ஜூனà¯","ஜூலை","ஆகஸà¯à®Ÿà¯","செபà¯à®Ÿà®®à¯à®ªà®°à¯","அகà¯à®Ÿà¯‹à®ªà®°à¯","நவமà¯à®ªà®°à¯","டிசமà¯à®ªà®°à¯r", NullS }; +static const char *my_locale_ab_month_names_ta_IN[13] = + {"ஜனவரி","பெபà¯à®°à®µà®°à®¿","மாரà¯à®šà¯","à®à®ªà¯à®°à®²à¯","மே","ஜூனà¯","ஜூலை","ஆகஸà¯à®Ÿà¯","செபà¯à®Ÿà®®à¯à®ªà®°à¯","அகà¯à®Ÿà¯‹à®ªà®°à¯","நவமà¯à®ªà®°à¯","டிசமà¯à®ªà®°à¯r", NullS }; +static const char *my_locale_day_names_ta_IN[8] = + {"திஙà¯à®•à®³à¯","செவà¯à®µà®¾à®¯à¯","பà¯à®¤à®©à¯","வியாழனà¯","வெளà¯à®³à®¿","சனி","ஞாயிறà¯", NullS }; +static const char *my_locale_ab_day_names_ta_IN[8] = + {"த","ச","ப","வ","வ","ச","ஞ", NullS }; +static TYPELIB my_locale_typelib_month_names_ta_IN = + { array_elements(my_locale_month_names_ta_IN)-1, "", my_locale_month_names_ta_IN, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ta_IN = + { array_elements(my_locale_ab_month_names_ta_IN)-1, "", my_locale_ab_month_names_ta_IN, NULL }; +static TYPELIB my_locale_typelib_day_names_ta_IN = + { array_elements(my_locale_day_names_ta_IN)-1, "", my_locale_day_names_ta_IN, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ta_IN = + { array_elements(my_locale_ab_day_names_ta_IN)-1, "", my_locale_ab_day_names_ta_IN, NULL }; +MY_LOCALE my_locale_ta_IN= + { "ta_IN", "Tamil - India", FALSE, &my_locale_typelib_month_names_ta_IN, &my_locale_typelib_ab_month_names_ta_IN, &my_locale_typelib_day_names_ta_IN, &my_locale_typelib_ab_day_names_ta_IN }; +/***** LOCALE END ta_IN *****/ + +/***** LOCALE BEGIN te_IN: Telugu - India *****/ +static const char *my_locale_month_names_te_IN[13] = + {"జనవరి","à°«à°¿à°¬à±à°°à°µà°°à°¿","మారà±à°šà°¿","à°à°ªà±à°°à°¿à°²à±","మే","జూనà±","జూలై","ఆగసà±à°Ÿà±","సెపà±à°Ÿà±†à°‚బరà±","à°…à°•à±à°Ÿà±‹à°¬à°°à±","నవంబరà±","డిసెంబరà±", NullS }; +static const char *my_locale_ab_month_names_te_IN[13] = + {"జనవరి","à°«à°¿à°¬à±à°°à°µà°°à°¿","మారà±à°šà°¿","à°à°ªà±à°°à°¿à°²à±","మే","జూనà±","జూలై","ఆగసà±à°Ÿà±","సెపà±à°Ÿà±†à°‚బరà±","à°…à°•à±à°Ÿà±‹à°¬à°°à±","నవంబరà±","డిసెంబరà±", NullS }; +static const char *my_locale_day_names_te_IN[8] = + {"సోమవారం","మంగళవారం","à°¬à±à°§à°µà°¾à°°à°‚","à°—à±à°°à±à°µà°¾à°°à°‚","à°¶à±à°•à±à°°à°µà°¾à°°à°‚","శనివారం","ఆదివారం", NullS }; +static const char *my_locale_ab_day_names_te_IN[8] = + {"సోమ","మంగళ","à°¬à±à°§","à°—à±à°°à±","à°¶à±à°•à±à°°","శని","ఆది", NullS }; +static TYPELIB my_locale_typelib_month_names_te_IN = + { array_elements(my_locale_month_names_te_IN)-1, "", my_locale_month_names_te_IN, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_te_IN = + { array_elements(my_locale_ab_month_names_te_IN)-1, "", my_locale_ab_month_names_te_IN, NULL }; +static TYPELIB my_locale_typelib_day_names_te_IN = + { array_elements(my_locale_day_names_te_IN)-1, "", my_locale_day_names_te_IN, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_te_IN = + { array_elements(my_locale_ab_day_names_te_IN)-1, "", my_locale_ab_day_names_te_IN, NULL }; +MY_LOCALE my_locale_te_IN= + { "te_IN", "Telugu - India", FALSE, &my_locale_typelib_month_names_te_IN, &my_locale_typelib_ab_month_names_te_IN, &my_locale_typelib_day_names_te_IN, &my_locale_typelib_ab_day_names_te_IN }; +/***** LOCALE END te_IN *****/ + +/***** LOCALE BEGIN th_TH: Thai - Thailand *****/ +static const char *my_locale_month_names_th_TH[13] = + {"มà¸à¸£à¸²à¸„ม","à¸à¸¸à¸¡à¸ าพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","à¸à¸£à¸à¸Žà¸²à¸„ม","สิงหาคม","à¸à¸±à¸™à¸¢à¸²à¸¢à¸™","ตุลาคม","พฤศจิà¸à¸²à¸¢à¸™","ธันวาคม", NullS }; +static const char *my_locale_ab_month_names_th_TH[13] = + {"ม.ค.","à¸.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","à¸.ค.","ส.ค.","à¸.ย.","ต.ค.","พ.ย.","ธ.ค.", NullS }; +static const char *my_locale_day_names_th_TH[8] = + {"จันทร์","à¸à¸±à¸‡à¸„าร","พุธ","พฤหัสบดี","ศุà¸à¸£à¹Œ","เสาร์","à¸à¸²à¸—ิตย์", NullS }; +static const char *my_locale_ab_day_names_th_TH[8] = + {"จ.","à¸.","พ.","พฤ.","ศ.","ส.","à¸à¸².", NullS }; +static TYPELIB my_locale_typelib_month_names_th_TH = + { array_elements(my_locale_month_names_th_TH)-1, "", my_locale_month_names_th_TH, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_th_TH = + { array_elements(my_locale_ab_month_names_th_TH)-1, "", my_locale_ab_month_names_th_TH, NULL }; +static TYPELIB my_locale_typelib_day_names_th_TH = + { array_elements(my_locale_day_names_th_TH)-1, "", my_locale_day_names_th_TH, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_th_TH = + { array_elements(my_locale_ab_day_names_th_TH)-1, "", my_locale_ab_day_names_th_TH, NULL }; +MY_LOCALE my_locale_th_TH= + { "th_TH", "Thai - Thailand", FALSE, &my_locale_typelib_month_names_th_TH, &my_locale_typelib_ab_month_names_th_TH, &my_locale_typelib_day_names_th_TH, &my_locale_typelib_ab_day_names_th_TH }; +/***** LOCALE END th_TH *****/ + +/***** LOCALE BEGIN tr_TR: Turkish - Turkey *****/ +static const char *my_locale_month_names_tr_TR[13] = + {"Ocak","Åžubat","Mart","Nisan","Mayıs","Haziran","Temmuz","AÄŸustos","Eylül","Ekim","Kasım","Aralık", NullS }; +static const char *my_locale_ab_month_names_tr_TR[13] = + {"Oca","Åžub","Mar","Nis","May","Haz","Tem","AÄŸu","Eyl","Eki","Kas","Ara", NullS }; +static const char *my_locale_day_names_tr_TR[8] = + {"Pazartesi","Salı","ÇarÅŸamba","PerÅŸembe","Cuma","Cumartesi","Pazar", NullS }; +static const char *my_locale_ab_day_names_tr_TR[8] = + {"Pzt","Sal","ÇrÅŸ","PrÅŸ","Cum","Cts","Paz", NullS }; +static TYPELIB my_locale_typelib_month_names_tr_TR = + { array_elements(my_locale_month_names_tr_TR)-1, "", my_locale_month_names_tr_TR, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_tr_TR = + { array_elements(my_locale_ab_month_names_tr_TR)-1, "", my_locale_ab_month_names_tr_TR, NULL }; +static TYPELIB my_locale_typelib_day_names_tr_TR = + { array_elements(my_locale_day_names_tr_TR)-1, "", my_locale_day_names_tr_TR, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_tr_TR = + { array_elements(my_locale_ab_day_names_tr_TR)-1, "", my_locale_ab_day_names_tr_TR, NULL }; +MY_LOCALE my_locale_tr_TR= + { "tr_TR", "Turkish - Turkey", FALSE, &my_locale_typelib_month_names_tr_TR, &my_locale_typelib_ab_month_names_tr_TR, &my_locale_typelib_day_names_tr_TR, &my_locale_typelib_ab_day_names_tr_TR }; +/***** LOCALE END tr_TR *****/ + +/***** LOCALE BEGIN uk_UA: Ukrainian - Ukraine *****/ +static const char *my_locale_month_names_uk_UA[13] = + {"Січень","Лютий","Березень","Квітень","Травень","Червень","Липень","Серпень","ВереÑень","Жовтень","ЛиÑтопад","Грудень", NullS }; +static const char *my_locale_ab_month_names_uk_UA[13] = + {"Січ","Лют","Бер","Кві","Тра","Чер","Лип","Сер","Вер","Жов","ЛиÑ","Гру", NullS }; +static const char *my_locale_day_names_uk_UA[8] = + {"Понеділок","Вівторок","Середа","Четвер","П'ÑтницÑ","Субота","ÐеділÑ", NullS }; +static const char *my_locale_ab_day_names_uk_UA[8] = + {"Пнд","Ð’Ñ‚Ñ€","Срд","Чтв","Птн","Сбт","Ðдл", NullS }; +static TYPELIB my_locale_typelib_month_names_uk_UA = + { array_elements(my_locale_month_names_uk_UA)-1, "", my_locale_month_names_uk_UA, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_uk_UA = + { array_elements(my_locale_ab_month_names_uk_UA)-1, "", my_locale_ab_month_names_uk_UA, NULL }; +static TYPELIB my_locale_typelib_day_names_uk_UA = + { array_elements(my_locale_day_names_uk_UA)-1, "", my_locale_day_names_uk_UA, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_uk_UA = + { array_elements(my_locale_ab_day_names_uk_UA)-1, "", my_locale_ab_day_names_uk_UA, NULL }; +MY_LOCALE my_locale_uk_UA= + { "uk_UA", "Ukrainian - Ukraine", FALSE, &my_locale_typelib_month_names_uk_UA, &my_locale_typelib_ab_month_names_uk_UA, &my_locale_typelib_day_names_uk_UA, &my_locale_typelib_ab_day_names_uk_UA }; +/***** LOCALE END uk_UA *****/ + +/***** LOCALE BEGIN ur_PK: Urdu - Pakistan *****/ +static const char *my_locale_month_names_ur_PK[13] = + {"جنوري","Ùروري","مارچ","اپريل","مٓی","جون","جولاي","اگست","ستمبر","اكتوبر","نومبر","دسمبر", NullS }; +static const char *my_locale_ab_month_names_ur_PK[13] = + {"جنوري","Ùروري","مارچ","اپريل","مٓی","جون","جولاي","اگست","ستمبر","اكتوبر","نومبر","دسمبر", NullS }; +static const char *my_locale_day_names_ur_PK[8] = + {"پير","منگل","بدھ","جمعرات","جمعه","Ù‡Ùته","اتوار", NullS }; +static const char *my_locale_ab_day_names_ur_PK[8] = + {"پير","منگل","بدھ","جمعرات","جمعه","Ù‡Ùته","اتوار", NullS }; +static TYPELIB my_locale_typelib_month_names_ur_PK = + { array_elements(my_locale_month_names_ur_PK)-1, "", my_locale_month_names_ur_PK, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_ur_PK = + { array_elements(my_locale_ab_month_names_ur_PK)-1, "", my_locale_ab_month_names_ur_PK, NULL }; +static TYPELIB my_locale_typelib_day_names_ur_PK = + { array_elements(my_locale_day_names_ur_PK)-1, "", my_locale_day_names_ur_PK, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_ur_PK = + { array_elements(my_locale_ab_day_names_ur_PK)-1, "", my_locale_ab_day_names_ur_PK, NULL }; +MY_LOCALE my_locale_ur_PK= + { "ur_PK", "Urdu - Pakistan", FALSE, &my_locale_typelib_month_names_ur_PK, &my_locale_typelib_ab_month_names_ur_PK, &my_locale_typelib_day_names_ur_PK, &my_locale_typelib_ab_day_names_ur_PK }; +/***** LOCALE END ur_PK *****/ + +/***** LOCALE BEGIN vi_VN: Vietnamese - Vietnam *****/ +static const char *my_locale_month_names_vi_VN[13] = + {"Tháng một","Tháng hai","Tháng ba","Tháng tÆ°","Tháng năm","Tháng sáu","Tháng bảy","Tháng tám","Tháng chÃn","Tháng mÆ°Æ¡Ì€i","Tháng mÆ°Æ¡Ì€i một","Tháng mÆ°Æ¡Ì€i hai", NullS }; +static const char *my_locale_ab_month_names_vi_VN[13] = + {"Thg 1","Thg 2","Thg 3","Thg 4","Thg 5","Thg 6","Thg 7","Thg 8","Thg 9","Thg 10","Thg 11","Thg 12", NullS }; +static const char *my_locale_day_names_vi_VN[8] = + {"ThÆ°Ì hai ","ThÆ°Ì ba ","ThÆ°Ì tÆ° ","ThÆ°Ì năm ","ThÆ°Ì sáu ","ThÆ°Ì bảy ","Chủ nhật ", NullS }; +static const char *my_locale_ab_day_names_vi_VN[8] = + {"Th 2 ","Th 3 ","Th 4 ","Th 5 ","Th 6 ","Th 7 ","CN ", NullS }; +static TYPELIB my_locale_typelib_month_names_vi_VN = + { array_elements(my_locale_month_names_vi_VN)-1, "", my_locale_month_names_vi_VN, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_vi_VN = + { array_elements(my_locale_ab_month_names_vi_VN)-1, "", my_locale_ab_month_names_vi_VN, NULL }; +static TYPELIB my_locale_typelib_day_names_vi_VN = + { array_elements(my_locale_day_names_vi_VN)-1, "", my_locale_day_names_vi_VN, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_vi_VN = + { array_elements(my_locale_ab_day_names_vi_VN)-1, "", my_locale_ab_day_names_vi_VN, NULL }; +MY_LOCALE my_locale_vi_VN= + { "vi_VN", "Vietnamese - Vietnam", FALSE, &my_locale_typelib_month_names_vi_VN, &my_locale_typelib_ab_month_names_vi_VN, &my_locale_typelib_day_names_vi_VN, &my_locale_typelib_ab_day_names_vi_VN }; +/***** LOCALE END vi_VN *****/ + +/***** LOCALE BEGIN zh_CN: Chinese - Peoples Republic of China *****/ +static const char *my_locale_month_names_zh_CN[13] = + {"一月","二月","三月","四月","五月","å…月","七月","八月","ä¹æœˆ","å月","å一月","å二月", NullS }; +static const char *my_locale_ab_month_names_zh_CN[13] = + {" 1月"," 2月"," 3月"," 4月"," 5月"," 6月"," 7月"," 8月"," 9月","10月","11月","12月", NullS }; +static const char *my_locale_day_names_zh_CN[8] = + {"星期一","星期二","星期三","星期四","星期五","星期å…","星期日", NullS }; +static const char *my_locale_ab_day_names_zh_CN[8] = + {"一","二","三","å››","五","å…","æ—¥", NullS }; +static TYPELIB my_locale_typelib_month_names_zh_CN = + { array_elements(my_locale_month_names_zh_CN)-1, "", my_locale_month_names_zh_CN, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_zh_CN = + { array_elements(my_locale_ab_month_names_zh_CN)-1, "", my_locale_ab_month_names_zh_CN, NULL }; +static TYPELIB my_locale_typelib_day_names_zh_CN = + { array_elements(my_locale_day_names_zh_CN)-1, "", my_locale_day_names_zh_CN, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_zh_CN = + { array_elements(my_locale_ab_day_names_zh_CN)-1, "", my_locale_ab_day_names_zh_CN, NULL }; +MY_LOCALE my_locale_zh_CN= + { "zh_CN", "Chinese - Peoples Republic of China", FALSE, &my_locale_typelib_month_names_zh_CN, &my_locale_typelib_ab_month_names_zh_CN, &my_locale_typelib_day_names_zh_CN, &my_locale_typelib_ab_day_names_zh_CN }; +/***** LOCALE END zh_CN *****/ + +/***** LOCALE BEGIN zh_TW: Chinese - Taiwan *****/ +static const char *my_locale_month_names_zh_TW[13] = + {"一月","二月","三月","四月","五月","å…月","七月","八月","ä¹æœˆ","å月","å一月","å二月", NullS }; +static const char *my_locale_ab_month_names_zh_TW[13] = + {" 1月"," 2月"," 3月"," 4月"," 5月"," 6月"," 7月"," 8月"," 9月","10月","11月","12月", NullS }; +static const char *my_locale_day_names_zh_TW[8] = + {"週一","週二","週三","週四","週五","週å…","週日", NullS }; +static const char *my_locale_ab_day_names_zh_TW[8] = + {"一","二","三","å››","五","å…","æ—¥", NullS }; +static TYPELIB my_locale_typelib_month_names_zh_TW = + { array_elements(my_locale_month_names_zh_TW)-1, "", my_locale_month_names_zh_TW, NULL }; +static TYPELIB my_locale_typelib_ab_month_names_zh_TW = + { array_elements(my_locale_ab_month_names_zh_TW)-1, "", my_locale_ab_month_names_zh_TW, NULL }; +static TYPELIB my_locale_typelib_day_names_zh_TW = + { array_elements(my_locale_day_names_zh_TW)-1, "", my_locale_day_names_zh_TW, NULL }; +static TYPELIB my_locale_typelib_ab_day_names_zh_TW = + { array_elements(my_locale_ab_day_names_zh_TW)-1, "", my_locale_ab_day_names_zh_TW, NULL }; +MY_LOCALE my_locale_zh_TW= + { "zh_TW", "Chinese - Taiwan", FALSE, &my_locale_typelib_month_names_zh_TW, &my_locale_typelib_ab_month_names_zh_TW, &my_locale_typelib_day_names_zh_TW, &my_locale_typelib_ab_day_names_zh_TW }; +/***** LOCALE END zh_TW *****/ + +/***** LOCALE BEGIN ar_DZ: Arabic - Algeria *****/ +MY_LOCALE my_locale_ar_DZ= + { "ar_DZ", "Arabic - Algeria", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH }; +/***** LOCALE END ar_DZ *****/ + +/***** LOCALE BEGIN ar_EG: Arabic - Egypt *****/ +MY_LOCALE my_locale_ar_EG= + { "ar_EG", "Arabic - Egypt", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH }; +/***** LOCALE END ar_EG *****/ + +/***** LOCALE BEGIN ar_IN: Arabic - Iran *****/ +MY_LOCALE my_locale_ar_IN= + { "ar_IN", "Arabic - Iran", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH }; +/***** LOCALE END ar_IN *****/ + +/***** LOCALE BEGIN ar_IQ: Arabic - Iraq *****/ +MY_LOCALE my_locale_ar_IQ= + { "ar_IQ", "Arabic - Iraq", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH }; +/***** LOCALE END ar_IQ *****/ + +/***** LOCALE BEGIN ar_KW: Arabic - Kuwait *****/ +MY_LOCALE my_locale_ar_KW= + { "ar_KW", "Arabic - Kuwait", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH }; +/***** LOCALE END ar_KW *****/ + +/***** LOCALE BEGIN ar_LB: Arabic - Lebanon *****/ +MY_LOCALE my_locale_ar_LB= + { "ar_LB", "Arabic - Lebanon", FALSE, &my_locale_typelib_month_names_ar_JO, &my_locale_typelib_ab_month_names_ar_JO, &my_locale_typelib_day_names_ar_JO, &my_locale_typelib_ab_day_names_ar_JO }; +/***** LOCALE END ar_LB *****/ + +/***** LOCALE BEGIN ar_LY: Arabic - Libya *****/ +MY_LOCALE my_locale_ar_LY= + { "ar_LY", "Arabic - Libya", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH }; +/***** LOCALE END ar_LY *****/ + +/***** LOCALE BEGIN ar_MA: Arabic - Morocco *****/ +MY_LOCALE my_locale_ar_MA= + { "ar_MA", "Arabic - Morocco", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH }; +/***** LOCALE END ar_MA *****/ + +/***** LOCALE BEGIN ar_OM: Arabic - Oman *****/ +MY_LOCALE my_locale_ar_OM= + { "ar_OM", "Arabic - Oman", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH }; +/***** LOCALE END ar_OM *****/ + +/***** LOCALE BEGIN ar_QA: Arabic - Qatar *****/ +MY_LOCALE my_locale_ar_QA= + { "ar_QA", "Arabic - Qatar", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH }; +/***** LOCALE END ar_QA *****/ + +/***** LOCALE BEGIN ar_SD: Arabic - Sudan *****/ +MY_LOCALE my_locale_ar_SD= + { "ar_SD", "Arabic - Sudan", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH }; +/***** LOCALE END ar_SD *****/ + +/***** LOCALE BEGIN ar_TN: Arabic - Tunisia *****/ +MY_LOCALE my_locale_ar_TN= + { "ar_TN", "Arabic - Tunisia", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH }; +/***** LOCALE END ar_TN *****/ + +/***** LOCALE BEGIN ar_YE: Arabic - Yemen *****/ +MY_LOCALE my_locale_ar_YE= + { "ar_YE", "Arabic - Yemen", FALSE, &my_locale_typelib_month_names_ar_BH, &my_locale_typelib_ab_month_names_ar_BH, &my_locale_typelib_day_names_ar_BH, &my_locale_typelib_ab_day_names_ar_BH }; +/***** LOCALE END ar_YE *****/ + +/***** LOCALE BEGIN de_BE: German - Belgium *****/ +MY_LOCALE my_locale_de_BE= + { "de_BE", "German - Belgium", FALSE, &my_locale_typelib_month_names_de_DE, &my_locale_typelib_ab_month_names_de_DE, &my_locale_typelib_day_names_de_DE, &my_locale_typelib_ab_day_names_de_DE }; +/***** LOCALE END de_BE *****/ + +/***** LOCALE BEGIN de_CH: German - Switzerland *****/ +MY_LOCALE my_locale_de_CH= + { "de_CH", "German - Switzerland", FALSE, &my_locale_typelib_month_names_de_DE, &my_locale_typelib_ab_month_names_de_DE, &my_locale_typelib_day_names_de_DE, &my_locale_typelib_ab_day_names_de_DE }; +/***** LOCALE END de_CH *****/ + +/***** LOCALE BEGIN de_LU: German - Luxembourg *****/ +MY_LOCALE my_locale_de_LU= + { "de_LU", "German - Luxembourg", FALSE, &my_locale_typelib_month_names_de_DE, &my_locale_typelib_ab_month_names_de_DE, &my_locale_typelib_day_names_de_DE, &my_locale_typelib_ab_day_names_de_DE }; +/***** LOCALE END de_LU *****/ + +/***** LOCALE BEGIN en_AU: English - Australia *****/ +MY_LOCALE my_locale_en_AU= + { "en_AU", "English - Australia", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US }; +/***** LOCALE END en_AU *****/ + +/***** LOCALE BEGIN en_CA: English - Canada *****/ +MY_LOCALE my_locale_en_CA= + { "en_CA", "English - Canada", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US }; +/***** LOCALE END en_CA *****/ + +/***** LOCALE BEGIN en_GB: English - United Kingdom *****/ +MY_LOCALE my_locale_en_GB= + { "en_GB", "English - United Kingdom", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US }; +/***** LOCALE END en_GB *****/ + +/***** LOCALE BEGIN en_IN: English - India *****/ +MY_LOCALE my_locale_en_IN= + { "en_IN", "English - India", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US }; +/***** LOCALE END en_IN *****/ + +/***** LOCALE BEGIN en_NZ: English - New Zealand *****/ +MY_LOCALE my_locale_en_NZ= + { "en_NZ", "English - New Zealand", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US }; +/***** LOCALE END en_NZ *****/ + +/***** LOCALE BEGIN en_PH: English - Philippines *****/ +MY_LOCALE my_locale_en_PH= + { "en_PH", "English - Philippines", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US }; +/***** LOCALE END en_PH *****/ + +/***** LOCALE BEGIN en_ZA: English - South Africa *****/ +MY_LOCALE my_locale_en_ZA= + { "en_ZA", "English - South Africa", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US }; +/***** LOCALE END en_ZA *****/ + +/***** LOCALE BEGIN en_ZW: English - Zimbabwe *****/ +MY_LOCALE my_locale_en_ZW= + { "en_ZW", "English - Zimbabwe", TRUE, &my_locale_typelib_month_names_en_US, &my_locale_typelib_ab_month_names_en_US, &my_locale_typelib_day_names_en_US, &my_locale_typelib_ab_day_names_en_US }; +/***** LOCALE END en_ZW *****/ + +/***** LOCALE BEGIN es_AR: Spanish - Argentina *****/ +MY_LOCALE my_locale_es_AR= + { "es_AR", "Spanish - Argentina", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_AR *****/ + +/***** LOCALE BEGIN es_BO: Spanish - Bolivia *****/ +MY_LOCALE my_locale_es_BO= + { "es_BO", "Spanish - Bolivia", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_BO *****/ + +/***** LOCALE BEGIN es_CL: Spanish - Chile *****/ +MY_LOCALE my_locale_es_CL= + { "es_CL", "Spanish - Chile", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_CL *****/ + +/***** LOCALE BEGIN es_CO: Spanish - Columbia *****/ +MY_LOCALE my_locale_es_CO= + { "es_CO", "Spanish - Columbia", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_CO *****/ + +/***** LOCALE BEGIN es_CR: Spanish - Costa Rica *****/ +MY_LOCALE my_locale_es_CR= + { "es_CR", "Spanish - Costa Rica", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_CR *****/ + +/***** LOCALE BEGIN es_DO: Spanish - Dominican Republic *****/ +MY_LOCALE my_locale_es_DO= + { "es_DO", "Spanish - Dominican Republic", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_DO *****/ + +/***** LOCALE BEGIN es_EC: Spanish - Ecuador *****/ +MY_LOCALE my_locale_es_EC= + { "es_EC", "Spanish - Ecuador", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_EC *****/ + +/***** LOCALE BEGIN es_GT: Spanish - Guatemala *****/ +MY_LOCALE my_locale_es_GT= + { "es_GT", "Spanish - Guatemala", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_GT *****/ + +/***** LOCALE BEGIN es_HN: Spanish - Honduras *****/ +MY_LOCALE my_locale_es_HN= + { "es_HN", "Spanish - Honduras", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_HN *****/ + +/***** LOCALE BEGIN es_MX: Spanish - Mexico *****/ +MY_LOCALE my_locale_es_MX= + { "es_MX", "Spanish - Mexico", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_MX *****/ + +/***** LOCALE BEGIN es_NI: Spanish - Nicaragua *****/ +MY_LOCALE my_locale_es_NI= + { "es_NI", "Spanish - Nicaragua", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_NI *****/ + +/***** LOCALE BEGIN es_PA: Spanish - Panama *****/ +MY_LOCALE my_locale_es_PA= + { "es_PA", "Spanish - Panama", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_PA *****/ + +/***** LOCALE BEGIN es_PE: Spanish - Peru *****/ +MY_LOCALE my_locale_es_PE= + { "es_PE", "Spanish - Peru", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_PE *****/ + +/***** LOCALE BEGIN es_PR: Spanish - Puerto Rico *****/ +MY_LOCALE my_locale_es_PR= + { "es_PR", "Spanish - Puerto Rico", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_PR *****/ + +/***** LOCALE BEGIN es_PY: Spanish - Paraguay *****/ +MY_LOCALE my_locale_es_PY= + { "es_PY", "Spanish - Paraguay", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_PY *****/ + +/***** LOCALE BEGIN es_SV: Spanish - El Salvador *****/ +MY_LOCALE my_locale_es_SV= + { "es_SV", "Spanish - El Salvador", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_SV *****/ + +/***** LOCALE BEGIN es_US: Spanish - United States *****/ +MY_LOCALE my_locale_es_US= + { "es_US", "Spanish - United States", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_US *****/ + +/***** LOCALE BEGIN es_UY: Spanish - Uruguay *****/ +MY_LOCALE my_locale_es_UY= + { "es_UY", "Spanish - Uruguay", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_UY *****/ + +/***** LOCALE BEGIN es_VE: Spanish - Venezuela *****/ +MY_LOCALE my_locale_es_VE= + { "es_VE", "Spanish - Venezuela", FALSE, &my_locale_typelib_month_names_es_ES, &my_locale_typelib_ab_month_names_es_ES, &my_locale_typelib_day_names_es_ES, &my_locale_typelib_ab_day_names_es_ES }; +/***** LOCALE END es_VE *****/ + +/***** LOCALE BEGIN fr_BE: French - Belgium *****/ +MY_LOCALE my_locale_fr_BE= + { "fr_BE", "French - Belgium", FALSE, &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, &my_locale_typelib_ab_day_names_fr_FR }; +/***** LOCALE END fr_BE *****/ + +/***** LOCALE BEGIN fr_CA: French - Canada *****/ +MY_LOCALE my_locale_fr_CA= + { "fr_CA", "French - Canada", FALSE, &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, &my_locale_typelib_ab_day_names_fr_FR }; +/***** LOCALE END fr_CA *****/ + +/***** LOCALE BEGIN fr_CH: French - Switzerland *****/ +MY_LOCALE my_locale_fr_CH= + { "fr_CH", "French - Switzerland", FALSE, &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, &my_locale_typelib_ab_day_names_fr_FR }; +/***** LOCALE END fr_CH *****/ + +/***** LOCALE BEGIN fr_LU: French - Luxembourg *****/ +MY_LOCALE my_locale_fr_LU= + { "fr_LU", "French - Luxembourg", FALSE, &my_locale_typelib_month_names_fr_FR, &my_locale_typelib_ab_month_names_fr_FR, &my_locale_typelib_day_names_fr_FR, &my_locale_typelib_ab_day_names_fr_FR }; +/***** LOCALE END fr_LU *****/ + +/***** LOCALE BEGIN it_IT: Italian - Italy *****/ +MY_LOCALE my_locale_it_IT= + { "it_IT", "Italian - Italy", FALSE, &my_locale_typelib_month_names_it_CH, &my_locale_typelib_ab_month_names_it_CH, &my_locale_typelib_day_names_it_CH, &my_locale_typelib_ab_day_names_it_CH }; +/***** LOCALE END it_IT *****/ + +/***** LOCALE BEGIN nl_BE: Dutch - Belgium *****/ +MY_LOCALE my_locale_nl_BE= + { "nl_BE", "Dutch - Belgium", TRUE, &my_locale_typelib_month_names_nl_NL, &my_locale_typelib_ab_month_names_nl_NL, &my_locale_typelib_day_names_nl_NL, &my_locale_typelib_ab_day_names_nl_NL }; +/***** LOCALE END nl_BE *****/ + +/***** LOCALE BEGIN no_NO: Norwegian - Norway *****/ +MY_LOCALE my_locale_no_NO= + { "no_NO", "Norwegian - Norway", FALSE, &my_locale_typelib_month_names_nb_NO, &my_locale_typelib_ab_month_names_nb_NO, &my_locale_typelib_day_names_nb_NO, &my_locale_typelib_ab_day_names_nb_NO }; +/***** LOCALE END no_NO *****/ + +/***** LOCALE BEGIN sv_FI: Swedish - Finland *****/ +MY_LOCALE my_locale_sv_FI= + { "sv_FI", "Swedish - Finland", FALSE, &my_locale_typelib_month_names_sv_SE, &my_locale_typelib_ab_month_names_sv_SE, &my_locale_typelib_day_names_sv_SE, &my_locale_typelib_ab_day_names_sv_SE }; +/***** LOCALE END sv_FI *****/ + +/***** LOCALE BEGIN zh_HK: Chinese - Hong Kong SAR *****/ +MY_LOCALE my_locale_zh_HK= + { "zh_HK", "Chinese - Hong Kong SAR", FALSE, &my_locale_typelib_month_names_zh_CN, &my_locale_typelib_ab_month_names_zh_CN, &my_locale_typelib_day_names_zh_CN, &my_locale_typelib_ab_day_names_zh_CN }; +/***** LOCALE END zh_HK *****/ + +MY_LOCALE *my_locales[]= + { + &my_locale_en_US, + &my_locale_en_GB, + &my_locale_ja_JP, + &my_locale_sv_SE, + &my_locale_de_DE, + &my_locale_fr_FR, + &my_locale_ar_AE, + &my_locale_ar_BH, + &my_locale_ar_JO, + &my_locale_ar_SA, + &my_locale_ar_SY, + &my_locale_be_BY, + &my_locale_bg_BG, + &my_locale_ca_ES, + &my_locale_cs_CZ, + &my_locale_da_DK, + &my_locale_de_AT, + &my_locale_es_ES, + &my_locale_et_EE, + &my_locale_eu_ES, + &my_locale_fi_FI, + &my_locale_fo_FO, + &my_locale_gl_ES, + &my_locale_gu_IN, + &my_locale_he_IL, + &my_locale_hi_IN, + &my_locale_hr_HR, + &my_locale_hu_HU, + &my_locale_id_ID, + &my_locale_is_IS, + &my_locale_it_CH, + &my_locale_ko_KR, + &my_locale_lt_LT, + &my_locale_lv_LV, + &my_locale_mk_MK, + &my_locale_mn_MN, + &my_locale_ms_MY, + &my_locale_nb_NO, + &my_locale_nl_NL, + &my_locale_pl_PL, + &my_locale_pt_BR, + &my_locale_pt_PT, + &my_locale_ro_RO, + &my_locale_ru_RU, + &my_locale_ru_UA, + &my_locale_sk_SK, + &my_locale_sl_SI, + &my_locale_sq_AL, + &my_locale_sr_YU, + &my_locale_ta_IN, + &my_locale_te_IN, + &my_locale_th_TH, + &my_locale_tr_TR, + &my_locale_uk_UA, + &my_locale_ur_PK, + &my_locale_vi_VN, + &my_locale_zh_CN, + &my_locale_zh_TW, + &my_locale_ar_DZ, + &my_locale_ar_EG, + &my_locale_ar_IN, + &my_locale_ar_IQ, + &my_locale_ar_KW, + &my_locale_ar_LB, + &my_locale_ar_LY, + &my_locale_ar_MA, + &my_locale_ar_OM, + &my_locale_ar_QA, + &my_locale_ar_SD, + &my_locale_ar_TN, + &my_locale_ar_YE, + &my_locale_de_BE, + &my_locale_de_CH, + &my_locale_de_LU, + &my_locale_en_AU, + &my_locale_en_CA, + &my_locale_en_IN, + &my_locale_en_NZ, + &my_locale_en_PH, + &my_locale_en_ZA, + &my_locale_en_ZW, + &my_locale_es_AR, + &my_locale_es_BO, + &my_locale_es_CL, + &my_locale_es_CO, + &my_locale_es_CR, + &my_locale_es_DO, + &my_locale_es_EC, + &my_locale_es_GT, + &my_locale_es_HN, + &my_locale_es_MX, + &my_locale_es_NI, + &my_locale_es_PA, + &my_locale_es_PE, + &my_locale_es_PR, + &my_locale_es_PY, + &my_locale_es_SV, + &my_locale_es_US, + &my_locale_es_UY, + &my_locale_es_VE, + &my_locale_fr_BE, + &my_locale_fr_CA, + &my_locale_fr_CH, + &my_locale_fr_LU, + &my_locale_it_IT, + &my_locale_nl_BE, + &my_locale_no_NO, + &my_locale_sv_FI, + &my_locale_zh_HK, + NULL + }; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7c07b4f8847..6dbd6623264 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1250,6 +1250,12 @@ pthread_handler_t handle_bootstrap(void *arg) thd->version=refresh_version; thd->security_ctx->priv_user= thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME)); + /* + Make the "client" handle multiple results. This is necessary + to enable stored procedures with SELECTs and Dynamic SQL + in init-file. + */ + thd->client_capabilities|= CLIENT_MULTI_RESULTS; buff= (char*) thd->net.buff; thd->init_for_queries(); @@ -2365,7 +2371,7 @@ static void reset_one_shot_variables(THD *thd) /* - Execute command saved in thd and current_lex->sql_command + Execute command saved in thd and lex->sql_command SYNOPSIS mysql_execute_command() @@ -3083,8 +3089,7 @@ end_with_restore_list: lex->key_list, select_lex->order_list.elements, (ORDER *) select_lex->order_list.first, - lex->duplicates, lex->ignore, &lex->alter_info, - 1); + lex->ignore, &lex->alter_info, 1); } break; } @@ -3457,7 +3462,7 @@ end_with_restore_list: { DBUG_ASSERT(first_table == all_tables && first_table != 0); TABLE_LIST *aux_tables= - (TABLE_LIST *)thd->lex->auxilliary_table_list.first; + (TABLE_LIST *)thd->lex->auxiliary_table_list.first; multi_delete *result; if (!thd->locked_tables && @@ -3893,11 +3898,13 @@ end_with_restore_list: if (thd->security_ctx->user) // If not replication { - LEX_USER *user; + LEX_USER *user, *tmp_user; List_iterator <LEX_USER> user_list(lex->users_list); - while ((user= user_list++)) + while ((tmp_user= user_list++)) { + if (!(user= get_current_user(thd, tmp_user))) + goto error; if (specialflag & SPECIAL_NO_RESOLVE && hostname_requires_resolving(user->host.str)) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, @@ -3979,9 +3986,13 @@ end_with_restore_list: if (lex->sql_command == SQLCOM_GRANT) { List_iterator <LEX_USER> str_list(lex->users_list); - LEX_USER *user; - while ((user=str_list++)) + LEX_USER *user, *tmp_user; + while ((tmp_user=str_list++)) + { + if (!(user= get_current_user(thd, tmp_user))) + goto error; reset_mqh(user); + } } } } @@ -4036,13 +4047,18 @@ end_with_restore_list: } #ifndef NO_EMBEDDED_ACCESS_CHECKS case SQLCOM_SHOW_GRANTS: + { + LEX_USER *grant_user= get_current_user(thd, lex->grant_user); + if (!grant_user) + goto error; if ((thd->security_ctx->priv_user && - !strcmp(thd->security_ctx->priv_user, lex->grant_user->user.str)) || + !strcmp(thd->security_ctx->priv_user, grant_user->user.str)) || !check_access(thd, SELECT_ACL, "mysql",0,1,0,0)) { - res = mysql_show_grants(thd,lex->grant_user); + res = mysql_show_grants(thd, grant_user); } break; + } #endif case SQLCOM_HA_OPEN: DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -5547,7 +5563,7 @@ bool check_stack_overrun(THD *thd, long margin, bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize) { - LEX *lex=current_lex; + LEX *lex= current_thd->lex; ulong old_info=0; if ((uint) *yystacksize >= MY_YACC_MAX) return 1; @@ -5762,7 +5778,7 @@ void mysql_init_multi_delete(LEX *lex) mysql_init_select(lex); lex->select_lex.select_limit= 0; lex->unit.select_limit_cnt= HA_POS_ERROR; - lex->select_lex.table_list.save_and_clear(&lex->auxilliary_table_list); + lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list); lex->lock_option= using_update_log ? TL_READ_NO_INSERT : TL_READ; lex->query_tables= 0; lex->query_tables_last= &lex->query_tables; @@ -5984,7 +6000,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, void store_position_for_column(const char *name) { - current_lex->last_field->after=my_const_cast(char*) (name); + current_thd->lex->last_field->after=my_const_cast(char*) (name); } bool @@ -7022,7 +7038,7 @@ bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, &create_info, table_list, fields, keys, 0, (ORDER*)0, - DUP_ERROR, 0, &alter_info, 1)); + 0, &alter_info, 1)); } @@ -7040,7 +7056,7 @@ bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info) DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, &create_info, table_list, fields, keys, 0, (ORDER*)0, - DUP_ERROR, 0, alter_info, 1)); + 0, alter_info, 1)); } @@ -7141,7 +7157,7 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) { SELECT_LEX *select_lex= &thd->lex->select_lex; TABLE_LIST *aux_tables= - (TABLE_LIST *)thd->lex->auxilliary_table_list.first; + (TABLE_LIST *)thd->lex->auxiliary_table_list.first; TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last; DBUG_ENTER("multi_delete_precheck"); @@ -7195,7 +7211,7 @@ bool multi_delete_set_locks_and_link_aux_tables(LEX *lex) lex->table_count= 0; - for (target_tbl= (TABLE_LIST *)lex->auxilliary_table_list.first; + for (target_tbl= (TABLE_LIST *)lex->auxiliary_table_list.first; target_tbl; target_tbl= target_tbl->next_local) { lex->table_count++; @@ -7501,3 +7517,34 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) return definer; } + + +/* + Retuns information about user or current user. + + SYNOPSIS + get_current_user() + thd [in] thread handler + user [in] user + + RETURN + On success, return a valid pointer to initialized + LEX_USER, which contains user information. + On error, return 0. +*/ + +LEX_USER *get_current_user(THD *thd, LEX_USER *user) +{ + LEX_USER *curr_user; + if (!user->user.str) // current_user + { + if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) + { + my_error(ER_OUTOFMEMORY, MYF(0), sizeof(LEX_USER)); + return 0; + } + get_default_definer(thd, curr_user); + return curr_user; + } + return user; +} diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 41ff9185cfb..8361986e020 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5482,6 +5482,7 @@ make_join_readinfo(JOIN *join, uint options) uint i; bool statistics= test(!(join->select_options & SELECT_DESCRIBE)); + bool ordered_set= 0; DBUG_ENTER("make_join_readinfo"); for (i=join->const_tables ; i < join->tables ; i++) @@ -5491,6 +5492,22 @@ make_join_readinfo(JOIN *join, uint options) tab->read_record.table= table; tab->read_record.file=table->file; tab->next_select=sub_select; /* normal select */ + + /* + Determine if the set is already ordered for ORDER BY, so it can + disable join cache because it will change the ordering of the results. + Code handles sort table that is at any location (not only first after + the const tables) despite the fact that it's currently prohibited. + */ + if (!ordered_set && + (table == join->sort_by_table && + (!join->order || join->skip_sort_order || + test_if_skip_sort_order(tab, join->order, join->select_limit, + 1)) + ) || + (join->sort_by_table == (TABLE *) 1 && i != join->const_tables)) + ordered_set= 1; + switch (tab->type) { case JT_SYSTEM: // Only happens with left join table->status=STATUS_NO_RECORD; @@ -5561,10 +5578,11 @@ make_join_readinfo(JOIN *join, uint options) case JT_ALL: /* If previous table use cache + If the incoming data set is already sorted don't use cache. */ table->status=STATUS_NO_RECORD; if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) && - tab->use_quick != 2 && !tab->first_inner) + tab->use_quick != 2 && !tab->first_inner && !ordered_set) { if ((options & SELECT_DESCRIBE) || !join_init_cache(join->thd,join->join_tab+join->const_tables, @@ -7854,7 +7872,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) Field *field=((Item_field*) args[0])->field; if (field->flags & AUTO_INCREMENT_FLAG && !field->table->maybe_null && (thd->options & OPTION_AUTO_IS_NULL) && - thd->insert_id()) + thd->insert_id() && thd->substitute_null_with_insert_id) { #ifdef HAVE_QUERY_CACHE query_cache_abort(&thd->net); @@ -7873,7 +7891,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) */ cond->fix_fields(thd, &cond); } - thd->insert_id(0); // Clear for next request + thd->substitute_null_with_insert_id= FALSE; // Clear for next request } /* fix to replace 'NULL' dates with '0' (shreeve@uci.edu) */ else if (((field->type() == FIELD_TYPE_DATE) || @@ -8017,7 +8035,8 @@ Field* create_tmp_field_from_field(THD *thd, Field* org_field, org_field->field_name, table, org_field->charset()); else - new_field= org_field->new_field(thd->mem_root, table); + new_field= org_field->new_field(thd->mem_root, table, + table == org_field->table); if (new_field) { if (item) @@ -8073,8 +8092,13 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, item->name, table, item->decimals); break; case INT_RESULT: - new_field=new Field_longlong(item->max_length, maybe_null, - item->name, table, item->unsigned_flag); + /* Select an integer type with the minimal fit precision */ + if (item->max_length > 11) + new_field=new Field_longlong(item->max_length, maybe_null, + item->name, table, item->unsigned_flag); + else + new_field=new Field_long(item->max_length, maybe_null, + item->name, table, item->unsigned_flag); break; case STRING_RESULT: DBUG_ASSERT(item->collation.collation); @@ -10607,8 +10631,13 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { if (!join->first_record) { + List_iterator_fast<Item> it(*join->fields); + Item *item; /* No matching rows for group function */ join->clear(); + + while ((item= it++)) + item->no_rows_in_result(); } if (join->having && join->having->val_int() == 0) error= -1; // Didn't satisfy having @@ -13062,7 +13091,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, saved value */ Field *field= item->field; - item->result_field=field->new_field(thd->mem_root,field->table); + item->result_field=field->new_field(thd->mem_root,field->table, 1); char *tmp=(char*) sql_alloc(field->pack_length()+1); if (!tmp) goto err; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 60d50c415d5..cabb04c5f16 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -582,7 +582,14 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) { if (!wild || !wild[0] || !wild_case_compare(system_charset_info, field->field_name,wild)) - field_list.push_back(new Item_field(field)); + { + if (table_list->view) + field_list.push_back(new Item_ident_for_show(field, + table_list->view_db.str, + table_list->view_name.str)); + else + field_list.push_back(new Item_field(field)); + } } restore_record(table, s->default_values); // Get empty record if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS | @@ -1073,10 +1080,10 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) packet->append(ha_row_type[(uint) share->row_type]); } table->file->append_create_info(packet); - if (share->comment && share->comment[0]) + if (share->comment.length) { packet->append(STRING_WITH_LEN(" COMMENT=")); - append_unescaped(packet, share->comment, strlen(share->comment)); + append_unescaped(packet, share->comment.str, share->comment.length); } if (share->connect_string.length) { @@ -2540,11 +2547,14 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables, (uint) (ptr-option_buff)-1), cs); { char *comment; - comment= show_table->file->update_table_comment(share->comment); + comment= show_table->file->update_table_comment(share->comment.str); if (comment) { - table->field[20]->store(comment, strlen(comment), cs); - if (comment != share->comment) + table->field[20]->store(comment, + (comment == share->comment.str ? + share->comment.length : + strlen(comment)), cs); + if (comment != share->comment.str) my_free(comment, MYF(0)); } } @@ -2916,6 +2926,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, { get_field(thd->mem_root, proc_table->field[10], &tmp_string); table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs); + table->field[7]->set_notnull(); } table->field[6]->store(STRING_WITH_LEN("SQL"), cs); table->field[10]->store(STRING_WITH_LEN("SQL"), cs); @@ -4069,7 +4080,7 @@ ST_FIELD_INFO proc_fields_info[]= {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type"}, {"DTD_IDENTIFIER", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, {"ROUTINE_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0}, - {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0}, + {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0}, {"EXTERNAL_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, {"EXTERNAL_LANGUAGE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0}, {"PARAMETER_STYLE", 8, MYSQL_TYPE_STRING, 0, 0, 0}, diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 91c71193df2..4772d64ad0a 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -35,9 +35,7 @@ const char *primary_key_name="PRIMARY"; static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end); static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end); static int copy_data_between_tables(TABLE *from,TABLE *to, - List<create_field> &create, - enum enum_duplicates handle_duplicates, - bool ignore, + List<create_field> &create, bool ignore, uint order_num, ORDER *order, ha_rows *copied,ha_rows *deleted); static bool prepare_blob_field(THD *thd, create_field *sql_field); @@ -3141,8 +3139,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, HA_CREATE_INFO *create_info, TABLE_LIST *table_list, List<create_field> &fields, List<Key> &keys, - uint order_num, ORDER *order, - enum enum_duplicates handle_duplicates, bool ignore, + uint order_num, ORDER *order, bool ignore, ALTER_INFO *alter_info, bool do_send_ok) { TABLE *table,*new_table=0; @@ -3240,9 +3237,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, DBUG_PRINT("info", ("old type: %d new type: %d", old_db_type, new_db_type)); if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) || - ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED) || - (old_db_type != new_db_type && - ha_check_storage_engine_flag(new_db_type, HTON_ALTER_CANNOT_CREATE))) + ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED)) { DBUG_PRINT("info", ("doesn't support alter")); my_error(ER_ILLEGAL_HA, MYF(0), table_name); @@ -3598,8 +3593,11 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, goto err; } create_info->db_type=new_db_type; - if (!create_info->comment) - create_info->comment= table->s->comment; + if (!create_info->comment.str) + { + create_info->comment.str= table->s->comment.str; + create_info->comment.length= table->s->comment.length; + } table->file->update_create_info(create_info); if ((create_info->table_options & @@ -3737,8 +3735,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, { new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; new_table->next_number_field=new_table->found_next_number_field; - error=copy_data_between_tables(table,new_table,create_list, - handle_duplicates, ignore, + error=copy_data_between_tables(table, new_table, create_list, ignore, order_num, order, &copied, &deleted); } thd->last_insert_id=next_insert_id; // Needed for correct log @@ -3961,7 +3958,6 @@ end_temporary: static int copy_data_between_tables(TABLE *from,TABLE *to, List<create_field> &create, - enum enum_duplicates handle_duplicates, bool ignore, uint order_num, ORDER *order, ha_rows *copied, @@ -4064,8 +4060,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, */ from->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1); - if (ignore || - handle_duplicates == DUP_REPLACE) + if (ignore) to->file->extra(HA_EXTRA_IGNORE_DUP_KEY); thd->row_count= 0; restore_record(to, s->default_values); // Create empty record @@ -4092,8 +4087,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, } if ((error=to->file->write_row((byte*) to->record[0]))) { - if ((!ignore && - handle_duplicates != DUP_REPLACE) || + if (!ignore || (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE)) { @@ -4171,7 +4165,7 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info, table_list, lex->create_list, lex->key_list, 0, (ORDER *) 0, - DUP_ERROR, 0, &lex->alter_info, do_send_ok)); + 0, &lex->alter_info, do_send_ok)); } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 28d7dc0bb9d..66a16f16d8c 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -747,7 +747,8 @@ bool Table_triggers_list::prepare_record1_accessors(TABLE *table) QQ: it is supposed that it is ok to use this function for field cloning... */ - if (!(*old_fld= (*fld)->new_field(&table->mem_root, table))) + if (!(*old_fld= (*fld)->new_field(&table->mem_root, table, + table == (*fld)->table))) return 1; (*old_fld)->move_field((my_ptrdiff_t)(table->record[1] - table->record[0])); @@ -1024,8 +1025,15 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, } /* - Let us bind Item_trigger_field objects representing access to fields - in old/new versions of row in trigger to Field objects in table being + Gather all Item_trigger_field objects representing access to fields + in old/new versions of row in trigger into lists containing all such + objects for the triggers with same action and timing. + */ + triggers->trigger_fields[lex.trg_chistics.event] + [lex.trg_chistics.action_time]= + (Item_trigger_field *)(lex.trg_table_fields.first); + /* + Also let us bind these objects to Field objects in table being opened. We ignore errors here, because if even something is wrong we still @@ -1536,6 +1544,39 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event, /* + Mark fields of subject table which we read/set in its triggers as such. + + SYNOPSIS + mark_fields_used() + thd Current thread context + event Type of event triggers for which we are going to inspect + + DESCRIPTION + This method marks fields of subject table which are read/set in its + triggers as such (by setting Field::query_id equal to THD::query_id) + and thus informs handler that values for these fields should be + retrieved/stored during execution of statement. +*/ + +void Table_triggers_list::mark_fields_used(THD *thd, trg_event_type event) +{ + int action_time; + Item_trigger_field *trg_field; + + for (action_time= 0; action_time < (int)TRG_ACTION_MAX; action_time++) + { + for (trg_field= trigger_fields[event][action_time]; trg_field; + trg_field= trg_field->next_trg_field) + { + /* We cannot mark fields which does not present in table. */ + if (trg_field->field_idx != (uint)-1) + table->field[trg_field->field_idx]->query_id = thd->query_id; + } + } +} + + +/* Trigger BUG#14090 compatibility hook SYNOPSIS diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index b67c22e0588..e736c3e0e1a 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -26,6 +26,11 @@ class Table_triggers_list: public Sql_alloc /* Triggers as SPs grouped by event, action_time */ sp_head *bodies[TRG_EVENT_MAX][TRG_ACTION_MAX]; /* + Heads of the lists linking items for all fields used in triggers + grouped by event and action_time. + */ + Item_trigger_field *trigger_fields[TRG_EVENT_MAX][TRG_ACTION_MAX]; + /* Copy of TABLE::Field array with field pointers set to TABLE::record[1] buffer instead of TABLE::record[0] (used for OLD values in on UPDATE trigger and DELETE trigger when it is called for REPLACE). @@ -82,6 +87,7 @@ public: record1_field(0), table(table_arg) { bzero((char *)bodies, sizeof(bodies)); + bzero((char *)trigger_fields, sizeof(trigger_fields)); bzero((char *)&subject_table_grants, sizeof(subject_table_grants)); } ~Table_triggers_list(); @@ -119,6 +125,8 @@ public: void set_table(TABLE *new_table); + void mark_fields_used(THD *thd, trg_event_type event); + friend class Item_trigger_field; friend int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, TABLE_LIST *table); diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 95589a58b37..8f98bab5c04 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -83,7 +83,7 @@ static char *init_syms(udf_func *tmp, char *nm) { char *end; - if (!((tmp->func= dlsym(tmp->dlhandle, tmp->name.str)))) + if (!((tmp->func= (Udf_func_any) dlsym(tmp->dlhandle, tmp->name.str)))) return tmp->name.str; end=strmov(nm,tmp->name.str); @@ -91,18 +91,18 @@ static char *init_syms(udf_func *tmp, char *nm) if (tmp->type == UDFTYPE_AGGREGATE) { (void)strmov(end, "_clear"); - if (!((tmp->func_clear= dlsym(tmp->dlhandle, nm)))) + if (!((tmp->func_clear= (Udf_func_clear) dlsym(tmp->dlhandle, nm)))) return nm; (void)strmov(end, "_add"); - if (!((tmp->func_add= dlsym(tmp->dlhandle, nm)))) + if (!((tmp->func_add= (Udf_func_add) dlsym(tmp->dlhandle, nm)))) return nm; } (void) strmov(end,"_deinit"); - tmp->func_deinit= dlsym(tmp->dlhandle, nm); + tmp->func_deinit= (Udf_func_deinit) dlsym(tmp->dlhandle, nm); (void) strmov(end,"_init"); - tmp->func_init= dlsym(tmp->dlhandle, nm); + tmp->func_init= (Udf_func_init) dlsym(tmp->dlhandle, nm); /* to prefent loading "udf" from, e.g. libc.so diff --git a/sql/sql_udf.h b/sql/sql_udf.h index d0729deecaa..21cf735f5ab 100644 --- a/sql/sql_udf.h +++ b/sql/sql_udf.h @@ -23,6 +23,15 @@ enum Item_udftype {UDFTYPE_FUNCTION=1,UDFTYPE_AGGREGATE}; +typedef void (*Udf_func_clear)(UDF_INIT *, uchar *, uchar *); +typedef void (*Udf_func_add)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *); +typedef void (*Udf_func_deinit)(UDF_INIT*); +typedef my_bool (*Udf_func_init)(UDF_INIT *, UDF_ARGS *, char *); +typedef void (*Udf_func_any)(); +typedef double (*Udf_func_double)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *); +typedef longlong (*Udf_func_longlong)(UDF_INIT *, UDF_ARGS *, uchar *, + uchar *); + typedef struct st_udf_func { LEX_STRING name; @@ -30,11 +39,11 @@ typedef struct st_udf_func Item_udftype type; char *dl; void *dlhandle; - void *func; - void *func_init; - void *func_deinit; - void *func_clear; - void *func_add; + Udf_func_any func; + Udf_func_init func_init; + Udf_func_deinit func_deinit; + Udf_func_clear func_clear; + Udf_func_add func_add; ulong usage_count; } udf_func; @@ -76,8 +85,7 @@ class udf_handler :public Sql_alloc *null_value=1; return 0.0; } - double (*func)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)= - (double (*)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)) u_d->func; + Udf_func_double func= (Udf_func_double) u_d->func; double tmp=func(&initid, &f_args, &is_null, &error); if (is_null || error) { @@ -95,8 +103,7 @@ class udf_handler :public Sql_alloc *null_value=1; return LL(0); } - longlong (*func)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)= - (longlong (*)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)) u_d->func; + Udf_func_longlong func= (Udf_func_longlong) u_d->func; longlong tmp=func(&initid, &f_args, &is_null, &error); if (is_null || error) { @@ -110,8 +117,7 @@ class udf_handler :public Sql_alloc void clear() { is_null= 0; - void (*func)(UDF_INIT *, uchar *, uchar *)= - (void (*)(UDF_INIT *, uchar *, uchar *)) u_d->func_clear; + Udf_func_clear func= u_d->func_clear; func(&initid, &is_null, &error); } void add(my_bool *null_value) @@ -121,8 +127,7 @@ class udf_handler :public Sql_alloc *null_value=1; return; } - void (*func)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)= - (void (*)(UDF_INIT *, UDF_ARGS *, uchar *, uchar *)) u_d->func_add; + Udf_func_add func= u_d->func_add; func(&initid, &f_args, &is_null, &error); *null_value= (my_bool) (is_null || error); } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index c2b7624c9e7..9a207845893 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -120,6 +120,7 @@ int mysql_update(THD *thd, bool using_limit= limit != HA_POS_ERROR; bool safe_update= thd->options & OPTION_SAFE_UPDATES; bool used_key_is_modified, transactional_table; + bool can_compare_record; int res; int error; uint used_index= MAX_KEY; @@ -433,6 +434,15 @@ int mysql_update(THD *thd, (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))); + if (table->triggers) + table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE); + + /* + We can use compare_record() to optimize away updates if + the table handler is returning all columns + */ + can_compare_record= !(table->file->table_flags() & + HA_PARTIAL_COLUMN_READ); while (!(error=info.read_record(&info)) && !thd->killed) { if (!(select && select->skip_record())) @@ -445,7 +455,7 @@ int mysql_update(THD *thd, found++; - if (compare_record(table, query_id)) + if (!can_compare_record || compare_record(table, query_id)) { if ((res= table_list->view_check_option(thd, ignore)) != VIEW_CHECK_OK) @@ -755,6 +765,9 @@ reopen_tables: DBUG_RETURN(TRUE); } + if (table->triggers) + table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE); + DBUG_PRINT("info",("setting table `%s` for update", tl->alias)); /* If table will be updated we should not downgrade lock for it and @@ -1248,8 +1261,15 @@ bool multi_update::send_data(List<Item> ¬_used_values) uint offset= cur_table->shared; table->file->position(table->record[0]); + /* + We can use compare_record() to optimize away updates if + the table handler is returning all columns + */ if (table == table_to_update) { + bool can_compare_record; + can_compare_record= !(table->file->table_flags() & + HA_PARTIAL_COLUMN_READ); table->status|= STATUS_UPDATED; store_record(table,record[1]); if (fill_record_n_invoke_before_triggers(thd, *fields_for_table[offset], @@ -1259,7 +1279,7 @@ bool multi_update::send_data(List<Item> ¬_used_values) DBUG_RETURN(1); found++; - if (compare_record(table, thd->query_id)) + if (!can_compare_record || compare_record(table, thd->query_id)) { int error; if ((error= cur_table->view_check_option(thd, ignore)) != @@ -1376,6 +1396,7 @@ int multi_update::do_updates(bool from_send_error) for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local) { byte *ref_pos; + bool can_compare_record; table = cur_table->table; if (table == table_to_update) @@ -1402,6 +1423,9 @@ int multi_update::do_updates(bool from_send_error) if ((local_error = tmp_table->file->ha_rnd_init(1))) goto err; + can_compare_record= !(table->file->table_flags() & + HA_PARTIAL_COLUMN_READ); + ref_pos= (byte*) tmp_table->field[0]->ptr; for (;;) { @@ -1431,7 +1455,7 @@ int multi_update::do_updates(bool from_send_error) TRG_ACTION_BEFORE, TRUE)) goto err2; - if (compare_record(table, thd->query_id)) + if (!can_compare_record || compare_record(table, thd->query_id)) { if ((local_error=table->file->update_row(table->record[1], table->record[0]))) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 952a8eb44ea..deac9cb5c40 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2529,7 +2529,7 @@ create_table_option: | MIN_ROWS opt_equal ulonglong_num { Lex->create_info.min_rows= $3; Lex->create_info.used_fields|= HA_CREATE_USED_MIN_ROWS;} | AVG_ROW_LENGTH opt_equal ulong_num { Lex->create_info.avg_row_length=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AVG_ROW_LENGTH;} | PASSWORD opt_equal TEXT_STRING_sys { Lex->create_info.password=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_PASSWORD; } - | COMMENT_SYM opt_equal TEXT_STRING_sys { Lex->create_info.comment=$3.str; Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT; } + | COMMENT_SYM opt_equal TEXT_STRING_sys { Lex->create_info.comment=$3; Lex->create_info.used_fields|= HA_CREATE_USED_COMMENT; } | AUTO_INC opt_equal ulonglong_num { Lex->create_info.auto_increment_value=$3; Lex->create_info.used_fields|= HA_CREATE_USED_AUTO;} | PACK_KEYS_SYM opt_equal ulong_num { @@ -4453,7 +4453,10 @@ simple_expr: Lex->safe_to_cache_query=0; } | CURRENT_USER optional_braces - { $$= create_func_current_user(); } + { + $$= new Item_func_current_user(Lex->current_context()); + Lex->safe_to_cache_query= 0; + } | DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')' { $$= new Item_date_add_interval($3,$5,$6,0); } | DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')' @@ -4810,7 +4813,7 @@ simple_expr: | UNIX_TIMESTAMP '(' expr ')' { $$= new Item_func_unix_timestamp($3); } | USER '(' ')' - { $$= new Item_func_user(FALSE); Lex->safe_to_cache_query=0; } + { $$= new Item_func_user(); Lex->safe_to_cache_query=0; } | UTC_DATE_SYM optional_braces { $$= new Item_func_curdate_utc(); Lex->safe_to_cache_query=0;} | UTC_TIME_SYM optional_braces @@ -6522,24 +6525,10 @@ show_param: { LEX *lex=Lex; lex->sql_command= SQLCOM_SHOW_GRANTS; - THD *thd= lex->thd; - Security_context *sctx= thd->security_ctx; LEX_USER *curr_user; - if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(st_lex_user)))) + if (!(curr_user= (LEX_USER*) lex->thd->alloc(sizeof(st_lex_user)))) YYABORT; - curr_user->user.str= sctx->priv_user; - curr_user->user.length= strlen(sctx->priv_user); - if (*sctx->priv_host != 0) - { - curr_user->host.str= sctx->priv_host; - curr_user->host.length= strlen(sctx->priv_host); - } - else - { - curr_user->host.str= (char *) "%"; - curr_user->host.length= 1; - } - curr_user->password=null_lex_str; + bzero(curr_user, sizeof(st_lex_user)); lex->grant_user= curr_user; } | GRANTS FOR_SYM user @@ -7489,22 +7478,14 @@ user: } | CURRENT_USER optional_braces { - THD *thd= YYTHD; - Security_context *sctx= thd->security_ctx; - if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) + if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user)))) YYABORT; - $$->user.str= sctx->priv_user; - $$->user.length= strlen(sctx->priv_user); - if (*sctx->priv_host != 0) - { - $$->host.str= sctx->priv_host; - $$->host.length= strlen(sctx->priv_host); - } - else - { - $$->host.str= (char *) "%"; - $$->host.length= 1; - } + /* + empty LEX_USER means current_user and + will be handled in the get_current_user() function + later + */ + bzero($$, sizeof(LEX_USER)); }; /* Keyword that we allow for identifiers (except SP labels) */ diff --git a/sql/table.cc b/sql/table.cc index 9ec9463c33c..728b98b2d35 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -410,7 +410,9 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, int_length= uint2korr(head+274); share->null_fields= uint2korr(head+282); com_length= uint2korr(head+284); - share->comment= strdup_root(&outparam->mem_root, (char*) head+47); + share->comment.length= (int) (head[46]); + share->comment.str= strmake_root(&outparam->mem_root, (char*) head+47, + share->comment.length); DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length)); @@ -678,6 +680,27 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, if (outparam->key_info[key].flags & HA_FULLTEXT) outparam->key_info[key].algorithm= HA_KEY_ALG_FULLTEXT; + if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME)) + { + /* + If the UNIQUE key doesn't have NULL columns and is not a part key + declare this as a primary key. + */ + primary_key=key; + for (i=0 ; i < keyinfo->key_parts ;i++) + { + uint fieldnr= key_part[i].fieldnr; + if (!fieldnr || + outparam->field[fieldnr-1]->null_ptr || + outparam->field[fieldnr-1]->key_length() != + key_part[i].length) + { + primary_key=MAX_KEY; // Can't be used + break; + } + } + } + for (i=0 ; i < keyinfo->key_parts ; key_part++,i++) { if (new_field_pack_flag <= 1) @@ -781,7 +804,8 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, if (!(field->flags & BLOB_FLAG)) { // Create a new field field=key_part->field=field->new_field(&outparam->mem_root, - outparam); + outparam, + outparam == field->table); field->field_length=key_part->length; } } diff --git a/sql/table.h b/sql/table.h index ebb4481ef3a..d23d58e964f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -124,7 +124,7 @@ typedef struct st_table_share #endif uint *blob_field; /* Index to blobs in Field arrray*/ byte *default_values; /* row with default values */ - char *comment; /* Comment about table */ + LEX_STRING comment; /* Comment about table */ CHARSET_INFO *table_charset; /* Default charset of string fields */ /* A pair "database_name\0table_name\0", widely used as simply a db name */ diff --git a/sql/unireg.cc b/sql/unireg.cc index 0ab77462f61..3a139aea4c7 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -76,7 +76,7 @@ bool mysql_create_frm(THD *thd, my_string file_name, handler *db_file) { LEX_STRING str_db_type; - uint reclength,info_length,screens,key_info_length,maxlength; + uint reclength, info_length, screens, key_info_length, maxlength, tmp_len; ulong key_buff_length; File file; ulong filepos, data_offset; @@ -143,10 +143,30 @@ bool mysql_create_frm(THD *thd, my_string file_name, fileinfo[26]= (uchar) test((create_info->max_rows == 1) && (create_info->min_rows == 1) && (keys == 0)); int2store(fileinfo+28,key_info_length); - strmake((char*) forminfo+47,create_info->comment ? create_info->comment : "", - 60); - forminfo[46]=(uchar) strlen((char*)forminfo+47); // Length of comment + tmp_len= system_charset_info->cset->charpos(system_charset_info, + create_info->comment.str, + create_info->comment.str + + create_info->comment.length, 60); + if (tmp_len < create_info->comment.length) + { + char buff[128]; + (void) my_snprintf(buff, sizeof(buff), "Too long comment for table '%s'", + table); + if ((thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))) + { + my_message(ER_UNKNOWN_ERROR, buff, MYF(0)); + goto err; + } + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), buff); + create_info->comment.length= tmp_len; + } + + strmake((char*) forminfo+47, create_info->comment.str ? + create_info->comment.str : "", create_info->comment.length); + forminfo[46]=(uchar) create_info->comment.length; if (my_pwrite(file,(byte*) fileinfo,64,0L,MYF_RW) || my_pwrite(file,(byte*) keybuff,key_info_length, (ulong) uint2korr(fileinfo+6),MYF_RW)) @@ -449,6 +469,27 @@ static bool pack_header(uchar *forminfo, enum db_type table_type, create_field *field; while ((field=it++)) { + + uint tmp_len= system_charset_info->cset->charpos(system_charset_info, + field->comment.str, + field->comment.str + + field->comment.length, 255); + if (tmp_len < field->comment.length) + { + char buff[128]; + (void) my_snprintf(buff,sizeof(buff), "Too long comment for field '%s'", + field->field_name); + if ((current_thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))) + { + my_message(ER_UNKNOWN_ERROR, buff, MYF(0)); + DBUG_RETURN(1); + } + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), buff); + field->comment.length= tmp_len; + } + totlength+= field->length; com_length+= field->comment.length; if (MTYP_TYPENR(field->unireg_check) == Field::NOEMPTY || diff --git a/strings/decimal.c b/strings/decimal.c index 8786a513945..5a0bc0968b6 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -171,6 +171,7 @@ static const dec1 frac_max[DIG_PER_DEC1-1]={ do \ { \ dec1 a=(from1)+(from2)+(carry); \ + DBUG_ASSERT((carry) <= 1); \ if (((carry)= a >= DIG_BASE)) /* no division here! */ \ a-=DIG_BASE; \ (to)=a; \ @@ -179,7 +180,7 @@ static const dec1 frac_max[DIG_PER_DEC1-1]={ #define ADD2(to, from1, from2, carry) \ do \ { \ - dec1 a=(from1)+(from2)+(carry); \ + dec2 a=((dec2)(from1))+(from2)+(carry); \ if (((carry)= a >= DIG_BASE)) \ a-=DIG_BASE; \ if (unlikely(a >= DIG_BASE)) \ @@ -187,7 +188,7 @@ static const dec1 frac_max[DIG_PER_DEC1-1]={ a-=DIG_BASE; \ carry++; \ } \ - (to)=a; \ + (to)=(dec1) a; \ } while(0) #define SUB(to, from1, from2, carry) /* to=from1-from2 */ \ @@ -1998,7 +1999,13 @@ int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to) ADD2(*buf0, *buf0, lo, carry); carry+=hi; } - for (; carry; buf0--) + if (carry) + { + if (buf0 < to->buf) + return E_DEC_OVERFLOW; + ADD2(*buf0, *buf0, 0, carry); + } + for (buf0--; carry; buf0--) { if (buf0 < to->buf) return E_DEC_OVERFLOW; diff --git a/strings/strtod.c b/strings/strtod.c index 61f2c107abe..e0910205d2f 100644 --- a/strings/strtod.c +++ b/strings/strtod.c @@ -26,7 +26,8 @@ */ -#include "my_base.h" /* Includes errno.h */ +#include "my_base.h" /* Defines EOVERFLOW on Windows */ +#include "my_global.h" /* Includes errno.h */ #include "m_ctype.h" #define MAX_DBL_EXP 308 diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index fd92c2bd25e..5a0963e4f93 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -27,6 +27,23 @@ %define see_base For a description of MySQL see the base MySQL RPM or http://www.mysql.com +# On SuSE 9 no separate "debuginfo" package is built. To enable basic +# debugging on that platform, we don't strip binaries on SuSE 9. We +# disable the strip of binaries by redefining the RPM macro +# "__os_install_post" leaving out the script calls that normally does +# this. We do this in all cases, as on platforms where "debuginfo" is +# created, a script "find-debuginfo.sh" will be called that will do +# the strip anyway, part of separating the executable and debug +# information into separate files put into separate packages. +# +# Some references (shows more advanced conditional usage): +# http://www.redhat.com/archives/rpm-list/2001-November/msg00257.html +# http://www.redhat.com/archives/rpm-list/2003-February/msg00275.html +# http://www.redhat.com/archives/rhl-devel-list/2004-January/msg01546.html +# http://lists.opensuse.org/archive/opensuse-commit/2006-May/1171.html + +%define __os_install_post /usr/lib/rpm/brp-compress + Name: MySQL Summary: MySQL: a very fast and reliable SQL database server Group: Applications/Databases @@ -325,7 +342,7 @@ then cp -fp config.log "$MYSQL_MAXCONFLOG_DEST" fi -make -i test-force || true +make -i test-force-pl || true # Save mysqld-max ./libtool --mode=execute cp sql/mysqld sql/mysqld-max @@ -384,7 +401,7 @@ then cp -fp config.log "$MYSQL_CONFLOG_DEST" fi -make -i test-force || true +make -i test-force-pl || true %install RBR=$RPM_BUILD_ROOT @@ -723,6 +740,15 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Mon Jul 10 2006 Joerg Bruehe <joerg@mysql.com> + +- Fix a typing error in the "make" target for the Perl script to run the tests. + +* Tue Jul 04 2006 Joerg Bruehe <joerg@mysql.com> + +- Use the Perl script to run the tests, because it will automatically check + whether the server is configured with SSL. + * Tue Jun 27 2006 Joerg Bruehe <joerg@mysql.com> - move "mysqldumpslow" from the client RPM to the server RPM (bug#20216) diff --git a/tests/Makefile.am b/tests/Makefile.am index ebe97393045..ab747d6e4ec 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -42,8 +42,14 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ LIBS = @CLIENT_LIBS@ LDADD = @CLIENT_EXTRA_LDFLAGS@ \ $(top_builddir)/libmysql/libmysqlclient.la +if HAVE_NETWARE +mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) +mysql_client_test_SOURCES= mysql_client_test.c $(yassl_dummy_link_fix) \ + ../mysys/my_memmem.c +else mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) -L../mysys -lmysys mysql_client_test_SOURCES= mysql_client_test.c $(yassl_dummy_link_fix) +endif insert_test_SOURCES= insert_test.c $(yassl_dummy_link_fix) select_test_SOURCES= select_test.c $(yassl_dummy_link_fix) insert_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 3876de58b0e..7ad902afb6c 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -8311,6 +8311,39 @@ static void test_list_fields() } +static void test_bug19671() +{ + MYSQL_RES *result; + int rc; + myheader("test_bug19671"); + + rc= mysql_query(mysql, "drop table if exists t1"); + myquery(rc); + + rc= mysql_query(mysql, "drop view if exists v1"); + myquery(rc); + + rc= mysql_query(mysql, "create table t1(f1 int)"); + myquery(rc); + + rc= mysql_query(mysql, "create view v1 as select va.* from t1 va"); + myquery(rc); + + result= mysql_list_fields(mysql, "v1", NULL); + mytest(result); + + rc= my_process_result_set(result); + DIE_UNLESS(rc == 0); + + verify_prepare_field(result, 0, "f1", "f1", MYSQL_TYPE_LONG, + "v1", "v1", current_db, 11, "0"); + + mysql_free_result(result); + myquery(mysql_query(mysql, "drop view v1")); + myquery(mysql_query(mysql, "drop table t1")); +} + + /* Test a memory ovverun bug */ static void test_mem_overun() @@ -14882,11 +14915,13 @@ static void test_bug17667() printf("success. All queries found intact in the log.\n"); - } else { + } + else + { fprintf(stderr, "Could not find the log file, var/log/master.log, so " - "test_bug17667 is \ninconclusive. Run test from the " - "mysql-test/mysql-test-run* program \nto set up the correct " - "environment for this test.\n\n"); + "test_bug17667 is \ninconclusive. Run test from the " + "mysql-test/mysql-test-run* program \nto set up the correct " + "environment for this test.\n\n"); } if (log_file != NULL) @@ -14896,7 +14931,8 @@ static void test_bug17667() /* - Bug#14169: type of group_concat() result changed to blob if tmp_table was used + Bug#14169: type of group_concat() result changed to blob if tmp_table was + used */ static void test_bug14169() { @@ -14929,7 +14965,62 @@ static void test_bug14169() rc= mysql_query(mysql, "drop table t1"); myquery(rc); -}/* +} + + +/* + Bug#20152: mysql_stmt_execute() writes to MYSQL_TYPE_DATE buffer +*/ + +static void test_bug20152() +{ + MYSQL_BIND bind[1]; + MYSQL_STMT *stmt; + MYSQL_TIME tm; + int rc; + const char *query= "INSERT INTO t1 (f1) VALUES (?)"; + + myheader("test_bug20152"); + + memset(bind, 0, sizeof(bind)); + bind[0].buffer_type= MYSQL_TYPE_DATE; + bind[0].buffer= (void*)&tm; + + tm.year = 2006; + tm.month = 6; + tm.day = 18; + tm.hour = 14; + tm.minute = 9; + tm.second = 42; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + rc= mysql_query(mysql, "CREATE TABLE t1 (f1 DATE)"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + check_execute(stmt, rc); + rc= mysql_stmt_bind_param(stmt, bind); + check_execute(stmt, rc); + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + rc= mysql_stmt_close(stmt); + check_execute(stmt, rc); + rc= mysql_query(mysql, "DROP TABLE t1"); + myquery(rc); + + if (tm.hour == 14 && tm.minute == 9 && tm.second == 42) { + if (!opt_silent) + printf("OK!"); + } else { + printf("[14:09:42] != [%02d:%02d:%02d]\n", tm.hour, tm.minute, tm.second); + DIE_UNLESS(0==1); + } +} + + +/* Read and parse arguments and MySQL options from my.cnf */ @@ -15193,8 +15284,10 @@ static struct my_tests_st my_tests[]= { { "test_bug12744", test_bug12744 }, { "test_bug16143", test_bug16143 }, { "test_bug15613", test_bug15613 }, + { "test_bug20152", test_bug20152 }, { "test_bug14169", test_bug14169 }, { "test_bug17667", test_bug17667 }, + { "test_bug19671", test_bug19671}, { 0, 0 } }; |