diff options
291 files changed, 6664 insertions, 7446 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 817e3224ea4..7d58e034e6b 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..cf3d7b72040 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) @@ -651,7 +651,7 @@ AC_ARG_ENABLE(assembler, AC_MSG_CHECKING(if we should use assembler functions) # For now we only support assembler on i386 and sparc systems -AM_CONDITIONAL(ASSEMBLER_x86, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "i386") +AM_CONDITIONAL(ASSEMBLER_x86, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "i386" && $AS strings/strings-x86.s -o checkassembler >/dev/null 2>&1 && test -f checkassembler && (rm -f checkassembler; exit 0;)) AM_CONDITIONAL(ASSEMBLER_sparc32, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparc") AM_CONDITIONAL(ASSEMBLER_sparc64, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparcv9") AM_CONDITIONAL(ASSEMBLER, test "$ASSEMBLER_x86_TRUE" = "" -o "$ASSEMBLER_sparc32_TRUE" = "") diff --git a/extra/yassl/FLOSS-EXCEPTIONS b/extra/yassl/FLOSS-EXCEPTIONS new file mode 100644 index 00000000000..344083b0114 --- /dev/null +++ b/extra/yassl/FLOSS-EXCEPTIONS @@ -0,0 +1,120 @@ +yaSSL FLOSS License Exception +**************************************** + +Version 0.1, 26 June 2006 + +The Sawtooth Consulting Ltd. Exception for Free/Libre and Open Source +Software-only Applications Using yaSSL Libraries (the "FLOSS Exception"). + +*Exception Intent* + +We want specified Free/Libre and Open Source Software ("FLOSS") +applications to be able to use specified GPL-licensed yaSSL +libraries (the "Program") despite the fact that not all FLOSS +licenses are compatible with version 2 of the GNU General Public +License (the "GPL"). + +*Legal Terms and Conditions* + +As a special exception to the terms and conditions of version 2.0 of +the GPL: + + 1. You are free to distribute a Derivative Work that is formed + entirely from the Program and one or more works (each, a "FLOSS + Work") licensed under one or more of the licenses listed below + in section 1, as long as: + + 1. You obey the GPL in all respects for the Program and the + Derivative Work, except for identifiable sections of the + Derivative Work which are not derived from the Program, + and which can reasonably be considered independent and + separate works in themselves, + + 2. all identifiable sections of the Derivative Work which + are not derived from the Program, and which can reasonably be + considered independent and separate works in themselves, + + * i + + are distributed subject to one of the FLOSS licenses + listed below, and + + * ii + + the object code or executable form of those sections are + accompanied by the complete corresponding machine-readable + source code for those sections on the same medium and under + the same FLOSS license as the corresponding object code or + executable forms of those sections, and + + + 3. any works which are aggregated with the Program or with + a Derivative Work on a volume of a storage or distribution + medium in accordance with the GPL, can reasonably be considered + independent and separate works in themselves which are not + derivatives of either the Program, a Derivative Work or a FLOSS + Work. + + + If the above conditions are not met, then the Program may only be + copied, modified, distributed or used under the terms and + conditions of the GPL or another valid licensing option from + Sawtooth Consulting Ltd. + + 2. FLOSS License List + + *License name* *Version(s)/Copyright Date* + Academic Free License 2.0 + Apache Software License 1.0/1.1/2.0 + Apple Public Source License 2.0 + Artistic license From Perl 5.8.0 + BSD license "July 22 1999" + Common Development and Distribution License (CDDL) 1.0 + Common Public License 1.0 + GNU Library or "Lesser" General Public 2.0/2.1 + License (LGPL) + Jabber Open Source License 1.0 + MIT license - + Mozilla Public License (MPL) 1.0/1.1 + Open Software License 2.0 + PHP License 3.0 + Python license (CNRI Python License) - + Python Software Foundation License 2.1.1 + Sleepycat License "1999" + W3C License "2001" + X11 License "2001" + Zlib/libpng License - + Zope Public License 2.0 + + Due to the many variants of some of the above licenses, we require + that any version follow the 2003 version of the Free Software + Foundation's Free Software Definition + (http://www.gnu.org/philosophy/free-sw.html + (http://www.gnu.org/philosophy/free-sw.html)) or version 1.9 of + the Open Source Definition by the Open Source Initiative + (http://www.opensource.org/docs/definition.php + (http://www.opensource.org/docs/definition.php)). + + 3. Definitions + + 1. Terms used, but not defined, herein shall have the + meaning provided in the GPL. + + 2. Derivative Work means a derivative work under copyright + law. + + + 4. Applicability This FLOSS Exception applies to all Programs that + contain a notice placed by Sawtooth Consulting Ltd. saying that the + Program may be distributed under the terms of this FLOSS Exception. + If you create or distribute a work which is a Derivative Work of + both the Program and any other work licensed under the GPL, then + this FLOSS Exception is not available for that work; thus, you + must remove the FLOSS Exception notice from that work and + comply with the GPL in all respects, including by retaining all + GPL notices. You may choose to redistribute a copy of the + Program exclusively under the terms of the GPL by removing the + FLOSS Exception notice from that copy of the Program, provided + that the copy has never been modified by you or any third party. + + diff --git a/extra/yassl/README b/extra/yassl/README index a5ff70aa6f6..25d4d94c306 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -1,4 +1,14 @@ -yaSSL Release notes, version 1.3.5 (06/01/06) +yaSSL Release notes, version 1.3.7 (06/26/06) + + + This release of yaSSL contains bug fixes, portability enhancements, + and libcurl 7.15.4 support (any newer versions may not build). + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0. + + +********************yaSSL Release notes, version 1.3.5 (06/01/06) This release of yaSSL contains bug fixes, portability enhancements, diff --git a/extra/yassl/include/buffer.hpp b/extra/yassl/include/buffer.hpp index 6b0e9e65389..4816f79a9bc 100644 --- a/extra/yassl/include/buffer.hpp +++ b/extra/yassl/include/buffer.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/include/cert_wrapper.hpp b/extra/yassl/include/cert_wrapper.hpp index 2a214c529fd..8b5b7491772 100644 --- a/extra/yassl/include/cert_wrapper.hpp +++ b/extra/yassl/include/cert_wrapper.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/include/crypto_wrapper.hpp b/extra/yassl/include/crypto_wrapper.hpp index cb542c25a67..4c4e4d5da5b 100644 --- a/extra/yassl/include/crypto_wrapper.hpp +++ b/extra/yassl/include/crypto_wrapper.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -36,6 +40,7 @@ #define yaSSL_CRYPTO_WRAPPER_HPP #include "yassl_types.hpp" +#include <stdio.h> // FILE namespace yaSSL { @@ -410,7 +415,8 @@ private: class x509; -x509* PemToDer(const char*, CertType); + +x509* PemToDer(FILE*, CertType); } // naemspace diff --git a/extra/yassl/include/factory.hpp b/extra/yassl/include/factory.hpp index f457188f587..5619e90cd62 100644 --- a/extra/yassl/include/factory.hpp +++ b/extra/yassl/include/factory.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/include/handshake.hpp b/extra/yassl/include/handshake.hpp index 6261359cd58..ea390fee322 100644 --- a/extra/yassl/include/handshake.hpp +++ b/extra/yassl/include/handshake.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -55,7 +59,7 @@ void sendCertificateVerify(SSL&, BufferOutput = buffered); int sendData(SSL&, const void*, int); int sendAlert(SSL& ssl, const Alert& alert); -int receiveData(SSL&, Data&); +int receiveData(SSL&, Data&, bool peek = false); void processReply(SSL&); void buildFinished(SSL&, Finished&, const opaque*); diff --git a/extra/yassl/include/lock.hpp b/extra/yassl/include/lock.hpp index f5231528821..5b585b1cf16 100644 --- a/extra/yassl/include/lock.hpp +++ b/extra/yassl/include/lock.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/include/log.hpp b/extra/yassl/include/log.hpp index c20116901ad..33cb38ebae0 100644 --- a/extra/yassl/include/log.hpp +++ b/extra/yassl/include/log.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index af801029561..47b4d075894 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -36,6 +40,10 @@ #include "opensslv.h" /* for version number */ #include "rsa.h" + +#define YASSL_VERSION "1.3.7" + + #if defined(__cplusplus) extern "C" { #endif @@ -414,6 +422,7 @@ int RAND_load_file(const char*, long); /* for libcurl */ int RAND_status(void); +int RAND_bytes(unsigned char* buf, int num); int DES_set_key(const_DES_cblock*, DES_key_schedule*); void DES_set_odd_parity(DES_cblock*); @@ -421,6 +430,7 @@ void DES_ecb_encrypt(DES_cblock*, DES_cblock*, DES_key_schedule*, int); void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX*, void* userdata); void SSL_SESSION_free(SSL_SESSION* session); +int SSL_peek(SSL* ssl, void* buf, int num); X509* SSL_get_certificate(SSL* ssl); EVP_PKEY* SSL_get_privatekey(SSL* ssl); @@ -513,6 +523,8 @@ void MD5_Init(MD5_CTX*); void MD5_Update(MD5_CTX*, const void*, unsigned long); void MD5_Final(unsigned char*, MD5_CTX*); +#define MD5_DIGEST_LENGTH 16 + #define SSL_DEFAULT_CIPHER_LIST "" /* default all */ diff --git a/extra/yassl/include/socket_wrapper.hpp b/extra/yassl/include/socket_wrapper.hpp index 16db142b3a2..1dd61b63148 100644 --- a/extra/yassl/include/socket_wrapper.hpp +++ b/extra/yassl/include/socket_wrapper.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/include/timer.hpp b/extra/yassl/include/timer.hpp index 3025b7a0bd9..ff90aa884de 100644 --- a/extra/yassl/include/timer.hpp +++ b/extra/yassl/include/timer.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/include/yassl_error.hpp b/extra/yassl/include/yassl_error.hpp index 2f35fecb59b..3c3d5fa5231 100644 --- a/extra/yassl/include/yassl_error.hpp +++ b/extra/yassl/include/yassl_error.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/include/yassl_imp.hpp b/extra/yassl/include/yassl_imp.hpp index 2f240b71c03..838aace72c8 100644 --- a/extra/yassl/include/yassl_imp.hpp +++ b/extra/yassl/include/yassl_imp.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -664,9 +668,9 @@ struct Parameters { char cipher_name_[MAX_SUITE_NAME]; char cipher_list_[MAX_CIPHERS][MAX_SUITE_NAME]; - Parameters(ConnectionEnd, const Ciphers&, ProtocolVersion); + Parameters(ConnectionEnd, const Ciphers&, ProtocolVersion, bool haveDH); - void SetSuites(ProtocolVersion pv); + void SetSuites(ProtocolVersion pv, bool removeDH = false); void SetCipherNames(); private: Parameters(const Parameters&); // hide copy diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp index 633b75d479f..26900aed3af 100644 --- a/extra/yassl/include/yassl_int.hpp +++ b/extra/yassl/include/yassl_int.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -429,9 +433,10 @@ private: // holds input and output buffers class Buffers { +public: typedef mySTL::list<input_buffer*> inputList; typedef mySTL::list<output_buffer*> outputList; - +private: inputList dataList_; // list of users app data / handshake outputList handShakeList_; // buffered handshake msgs public: @@ -458,7 +463,7 @@ class Security { bool resuming_; // trying to resume public: Security(ProtocolVersion, RandomPool&, ConnectionEnd, const Ciphers&, - SSL_CTX*); + SSL_CTX*, bool); const SSL_CTX* GetContext() const; const Connection& get_connection() const; @@ -521,6 +526,7 @@ public: void makeTLSMasterSecret(); void addData(input_buffer* data); void fillData(Data&); + void PeekData(Data&); void addBuffer(output_buffer* b); void flushBuffer(); void verifyState(const RecordLayerHeader&); diff --git a/extra/yassl/include/yassl_types.hpp b/extra/yassl/include/yassl_types.hpp index 76c807cd05f..b75a2a45302 100644 --- a/extra/yassl/include/yassl_types.hpp +++ b/extra/yassl/include/yassl_types.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/mySTL/algorithm.hpp b/extra/yassl/mySTL/algorithm.hpp index 3ceb0ca5fdc..efc7aa21a07 100644 --- a/extra/yassl/mySTL/algorithm.hpp +++ b/extra/yassl/mySTL/algorithm.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/mySTL/helpers.hpp b/extra/yassl/mySTL/helpers.hpp index df79025197a..c4449519db3 100644 --- a/extra/yassl/mySTL/helpers.hpp +++ b/extra/yassl/mySTL/helpers.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/mySTL/list.hpp b/extra/yassl/mySTL/list.hpp index dd8485f48a7..11a1a914868 100644 --- a/extra/yassl/mySTL/list.hpp +++ b/extra/yassl/mySTL/list.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/mySTL/memory.hpp b/extra/yassl/mySTL/memory.hpp index cc70fbf60d8..f480af12316 100644 --- a/extra/yassl/mySTL/memory.hpp +++ b/extra/yassl/mySTL/memory.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/mySTL/pair.hpp b/extra/yassl/mySTL/pair.hpp index c9bb03b5953..13916fece13 100644 --- a/extra/yassl/mySTL/pair.hpp +++ b/extra/yassl/mySTL/pair.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/mySTL/stdexcept.hpp b/extra/yassl/mySTL/stdexcept.hpp index 33ea43bf0e0..4fd343ae6fd 100644 --- a/extra/yassl/mySTL/stdexcept.hpp +++ b/extra/yassl/mySTL/stdexcept.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/mySTL/vector.hpp b/extra/yassl/mySTL/vector.hpp index 9eab91cfda8..6a412447b91 100644 --- a/extra/yassl/mySTL/vector.hpp +++ b/extra/yassl/mySTL/vector.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/src/buffer.cpp b/extra/yassl/src/buffer.cpp index 3bc6dced887..4d396a8d29f 100644 --- a/extra/yassl/src/buffer.cpp +++ b/extra/yassl/src/buffer.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp index ae609b510ba..6ad0aa568ed 100644 --- a/extra/yassl/src/cert_wrapper.cpp +++ b/extra/yassl/src/cert_wrapper.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -182,7 +186,8 @@ int CertManager::CopyCaCert(const x509* x) signers_.push_back(NEW_YS TaoCrypt::Signer(key.GetKey(), key.size(), cert.GetCommonName(), cert.GetHash())); } - return cert.GetError().What(); + // just don't add, not an error return cert.GetError().What(); + return 0; } diff --git a/extra/yassl/src/crypto_wrapper.cpp b/extra/yassl/src/crypto_wrapper.cpp index 8859fbdd70f..799106ec7c0 100644 --- a/extra/yassl/src/crypto_wrapper.cpp +++ b/extra/yassl/src/crypto_wrapper.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -904,7 +908,7 @@ void DiffieHellman::get_parms(byte* bp, byte* bg, byte* bpub) const // convert PEM file to DER x509 type -x509* PemToDer(const char* fname, CertType type) +x509* PemToDer(FILE* file, CertType type) { using namespace TaoCrypt; @@ -919,10 +923,6 @@ x509* PemToDer(const char* fname, CertType type) strncpy(footer, "-----END RSA PRIVATE KEY-----", sizeof(header)); } - FILE* file = fopen(fname, "rb"); - if (!file) - return 0; - long begin = -1; long end = 0; bool foundEnd = false; @@ -943,18 +943,14 @@ x509* PemToDer(const char* fname, CertType type) else end = ftell(file); - if (begin == -1 || !foundEnd) { - fclose(file); + if (begin == -1 || !foundEnd) return 0; - } input_buffer tmp(end - begin); fseek(file, begin, SEEK_SET); size_t bytes = fread(tmp.get_buffer(), end - begin, 1, file); - if (bytes != 1) { - fclose(file); + if (bytes != 1) return 0; - } Source der(tmp.get_buffer(), end - begin); Base64Decoder b64Dec(der); @@ -963,7 +959,6 @@ x509* PemToDer(const char* fname, CertType type) mySTL::auto_ptr<x509> x(NEW_YS x509(sz), ysDelete); memcpy(x->use_buffer(), der.get_buffer(), sz); - fclose(file); return x.release(); } diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index 66ec64f4af8..e93f5385b3d 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -912,7 +916,7 @@ int sendAlert(SSL& ssl, const Alert& alert) // process input data -int receiveData(SSL& ssl, Data& data) +int receiveData(SSL& ssl, Data& data, bool peek) { if (ssl.GetError() == YasslError(SSL_ERROR_WANT_READ)) ssl.SetError(no_error); @@ -922,9 +926,13 @@ int receiveData(SSL& ssl, Data& data) if (!ssl.bufferedData()) processReply(ssl); + + if (peek) + ssl.PeekData(data); + else ssl.fillData(data); - ssl.useLog().ShowData(data.get_length()); + ssl.useLog().ShowData(data.get_length()); if (ssl.GetError()) return -1; if (data.get_length() == 0 && ssl.getSocket().WouldBlock()) { diff --git a/extra/yassl/src/lock.cpp b/extra/yassl/src/lock.cpp index 4827d396e81..0f4c80b1616 100644 --- a/extra/yassl/src/lock.cpp +++ b/extra/yassl/src/lock.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/src/log.cpp b/extra/yassl/src/log.cpp index 8ab351ee2b1..c8030787f3d 100644 --- a/extra/yassl/src/log.cpp +++ b/extra/yassl/src/log.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp index 06b403c999d..7790001fc2d 100644 --- a/extra/yassl/src/socket_wrapper.cpp +++ b/extra/yassl/src/socket_wrapper.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index 07f5e9859b2..81e585ff735 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -64,12 +68,15 @@ int read_file(SSL_CTX* ctx, const char* file, int format, CertType type) return SSL_BAD_FILE; if (type == CA) { - x509* ptr = PemToDer(file, Cert); - if (!ptr) { + // may have a bunch of CAs + x509* ptr; + while ( (ptr = PemToDer(input, Cert)) ) + ctx->AddCA(ptr); + + if (!feof(input)) { fclose(input); return SSL_BAD_FILE; } - ctx->AddCA(ptr); // takes ownership } else { x509*& x = (type == Cert) ? ctx->certificate_ : ctx->privateKey_; @@ -86,7 +93,7 @@ int read_file(SSL_CTX* ctx, const char* file, int format, CertType type) } } else { - x = PemToDer(file, type); + x = PemToDer(input, type); if (!x) { fclose(input); return SSL_BAD_FILE; @@ -1189,6 +1196,35 @@ void MD5_Final(unsigned char* hash, MD5_CTX* md5) } +int RAND_bytes(unsigned char* buf, int num) +{ + RandomPool ran; + + if (ran.GetError()) return 0; + + ran.Fill(buf, num); + return 1; +} + + +int SSL_peek(SSL* ssl, void* buffer, int sz) +{ + Data data(min(sz, MAX_RECORD_SIZE), static_cast<opaque*>(buffer)); + return receiveData(*ssl, data, true); +} + + +int SSL_pending(SSL* ssl) +{ + // Just in case there's pending data that hasn't been processed yet... + char c; + SSL_peek(ssl, &c, 1); + + return ssl->bufferedData(); +} + + + // functions for stunnel void RAND_screen() @@ -1352,12 +1388,6 @@ void MD5_Final(unsigned char* hash, MD5_CTX* md5) } - int SSL_pending(SSL*) - { - return SSL_SUCCESS; // TODO: - } - - int SSL_want_read(SSL*) { return 0; // TODO: diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp index ce8972c72fe..c5fc23dabdb 100644 --- a/extra/yassl/src/template_instnt.cpp +++ b/extra/yassl/src/template_instnt.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/src/timer.cpp b/extra/yassl/src/timer.cpp index 8b7d2d17a84..8500d09120b 100644 --- a/extra/yassl/src/timer.cpp +++ b/extra/yassl/src/timer.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/src/yassl.cpp b/extra/yassl/src/yassl.cpp index 86af12fd448..5bc8bad8bbc 100644 --- a/extra/yassl/src/yassl.cpp +++ b/extra/yassl/src/yassl.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp index 72b8e459241..4f75de34a98 100644 --- a/extra/yassl/src/yassl_error.cpp +++ b/extra/yassl/src/yassl_error.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp index 4d6d1fc7aff..310e8819c54 100644 --- a/extra/yassl/src/yassl_imp.cpp +++ b/extra/yassl/src/yassl_imp.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -428,7 +432,7 @@ opaque* DH_Server::get_serverKey() const // set available suites Parameters::Parameters(ConnectionEnd ce, const Ciphers& ciphers, - ProtocolVersion pv) : entity_(ce) + ProtocolVersion pv, bool haveDH) : entity_(ce) { pending_ = true; // suite not set yet @@ -438,11 +442,11 @@ Parameters::Parameters(ConnectionEnd ce, const Ciphers& ciphers, SetCipherNames(); } else - SetSuites(pv); // defaults + SetSuites(pv, ce == server_end && !haveDH); // defaults } -void Parameters::SetSuites(ProtocolVersion pv) +void Parameters::SetSuites(ProtocolVersion pv, bool removeDH) { int i = 0; // available suites, best first @@ -450,19 +454,23 @@ void Parameters::SetSuites(ProtocolVersion pv) // MAX_CIPHERS is big enough if (isTLS(pv)) { + if (!removeDH) { suites_[i++] = 0x00; suites_[i++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA; suites_[i++] = 0x00; suites_[i++] = TLS_DHE_DSS_WITH_AES_256_CBC_SHA; + } suites_[i++] = 0x00; suites_[i++] = TLS_RSA_WITH_AES_256_CBC_SHA; - suites_[i++] = 0x00; - suites_[i++] = TLS_RSA_WITH_AES_128_CBC_SHA; + if (!removeDH) { suites_[i++] = 0x00; suites_[i++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA; suites_[i++] = 0x00; suites_[i++] = TLS_DHE_DSS_WITH_AES_128_CBC_SHA; + } + suites_[i++] = 0x00; + suites_[i++] = TLS_RSA_WITH_AES_128_CBC_SHA; suites_[i++] = 0x00; suites_[i++] = TLS_RSA_WITH_AES_256_CBC_RMD160; @@ -471,6 +479,7 @@ void Parameters::SetSuites(ProtocolVersion pv) suites_[i++] = 0x00; suites_[i++] = TLS_RSA_WITH_3DES_EDE_CBC_RMD160; + if (!removeDH) { suites_[i++] = 0x00; suites_[i++] = TLS_DHE_RSA_WITH_AES_256_CBC_RMD160; suites_[i++] = 0x00; @@ -485,6 +494,7 @@ void Parameters::SetSuites(ProtocolVersion pv) suites_[i++] = 0x00; suites_[i++] = TLS_DHE_DSS_WITH_3DES_EDE_CBC_RMD160; } + } suites_[i++] = 0x00; suites_[i++] = SSL_RSA_WITH_RC4_128_SHA; @@ -496,6 +506,7 @@ void Parameters::SetSuites(ProtocolVersion pv) suites_[i++] = 0x00; suites_[i++] = SSL_RSA_WITH_DES_CBC_SHA; + if (!removeDH) { suites_[i++] = 0x00; suites_[i++] = SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA; suites_[i++] = 0x00; @@ -505,6 +516,7 @@ void Parameters::SetSuites(ProtocolVersion pv) suites_[i++] = SSL_DHE_RSA_WITH_DES_CBC_SHA; suites_[i++] = 0x00; suites_[i++] = SSL_DHE_DSS_WITH_DES_CBC_SHA; + } suites_size_ = i; diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp index 1ff46903bfd..831942aaf69 100644 --- a/extra/yassl/src/yassl_int.cpp +++ b/extra/yassl/src/yassl_int.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -260,7 +264,8 @@ const ClientKeyFactory& sslFactory::getClientKey() const // extract context parameters and store SSL::SSL(SSL_CTX* ctx) : secure_(ctx->getMethod()->getVersion(), crypto_.use_random(), - ctx->getMethod()->getSide(), ctx->GetCiphers(), ctx) + ctx->getMethod()->getSide(), ctx->GetCiphers(), ctx, + ctx->GetDH_Parms().set_) { if (int err = crypto_.get_random().GetError()) { SetError(YasslError(err)); @@ -986,6 +991,36 @@ void SSL::fillData(Data& data) } +// like Fill but keep data in buffer +void SSL::PeekData(Data& data) +{ + if (GetError()) return; + uint dataSz = data.get_length(); // input, data size to fill + uint elements = buffers_.getData().size(); + + data.set_length(0); // output, actual data filled + dataSz = min(dataSz, bufferedData()); + + Buffers::inputList::iterator front = buffers_.getData().begin(); + + while (elements) { + uint frontSz = (*front)->get_remaining(); + uint readSz = min(dataSz - data.get_length(), frontSz); + uint before = (*front)->get_current(); + + (*front)->read(data.set_buffer() + data.get_length(), readSz); + data.set_length(data.get_length() + readSz); + (*front)->set_current(before); + + if (data.get_length() == dataSz) + break; + + elements--; + front++; + } +} + + // flush output buffer void SSL::flushBuffer() { @@ -1910,9 +1945,9 @@ Buffers::outputList& Buffers::useHandShake() Security::Security(ProtocolVersion pv, RandomPool& ran, ConnectionEnd ce, - const Ciphers& ciphers, SSL_CTX* ctx) - : conn_(pv, ran), parms_(ce, ciphers, pv), resumeSession_(ran), ctx_(ctx), - resuming_(false) + const Ciphers& ciphers, SSL_CTX* ctx, bool haveDH) + : conn_(pv, ran), parms_(ce, ciphers, pv, haveDH), resumeSession_(ran), + ctx_(ctx), resuming_(false) {} diff --git a/extra/yassl/taocrypt/include/aes.hpp b/extra/yassl/taocrypt/include/aes.hpp index e2c1a34b0e3..cb70f5c0e7e 100644 --- a/extra/yassl/taocrypt/include/aes.hpp +++ b/extra/yassl/taocrypt/include/aes.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/algebra.hpp b/extra/yassl/taocrypt/include/algebra.hpp index a09ac8dce16..07fc405f093 100644 --- a/extra/yassl/taocrypt/include/algebra.hpp +++ b/extra/yassl/taocrypt/include/algebra.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/arc4.hpp b/extra/yassl/taocrypt/include/arc4.hpp index c37b89fb294..05b0921f5a1 100644 --- a/extra/yassl/taocrypt/include/arc4.hpp +++ b/extra/yassl/taocrypt/include/arc4.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp index da4c0ce1349..90bc46a59fd 100644 --- a/extra/yassl/taocrypt/include/asn.hpp +++ b/extra/yassl/taocrypt/include/asn.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/block.hpp b/extra/yassl/taocrypt/include/block.hpp index 76836615ce6..88cb06f62f1 100644 --- a/extra/yassl/taocrypt/include/block.hpp +++ b/extra/yassl/taocrypt/include/block.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/blowfish.hpp b/extra/yassl/taocrypt/include/blowfish.hpp index 7d794a37329..fbc4f223702 100644 --- a/extra/yassl/taocrypt/include/blowfish.hpp +++ b/extra/yassl/taocrypt/include/blowfish.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/coding.hpp b/extra/yassl/taocrypt/include/coding.hpp index 9aab2a30c7e..da6771a5bea 100644 --- a/extra/yassl/taocrypt/include/coding.hpp +++ b/extra/yassl/taocrypt/include/coding.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/des.hpp b/extra/yassl/taocrypt/include/des.hpp index e0867b09166..48bb1e9119d 100644 --- a/extra/yassl/taocrypt/include/des.hpp +++ b/extra/yassl/taocrypt/include/des.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/dh.hpp b/extra/yassl/taocrypt/include/dh.hpp index 75a5d6280d3..869c3edf5b3 100644 --- a/extra/yassl/taocrypt/include/dh.hpp +++ b/extra/yassl/taocrypt/include/dh.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/dsa.hpp b/extra/yassl/taocrypt/include/dsa.hpp index f1fdd2dfa25..a5ba416382d 100644 --- a/extra/yassl/taocrypt/include/dsa.hpp +++ b/extra/yassl/taocrypt/include/dsa.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/error.hpp b/extra/yassl/taocrypt/include/error.hpp index 55ab39313f5..b0ff9b280ba 100644 --- a/extra/yassl/taocrypt/include/error.hpp +++ b/extra/yassl/taocrypt/include/error.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/file.hpp b/extra/yassl/taocrypt/include/file.hpp index fe7e1073c99..87fc6139f8f 100644 --- a/extra/yassl/taocrypt/include/file.hpp +++ b/extra/yassl/taocrypt/include/file.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/hash.hpp b/extra/yassl/taocrypt/include/hash.hpp index 16112cb644d..e3030088e0e 100644 --- a/extra/yassl/taocrypt/include/hash.hpp +++ b/extra/yassl/taocrypt/include/hash.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/hmac.hpp b/extra/yassl/taocrypt/include/hmac.hpp index 543366afc3a..d46a6d4e7c3 100644 --- a/extra/yassl/taocrypt/include/hmac.hpp +++ b/extra/yassl/taocrypt/include/hmac.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/integer.hpp b/extra/yassl/taocrypt/include/integer.hpp index ee83906cfbc..7e4f6450316 100644 --- a/extra/yassl/taocrypt/include/integer.hpp +++ b/extra/yassl/taocrypt/include/integer.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/kernelc.hpp b/extra/yassl/taocrypt/include/kernelc.hpp index bb74c10ad07..317359553e4 100644 --- a/extra/yassl/taocrypt/include/kernelc.hpp +++ b/extra/yassl/taocrypt/include/kernelc.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/md2.hpp b/extra/yassl/taocrypt/include/md2.hpp index 1e1c17e9cbe..89856adffe9 100644 --- a/extra/yassl/taocrypt/include/md2.hpp +++ b/extra/yassl/taocrypt/include/md2.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/md4.hpp b/extra/yassl/taocrypt/include/md4.hpp index aac930d7498..d2da7e35e4d 100644 --- a/extra/yassl/taocrypt/include/md4.hpp +++ b/extra/yassl/taocrypt/include/md4.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/md5.hpp b/extra/yassl/taocrypt/include/md5.hpp index 981f29108fe..30d14d54fbf 100644 --- a/extra/yassl/taocrypt/include/md5.hpp +++ b/extra/yassl/taocrypt/include/md5.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/misc.hpp b/extra/yassl/taocrypt/include/misc.hpp index 0808d76ccdf..48604620706 100644 --- a/extra/yassl/taocrypt/include/misc.hpp +++ b/extra/yassl/taocrypt/include/misc.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/modarith.hpp b/extra/yassl/taocrypt/include/modarith.hpp index 66a841b05c3..47b91560657 100644 --- a/extra/yassl/taocrypt/include/modarith.hpp +++ b/extra/yassl/taocrypt/include/modarith.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/modes.hpp b/extra/yassl/taocrypt/include/modes.hpp index 10f336c00eb..65b7318661e 100644 --- a/extra/yassl/taocrypt/include/modes.hpp +++ b/extra/yassl/taocrypt/include/modes.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/pwdbased.hpp b/extra/yassl/taocrypt/include/pwdbased.hpp index f40c48fe026..c3e916e3d83 100644 --- a/extra/yassl/taocrypt/include/pwdbased.hpp +++ b/extra/yassl/taocrypt/include/pwdbased.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/random.hpp b/extra/yassl/taocrypt/include/random.hpp index 62f49a8716f..628faaf116c 100644 --- a/extra/yassl/taocrypt/include/random.hpp +++ b/extra/yassl/taocrypt/include/random.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/ripemd.hpp b/extra/yassl/taocrypt/include/ripemd.hpp index b72e503f095..2e594b7604d 100644 --- a/extra/yassl/taocrypt/include/ripemd.hpp +++ b/extra/yassl/taocrypt/include/ripemd.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/rsa.hpp b/extra/yassl/taocrypt/include/rsa.hpp index e327fdd20ad..1b531b9d0c0 100644 --- a/extra/yassl/taocrypt/include/rsa.hpp +++ b/extra/yassl/taocrypt/include/rsa.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/runtime.hpp b/extra/yassl/taocrypt/include/runtime.hpp index 88559cb0ca0..3a72b2917f8 100644 --- a/extra/yassl/taocrypt/include/runtime.hpp +++ b/extra/yassl/taocrypt/include/runtime.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/sha.hpp b/extra/yassl/taocrypt/include/sha.hpp index 3e301a6f0ae..2d65932dc17 100644 --- a/extra/yassl/taocrypt/include/sha.hpp +++ b/extra/yassl/taocrypt/include/sha.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/twofish.hpp b/extra/yassl/taocrypt/include/twofish.hpp index 8605221854f..0529c37d6c5 100644 --- a/extra/yassl/taocrypt/include/twofish.hpp +++ b/extra/yassl/taocrypt/include/twofish.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/type_traits.hpp b/extra/yassl/taocrypt/include/type_traits.hpp index d03ccae64ed..b985358e1c1 100644 --- a/extra/yassl/taocrypt/include/type_traits.hpp +++ b/extra/yassl/taocrypt/include/type_traits.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/include/types.hpp b/extra/yassl/taocrypt/include/types.hpp index a2453a994fb..9c3fa8f64f2 100644 --- a/extra/yassl/taocrypt/include/types.hpp +++ b/extra/yassl/taocrypt/include/types.hpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/aes.cpp b/extra/yassl/taocrypt/src/aes.cpp index e737af33df3..574a88a736c 100644 --- a/extra/yassl/taocrypt/src/aes.cpp +++ b/extra/yassl/taocrypt/src/aes.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/aestables.cpp b/extra/yassl/taocrypt/src/aestables.cpp index af9924703ef..4118715fd0c 100644 --- a/extra/yassl/taocrypt/src/aestables.cpp +++ b/extra/yassl/taocrypt/src/aestables.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp index 9c485609dd0..e9bc3fceac0 100644 --- a/extra/yassl/taocrypt/src/algebra.cpp +++ b/extra/yassl/taocrypt/src/algebra.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/arc4.cpp b/extra/yassl/taocrypt/src/arc4.cpp index 6d1c4d4e3a6..ea1e084014c 100644 --- a/extra/yassl/taocrypt/src/arc4.cpp +++ b/extra/yassl/taocrypt/src/arc4.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp index 383fe65dea6..beb5490bb66 100644 --- a/extra/yassl/taocrypt/src/asn.cpp +++ b/extra/yassl/taocrypt/src/asn.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -472,16 +476,7 @@ void CertDecoder::Decode(SignerList* signers, CertType ct) return; } - if (ct == CA) { - if ( memcmp(issuerHash_, subjectHash_, SHA::DIGEST_SIZE) == 0 ) { - if (!ValidateSelfSignature() && verify_) - source_.SetError(SIG_CONFIRM_E); - } - else - if (!ValidateSignature(signers) && verify_) - source_.SetError(SIG_OTHER_E); - } - else if (!ValidateSignature(signers) && verify_) + if (ct != CA && verify_ && !ValidateSignature(signers)) source_.SetError(SIG_OTHER_E); } diff --git a/extra/yassl/taocrypt/src/bftables.cpp b/extra/yassl/taocrypt/src/bftables.cpp index e072b117f54..2dbb6c01674 100644 --- a/extra/yassl/taocrypt/src/bftables.cpp +++ b/extra/yassl/taocrypt/src/bftables.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/blowfish.cpp b/extra/yassl/taocrypt/src/blowfish.cpp index 16e2277dc10..cc929cd7d41 100644 --- a/extra/yassl/taocrypt/src/blowfish.cpp +++ b/extra/yassl/taocrypt/src/blowfish.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/coding.cpp b/extra/yassl/taocrypt/src/coding.cpp index 01ea399df13..b8bbd29bb2b 100644 --- a/extra/yassl/taocrypt/src/coding.cpp +++ b/extra/yassl/taocrypt/src/coding.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/des.cpp b/extra/yassl/taocrypt/src/des.cpp index d2db4fc939e..054c8c2eb78 100644 --- a/extra/yassl/taocrypt/src/des.cpp +++ b/extra/yassl/taocrypt/src/des.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/dh.cpp b/extra/yassl/taocrypt/src/dh.cpp index 44934394343..aec7122b70b 100644 --- a/extra/yassl/taocrypt/src/dh.cpp +++ b/extra/yassl/taocrypt/src/dh.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/dsa.cpp b/extra/yassl/taocrypt/src/dsa.cpp index 4574fe5ebd8..a132c7339f5 100644 --- a/extra/yassl/taocrypt/src/dsa.cpp +++ b/extra/yassl/taocrypt/src/dsa.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/file.cpp b/extra/yassl/taocrypt/src/file.cpp index 4d48b9e7bca..7c59af09708 100644 --- a/extra/yassl/taocrypt/src/file.cpp +++ b/extra/yassl/taocrypt/src/file.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/hash.cpp b/extra/yassl/taocrypt/src/hash.cpp index 4e783e2c3b1..fbbdf0c8c31 100644 --- a/extra/yassl/taocrypt/src/hash.cpp +++ b/extra/yassl/taocrypt/src/hash.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index a296e122985..823c0c5e193 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/md2.cpp b/extra/yassl/taocrypt/src/md2.cpp index 16834b6bc89..aeadbdfb367 100644 --- a/extra/yassl/taocrypt/src/md2.cpp +++ b/extra/yassl/taocrypt/src/md2.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/md4.cpp b/extra/yassl/taocrypt/src/md4.cpp index dfc2b079141..6012330cba3 100644 --- a/extra/yassl/taocrypt/src/md4.cpp +++ b/extra/yassl/taocrypt/src/md4.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/md5.cpp b/extra/yassl/taocrypt/src/md5.cpp index 3d64ff8a8a1..f7b0b1ee2dc 100644 --- a/extra/yassl/taocrypt/src/md5.cpp +++ b/extra/yassl/taocrypt/src/md5.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp index 2869df71c8a..b8095334789 100644 --- a/extra/yassl/taocrypt/src/misc.cpp +++ b/extra/yassl/taocrypt/src/misc.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp index 945a7fa6ff7..2ee1e57a663 100644 --- a/extra/yassl/taocrypt/src/random.cpp +++ b/extra/yassl/taocrypt/src/random.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/ripemd.cpp b/extra/yassl/taocrypt/src/ripemd.cpp index da96b6cc1b4..c791189544f 100644 --- a/extra/yassl/taocrypt/src/ripemd.cpp +++ b/extra/yassl/taocrypt/src/ripemd.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/rsa.cpp b/extra/yassl/taocrypt/src/rsa.cpp index 021fd992b5c..b280c48f1af 100644 --- a/extra/yassl/taocrypt/src/rsa.cpp +++ b/extra/yassl/taocrypt/src/rsa.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/sha.cpp b/extra/yassl/taocrypt/src/sha.cpp index 12f80c1af75..b877e2b7857 100644 --- a/extra/yassl/taocrypt/src/sha.cpp +++ b/extra/yassl/taocrypt/src/sha.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp index 12bcd8238f2..512c5cf9dce 100644 --- a/extra/yassl/taocrypt/src/template_instnt.cpp +++ b/extra/yassl/taocrypt/src/template_instnt.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/tftables.cpp b/extra/yassl/taocrypt/src/tftables.cpp index 55846d5f79d..7d7f2e98ac3 100644 --- a/extra/yassl/taocrypt/src/tftables.cpp +++ b/extra/yassl/taocrypt/src/tftables.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/extra/yassl/taocrypt/src/twofish.cpp b/extra/yassl/taocrypt/src/twofish.cpp index 8b896ad5dc4..a16a8f0d169 100644 --- a/extra/yassl/taocrypt/src/twofish.cpp +++ b/extra/yassl/taocrypt/src/twofish.cpp @@ -9,6 +9,10 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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..91a9a758d1d 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 @@ -3069,6 +3074,7 @@ sub run_mysqltest ($) { my $cmdline_mysql_client_test= "$exe_mysql_client_test --no-defaults --testcase --user=root --silent " . "--port=$master->[0]->{'path_myport'} " . + "--vardir=$opt_vardir " . "--socket=$master->[0]->{'path_mysock'}"; if ( $glob_use_embedded_server ) 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/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/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index f060c3c9bf6..890cdfd5cfc 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -704,6 +704,32 @@ select f1 from t1 where f1 like 'a%'; f1 a drop table t1; +create table t1 (utext varchar(20) character set ucs2); +insert into t1 values ("lily"); +insert into t1 values ("river"); +prepare stmt from 'select utext from t1 where utext like ?'; +set @param1='%%'; +execute stmt using @param1; +utext +lily +river +execute stmt using @param1; +utext +lily +river +select utext from t1 where utext like '%%'; +utext +lily +river +drop table t1; +deallocate prepare stmt; +CREATE TABLE t1 (id int, s char(5) CHARACTER SET ucs2 COLLATE ucs2_unicode_ci); +INSERT INTO t1 VALUES (1, 'ZZZZZ'), (1, 'ZZZ'), (2, 'ZZZ'), (2, 'ZZZZZ'); +SELECT id, MIN(s) FROM t1 GROUP BY id; +id MIN(s) +1 ZZZ +2 ZZZ +DROP TABLE t1; CREATE TABLE t1 (a varchar(64) character set ucs2, b decimal(10,3)); INSERT INTO t1 VALUES ("1.1", 0), ("2.1", 0); update t1 set b=a; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 991d1711a9e..934f56877ac 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1152,6 +1152,135 @@ id a 6 bbbbbb 11 bbbbbb DROP TABLE t1; +SET NAMES utf8; +CREATE TABLE t1 ( +a CHAR(13) DEFAULT '', +INDEX(a) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; +INSERT INTO t1 VALUES +('Käli Käli 2-4'), ('Käli Käli 2-4'), +('Käli Käli 2+4'), ('Käli Käli 2+4'), +('Käli Käli 2-6'), ('Käli Käli 2-6'); +INSERT INTO t1 SELECT * FROM t1; +CREATE TABLE t2 ( +a CHAR(13) DEFAULT '', +INDEX(a) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci; +INSERT INTO t2 VALUES +('Kali Kali 2-4'), ('Kali Kali 2-4'), +('Kali Kali 2+4'), ('Kali Kali 2+4'), +('Kali Kali 2-6'), ('Kali Kali 2-6'); +INSERT INTO t2 SELECT * FROM t2; +SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4'; +a +Käli Käli 2+4 +Käli Käli 2+4 +Käli Käli 2+4 +Käli Käli 2+4 +SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4'; +a +Kali Kali 2+4 +Kali Kali 2+4 +Kali Kali 2+4 +Kali Kali 2+4 +EXPLAIN SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 40 NULL 4 Using where; Using index +EXPLAIN SELECT a FROM t1 WHERE a = 'Käli Käli 2+4'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref a a 40 const 4 Using where; Using index +EXPLAIN SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range a a 14 NULL 4 Using where; Using index +EXPLAIN SELECT a FROM t2 WHERE a = 'Kali Kali 2+4'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref a a 14 const 4 Using where; Using index +DROP TABLE t1,t2; +CREATE TABLE t1 ( +a char(255) DEFAULT '', +KEY(a(10)) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; +INSERT INTO t1 VALUES ('Käli Käli 2-4'); +SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%'; +a +Käli Käli 2-4 +INSERT INTO t1 VALUES ('Käli Käli 2-4'); +SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%'; +a +Käli Käli 2-4 +Käli Käli 2-4 +DROP TABLE t1; +CREATE TABLE t1 ( +a char(255) DEFAULT '' +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; +INSERT INTO t1 VALUES ('Käli Käli 2-4'); +INSERT INTO t1 VALUES ('Käli Käli 2-4'); +SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%'; +a +Käli Käli 2-4 +Käli Käli 2-4 +ALTER TABLE t1 ADD KEY (a(10)); +SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%'; +a +Käli Käli 2-4 +Käli Käli 2-4 +DROP TABLE t1; +SET NAMES latin2; +CREATE TABLE t1 ( +id int(11) NOT NULL default '0', +tid int(11) NOT NULL default '0', +val text NOT NULL, +INDEX idx(tid, val(10)) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +INSERT INTO t1 VALUES +(40988,72,'VOLNÝ ADSL'),(41009,72,'VOLNÝ ADSL'), +(41032,72,'VOLNÝ ADSL'),(41038,72,'VOLNÝ ADSL'), +(41063,72,'VOLNÝ ADSL'),(41537,72,'VOLNÝ ADSL Office'), +(42141,72,'VOLNÝ ADSL'),(42565,72,'VOLNÝ ADSL Combi'), +(42749,72,'VOLNÝ ADSL'),(44205,72,'VOLNÝ ADSL'); +SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNY ADSL'; +id tid val +40988 72 VOLNÝ ADSL +41009 72 VOLNÝ ADSL +41032 72 VOLNÝ ADSL +41038 72 VOLNÝ ADSL +41063 72 VOLNÝ ADSL +42141 72 VOLNÝ ADSL +42749 72 VOLNÝ ADSL +44205 72 VOLNÝ ADSL +SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNÝ ADSL'; +id tid val +40988 72 VOLNÝ ADSL +41009 72 VOLNÝ ADSL +41032 72 VOLNÝ ADSL +41038 72 VOLNÝ ADSL +41063 72 VOLNÝ ADSL +42141 72 VOLNÝ ADSL +42749 72 VOLNÝ ADSL +44205 72 VOLNÝ ADSL +SELECT * FROM t1 WHERE tid=72 and val LIKE '%VOLNÝ ADSL'; +id tid val +40988 72 VOLNÝ ADSL +41009 72 VOLNÝ ADSL +41032 72 VOLNÝ ADSL +41038 72 VOLNÝ ADSL +41063 72 VOLNÝ ADSL +42141 72 VOLNÝ ADSL +42749 72 VOLNÝ ADSL +44205 72 VOLNÝ ADSL +ALTER TABLE t1 DROP KEY idx; +ALTER TABLE t1 ADD KEY idx (tid,val(11)); +SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNÝ ADSL'; +id tid val +40988 72 VOLNÝ ADSL +41009 72 VOLNÝ ADSL +41032 72 VOLNÝ ADSL +41038 72 VOLNÝ ADSL +41063 72 VOLNÝ ADSL +42141 72 VOLNÝ ADSL +42749 72 VOLNÝ ADSL +44205 72 VOLNÝ ADSL +DROP TABLE t1; CREATE TABLE t1(id varchar(20) NOT NULL) DEFAULT CHARSET=utf8; INSERT INTO t1 VALUES ('xxx'), ('aa'), ('yyy'), ('aa'); SELECT id FROM t1; 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/distinct.result b/mysql-test/r/distinct.result index 89b17d69f40..a3d1e8bf3bb 100644 --- a/mysql-test/r/distinct.result +++ b/mysql-test/r/distinct.result @@ -504,6 +504,57 @@ a 2 b 2 2 4 3 2 5 DROP TABLE t1,t2; +CREATE TABLE t1(a INT PRIMARY KEY, b INT); +INSERT INTO t1 VALUES (1,1), (2,1), (3,1); +EXPLAIN SELECT DISTINCT a FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL 3 Using index +EXPLAIN SELECT DISTINCT a,b FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +EXPLAIN SELECT DISTINCT t1_1.a, t1_1.b FROM t1 t1_1, t1 t1_2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1_1 ALL NULL NULL NULL NULL 3 Using temporary +1 SIMPLE t1_2 index NULL PRIMARY 4 NULL 3 Using index; Distinct +EXPLAIN SELECT DISTINCT t1_1.a, t1_1.b FROM t1 t1_1, t1 t1_2 +WHERE t1_1.a = t1_2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1_1 ALL PRIMARY NULL NULL NULL 3 Using temporary +1 SIMPLE t1_2 eq_ref PRIMARY PRIMARY 4 test.t1_1.a 1 Using index; Distinct +EXPLAIN SELECT a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL 3 Using index +EXPLAIN SELECT a,b FROM t1 GROUP BY a,b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +EXPLAIN SELECT DISTINCT a,b FROM t1 GROUP BY a,b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +CREATE TABLE t2(a INT, b INT, c INT, d INT, PRIMARY KEY (a,b)); +INSERT INTO t2 VALUES (1,1,1,50), (1,2,3,40), (2,1,3,4); +EXPLAIN SELECT DISTINCT a FROM t2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index NULL PRIMARY 8 NULL 3 Using index +EXPLAIN SELECT DISTINCT a,a FROM t2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index NULL PRIMARY 8 NULL 3 Using index +EXPLAIN SELECT DISTINCT b,a FROM t2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index NULL PRIMARY 8 NULL 3 Using index +EXPLAIN SELECT DISTINCT a,c FROM t2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using temporary +EXPLAIN SELECT DISTINCT c,a,b FROM t2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 +EXPLAIN SELECT DISTINCT a,b,d FROM t2 GROUP BY c,b,d; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using temporary; Using filesort +CREATE UNIQUE INDEX c_b_unq ON t2 (c,b); +EXPLAIN SELECT DISTINCT a,b,d FROM t2 GROUP BY c,b,d; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 +DROP TABLE t1,t2; create table t1 (id int, dsc varchar(50)); insert into t1 values (1, "line number one"), (2, "line number two"), (3, "line number three"); select distinct id, IFNULL(dsc, '-') from t1; 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_compress.result b/mysql-test/r/func_compress.result index e3d31566741..df8939d98f1 100644 --- a/mysql-test/r/func_compress.result +++ b/mysql-test/r/func_compress.result @@ -79,3 +79,31 @@ uncompress(a) uncompressed_length(a) NULL NULL a 1 drop table t1; +create table t1 (a varchar(32) not null); +insert into t1 values ('foo'); +explain select * from t1 where uncompress(a) is null; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +Warnings: +Error 1256 Uncompressed data size too large; the maximum size is 104857600 (probably, length of uncompressed data was corrupted) +select * from t1 where uncompress(a) is null; +a +foo +Warnings: +Error 1256 Uncompressed data size too large; the maximum size is 104857600 (probably, length of uncompressed data was corrupted) +explain select *, uncompress(a) from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +select *, uncompress(a) from t1; +a uncompress(a) +foo NULL +Warnings: +Error 1256 Uncompressed data size too large; the maximum size is 104857600 (probably, length of uncompressed data was corrupted) +select *, uncompress(a), uncompress(a) is null from t1; +a uncompress(a) uncompress(a) is null +foo NULL 1 +Warnings: +Error 1256 Uncompressed data size too large; the maximum size is 104857600 (probably, length of uncompressed data was corrupted) +Error 1256 Uncompressed data size too large; the maximum size is 104857600 (probably, length of uncompressed data was corrupted) +drop table t1; +End of 5.0 tests diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result index d984eee80fa..64eb6eefd1a 100644 --- a/mysql-test/r/func_sapdb.result +++ b/mysql-test/r/func_sapdb.result @@ -81,6 +81,12 @@ makedate(1997,1) select makedate(1997,0); makedate(1997,0) NULL +select makedate(9999,365); +makedate(9999,365) +9999-12-31 +select makedate(9999,366); +makedate(9999,366) +NULL select addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002"); addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002") 1998-01-02 01:01:01.000001 diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index a10e6675522..66fe355ffce 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -397,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/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/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..cd66e8727c1 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -132,3 +132,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/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_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/symlink.result b/mysql-test/r/symlink.result index 3ce7cc0c835..272836c450a 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -74,18 +74,24 @@ t9 CREATE TABLE `t9` ( ) ENGINE=MyISAM AUTO_INCREMENT=16725 DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' INDEX DIRECTORY='MYSQLTEST_VARDIR/run/' drop database mysqltest; create table t1 (a int not null) engine=myisam; +Warnings: +Warning 0 DATA DIRECTORY option ignored show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 alter table t1 add b int; +Warnings: +Warning 0 DATA DIRECTORY option ignored show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, `b` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Warnings: +Warning 0 INDEX DIRECTORY option ignored show create table t1; Table Create Table t1 CREATE TABLE `t1` ( 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/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index c7662f4f85a..eea0b06b224 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -439,6 +439,32 @@ insert into t1 values('a'); create index t1f1 on t1(f1); select f1 from t1 where f1 like 'a%'; drop table t1; + +# +# Bug#9442 Set parameter make query fail if column character set is UCS2 +# +create table t1 (utext varchar(20) character set ucs2); +insert into t1 values ("lily"); +insert into t1 values ("river"); +prepare stmt from 'select utext from t1 where utext like ?'; +set @param1='%%'; +execute stmt using @param1; +execute stmt using @param1; +select utext from t1 where utext like '%%'; +drop table t1; +deallocate prepare stmt; + +# +# Bug #20076: server crashes for a query with GROUP BY if MIN/MAX aggregation +# over a 'ucs2' field uses a temporary table +# + +CREATE TABLE t1 (id int, s char(5) CHARACTER SET ucs2 COLLATE ucs2_unicode_ci); +INSERT INTO t1 VALUES (1, 'ZZZZZ'), (1, 'ZZZ'), (2, 'ZZZ'), (2, 'ZZZZZ'); + +SELECT id, MIN(s) FROM t1 GROUP BY id; + +DROP TABLE t1; # End of 4.1 tests # diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index b58a2cf97d4..77b76a14171 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -938,6 +938,94 @@ SELECT id, a FROM t1 WHERE a='bbbbbb' ORDER BY b; DROP TABLE t1; +# +# Bug#16674: LIKE predicate for a utf8 character set column +# + +SET NAMES utf8; + +CREATE TABLE t1 ( + a CHAR(13) DEFAULT '', + INDEX(a) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; +INSERT INTO t1 VALUES + ('Käli Käli 2-4'), ('Käli Käli 2-4'), + ('Käli Käli 2+4'), ('Käli Käli 2+4'), + ('Käli Käli 2-6'), ('Käli Käli 2-6'); +INSERT INTO t1 SELECT * FROM t1; + +CREATE TABLE t2 ( + a CHAR(13) DEFAULT '', + INDEX(a) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci; + +INSERT INTO t2 VALUES + ('Kali Kali 2-4'), ('Kali Kali 2-4'), + ('Kali Kali 2+4'), ('Kali Kali 2+4'), + ('Kali Kali 2-6'), ('Kali Kali 2-6'); +INSERT INTO t2 SELECT * FROM t2; + +SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4'; +SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4'; + +EXPLAIN SELECT a FROM t1 WHERE a LIKE 'Käli Käli 2+4'; +EXPLAIN SELECT a FROM t1 WHERE a = 'Käli Käli 2+4'; +EXPLAIN SELECT a FROM t2 WHERE a LIKE 'Kali Kali 2+4'; +EXPLAIN SELECT a FROM t2 WHERE a = 'Kali Kali 2+4'; + +DROP TABLE t1,t2; + +CREATE TABLE t1 ( + a char(255) DEFAULT '', + KEY(a(10)) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; +INSERT INTO t1 VALUES ('Käli Käli 2-4'); +SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%'; +INSERT INTO t1 VALUES ('Käli Käli 2-4'); +SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%'; +DROP TABLE t1; + +CREATE TABLE t1 ( + a char(255) DEFAULT '' +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; +INSERT INTO t1 VALUES ('Käli Käli 2-4'); +INSERT INTO t1 VALUES ('Käli Käli 2-4'); +SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%'; +ALTER TABLE t1 ADD KEY (a(10)); +SELECT * FROM t1 WHERE a LIKE 'Käli Käli 2%'; +DROP TABLE t1; + +# +# Bug#18359: LIKE predicate for a 'utf8' text column with a partial index +# (see bug #16674 as well) +# + +SET NAMES latin2; + +CREATE TABLE t1 ( + id int(11) NOT NULL default '0', + tid int(11) NOT NULL default '0', + val text NOT NULL, + INDEX idx(tid, val(10)) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO t1 VALUES + (40988,72,'VOLNÝ ADSL'),(41009,72,'VOLNÝ ADSL'), + (41032,72,'VOLNÝ ADSL'),(41038,72,'VOLNÝ ADSL'), + (41063,72,'VOLNÝ ADSL'),(41537,72,'VOLNÝ ADSL Office'), + (42141,72,'VOLNÝ ADSL'),(42565,72,'VOLNÝ ADSL Combi'), + (42749,72,'VOLNÝ ADSL'),(44205,72,'VOLNÝ ADSL'); + +SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNY ADSL'; +SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNÝ ADSL'; +SELECT * FROM t1 WHERE tid=72 and val LIKE '%VOLNÝ ADSL'; + +ALTER TABLE t1 DROP KEY idx; +ALTER TABLE t1 ADD KEY idx (tid,val(11)); + +SELECT * FROM t1 WHERE tid=72 and val LIKE 'VOLNÝ ADSL'; + +DROP TABLE t1; # End of 4.1 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/distinct.test b/mysql-test/t/distinct.test index 09f07c2852f..61250a7105e 100644 --- a/mysql-test/t/distinct.test +++ b/mysql-test/t/distinct.test @@ -349,6 +349,34 @@ SELECT DISTINCT 2, a, b FROM t2; SELECT DISTINCT a, 2, b FROM t2; DROP TABLE t1,t2; +# +# Bug#16458: Simple SELECT FOR UPDATE causes "Result Set not updatable" +# error. +# +CREATE TABLE t1(a INT PRIMARY KEY, b INT); +INSERT INTO t1 VALUES (1,1), (2,1), (3,1); +EXPLAIN SELECT DISTINCT a FROM t1; +EXPLAIN SELECT DISTINCT a,b FROM t1; +EXPLAIN SELECT DISTINCT t1_1.a, t1_1.b FROM t1 t1_1, t1 t1_2; +EXPLAIN SELECT DISTINCT t1_1.a, t1_1.b FROM t1 t1_1, t1 t1_2 + WHERE t1_1.a = t1_2.a; +EXPLAIN SELECT a FROM t1 GROUP BY a; +EXPLAIN SELECT a,b FROM t1 GROUP BY a,b; +EXPLAIN SELECT DISTINCT a,b FROM t1 GROUP BY a,b; + +CREATE TABLE t2(a INT, b INT, c INT, d INT, PRIMARY KEY (a,b)); +INSERT INTO t2 VALUES (1,1,1,50), (1,2,3,40), (2,1,3,4); +EXPLAIN SELECT DISTINCT a FROM t2; +EXPLAIN SELECT DISTINCT a,a FROM t2; +EXPLAIN SELECT DISTINCT b,a FROM t2; +EXPLAIN SELECT DISTINCT a,c FROM t2; +EXPLAIN SELECT DISTINCT c,a,b FROM t2; + +EXPLAIN SELECT DISTINCT a,b,d FROM t2 GROUP BY c,b,d; +CREATE UNIQUE INDEX c_b_unq ON t2 (c,b); +EXPLAIN SELECT DISTINCT a,b,d FROM t2 GROUP BY c,b,d; + +DROP TABLE t1,t2; # Bug 9784 DISTINCT IFNULL truncates data # 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_compress.test b/mysql-test/t/func_compress.test index 4ae749f2343..eeb5d509b94 100644 --- a/mysql-test/t/func_compress.test +++ b/mysql-test/t/func_compress.test @@ -57,3 +57,17 @@ select uncompress(a), uncompressed_length(a) from t1; drop table t1; # End of 4.1 tests + +# +# Bug #18539: uncompress(d) is null: impossible? +# +create table t1 (a varchar(32) not null); +insert into t1 values ('foo'); +explain select * from t1 where uncompress(a) is null; +select * from t1 where uncompress(a) is null; +explain select *, uncompress(a) from t1; +select *, uncompress(a) from t1; +select *, uncompress(a), uncompress(a) is null from t1; +drop table t1; + +--echo End of 5.0 tests diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test index 6189712b5fe..97101fba615 100644 --- a/mysql-test/t/func_sapdb.test +++ b/mysql-test/t/func_sapdb.test @@ -43,6 +43,8 @@ select weekofyear("1997-11-30 23:59:59.000001"); select makedate(1997,1); select makedate(1997,0); +select makedate(9999,365); +select makedate(9999,366); #Time functions diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 05c033f2b22..188e5667009 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -158,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/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/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..90a123cf5dc 100644 --- a/mysql-test/t/rpl_insert_id.test +++ b/mysql-test/t/rpl_insert_id.test @@ -147,6 +147,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/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/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..19d3c4902a8 100644 --- a/ndb/test/ndbapi/Makefile.am +++ b/ndb/test/ndbapi/Makefile.am @@ -31,13 +31,11 @@ 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 #flexTimedAsynch #testBlobs 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/mysql_explain_log.sh b/scripts/mysql_explain_log.sh index 973d9e8a363..fd468fdf091 100644 --- a/scripts/mysql_explain_log.sh +++ b/scripts/mysql_explain_log.sh @@ -1,5 +1,6 @@ -#!@PERL@ -w +#!@PERL@ use strict; +use warnings; use DBI; use Getopt::Long; @@ -58,7 +59,7 @@ else { } else { $Param->{Start} = time; - while(<STDIN>) { + while(<>) { $Param->{LineCount} ++ ; if ($Param->{ViewDate} ) { @@ -317,6 +318,8 @@ Usage: $0 [OPTIONS] < LOGFILE -p=PASSWORD --socket=SOCKET mysqld socket file to connect -s=SOCKET +--printerror=1 enable error output +-e 1 Read logfile from STDIN an try to EXPLAIN all SELECT statements. All UPDATE statements are rewritten to an EXPLAIN SELECT statement. The results of the EXPLAIN statement are collected and counted. All results with type=ALL are collected in an separete list. Results are printed to STDOUT. @@ -331,7 +334,7 @@ __END__ =head1 NAME -explain_log.pl +mysql_explain_log Feed a mysqld general logfile (created with mysqld --log) back into mysql and collect statistics about index usage with EXPLAIN. @@ -348,7 +351,7 @@ Then add indices to avoid table scans and remove those which aren't used. =head1 USAGE -explain_log.pl [--date=YYMMDD] --host=dbhost] [--user=dbuser] [--password=dbpw] [--socket=/path/to/socket] < logfile +mysql_explain_log [--date=YYMMDD] --host=dbhost] [--user=dbuser] [--password=dbpw] [--socket=/path/to/socket] < logfile --date=YYMMDD select only entrys of date @@ -370,21 +373,20 @@ explain_log.pl [--date=YYMMDD] --host=dbhost] [--user=dbuser] [--password=dbpw] -s=SOCKET +--printerror=1 enable error output + +-e 1 + =head1 EXAMPLE -explain_log.pl --host=localhost --user=foo --password=bar < /var/lib/mysql/mobile.log +mysql_explain_log --host=localhost --user=foo --password=bar < /var/lib/mysql/mobile.log =head1 AUTHORS Stefan Nitz - Jan Willamowius <jan@mobile.de>, http://www.mobile.de + Jan Willamowius <jan@willamowius.de>, http://www.willamowius.de Dennis Haney <davh@davh.dk> (Added socket support) -=head1 RECRUITING - -If you are looking for a MySQL or Perl job, take a look at http://www.mobile.de -and send me an email with your resume (you must be speaking German!). - =head1 SEE ALSO mysql documentation 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 a9c23485042..1af677fa754 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -363,6 +363,7 @@ void ha_ndbcluster::records_update() { Ndb *ndb= get_ndb(); struct Ndb_statistics stat; + ndb->setDatabaseName(m_dbname); if (ndb_get_table_statistics(ndb, m_tabname, &stat) == 0){ mean_rec_length= stat.row_size; data_file_length= stat.fragment_memory; @@ -2253,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()); @@ -2581,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; @@ -3081,6 +3085,7 @@ void ha_ndbcluster::info(uint flag) DBUG_VOID_RETURN; Ndb *ndb= get_ndb(); struct Ndb_statistics stat; + ndb->setDatabaseName(m_dbname); if (current_thd->variables.ndb_use_exact_count && ndb_get_table_statistics(ndb, m_tabname, &stat) == 0) { @@ -3212,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 @@ -3255,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); @@ -4099,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 @@ -4578,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), @@ -5491,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); @@ -5516,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; } @@ -5566,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)); @@ -5588,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 */ @@ -5603,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); } @@ -5636,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)); @@ -5649,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; @@ -5658,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); } @@ -5839,65 +5851,64 @@ 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 { - pTrans= ndb->startTransaction(); - if (pTrans == NULL) + Uint64 rows, commits, mem; + Uint32 size; + Uint32 count= 0; + Uint64 sum_rows= 0; + Uint64 sum_commits= 0; + Uint64 sum_row_size= 0; + Uint64 sum_mem= 0; + NdbScanOperation*pOp; + NdbResultSet *rs; + int check; + + if ((pTrans= ndb->startTransaction()) == NULL) { - if (ndb->getNdbError().status == NdbError::TemporaryError && - retries--) - { - my_sleep(retry_sleep); - continue; - } - break; + error= ndb->getNdbError(); + goto retry; + } + + if ((pOp= pTrans->getNdbScanOperation(table)) == NULL) + { + error= pTrans->getNdbError(); + goto retry; } - - NdbScanOperation* pOp= pTrans->getNdbScanOperation(table); - if (pOp == NULL) - break; if (pOp->readTuples(NdbOperation::LM_CommittedRead)) - break; + { + error= pOp->getNdbError(); + goto retry; + } - int check= pOp->interpret_exit_last_row(); - if (check == -1) - break; + if (pOp->interpret_exit_last_row() == -1) + { + error= pOp->getNdbError(); + goto retry; + } - Uint64 rows, commits, mem; - Uint32 size; pOp->getValue(NdbDictionary::Column::ROW_COUNT, (char*)&rows); pOp->getValue(NdbDictionary::Column::COMMIT_COUNT, (char*)&commits); pOp->getValue(NdbDictionary::Column::ROW_SIZE, (char*)&size); pOp->getValue(NdbDictionary::Column::FRAGMENT_MEMORY, (char*)&mem); - check= pTrans->execute(NdbTransaction::NoCommit, - NdbTransaction::AbortOnError, - TRUE); - if (check == -1) + if (pTrans->execute(NdbTransaction::NoCommit, + NdbTransaction::AbortOnError, + TRUE) == -1) { - if (pTrans->getNdbError().status == NdbError::TemporaryError && - retries--) - { - ndb->closeTransaction(pTrans); - pTrans= 0; - my_sleep(retry_sleep); - continue; - } - break; + error= pTrans->getNdbError(); + goto retry; } - - Uint32 count= 0; - Uint64 sum_rows= 0; - Uint64 sum_commits= 0; - Uint64 sum_row_size= 0; - Uint64 sum_mem= 0; + while ((check= pOp->nextResult(TRUE, TRUE)) == 0) { sum_rows+= rows; @@ -5909,7 +5920,10 @@ ndb_get_table_statistics(Ndb* ndb, const char * table, } if (check == -1) - break; + { + error= pOp->getNdbError(); + goto retry; + } pOp->close(TRUE); @@ -5920,18 +5934,30 @@ 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: + if (pTrans) + { + ndb->closeTransaction(pTrans); + pTrans= NULL; + } + if (error.status == NdbError::TemporaryError && retries--) + { + my_sleep(retry_sleep); + continue; + } + break; } while(1); - - if (pTrans) - ndb->closeTransaction(pTrans); - DBUG_PRINT("exit", ("failed")); - DBUG_RETURN(-1); + DBUG_PRINT("exit", ("failed, error %u(%s)", error.code, error.message)); + ERR_RETURN(error); } /* @@ -6449,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..b7b9f972f67 100644 --- a/sql/item.h +++ b/sql/item.h @@ -827,13 +827,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 +1068,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 +1134,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..8bc1bfaf7dd 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; /* @@ -937,7 +937,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 +982,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 +1157,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 +1493,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 +1670,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 +1889,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 +1956,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 +2164,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 +2246,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 +2705,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..13d32765c21 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -385,21 +385,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()"; } }; @@ -784,7 +803,7 @@ class Item_func_uncompress: public Item_str_func String buffer; public: Item_func_uncompress(Item *a): Item_str_func(a){} - void fix_length_and_dec(){max_length= MAX_BLOB_WIDTH;} + void fix_length_and_dec(){ maybe_null= 1; max_length= MAX_BLOB_WIDTH; } const char *func_name() const{return "uncompress";} String *val_str(String *) ZLIB_DEPENDED_FUNCTION }; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 962454e237e..4d70debb966 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -2102,7 +2102,6 @@ Item_sum_hybrid::min_max_update_str_field() if (!args[0]->null_value) { - res_str->strip_sp(); result_field->val_str(&tmp_value); if (result_field->is_null() || @@ -3229,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 d8b309978d5..9e1962835c8 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -27,27 +27,9 @@ /* TODO: Move month and days to language files */ +/* 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 @@ -222,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; @@ -298,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': @@ -408,7 +397,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, if (yearday > 0) { uint days= calc_daynr(l_time->year,1,1) + yearday - 1; - if (days <= 0 || days >= MAX_DAY_NUMBER) + if (days <= 0 || days > MAX_DAY_NUMBER) goto err; get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day); } @@ -454,7 +443,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, (weekday - 1); } - if (days <= 0 || days >= MAX_DAY_NUMBER) + if (days <= 0 || days > MAX_DAY_NUMBER) goto err; get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day); } @@ -501,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('-'); @@ -519,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) @@ -918,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) { @@ -925,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; } @@ -1050,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; } @@ -1675,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 */ @@ -1685,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; @@ -2035,7 +2047,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date) ltime->hour= (uint) (sec/3600); daynr= calc_daynr(ltime->year,ltime->month,1) + days; /* Day number from year 0 to 9999-12-31 */ - if ((ulonglong) daynr >= MAX_DAY_NUMBER) + if ((ulonglong) daynr > MAX_DAY_NUMBER) goto invalid_date; get_date_from_daynr((long) daynr, <ime->year, <ime->month, <ime->day); @@ -2046,7 +2058,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date) period= (calc_daynr(ltime->year,ltime->month,ltime->day) + sign * (long) interval.day); /* Daynumber from year 0 to 9999-12-31 */ - if ((ulong) period >= MAX_DAY_NUMBER) + if ((ulong) period > MAX_DAY_NUMBER) goto invalid_date; get_date_from_daynr((long) period,<ime->year,<ime->month,<ime->day); break; @@ -2570,7 +2582,7 @@ String *Item_func_makedate::val_str(String *str) days= calc_daynr(yearnr,1,1) + daynr - 1; /* Day number from year 0 to 9999-12-31 */ - if (days >= 0 && days < MAX_DAY_NUMBER) + if (days >= 0 && days <= MAX_DAY_NUMBER) { null_value=0; get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day); 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 cb0f35a425e..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; @@ -80,8 +181,8 @@ public: SEL_ARG(Field *field, uint8 part, char *min_value, char *max_value, uint8 min_flag, uint8 max_flag, uint8 maybe_flag); SEL_ARG(enum Type type_arg) - :elements(1),use_count(1),left(0),next_key_part(0),color(BLACK), - type(type_arg),min_flag(0) + :min_flag(0),elements(1),use_count(1),left(0),next_key_part(0), + color(BLACK), type(type_arg) {} inline bool is_same(SEL_ARG *arg) { @@ -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..5c8bd797e7c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -306,6 +306,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 +931,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 +1141,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 +1298,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 +1947,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..45dc90f25b3 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 */ 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..eaa7d3a72db 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) @@ -954,7 +1035,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 +1107,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 +1149,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 +1212,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 +1516,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 +1540,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); - - /* Make a copy of all fields */ + /* 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); - 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 +1607,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 +1971,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 +2034,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 +2053,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 +2303,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 +2318,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 +2487,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 +2717,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 +2762,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 +2796,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 cd57c280950..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() @@ -3057,6 +3063,12 @@ end_with_restore_list: } } /* Don't yet allow changing of symlinks with ALTER TABLE */ + if (lex->create_info.data_file_name) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, + "DATA DIRECTORY option ignored"); + if (lex->create_info.index_file_name) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, + "INDEX DIRECTORY option ignored"); lex->create_info.data_file_name=lex->create_info.index_file_name=0; /* ALTER TABLE ends previous transaction */ if (end_active_trans(thd)) @@ -3077,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; } @@ -3451,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 && @@ -3887,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, @@ -3973,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); + } } } } @@ -4030,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); @@ -5541,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; @@ -5756,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; @@ -5978,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 @@ -7016,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)); } @@ -7034,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)); } @@ -7135,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"); @@ -7189,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++; @@ -7495,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 4899c1e16a3..400342854a6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -163,6 +163,10 @@ static Item* part_of_refkey(TABLE *form,Field *field); uint find_shortest_key(TABLE *table, const key_map *usable_keys); static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order, ha_rows select_limit, bool no_changes); +static bool list_contains_unique_index(TABLE *table, + bool (*find_func) (Field *, void *), void *data); +static bool find_field_in_item_list (Field *field, void *data); +static bool find_field_in_order_list (Field *field, void *data); static int create_sort_index(THD *thd, JOIN *join, ORDER *order, ha_rows filesort_limit, ha_rows select_limit); static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields, @@ -858,6 +862,40 @@ JOIN::optimize() if (old_group_list && !group_list) select_distinct= 0; } + /* + Check if we can optimize away GROUP BY/DISTINCT. + We can do that if there are no aggregate functions and the + fields in DISTINCT clause (if present) and/or columns in GROUP BY + (if present) contain direct references to all key parts of + an unique index (in whatever order). + Note that the unique keys for DISTINCT and GROUP BY should not + be the same (as long as they are unique). + + The FROM clause must contain a single non-constant table. + */ + if (tables - const_tables == 1 && (group_list || select_distinct) && + !tmp_table_param.sum_func_count && + (!join_tab[const_tables].select || + !join_tab[const_tables].select->quick || + join_tab[const_tables].select->quick->get_type() != + QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)) + { + if (group_list && + list_contains_unique_index(join_tab[const_tables].table, + find_field_in_order_list, + (void *) group_list)) + { + group_list= 0; + group= 0; + } + if (select_distinct && + list_contains_unique_index(join_tab[const_tables].table, + find_field_in_item_list, + (void *) &fields_list)) + { + select_distinct= 0; + } + } if (!group_list && group) { order=0; // The output has only one row @@ -7979,7 +8017,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) @@ -11209,6 +11248,140 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts, return best; } + +/* + Check if GROUP BY/DISTINCT can be optimized away because the set is + already known to be distinct. + + SYNOPSIS + list_contains_unique_index () + table The table to operate on. + find_func function to iterate over the list and search + for a field + + DESCRIPTION + Used in removing the GROUP BY/DISTINCT of the following types of + statements: + SELECT [DISTINCT] <unique_key_cols>... FROM <single_table_ref> + [GROUP BY <unique_key_cols>,...] + + If (a,b,c is distinct) + then <any combination of a,b,c>,{whatever} is also distinct + + This function checks if all the key parts of any of the unique keys + of the table are referenced by a list : either the select list + through find_field_in_item_list or GROUP BY list through + find_field_in_order_list. + If the above holds then we can safely remove the GROUP BY/DISTINCT, + as no result set can be more distinct than an unique key. + + RETURN VALUE + 1 found + 0 not found. +*/ + +static bool +list_contains_unique_index(TABLE *table, + bool (*find_func) (Field *, void *), void *data) +{ + for (uint keynr= 0; keynr < table->s->keys; keynr++) + { + if (keynr == table->s->primary_key || + (table->key_info[keynr].flags & HA_NOSAME)) + { + KEY *keyinfo= table->key_info + keynr; + KEY_PART_INFO *key_part, *key_part_end; + + for (key_part=keyinfo->key_part, + key_part_end=key_part+ keyinfo->key_parts; + key_part < key_part_end; + key_part++) + { + if (!find_func(key_part->field, data)) + break; + } + if (key_part == key_part_end) + return 1; + } + } + return 0; +} + + +/* + Helper function for list_contains_unique_index. + Find a field reference in a list of ORDER structures. + + SYNOPSIS + find_field_in_order_list () + field The field to search for. + data ORDER *.The list to search in + + DESCRIPTION + Finds a direct reference of the Field in the list. + + RETURN VALUE + 1 found + 0 not found. +*/ + +static bool +find_field_in_order_list (Field *field, void *data) +{ + ORDER *group= (ORDER *) data; + bool part_found= 0; + for (ORDER *tmp_group= group; tmp_group; tmp_group=tmp_group->next) + { + Item *item= (*tmp_group->item)->real_item(); + if (item->type() == Item::FIELD_ITEM && + ((Item_field*) item)->field->eq(field)) + { + part_found= 1; + break; + } + } + return part_found; +} + + +/* + Helper function for list_contains_unique_index. + Find a field reference in a dynamic list of Items. + + SYNOPSIS + find_field_in_item_list () + field in The field to search for. + data in List<Item> *.The list to search in + + DESCRIPTION + Finds a direct reference of the Field in the list. + + RETURN VALUE + 1 found + 0 not found. +*/ + +static bool +find_field_in_item_list (Field *field, void *data) +{ + List<Item> *fields= (List<Item> *) data; + bool part_found= 0; + List_iterator<Item> li(*fields); + Item *item; + + while ((item= li++)) + { + if (item->type() == Item::FIELD_ITEM && + ((Item_field*) item)->field->eq(field)) + { + part_found= 1; + break; + } + } + return part_found; +} + + /* Test if we can skip the ORDER BY by using an index. @@ -12890,7 +13063,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 5f1c156973c..163801e2f1e 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/ctype-mb.c b/strings/ctype-mb.c index 0d73c7d1e51..0f95a688d85 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -527,27 +527,20 @@ my_bool my_like_range_mb(CHARSET_INFO *cs, char *min_str,char *max_str, uint *min_length,uint *max_length) { + uint mblen; const char *end= ptr + ptr_length; char *min_org= min_str; char *min_end= min_str + res_length; char *max_end= max_str + res_length; - uint charlen= res_length / cs->mbmaxlen; + uint maxcharlen= res_length / cs->mbmaxlen; - for (; ptr != end && min_str != min_end && charlen > 0 ; ptr++, charlen--) + for (; ptr != end && min_str != min_end && maxcharlen ; maxcharlen--) { + /* We assume here that escape, w_any, w_namy are one-byte characters */ if (*ptr == escape && ptr+1 != end) - { - ptr++; /* Skip escape */ - *min_str++= *max_str++ = *ptr; - continue; - } - if (*ptr == w_one || *ptr == w_many) /* '_' and '%' in SQL */ - { - charlen= my_charpos(cs, min_org, min_str, res_length/cs->mbmaxlen); - - if (charlen < (uint) (min_str - min_org)) - min_str= min_org + charlen; - + ptr++; /* Skip escape */ + else if (*ptr == w_one || *ptr == w_many) /* '_' and '%' in SQL */ + { /* Calculate length of keys: 'a\0\0... is the smallest possible string when we have space expand @@ -571,7 +564,16 @@ my_bool my_like_range_mb(CHARSET_INFO *cs, pad_max_char(cs, max_str, max_end); return 0; } - *min_str++= *max_str++ = *ptr; + if ((mblen= my_ismbchar(cs, ptr, end)) > 1) + { + if (ptr+mblen > end || min_str+mblen > min_end) + break; + while (mblen--) + *min_str++= *max_str++= *ptr++; + } + else + *min_str++= *max_str++= *ptr++; + } *min_length= *max_length = (uint) (min_str - min_org); 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..04eb427b35f 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -58,6 +58,7 @@ static unsigned int iter_count= 0; static my_bool have_innodb= FALSE; static const char *opt_basedir= "./"; +static const char *opt_vardir= "mysql-test/var"; static longlong opt_getopt_ll_test= 0; @@ -8311,6 +8312,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() @@ -14850,6 +14884,7 @@ static void test_bug17667() struct buffer_and_length *statement_cursor; FILE *log_file; + char *master_log_filename; myheader("test_bug17667"); @@ -14861,7 +14896,13 @@ static void test_bug17667() } sleep(1); /* The server may need time to flush the data to the log. */ - log_file= fopen("var/log/master.log", "r"); + + master_log_filename = (char *) malloc(strlen(opt_vardir) + strlen("/log/master.log") + 1); + strcpy(master_log_filename, opt_vardir); + strcat(master_log_filename, "/log/master.log"); + log_file= fopen(master_log_filename, "r"); + free(master_log_filename); + if (log_file != NULL) { for (statement_cursor= statements; statement_cursor->buffer != NULL; @@ -14882,11 +14923,13 @@ static void test_bug17667() printf("success. All queries found intact in the log.\n"); - } 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"); + } + else + { + fprintf(stderr, "Could not find the log file, VARDIR/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"); } if (log_file != NULL) @@ -14896,7 +14939,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 +14973,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 */ @@ -14971,6 +15070,8 @@ static struct my_option client_test_long_options[] = {"user", 'u', "User for login if not current user", (char **) &opt_user, (char **) &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif + {"vardir", 'v', "Data dir for tests.", (gptr*) &opt_vardir, + (gptr*) &opt_vardir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"getopt-ll-test", 'g', "Option for testing bug in getopt library", (char **) &opt_getopt_ll_test, (char **) &opt_getopt_ll_test, 0, GET_LL, REQUIRED_ARG, 0, 0, LONGLONG_MAX, 0, 0, 0}, @@ -15193,8 +15294,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 } }; |