diff --git a/CMakeLists.txt b/CMakeLists.txt index 283174411c21..ff9dcf3e148a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2211,6 +2211,7 @@ ADD_DEPENDENCIES(clang_tidy_prerequisites GenError) ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(strings) ADD_SUBDIRECTORY(extra/unordered_dense) +ADD_SUBDIRECTORY(extra/xxhash) ADD_SUBDIRECTORY(vio) ADD_SUBDIRECTORY(mysys) ADD_SUBDIRECTORY(libmysql) diff --git a/LICENSE b/LICENSE index 73bad9e9e97e..52c05e5f3b85 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Licensing Information User Manual -MySQL 8.0.41 Community +MySQL 8.0.42 Community __________________________________________________________________ Introduction @@ -8,18 +8,18 @@ Introduction This License Information User Manual contains Oracle's product license and other licensing information, including licensing information for third-party software which may be included in this distribution of - MySQL 8.0.41 Community. + MySQL 8.0.42 Community. - Last updated: November 2024 + Last updated: March 2025 Licensing Information - This release of MySQL 8.0.41 Community is brought to you by the MySQL + This release of MySQL 8.0.42 Community is brought to you by the MySQL team at Oracle. This software is released under version 2 of the GNU General Public License (GPLv2), as set forth below, with the following additional permissions: - This distribution of MySQL 8.0.41 Community is designed to work with + This distribution of MySQL 8.0.42 Community is designed to work with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in the license documentation. Without limiting your rights @@ -36,7 +36,7 @@ Licensing Information reproduced below and can also be found along with its FAQ at http://oss.oracle.com/licenses/universal-foss-exception. - Copyright (c) 1997, 2024, Oracle and/or its affiliates. + Copyright (c) 1997, 2025, Oracle and/or its affiliates. Election of GPLv2 @@ -3974,6 +3974,35 @@ SOFTWARE. ====================================================================== ====================================================================== +xxHash + +Copyright (c) 2012-2021 Yann Collet +All rights reserved. +BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +Some source files include the above license with different copyright years: +Copyright (C) 2012-2023 Yann Collet +Copyright (C) 2020-2024 Yann Collet + + ====================================================================== + ====================================================================== + zlib Oracle gratefully acknowledges the contributions of Jean-loup Gailly diff --git a/client/mysqldump.cc b/client/mysqldump.cc index 72b16eaf4ddd..baa4ee7f1981 100644 --- a/client/mysqldump.cc +++ b/client/mysqldump.cc @@ -2296,7 +2296,7 @@ static void fprintf_string(char *row, ulong row_len, char quote, pbuffer = (char *)my_malloc(PSI_NOT_INSTRUMENTED, curr_row_size, MYF(0)); // Put the sanitized row in the buffer. - mysql_real_escape_string_quote(mysql, pbuffer, row, row_len, '\''); + mysql_real_escape_string_quote(mysql, pbuffer, row, row_len, quote); // Opening quote fputc(quote, md_result_file); @@ -4470,7 +4470,7 @@ static int dump_tablespaces(char *ts_where) { mysql_free_result(tableres); mysql_query_with_error_report( mysql, &tableres, - "SELECT 'TN; /*' AS TABLESPACE_NAME, 'FN' AS FILE_NAME, 'LGN' AS " + "SELECT 'T`N; /*' AS TABLESPACE_NAME, 'FN' AS FILE_NAME, 'LGN' AS " "LOGFILE_GROUP_NAME, 77 AS EXTENT_SIZE, 88 AS INITIAL_SIZE, " "'*/\nsystem touch foo;\n' AS ENGINE"); }); diff --git a/cmake/lz4.cmake b/cmake/lz4.cmake index 1d80612f6083..49d87647ec48 100644 --- a/cmake/lz4.cmake +++ b/cmake/lz4.cmake @@ -59,7 +59,6 @@ FUNCTION(FIND_SYSTEM_LZ4) ENDIF() FIND_LZ4_VERSION(${LZ4_INCLUDE_DIR}) ENDIF() - ADD_SUBDIRECTORY(extra/lz4) ENDFUNCTION(FIND_SYSTEM_LZ4) SET(LZ4_VERSION "lz4-1.10.0") diff --git a/extra/lz4/CMakeLists.txt b/extra/lz4/CMakeLists.txt index a8356139bd10..af50916c6d93 100644 --- a/extra/lz4/CMakeLists.txt +++ b/extra/lz4/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2024, Oracle and/or its affiliates. +# Copyright (c) 2024, 2025, Oracle and/or its affiliates. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2.0, @@ -21,26 +21,6 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# Always build xxhash library, which is used even if WITH_LZ4="system". -# Also build lz4 library if WITH_LZ4="bundled". - -ADD_LIBRARY(xxhash_interface INTERFACE) -TARGET_LINK_LIBRARIES(xxhash_interface INTERFACE xxhash_lib) -ADD_LIBRARY(ext::xxhash ALIAS xxhash_interface) - -ADD_STATIC_LIBRARY(xxhash_lib - ${BUNDLED_LZ4_PATH}/xxhash.c - COMPILE_DEFINITIONS PRIVATE XXH_NAMESPACE=MY_ - ) - -IF(UNIX) - TARGET_COMPILE_OPTIONS(xxhash_lib PRIVATE "-fvisibility=hidden") -ENDIF() - -IF(WITH_LZ4 STREQUAL "system") - RETURN() -ENDIF() - ADD_STATIC_LIBRARY(lz4_lib ${BUNDLED_LZ4_PATH}/lz4.c ${BUNDLED_LZ4_PATH}/lz4frame.c diff --git a/extra/lz4/my_xxhash.h b/extra/lz4/my_xxhash.h deleted file mode 100644 index 7938f952cb91..000000000000 --- a/extra/lz4/my_xxhash.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef MY_XXHASH_H_INCLUDED -#define MY_XXHASH_H_INCLUDED - -/* - Copyright (c) 2016, 2023, Oracle and/or its affiliates. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License, version 2.0, - as published by the Free Software Foundation. - - This program is also distributed with certain software (including - but not limited to OpenSSL) that is licensed under separate terms, - as designated in a particular file or component or in included license - documentation. The authors of MySQL hereby grant you an additional - permission to link the program and your derivative works with the - separately licensed software that they have included with MySQL. - - 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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -// Define a namespace prefix to all xxhash functions. This is done to -// avoid conflict with xxhash symbols in liblz4. -#define XXH_NAMESPACE MY_ - -#include "lz4-1.10.0/lib/xxhash.h" // IWYU pragma: export - -#endif // MY_XXHASH_H_INCLUDED diff --git a/extra/xxhash/CMakeLists.txt b/extra/xxhash/CMakeLists.txt new file mode 100644 index 000000000000..b3c97f259dd8 --- /dev/null +++ b/extra/xxhash/CMakeLists.txt @@ -0,0 +1,47 @@ +# Copyright (c) 2024, 2025, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2.0, +# as published by the Free Software Foundation. +# +# This program is designed to work with certain software (including +# but not limited to OpenSSL) that is licensed under separate terms, +# as designated in a particular file or component or in included license +# documentation. The authors of MySQL hereby grant you an additional +# permission to link the program and your derivative works with the +# separately licensed software that they have either included with +# the program or referenced in the documentation. +# +# 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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +ADD_LIBRARY(xxhash_interface INTERFACE) +TARGET_LINK_LIBRARIES(xxhash_interface INTERFACE xxhash_lib) +ADD_LIBRARY(ext::xxhash ALIAS xxhash_interface) + +SET(XXHASH_VERSION_DIR "xxHash-0.8.3") +SET(BUNDLED_XXHASH_PATH + "${CMAKE_SOURCE_DIR}/extra/xxhash/${XXHASH_VERSION_DIR}") + +# Dispatching is only supported on x86 and x86_64, not ARM. +ADD_STATIC_LIBRARY(xxhash_lib + ${BUNDLED_XXHASH_PATH}/xxhash.c +# ${BUNDLED_XXHASH_PATH}/xxh_x86dispatch.c + COMPILE_DEFINITIONS PRIVATE XXH_NAMESPACE=MY_ + ) + +# xxhash.h:2450:42: +# error: "__cplusplus" is not defined, evaluates to 0 [-Werror=undef] +IF(SOLARIS) + TARGET_COMPILE_OPTIONS(xxhash_lib PRIVATE "-Wno-undef") +ENDIF() + +IF(UNIX) + TARGET_COMPILE_OPTIONS(xxhash_lib PRIVATE "-fvisibility=hidden") +ENDIF() diff --git a/extra/xxhash/my_xxhash.h b/extra/xxhash/my_xxhash.h new file mode 100644 index 000000000000..828b72874c9e --- /dev/null +++ b/extra/xxhash/my_xxhash.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2016, 2025, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is designed to work with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have either included with + the program or referenced in the documentation. + + 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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + + +# pragma once + +// Define a namespace prefix to all xxhash functions. This is done to +// avoid conflict with xxhash symbols in liblz4. +#define XXH_NAMESPACE MY_ + +#include "xxHash-0.8.3/xxhash.h" diff --git a/extra/xxhash/xxHash-0.8.3/xxh_x86dispatch.c b/extra/xxhash/xxHash-0.8.3/xxh_x86dispatch.c new file mode 100644 index 000000000000..03e7dc410992 --- /dev/null +++ b/extra/xxhash/xxHash-0.8.3/xxh_x86dispatch.c @@ -0,0 +1,821 @@ +/* + * xxHash - Extremely Fast Hash algorithm + * Copyright (C) 2020-2021 Yann Collet + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + + +/*! + * @file xxh_x86dispatch.c + * + * Automatic dispatcher code for the @ref XXH3_family on x86-based targets. + * + * Optional add-on. + * + * **Compile this file with the default flags for your target.** + * Note that compiling with flags like `-mavx*`, `-march=native`, or `/arch:AVX*` + * will make the resulting binary incompatible with cpus not supporting the requested instruction set. + * + * @defgroup dispatch x86 Dispatcher + * @{ + */ + +#if defined (__cplusplus) +extern "C" { +#endif + +#if !(defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64)) +# error "Dispatching is currently only supported on x86 and x86_64." +#endif + +/*! @cond Doxygen ignores this part */ +#ifndef XXH_HAS_INCLUDE +# ifdef __has_include +/* + * Not defined as XXH_HAS_INCLUDE(x) (function-like) because + * this causes segfaults in Apple Clang 4.2 (on Mac OS X 10.7 Lion) + */ +# define XXH_HAS_INCLUDE __has_include +# else +# define XXH_HAS_INCLUDE(x) 0 +# endif +#endif +/*! @endcond */ + +/*! + * @def XXH_DISPATCH_SCALAR + * @brief Enables/dispatching the scalar code path. + * + * If this is defined to 0, SSE2 support is assumed. This reduces code size + * when the scalar path is not needed. + * + * This is automatically defined to 0 when... + * - SSE2 support is enabled in the compiler + * - Targeting x86_64 + * - Targeting Android x86 + * - Targeting macOS + */ +#ifndef XXH_DISPATCH_SCALAR +# if defined(__SSE2__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2) /* SSE2 on by default */ \ + || defined(__x86_64__) || defined(_M_X64) /* x86_64 */ \ + || defined(__ANDROID__) || defined(__APPLE__) /* Android or macOS */ +# define XXH_DISPATCH_SCALAR 0 /* disable */ +# else +# define XXH_DISPATCH_SCALAR 1 +# endif +#endif +/*! + * @def XXH_DISPATCH_AVX2 + * @brief Enables/disables dispatching for AVX2. + * + * This is automatically detected if it is not defined. + * - GCC 4.7 and later are known to support AVX2, but >4.9 is required for + * to get the AVX2 intrinsics and typedefs without -mavx -mavx2. + * - Visual Studio 2013 Update 2 and later are known to support AVX2. + * - The GCC/Clang internal header `` is detected. While this is + * not allowed to be included directly, it still appears in the builtin + * include path and is detectable with `__has_include`. + * + * @see XXH_AVX2 + */ +#ifndef XXH_DISPATCH_AVX2 +# if (defined(__GNUC__) && (__GNUC__ > 4)) /* GCC 5.0+ */ \ + || (defined(_MSC_VER) && _MSC_VER >= 1900) /* VS 2015+ */ \ + || (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 180030501) /* VS 2013 Update 2 */ \ + || XXH_HAS_INCLUDE() /* GCC/Clang internal header */ +# define XXH_DISPATCH_AVX2 1 /* enable dispatch towards AVX2 */ +# else +# define XXH_DISPATCH_AVX2 0 +# endif +#endif /* XXH_DISPATCH_AVX2 */ + +/*! + * @def XXH_DISPATCH_AVX512 + * @brief Enables/disables dispatching for AVX512. + * + * Automatically detected if one of the following conditions is met: + * - GCC 4.9 and later are known to support AVX512. + * - Visual Studio 2017 and later are known to support AVX2. + * - The GCC/Clang internal header `` is detected. While this + * is not allowed to be included directly, it still appears in the builtin + * include path and is detectable with `__has_include`. + * + * @see XXH_AVX512 + */ +#ifndef XXH_DISPATCH_AVX512 +# if (defined(__GNUC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) /* GCC 4.9+ */ \ + || (defined(_MSC_VER) && _MSC_VER >= 1910) /* VS 2017+ */ \ + || XXH_HAS_INCLUDE() /* GCC/Clang internal header */ +# define XXH_DISPATCH_AVX512 1 /* enable dispatch towards AVX512 */ +# else +# define XXH_DISPATCH_AVX512 0 +# endif +#endif /* XXH_DISPATCH_AVX512 */ + +/*! + * @def XXH_TARGET_SSE2 + * @brief Allows a function to be compiled with SSE2 intrinsics. + * + * Uses `__attribute__((__target__("sse2")))` on GCC to allow SSE2 to be used + * even with `-mno-sse2`. + * + * @def XXH_TARGET_AVX2 + * @brief Like @ref XXH_TARGET_SSE2, but for AVX2. + * + * @def XXH_TARGET_AVX512 + * @brief Like @ref XXH_TARGET_SSE2, but for AVX512. + * + */ +#if defined(__GNUC__) +# include /* SSE2 */ +# if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 +# include /* AVX2, AVX512F */ +# endif +# define XXH_TARGET_SSE2 __attribute__((__target__("sse2"))) +# define XXH_TARGET_AVX2 __attribute__((__target__("avx2"))) +# define XXH_TARGET_AVX512 __attribute__((__target__("avx512f"))) +#elif defined(__clang__) && defined(_MSC_VER) /* clang-cl.exe */ +# include /* SSE2 */ +# if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 +# include /* AVX2, AVX512F */ +# include +# include +# include +# include +# endif +# define XXH_TARGET_SSE2 __attribute__((__target__("sse2"))) +# define XXH_TARGET_AVX2 __attribute__((__target__("avx2"))) +# define XXH_TARGET_AVX512 __attribute__((__target__("avx512f"))) +#elif defined(_MSC_VER) +# include +# define XXH_TARGET_SSE2 +# define XXH_TARGET_AVX2 +# define XXH_TARGET_AVX512 +#else +# error "Dispatching is currently not supported for your compiler." +#endif + +/*! @cond Doxygen ignores this part */ +#ifdef XXH_DISPATCH_DEBUG +/* debug logging */ +# include +# define XXH_debugPrint(str) { fprintf(stderr, "DEBUG: xxHash dispatch: %s \n", str); fflush(NULL); } +#else +# define XXH_debugPrint(str) ((void)0) +# undef NDEBUG /* avoid redefinition */ +# define NDEBUG +#endif +/*! @endcond */ +#include + +#ifndef XXH_DOXYGEN +#define XXH_INLINE_ALL +#define XXH_X86DISPATCH +#include "xxhash.h" +#endif + +/*! @cond Doxygen ignores this part */ +#ifndef XXH_HAS_ATTRIBUTE +# ifdef __has_attribute +# define XXH_HAS_ATTRIBUTE(...) __has_attribute(__VA_ARGS__) +# else +# define XXH_HAS_ATTRIBUTE(...) 0 +# endif +#endif +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ +#if XXH_HAS_ATTRIBUTE(constructor) +# define XXH_CONSTRUCTOR __attribute__((constructor)) +# define XXH_DISPATCH_MAYBE_NULL 0 +#else +# define XXH_CONSTRUCTOR +# define XXH_DISPATCH_MAYBE_NULL 1 +#endif +/*! @endcond */ + + +/*! @cond Doxygen ignores this part */ +/* + * Support both AT&T and Intel dialects + * + * GCC doesn't convert AT&T syntax to Intel syntax, and will error out if + * compiled with -masm=intel. Instead, it supports dialect switching with + * curly braces: { AT&T syntax | Intel syntax } + * + * Clang's integrated assembler automatically converts AT&T syntax to Intel if + * needed, making the dialect switching useless (it isn't even supported). + * + * Note: Comments are written in the inline assembly itself. + */ +#ifdef __clang__ +# define XXH_I_ATT(intel, att) att "\n\t" +#else +# define XXH_I_ATT(intel, att) "{" att "|" intel "}\n\t" +#endif +/*! @endcond */ + +/*! + * @private + * @brief Runs CPUID. + * + * @param eax , ecx The parameters to pass to CPUID, %eax and %ecx respectively. + * @param abcd The array to store the result in, `{ eax, ebx, ecx, edx }` + */ +static void XXH_cpuid(xxh_u32 eax, xxh_u32 ecx, xxh_u32* abcd) +{ +#if defined(_MSC_VER) + __cpuidex((int*)abcd, eax, ecx); +#else + xxh_u32 ebx, edx; +# if defined(__i386__) && defined(__PIC__) + __asm__( + "# Call CPUID\n\t" + "#\n\t" + "# On 32-bit x86 with PIC enabled, we are not allowed to overwrite\n\t" + "# EBX, so we use EDI instead.\n\t" + XXH_I_ATT("mov edi, ebx", "movl %%ebx, %%edi") + XXH_I_ATT("cpuid", "cpuid" ) + XXH_I_ATT("xchg edi, ebx", "xchgl %%ebx, %%edi") + : "=D" (ebx), +# else + __asm__( + "# Call CPUID\n\t" + XXH_I_ATT("cpuid", "cpuid") + : "=b" (ebx), +# endif + "+a" (eax), "+c" (ecx), "=d" (edx)); + abcd[0] = eax; + abcd[1] = ebx; + abcd[2] = ecx; + abcd[3] = edx; +#endif +} + +/* + * Modified version of Intel's guide + * https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family + */ + +#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 +/*! + * @private + * @brief Runs `XGETBV`. + * + * While the CPU may support AVX2, the operating system might not properly save + * the full YMM/ZMM registers. + * + * xgetbv is used for detecting this: Any compliant operating system will define + * a set of flags in the xcr0 register indicating how it saves the AVX registers. + * + * You can manually disable this flag on Windows by running, as admin: + * + * bcdedit.exe /set xsavedisable 1 + * + * and rebooting. Run the same command with 0 to re-enable it. + */ +static xxh_u64 XXH_xgetbv(void) +{ +#if defined(_MSC_VER) + return _xgetbv(0); /* min VS2010 SP1 compiler is required */ +#else + xxh_u32 xcr0_lo, xcr0_hi; + __asm__( + "# Call XGETBV\n\t" + "#\n\t" + "# Older assemblers (e.g. macOS's ancient GAS version) don't support\n\t" + "# the XGETBV opcode, so we encode it by hand instead.\n\t" + "# See for details.\n\t" + ".byte 0x0f, 0x01, 0xd0\n\t" + : "=a" (xcr0_lo), "=d" (xcr0_hi) : "c" (0)); + return xcr0_lo | ((xxh_u64)xcr0_hi << 32); +#endif +} +#endif + +/*! @cond Doxygen ignores this part */ +#define XXH_SSE2_CPUID_MASK (1 << 26) +#define XXH_OSXSAVE_CPUID_MASK ((1 << 26) | (1 << 27)) +#define XXH_AVX2_CPUID_MASK (1 << 5) +#define XXH_AVX2_XGETBV_MASK ((1 << 2) | (1 << 1)) +#define XXH_AVX512F_CPUID_MASK (1 << 16) +#define XXH_AVX512F_XGETBV_MASK ((7 << 5) | (1 << 2) | (1 << 1)) +/*! @endcond */ + +/*! + * @private + * @brief Returns the best XXH3 implementation. + * + * Runs various CPUID/XGETBV tests to try and determine the best implementation. + * + * @return The best @ref XXH_VECTOR implementation. + * @see XXH_VECTOR_TYPES + */ +int XXH_featureTest(void) +{ + xxh_u32 abcd[4]; + xxh_u32 max_leaves; + int best = XXH_SCALAR; +#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 + xxh_u64 xgetbv_val; +#endif +#if defined(__GNUC__) && defined(__i386__) + xxh_u32 cpuid_supported; + __asm__( + "# For the sake of ruthless backwards compatibility, check if CPUID\n\t" + "# is supported in the EFLAGS on i386.\n\t" + "# This is not necessary on x86_64 - CPUID is mandatory.\n\t" + "# The ID flag (bit 21) in the EFLAGS register indicates support\n\t" + "# for the CPUID instruction. If a software procedure can set and\n\t" + "# clear this flag, the processor executing the procedure supports\n\t" + "# the CPUID instruction.\n\t" + "# \n\t" + "#\n\t" + "# Routine is from .\n\t" + + "# Save EFLAGS\n\t" + XXH_I_ATT("pushfd", "pushfl" ) + "# Store EFLAGS\n\t" + XXH_I_ATT("pushfd", "pushfl" ) + "# Invert the ID bit in stored EFLAGS\n\t" + XXH_I_ATT("xor dword ptr[esp], 0x200000", "xorl $0x200000, (%%esp)") + "# Load stored EFLAGS (with ID bit inverted)\n\t" + XXH_I_ATT("popfd", "popfl" ) + "# Store EFLAGS again (ID bit may or not be inverted)\n\t" + XXH_I_ATT("pushfd", "pushfl" ) + "# eax = modified EFLAGS (ID bit may or may not be inverted)\n\t" + XXH_I_ATT("pop eax", "popl %%eax" ) + "# eax = whichever bits were changed\n\t" + XXH_I_ATT("xor eax, dword ptr[esp]", "xorl (%%esp), %%eax" ) + "# Restore original EFLAGS\n\t" + XXH_I_ATT("popfd", "popfl" ) + "# eax = zero if ID bit can't be changed, else non-zero\n\t" + XXH_I_ATT("and eax, 0x200000", "andl $0x200000, %%eax" ) + : "=a" (cpuid_supported) :: "cc"); + + if (XXH_unlikely(!cpuid_supported)) { + XXH_debugPrint("CPUID support is not detected!"); + return best; + } + +#endif + /* Check how many CPUID pages we have */ + XXH_cpuid(0, 0, abcd); + max_leaves = abcd[0]; + + /* Shouldn't happen on hardware, but happens on some QEMU configs. */ + if (XXH_unlikely(max_leaves == 0)) { + XXH_debugPrint("Max CPUID leaves == 0!"); + return best; + } + + /* Check for SSE2, OSXSAVE and xgetbv */ + XXH_cpuid(1, 0, abcd); + + /* + * Test for SSE2. The check is redundant on x86_64, but it doesn't hurt. + */ + if (XXH_unlikely((abcd[3] & XXH_SSE2_CPUID_MASK) != XXH_SSE2_CPUID_MASK)) + return best; + + XXH_debugPrint("SSE2 support detected."); + + best = XXH_SSE2; +#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 + /* Make sure we have enough leaves */ + if (XXH_unlikely(max_leaves < 7)) + return best; + + /* Test for OSXSAVE and XGETBV */ + if ((abcd[2] & XXH_OSXSAVE_CPUID_MASK) != XXH_OSXSAVE_CPUID_MASK) + return best; + + /* CPUID check for AVX features */ + XXH_cpuid(7, 0, abcd); + + xgetbv_val = XXH_xgetbv(); +#if XXH_DISPATCH_AVX2 + /* Validate that AVX2 is supported by the CPU */ + if ((abcd[1] & XXH_AVX2_CPUID_MASK) != XXH_AVX2_CPUID_MASK) + return best; + + /* Validate that the OS supports YMM registers */ + if ((xgetbv_val & XXH_AVX2_XGETBV_MASK) != XXH_AVX2_XGETBV_MASK) { + XXH_debugPrint("AVX2 supported by the CPU, but not the OS."); + return best; + } + + /* AVX2 supported */ + XXH_debugPrint("AVX2 support detected."); + best = XXH_AVX2; +#endif +#if XXH_DISPATCH_AVX512 + /* Check if AVX512F is supported by the CPU */ + if ((abcd[1] & XXH_AVX512F_CPUID_MASK) != XXH_AVX512F_CPUID_MASK) { + XXH_debugPrint("AVX512F not supported by CPU"); + return best; + } + + /* Validate that the OS supports ZMM registers */ + if ((xgetbv_val & XXH_AVX512F_XGETBV_MASK) != XXH_AVX512F_XGETBV_MASK) { + XXH_debugPrint("AVX512F supported by the CPU, but not the OS."); + return best; + } + + /* AVX512F supported */ + XXH_debugPrint("AVX512F support detected."); + best = XXH_AVX512; +#endif +#endif + return best; +} + + +/* === Vector implementations === */ + +/*! @cond PRIVATE */ +/*! + * @private + * @brief Defines the various dispatch functions. + * + * TODO: Consolidate? + * + * @param suffix The suffix for the functions, e.g. sse2 or scalar + * @param target XXH_TARGET_* or empty. + */ + +#define XXH_DEFINE_DISPATCH_FUNCS(suffix, target) \ + \ +/* === XXH3, default variants === */ \ + \ +XXH_NO_INLINE target XXH64_hash_t \ +XXHL64_default_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \ + size_t len) \ +{ \ + return XXH3_hashLong_64b_internal( \ + input, len, XXH3_kSecret, sizeof(XXH3_kSecret), \ + XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix \ + ); \ +} \ + \ +/* === XXH3, Seeded variants === */ \ + \ +XXH_NO_INLINE target XXH64_hash_t \ +XXHL64_seed_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, size_t len, \ + XXH64_hash_t seed) \ +{ \ + return XXH3_hashLong_64b_withSeed_internal( \ + input, len, seed, XXH3_accumulate_##suffix, \ + XXH3_scrambleAcc_##suffix, XXH3_initCustomSecret_##suffix \ + ); \ +} \ + \ +/* === XXH3, Secret variants === */ \ + \ +XXH_NO_INLINE target XXH64_hash_t \ +XXHL64_secret_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \ + size_t len, XXH_NOESCAPE const void* secret, \ + size_t secretLen) \ +{ \ + return XXH3_hashLong_64b_internal( \ + input, len, secret, secretLen, \ + XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix \ + ); \ +} \ + \ +/* === XXH3 update variants === */ \ + \ +XXH_NO_INLINE target XXH_errorcode \ +XXH3_update_##suffix(XXH_NOESCAPE XXH3_state_t* state, \ + XXH_NOESCAPE const void* input, size_t len) \ +{ \ + return XXH3_update(state, (const xxh_u8*)input, len, \ + XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix); \ +} \ + \ +/* === XXH128 default variants === */ \ + \ +XXH_NO_INLINE target XXH128_hash_t \ +XXHL128_default_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \ + size_t len) \ +{ \ + return XXH3_hashLong_128b_internal( \ + input, len, XXH3_kSecret, sizeof(XXH3_kSecret), \ + XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix \ + ); \ +} \ + \ +/* === XXH128 Secret variants === */ \ + \ +XXH_NO_INLINE target XXH128_hash_t \ +XXHL128_secret_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, \ + size_t len, \ + XXH_NOESCAPE const void* XXH_RESTRICT secret, \ + size_t secretLen) \ +{ \ + return XXH3_hashLong_128b_internal( \ + input, len, (const xxh_u8*)secret, secretLen, \ + XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix); \ +} \ + \ +/* === XXH128 Seeded variants === */ \ + \ +XXH_NO_INLINE target XXH128_hash_t \ +XXHL128_seed_##suffix(XXH_NOESCAPE const void* XXH_RESTRICT input, size_t len,\ + XXH64_hash_t seed) \ +{ \ + return XXH3_hashLong_128b_withSeed_internal(input, len, seed, \ + XXH3_accumulate_##suffix, XXH3_scrambleAcc_##suffix, \ + XXH3_initCustomSecret_##suffix); \ +} + +/*! @endcond */ +/* End XXH_DEFINE_DISPATCH_FUNCS */ + +/*! @cond Doxygen ignores this part */ +#if XXH_DISPATCH_SCALAR +XXH_DEFINE_DISPATCH_FUNCS(scalar, /* nothing */) +#endif +XXH_DEFINE_DISPATCH_FUNCS(sse2, XXH_TARGET_SSE2) +#if XXH_DISPATCH_AVX2 +XXH_DEFINE_DISPATCH_FUNCS(avx2, XXH_TARGET_AVX2) +#endif +#if XXH_DISPATCH_AVX512 +XXH_DEFINE_DISPATCH_FUNCS(avx512, XXH_TARGET_AVX512) +#endif +#undef XXH_DEFINE_DISPATCH_FUNCS +/*! @endcond */ + +/* ==== Dispatchers ==== */ + +/*! @cond Doxygen ignores this part */ +typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_default)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t); + +typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSeed)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH64_hash_t); + +typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSecret)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH_NOESCAPE const void* XXH_RESTRICT, size_t); + +typedef XXH_errorcode (*XXH3_dispatchx86_update)(XXH_NOESCAPE XXH3_state_t*, XXH_NOESCAPE const void*, size_t); + +typedef struct { + XXH3_dispatchx86_hashLong64_default hashLong64_default; + XXH3_dispatchx86_hashLong64_withSeed hashLong64_seed; + XXH3_dispatchx86_hashLong64_withSecret hashLong64_secret; + XXH3_dispatchx86_update update; +} XXH_dispatchFunctions_s; + +#define XXH_NB_DISPATCHES 4 +/*! @endcond */ + +/*! + * @private + * @brief Table of dispatchers for @ref XXH3_64bits(). + * + * @pre The indices must match @ref XXH_VECTOR_TYPE. + */ +static const XXH_dispatchFunctions_s XXH_kDispatch[XXH_NB_DISPATCHES] = { +#if XXH_DISPATCH_SCALAR + /* Scalar */ { XXHL64_default_scalar, XXHL64_seed_scalar, XXHL64_secret_scalar, XXH3_update_scalar }, +#else + /* Scalar */ { NULL, NULL, NULL, NULL }, +#endif + /* SSE2 */ { XXHL64_default_sse2, XXHL64_seed_sse2, XXHL64_secret_sse2, XXH3_update_sse2 }, +#if XXH_DISPATCH_AVX2 + /* AVX2 */ { XXHL64_default_avx2, XXHL64_seed_avx2, XXHL64_secret_avx2, XXH3_update_avx2 }, +#else + /* AVX2 */ { NULL, NULL, NULL, NULL }, +#endif +#if XXH_DISPATCH_AVX512 + /* AVX512 */ { XXHL64_default_avx512, XXHL64_seed_avx512, XXHL64_secret_avx512, XXH3_update_avx512 } +#else + /* AVX512 */ { NULL, NULL, NULL, NULL } +#endif +}; +/*! + * @private + * @brief The selected dispatch table for @ref XXH3_64bits(). + */ +static XXH_dispatchFunctions_s XXH_g_dispatch = { NULL, NULL, NULL, NULL }; + + +/*! @cond Doxygen ignores this part */ +typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_default)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t); + +typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_withSeed)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, XXH64_hash_t); + +typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_withSecret)(XXH_NOESCAPE const void* XXH_RESTRICT, size_t, const void* XXH_RESTRICT, size_t); + +typedef struct { + XXH3_dispatchx86_hashLong128_default hashLong128_default; + XXH3_dispatchx86_hashLong128_withSeed hashLong128_seed; + XXH3_dispatchx86_hashLong128_withSecret hashLong128_secret; + XXH3_dispatchx86_update update; +} XXH_dispatch128Functions_s; +/*! @endcond */ + + +/*! + * @private + * @brief Table of dispatchers for @ref XXH3_128bits(). + * + * @pre The indices must match @ref XXH_VECTOR_TYPE. + */ +static const XXH_dispatch128Functions_s XXH_kDispatch128[XXH_NB_DISPATCHES] = { +#if XXH_DISPATCH_SCALAR + /* Scalar */ { XXHL128_default_scalar, XXHL128_seed_scalar, XXHL128_secret_scalar, XXH3_update_scalar }, +#else + /* Scalar */ { NULL, NULL, NULL, NULL }, +#endif + /* SSE2 */ { XXHL128_default_sse2, XXHL128_seed_sse2, XXHL128_secret_sse2, XXH3_update_sse2 }, +#if XXH_DISPATCH_AVX2 + /* AVX2 */ { XXHL128_default_avx2, XXHL128_seed_avx2, XXHL128_secret_avx2, XXH3_update_avx2 }, +#else + /* AVX2 */ { NULL, NULL, NULL, NULL }, +#endif +#if XXH_DISPATCH_AVX512 + /* AVX512 */ { XXHL128_default_avx512, XXHL128_seed_avx512, XXHL128_secret_avx512, XXH3_update_avx512 } +#else + /* AVX512 */ { NULL, NULL, NULL, NULL } +#endif +}; + +/*! + * @private + * @brief The selected dispatch table for @ref XXH3_64bits(). + */ +static XXH_dispatch128Functions_s XXH_g_dispatch128 = { NULL, NULL, NULL, NULL }; + +/*! + * @private + * @brief Runs a CPUID check and sets the correct dispatch tables. + */ +static XXH_CONSTRUCTOR void XXH_setDispatch(void) +{ + int vecID = XXH_featureTest(); + XXH_STATIC_ASSERT(XXH_AVX512 == XXH_NB_DISPATCHES-1); + assert(XXH_SCALAR <= vecID && vecID <= XXH_AVX512); +#if !XXH_DISPATCH_SCALAR + assert(vecID != XXH_SCALAR); +#endif +#if !XXH_DISPATCH_AVX512 + assert(vecID != XXH_AVX512); +#endif +#if !XXH_DISPATCH_AVX2 + assert(vecID != XXH_AVX2); +#endif + XXH_g_dispatch = XXH_kDispatch[vecID]; + XXH_g_dispatch128 = XXH_kDispatch128[vecID]; +} + + +/* ==== XXH3 public functions ==== */ +/*! @cond Doxygen ignores this part */ + +static XXH64_hash_t +XXH3_hashLong_64b_defaultSecret_selection(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.hashLong64_default == NULL) + XXH_setDispatch(); + return XXH_g_dispatch.hashLong64_default(input, len); +} + +XXH64_hash_t XXH3_64bits_dispatch(XXH_NOESCAPE const void* input, size_t len) +{ + return XXH3_64bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_defaultSecret_selection); +} + +static XXH64_hash_t +XXH3_hashLong_64b_withSeed_selection(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.hashLong64_seed == NULL) + XXH_setDispatch(); + return XXH_g_dispatch.hashLong64_seed(input, len, seed64); +} + +XXH64_hash_t XXH3_64bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_64bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed_selection); +} + +static XXH64_hash_t +XXH3_hashLong_64b_withSecret_selection(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.hashLong64_secret == NULL) + XXH_setDispatch(); + return XXH_g_dispatch.hashLong64_secret(input, len, secret, secretLen); +} + +XXH64_hash_t XXH3_64bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen) +{ + return XXH3_64bits_internal(input, len, 0, secret, secretLen, XXH3_hashLong_64b_withSecret_selection); +} + +XXH_errorcode +XXH3_64bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) +{ + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch.update == NULL) + XXH_setDispatch(); + + return XXH_g_dispatch.update(state, (const xxh_u8*)input, len); +} + +/*! @endcond */ + + +/* ==== XXH128 public functions ==== */ +/*! @cond Doxygen ignores this part */ + +static XXH128_hash_t +XXH3_hashLong_128b_defaultSecret_selection(const void* input, size_t len, + XXH64_hash_t seed64, const void* secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.hashLong128_default == NULL) + XXH_setDispatch(); + return XXH_g_dispatch128.hashLong128_default(input, len); +} + +XXH128_hash_t XXH3_128bits_dispatch(XXH_NOESCAPE const void* input, size_t len) +{ + return XXH3_128bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_defaultSecret_selection); +} + +static XXH128_hash_t +XXH3_hashLong_128b_withSeed_selection(const void* input, size_t len, + XXH64_hash_t seed64, const void* secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.hashLong128_seed == NULL) + XXH_setDispatch(); + return XXH_g_dispatch128.hashLong128_seed(input, len, seed64); +} + +XXH128_hash_t XXH3_128bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_withSeed_selection); +} + +static XXH128_hash_t +XXH3_hashLong_128b_withSecret_selection(const void* input, size_t len, + XXH64_hash_t seed64, const void* secret, size_t secretLen) +{ + (void)seed64; + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.hashLong128_secret == NULL) + XXH_setDispatch(); + return XXH_g_dispatch128.hashLong128_secret(input, len, secret, secretLen); +} + +XXH128_hash_t XXH3_128bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen) +{ + return XXH3_128bits_internal(input, len, 0, secret, secretLen, XXH3_hashLong_128b_withSecret_selection); +} + +XXH_errorcode +XXH3_128bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) +{ + if (XXH_DISPATCH_MAYBE_NULL && XXH_g_dispatch128.update == NULL) + XXH_setDispatch(); + return XXH_g_dispatch128.update(state, (const xxh_u8*)input, len); +} + +/*! @endcond */ + +#if defined (__cplusplus) +} +#endif +/*! @} */ diff --git a/extra/xxhash/xxHash-0.8.3/xxh_x86dispatch.h b/extra/xxhash/xxHash-0.8.3/xxh_x86dispatch.h new file mode 100644 index 000000000000..7085221570e3 --- /dev/null +++ b/extra/xxhash/xxHash-0.8.3/xxh_x86dispatch.h @@ -0,0 +1,93 @@ +/* + * xxHash - XXH3 Dispatcher for x86-based targets + * Copyright (C) 2020-2024 Yann Collet + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +#ifndef XXH_X86DISPATCH_H_13563687684 +#define XXH_X86DISPATCH_H_13563687684 + +#include "xxhash.h" /* XXH64_hash_t, XXH3_state_t */ + +#if defined (__cplusplus) +extern "C" { +#endif + +/*! + * @brief Returns the best XXH3 implementation for x86 + * + * @return The best @ref XXH_VECTOR implementation. + * @see XXH_VECTOR_TYPES + */ +XXH_PUBLIC_API int XXH_featureTest(void); + +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_dispatch(XXH_NOESCAPE const void* input, size_t len); +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed); +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen); +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len); + +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_dispatch(XXH_NOESCAPE const void* input, size_t len); +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSeed_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed); +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecret_dispatch(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretLen); +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update_dispatch(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len); + +#if defined (__cplusplus) +} +#endif + + +/* automatic replacement of XXH3 functions. + * can be disabled by setting XXH_DISPATCH_DISABLE_REPLACE */ +#ifndef XXH_DISPATCH_DISABLE_REPLACE + +# undef XXH3_64bits +# define XXH3_64bits XXH3_64bits_dispatch +# undef XXH3_64bits_withSeed +# define XXH3_64bits_withSeed XXH3_64bits_withSeed_dispatch +# undef XXH3_64bits_withSecret +# define XXH3_64bits_withSecret XXH3_64bits_withSecret_dispatch +# undef XXH3_64bits_update +# define XXH3_64bits_update XXH3_64bits_update_dispatch + +# undef XXH128 +# define XXH128 XXH3_128bits_withSeed_dispatch +# undef XXH3_128bits +# define XXH3_128bits XXH3_128bits_dispatch +# undef XXH3_128bits_withSeed +# define XXH3_128bits_withSeed XXH3_128bits_withSeed_dispatch +# undef XXH3_128bits_withSecret +# define XXH3_128bits_withSecret XXH3_128bits_withSecret_dispatch +# undef XXH3_128bits_update +# define XXH3_128bits_update XXH3_128bits_update_dispatch + +#endif /* XXH_DISPATCH_DISABLE_REPLACE */ + +#endif /* XXH_X86DISPATCH_H_13563687684 */ diff --git a/extra/xxhash/xxHash-0.8.3/xxhash.c b/extra/xxhash/xxHash-0.8.3/xxhash.c new file mode 100644 index 000000000000..e60cc37f13c2 --- /dev/null +++ b/extra/xxhash/xxHash-0.8.3/xxhash.c @@ -0,0 +1,42 @@ +/* + * xxHash - Extremely Fast Hash algorithm + * Copyright (C) 2012-2023 Yann Collet + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +/* + * xxhash.c instantiates functions defined in xxhash.h + */ + +#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */ +#define XXH_IMPLEMENTATION /* access definitions */ + +#include "xxhash.h" diff --git a/extra/xxhash/xxHash-0.8.3/xxhash.h b/extra/xxhash/xxHash-0.8.3/xxhash.h new file mode 100644 index 000000000000..78fc2e8dbf6d --- /dev/null +++ b/extra/xxhash/xxHash-0.8.3/xxhash.h @@ -0,0 +1,7238 @@ +/* + * xxHash - Extremely Fast Hash algorithm + * Header File + * Copyright (C) 2012-2023 Yann Collet + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +/*! + * @mainpage xxHash + * + * xxHash is an extremely fast non-cryptographic hash algorithm, working at RAM speed + * limits. + * + * It is proposed in four flavors, in three families: + * 1. @ref XXH32_family + * - Classic 32-bit hash function. Simple, compact, and runs on almost all + * 32-bit and 64-bit systems. + * 2. @ref XXH64_family + * - Classic 64-bit adaptation of XXH32. Just as simple, and runs well on most + * 64-bit systems (but _not_ 32-bit systems). + * 3. @ref XXH3_family + * - Modern 64-bit and 128-bit hash function family which features improved + * strength and performance across the board, especially on smaller data. + * It benefits greatly from SIMD and 64-bit without requiring it. + * + * Benchmarks + * --- + * The reference system uses an Intel i7-9700K CPU, and runs Ubuntu x64 20.04. + * The open source benchmark program is compiled with clang v10.0 using -O3 flag. + * + * | Hash Name | ISA ext | Width | Large Data Speed | Small Data Velocity | + * | -------------------- | ------- | ----: | ---------------: | ------------------: | + * | XXH3_64bits() | @b AVX2 | 64 | 59.4 GB/s | 133.1 | + * | MeowHash | AES-NI | 128 | 58.2 GB/s | 52.5 | + * | XXH3_128bits() | @b AVX2 | 128 | 57.9 GB/s | 118.1 | + * | CLHash | PCLMUL | 64 | 37.1 GB/s | 58.1 | + * | XXH3_64bits() | @b SSE2 | 64 | 31.5 GB/s | 133.1 | + * | XXH3_128bits() | @b SSE2 | 128 | 29.6 GB/s | 118.1 | + * | RAM sequential read | | N/A | 28.0 GB/s | N/A | + * | ahash | AES-NI | 64 | 22.5 GB/s | 107.2 | + * | City64 | | 64 | 22.0 GB/s | 76.6 | + * | T1ha2 | | 64 | 22.0 GB/s | 99.0 | + * | City128 | | 128 | 21.7 GB/s | 57.7 | + * | FarmHash | AES-NI | 64 | 21.3 GB/s | 71.9 | + * | XXH64() | | 64 | 19.4 GB/s | 71.0 | + * | SpookyHash | | 64 | 19.3 GB/s | 53.2 | + * | Mum | | 64 | 18.0 GB/s | 67.0 | + * | CRC32C | SSE4.2 | 32 | 13.0 GB/s | 57.9 | + * | XXH32() | | 32 | 9.7 GB/s | 71.9 | + * | City32 | | 32 | 9.1 GB/s | 66.0 | + * | Blake3* | @b AVX2 | 256 | 4.4 GB/s | 8.1 | + * | Murmur3 | | 32 | 3.9 GB/s | 56.1 | + * | SipHash* | | 64 | 3.0 GB/s | 43.2 | + * | Blake3* | @b SSE2 | 256 | 2.4 GB/s | 8.1 | + * | HighwayHash | | 64 | 1.4 GB/s | 6.0 | + * | FNV64 | | 64 | 1.2 GB/s | 62.7 | + * | Blake2* | | 256 | 1.1 GB/s | 5.1 | + * | SHA1* | | 160 | 0.8 GB/s | 5.6 | + * | MD5* | | 128 | 0.6 GB/s | 7.8 | + * @note + * - Hashes which require a specific ISA extension are noted. SSE2 is also noted, + * even though it is mandatory on x64. + * - Hashes with an asterisk are cryptographic. Note that MD5 is non-cryptographic + * by modern standards. + * - Small data velocity is a rough average of algorithm's efficiency for small + * data. For more accurate information, see the wiki. + * - More benchmarks and strength tests are found on the wiki: + * https://github.com/Cyan4973/xxHash/wiki + * + * Usage + * ------ + * All xxHash variants use a similar API. Changing the algorithm is a trivial + * substitution. + * + * @pre + * For functions which take an input and length parameter, the following + * requirements are assumed: + * - The range from [`input`, `input + length`) is valid, readable memory. + * - The only exception is if the `length` is `0`, `input` may be `NULL`. + * - For C++, the objects must have the *TriviallyCopyable* property, as the + * functions access bytes directly as if it was an array of `unsigned char`. + * + * @anchor single_shot_example + * **Single Shot** + * + * These functions are stateless functions which hash a contiguous block of memory, + * immediately returning the result. They are the easiest and usually the fastest + * option. + * + * XXH32(), XXH64(), XXH3_64bits(), XXH3_128bits() + * + * @code{.c} + * #include + * #include "xxhash.h" + * + * // Example for a function which hashes a null terminated string with XXH32(). + * XXH32_hash_t hash_string(const char* string, XXH32_hash_t seed) + * { + * // NULL pointers are only valid if the length is zero + * size_t length = (string == NULL) ? 0 : strlen(string); + * return XXH32(string, length, seed); + * } + * @endcode + * + * + * @anchor streaming_example + * **Streaming** + * + * These groups of functions allow incremental hashing of unknown size, even + * more than what would fit in a size_t. + * + * XXH32_reset(), XXH64_reset(), XXH3_64bits_reset(), XXH3_128bits_reset() + * + * @code{.c} + * #include + * #include + * #include "xxhash.h" + * // Example for a function which hashes a FILE incrementally with XXH3_64bits(). + * XXH64_hash_t hashFile(FILE* f) + * { + * // Allocate a state struct. Do not just use malloc() or new. + * XXH3_state_t* state = XXH3_createState(); + * assert(state != NULL && "Out of memory!"); + * // Reset the state to start a new hashing session. + * XXH3_64bits_reset(state); + * char buffer[4096]; + * size_t count; + * // Read the file in chunks + * while ((count = fread(buffer, 1, sizeof(buffer), f)) != 0) { + * // Run update() as many times as necessary to process the data + * XXH3_64bits_update(state, buffer, count); + * } + * // Retrieve the finalized hash. This will not change the state. + * XXH64_hash_t result = XXH3_64bits_digest(state); + * // Free the state. Do not use free(). + * XXH3_freeState(state); + * return result; + * } + * @endcode + * + * Streaming functions generate the xxHash value from an incremental input. + * This method is slower than single-call functions, due to state management. + * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. + * + * An XXH state must first be allocated using `XXH*_createState()`. + * + * Start a new hash by initializing the state with a seed using `XXH*_reset()`. + * + * Then, feed the hash state by calling `XXH*_update()` as many times as necessary. + * + * The function returns an error code, with 0 meaning OK, and any other value + * meaning there is an error. + * + * Finally, a hash value can be produced anytime, by using `XXH*_digest()`. + * This function returns the nn-bits hash as an int or long long. + * + * It's still possible to continue inserting input into the hash state after a + * digest, and generate new hash values later on by invoking `XXH*_digest()`. + * + * When done, release the state using `XXH*_freeState()`. + * + * + * @anchor canonical_representation_example + * **Canonical Representation** + * + * The default return values from XXH functions are unsigned 32, 64 and 128 bit + * integers. + * This the simplest and fastest format for further post-processing. + * + * However, this leaves open the question of what is the order on the byte level, + * since little and big endian conventions will store the same number differently. + * + * The canonical representation settles this issue by mandating big-endian + * convention, the same convention as human-readable numbers (large digits first). + * + * When writing hash values to storage, sending them over a network, or printing + * them, it's highly recommended to use the canonical representation to ensure + * portability across a wider range of systems, present and future. + * + * The following functions allow transformation of hash values to and from + * canonical format. + * + * XXH32_canonicalFromHash(), XXH32_hashFromCanonical(), + * XXH64_canonicalFromHash(), XXH64_hashFromCanonical(), + * XXH128_canonicalFromHash(), XXH128_hashFromCanonical(), + * + * @code{.c} + * #include + * #include "xxhash.h" + * + * // Example for a function which prints XXH32_hash_t in human readable format + * void printXxh32(XXH32_hash_t hash) + * { + * XXH32_canonical_t cano; + * XXH32_canonicalFromHash(&cano, hash); + * size_t i; + * for(i = 0; i < sizeof(cano.digest); ++i) { + * printf("%02x", cano.digest[i]); + * } + * printf("\n"); + * } + * + * // Example for a function which converts XXH32_canonical_t to XXH32_hash_t + * XXH32_hash_t convertCanonicalToXxh32(XXH32_canonical_t cano) + * { + * XXH32_hash_t hash = XXH32_hashFromCanonical(&cano); + * return hash; + * } + * @endcode + * + * + * @file xxhash.h + * xxHash prototypes and implementation + */ + +#if defined (__cplusplus) +extern "C" { +#endif + +/* **************************** + * INLINE mode + ******************************/ +/*! + * @defgroup public Public API + * Contains details on the public xxHash functions. + * @{ + */ +#ifdef XXH_DOXYGEN +/*! + * @brief Gives access to internal state declaration, required for static allocation. + * + * Incompatible with dynamic linking, due to risks of ABI changes. + * + * Usage: + * @code{.c} + * #define XXH_STATIC_LINKING_ONLY + * #include "xxhash.h" + * @endcode + */ +# define XXH_STATIC_LINKING_ONLY +/* Do not undef XXH_STATIC_LINKING_ONLY for Doxygen */ + +/*! + * @brief Gives access to internal definitions. + * + * Usage: + * @code{.c} + * #define XXH_STATIC_LINKING_ONLY + * #define XXH_IMPLEMENTATION + * #include "xxhash.h" + * @endcode + */ +# define XXH_IMPLEMENTATION +/* Do not undef XXH_IMPLEMENTATION for Doxygen */ + +/*! + * @brief Exposes the implementation and marks all functions as `inline`. + * + * Use these build macros to inline xxhash into the target unit. + * Inlining improves performance on small inputs, especially when the length is + * expressed as a compile-time constant: + * + * https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html + * + * It also keeps xxHash symbols private to the unit, so they are not exported. + * + * Usage: + * @code{.c} + * #define XXH_INLINE_ALL + * #include "xxhash.h" + * @endcode + * Do not compile and link xxhash.o as a separate object, as it is not useful. + */ +# define XXH_INLINE_ALL +# undef XXH_INLINE_ALL +/*! + * @brief Exposes the implementation without marking functions as inline. + */ +# define XXH_PRIVATE_API +# undef XXH_PRIVATE_API +/*! + * @brief Emulate a namespace by transparently prefixing all symbols. + * + * If you want to include _and expose_ xxHash functions from within your own + * library, but also want to avoid symbol collisions with other libraries which + * may also include xxHash, you can use @ref XXH_NAMESPACE to automatically prefix + * any public symbol from xxhash library with the value of @ref XXH_NAMESPACE + * (therefore, avoid empty or numeric values). + * + * Note that no change is required within the calling program as long as it + * includes `xxhash.h`: Regular symbol names will be automatically translated + * by this header. + */ +# define XXH_NAMESPACE /* YOUR NAME HERE */ +# undef XXH_NAMESPACE +#endif + +#if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \ + && !defined(XXH_INLINE_ALL_31684351384) + /* this section should be traversed only once */ +# define XXH_INLINE_ALL_31684351384 + /* give access to the advanced API, required to compile implementations */ +# undef XXH_STATIC_LINKING_ONLY /* avoid macro redef */ +# define XXH_STATIC_LINKING_ONLY + /* make all functions private */ +# undef XXH_PUBLIC_API +# if defined(__GNUC__) +# define XXH_PUBLIC_API static __inline __attribute__((__unused__)) +# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# define XXH_PUBLIC_API static inline +# elif defined(_MSC_VER) +# define XXH_PUBLIC_API static __inline +# else + /* note: this version may generate warnings for unused static functions */ +# define XXH_PUBLIC_API static +# endif + + /* + * This part deals with the special case where a unit wants to inline xxHash, + * but "xxhash.h" has previously been included without XXH_INLINE_ALL, + * such as part of some previously included *.h header file. + * Without further action, the new include would just be ignored, + * and functions would effectively _not_ be inlined (silent failure). + * The following macros solve this situation by prefixing all inlined names, + * avoiding naming collision with previous inclusions. + */ + /* Before that, we unconditionally #undef all symbols, + * in case they were already defined with XXH_NAMESPACE. + * They will then be redefined for XXH_INLINE_ALL + */ +# undef XXH_versionNumber + /* XXH32 */ +# undef XXH32 +# undef XXH32_createState +# undef XXH32_freeState +# undef XXH32_reset +# undef XXH32_update +# undef XXH32_digest +# undef XXH32_copyState +# undef XXH32_canonicalFromHash +# undef XXH32_hashFromCanonical + /* XXH64 */ +# undef XXH64 +# undef XXH64_createState +# undef XXH64_freeState +# undef XXH64_reset +# undef XXH64_update +# undef XXH64_digest +# undef XXH64_copyState +# undef XXH64_canonicalFromHash +# undef XXH64_hashFromCanonical + /* XXH3_64bits */ +# undef XXH3_64bits +# undef XXH3_64bits_withSecret +# undef XXH3_64bits_withSeed +# undef XXH3_64bits_withSecretandSeed +# undef XXH3_createState +# undef XXH3_freeState +# undef XXH3_copyState +# undef XXH3_64bits_reset +# undef XXH3_64bits_reset_withSeed +# undef XXH3_64bits_reset_withSecret +# undef XXH3_64bits_update +# undef XXH3_64bits_digest +# undef XXH3_generateSecret + /* XXH3_128bits */ +# undef XXH128 +# undef XXH3_128bits +# undef XXH3_128bits_withSeed +# undef XXH3_128bits_withSecret +# undef XXH3_128bits_reset +# undef XXH3_128bits_reset_withSeed +# undef XXH3_128bits_reset_withSecret +# undef XXH3_128bits_reset_withSecretandSeed +# undef XXH3_128bits_update +# undef XXH3_128bits_digest +# undef XXH128_isEqual +# undef XXH128_cmp +# undef XXH128_canonicalFromHash +# undef XXH128_hashFromCanonical + /* Finally, free the namespace itself */ +# undef XXH_NAMESPACE + + /* employ the namespace for XXH_INLINE_ALL */ +# define XXH_NAMESPACE XXH_INLINE_ + /* + * Some identifiers (enums, type names) are not symbols, + * but they must nonetheless be renamed to avoid redeclaration. + * Alternative solution: do not redeclare them. + * However, this requires some #ifdefs, and has a more dispersed impact. + * Meanwhile, renaming can be achieved in a single place. + */ +# define XXH_IPREF(Id) XXH_NAMESPACE ## Id +# define XXH_OK XXH_IPREF(XXH_OK) +# define XXH_ERROR XXH_IPREF(XXH_ERROR) +# define XXH_errorcode XXH_IPREF(XXH_errorcode) +# define XXH32_canonical_t XXH_IPREF(XXH32_canonical_t) +# define XXH64_canonical_t XXH_IPREF(XXH64_canonical_t) +# define XXH128_canonical_t XXH_IPREF(XXH128_canonical_t) +# define XXH32_state_s XXH_IPREF(XXH32_state_s) +# define XXH32_state_t XXH_IPREF(XXH32_state_t) +# define XXH64_state_s XXH_IPREF(XXH64_state_s) +# define XXH64_state_t XXH_IPREF(XXH64_state_t) +# define XXH3_state_s XXH_IPREF(XXH3_state_s) +# define XXH3_state_t XXH_IPREF(XXH3_state_t) +# define XXH128_hash_t XXH_IPREF(XXH128_hash_t) + /* Ensure the header is parsed again, even if it was previously included */ +# undef XXHASH_H_5627135585666179 +# undef XXHASH_H_STATIC_13879238742 +#endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */ + +/* **************************************************************** + * Stable API + *****************************************************************/ +#ifndef XXHASH_H_5627135585666179 +#define XXHASH_H_5627135585666179 1 + +/*! @brief Marks a global symbol. */ +#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) +# if defined(_WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) +# ifdef XXH_EXPORT +# define XXH_PUBLIC_API __declspec(dllexport) +# elif XXH_IMPORT +# define XXH_PUBLIC_API __declspec(dllimport) +# endif +# else +# define XXH_PUBLIC_API /* do nothing */ +# endif +#endif + +#ifdef XXH_NAMESPACE +# define XXH_CAT(A,B) A##B +# define XXH_NAME2(A,B) XXH_CAT(A,B) +# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) +/* XXH32 */ +# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) +# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) +# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) +# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) +# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) +# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) +# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) +# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) +# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) +/* XXH64 */ +# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) +# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) +# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) +# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) +# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) +# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) +# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) +# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) +# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) +/* XXH3_64bits */ +# define XXH3_64bits XXH_NAME2(XXH_NAMESPACE, XXH3_64bits) +# define XXH3_64bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecret) +# define XXH3_64bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSeed) +# define XXH3_64bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecretandSeed) +# define XXH3_createState XXH_NAME2(XXH_NAMESPACE, XXH3_createState) +# define XXH3_freeState XXH_NAME2(XXH_NAMESPACE, XXH3_freeState) +# define XXH3_copyState XXH_NAME2(XXH_NAMESPACE, XXH3_copyState) +# define XXH3_64bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset) +# define XXH3_64bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSeed) +# define XXH3_64bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecret) +# define XXH3_64bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecretandSeed) +# define XXH3_64bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_update) +# define XXH3_64bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_digest) +# define XXH3_generateSecret XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret) +# define XXH3_generateSecret_fromSeed XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret_fromSeed) +/* XXH3_128bits */ +# define XXH128 XXH_NAME2(XXH_NAMESPACE, XXH128) +# define XXH3_128bits XXH_NAME2(XXH_NAMESPACE, XXH3_128bits) +# define XXH3_128bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSeed) +# define XXH3_128bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecret) +# define XXH3_128bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecretandSeed) +# define XXH3_128bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset) +# define XXH3_128bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSeed) +# define XXH3_128bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecret) +# define XXH3_128bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecretandSeed) +# define XXH3_128bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_update) +# define XXH3_128bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_digest) +# define XXH128_isEqual XXH_NAME2(XXH_NAMESPACE, XXH128_isEqual) +# define XXH128_cmp XXH_NAME2(XXH_NAMESPACE, XXH128_cmp) +# define XXH128_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH128_canonicalFromHash) +# define XXH128_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH128_hashFromCanonical) +#endif + + +/* ************************************* +* Compiler specifics +***************************************/ + +/* specific declaration modes for Windows */ +#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) +# if defined(_WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) +# ifdef XXH_EXPORT +# define XXH_PUBLIC_API __declspec(dllexport) +# elif XXH_IMPORT +# define XXH_PUBLIC_API __declspec(dllimport) +# endif +# else +# define XXH_PUBLIC_API /* do nothing */ +# endif +#endif + +#if defined (__GNUC__) +# define XXH_CONSTF __attribute__((__const__)) +# define XXH_PUREF __attribute__((__pure__)) +# define XXH_MALLOCF __attribute__((__malloc__)) +#else +# define XXH_CONSTF /* disable */ +# define XXH_PUREF +# define XXH_MALLOCF +#endif + +/* ************************************* +* Version +***************************************/ +#define XXH_VERSION_MAJOR 0 +#define XXH_VERSION_MINOR 8 +#define XXH_VERSION_RELEASE 3 +/*! @brief Version number, encoded as two digits each */ +#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) + +/*! + * @brief Obtains the xxHash version. + * + * This is mostly useful when xxHash is compiled as a shared library, + * since the returned value comes from the library, as opposed to header file. + * + * @return @ref XXH_VERSION_NUMBER of the invoked library. + */ +XXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber (void); + + +/* **************************** +* Common basic types +******************************/ +#include /* size_t */ +/*! + * @brief Exit code for the streaming API. + */ +typedef enum { + XXH_OK = 0, /*!< OK */ + XXH_ERROR /*!< Error */ +} XXH_errorcode; + + +/*-********************************************************************** +* 32-bit hash +************************************************************************/ +#if defined(XXH_DOXYGEN) /* Don't show include */ +/*! + * @brief An unsigned 32-bit integer. + * + * Not necessarily defined to `uint32_t` but functionally equivalent. + */ +typedef uint32_t XXH32_hash_t; + +#elif !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# ifdef _AIX +# include +# else +# include +# endif + typedef uint32_t XXH32_hash_t; + +#else +# include +# if UINT_MAX == 0xFFFFFFFFUL + typedef unsigned int XXH32_hash_t; +# elif ULONG_MAX == 0xFFFFFFFFUL + typedef unsigned long XXH32_hash_t; +# else +# error "unsupported platform: need a 32-bit type" +# endif +#endif + +/*! + * @} + * + * @defgroup XXH32_family XXH32 family + * @ingroup public + * Contains functions used in the classic 32-bit xxHash algorithm. + * + * @note + * XXH32 is useful for older platforms, with no or poor 64-bit performance. + * Note that the @ref XXH3_family provides competitive speed for both 32-bit + * and 64-bit systems, and offers true 64/128 bit hash results. + * + * @see @ref XXH64_family, @ref XXH3_family : Other xxHash families + * @see @ref XXH32_impl for implementation details + * @{ + */ + +/*! + * @brief Calculates the 32-bit hash of @p input using xxHash32. + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * @param seed The 32-bit seed to alter the hash's output predictably. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 32-bit xxHash32 value. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed); + +#ifndef XXH_NO_STREAM +/*! + * @typedef struct XXH32_state_s XXH32_state_t + * @brief The opaque state struct for the XXH32 streaming API. + * + * @see XXH32_state_s for details. + * @see @ref streaming_example "Streaming Example" + */ +typedef struct XXH32_state_s XXH32_state_t; + +/*! + * @brief Allocates an @ref XXH32_state_t. + * + * @return An allocated pointer of @ref XXH32_state_t on success. + * @return `NULL` on failure. + * + * @note Must be freed with XXH32_freeState(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_MALLOCF XXH32_state_t* XXH32_createState(void); +/*! + * @brief Frees an @ref XXH32_state_t. + * + * @param statePtr A pointer to an @ref XXH32_state_t allocated with @ref XXH32_createState(). + * + * @return @ref XXH_OK. + * + * @note @p statePtr must be allocated with XXH32_createState(). + * + * @see @ref streaming_example "Streaming Example" + * + */ +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); +/*! + * @brief Copies one @ref XXH32_state_t to another. + * + * @param dst_state The state to copy to. + * @param src_state The state to copy from. + * @pre + * @p dst_state and @p src_state must not be `NULL` and must not overlap. + */ +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); + +/*! + * @brief Resets an @ref XXH32_state_t to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param seed The 32-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note This function resets and seeds a state. Call it before @ref XXH32_update(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, XXH32_hash_t seed); + +/*! + * @brief Consumes a block of @p input to an @ref XXH32_state_t. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note Call this to incrementally consume blocks of data. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); + +/*! + * @brief Returns the calculated hash value from an @ref XXH32_state_t. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated 32-bit xxHash32 value from that state. + * + * @note + * Calling XXH32_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ + +/******* Canonical representation *******/ + +/*! + * @brief Canonical (big endian) representation of @ref XXH32_hash_t. + */ +typedef struct { + unsigned char digest[4]; /*!< Hash bytes, big endian */ +} XXH32_canonical_t; + +/*! + * @brief Converts an @ref XXH32_hash_t to a big endian @ref XXH32_canonical_t. + * + * @param dst The @ref XXH32_canonical_t pointer to be stored to. + * @param hash The @ref XXH32_hash_t to be converted. + * + * @pre + * @p dst must not be `NULL`. + * + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); + +/*! + * @brief Converts an @ref XXH32_canonical_t to a native @ref XXH32_hash_t. + * + * @param src The @ref XXH32_canonical_t to convert. + * + * @pre + * @p src must not be `NULL`. + * + * @return The converted hash. + * + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); + + +/*! @cond Doxygen ignores this part */ +#ifdef __has_attribute +# define XXH_HAS_ATTRIBUTE(x) __has_attribute(x) +#else +# define XXH_HAS_ATTRIBUTE(x) 0 +#endif +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ +/* + * C23 __STDC_VERSION__ number hasn't been specified yet. For now + * leave as `201711L` (C17 + 1). + * TODO: Update to correct value when its been specified. + */ +#define XXH_C23_VN 201711L +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ +/* C-language Attributes are added in C23. */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) && defined(__has_c_attribute) +# define XXH_HAS_C_ATTRIBUTE(x) __has_c_attribute(x) +#else +# define XXH_HAS_C_ATTRIBUTE(x) 0 +#endif +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ +#if defined(__cplusplus) && defined(__has_cpp_attribute) +# define XXH_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +# define XXH_HAS_CPP_ATTRIBUTE(x) 0 +#endif +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ +/* + * Define XXH_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute + * introduced in CPP17 and C23. + * CPP17 : https://en.cppreference.com/w/cpp/language/attributes/fallthrough + * C23 : https://en.cppreference.com/w/c/language/attributes/fallthrough + */ +#if XXH_HAS_C_ATTRIBUTE(fallthrough) || XXH_HAS_CPP_ATTRIBUTE(fallthrough) +# define XXH_FALLTHROUGH [[fallthrough]] +#elif XXH_HAS_ATTRIBUTE(__fallthrough__) +# define XXH_FALLTHROUGH __attribute__ ((__fallthrough__)) +#else +# define XXH_FALLTHROUGH /* fallthrough */ +#endif +/*! @endcond */ + +/*! @cond Doxygen ignores this part */ +/* + * Define XXH_NOESCAPE for annotated pointers in public API. + * https://clang.llvm.org/docs/AttributeReference.html#noescape + * As of writing this, only supported by clang. + */ +#if XXH_HAS_ATTRIBUTE(noescape) +# define XXH_NOESCAPE __attribute__((__noescape__)) +#else +# define XXH_NOESCAPE +#endif +/*! @endcond */ + + +/*! + * @} + * @ingroup public + * @{ + */ + +#ifndef XXH_NO_LONG_LONG +/*-********************************************************************** +* 64-bit hash +************************************************************************/ +#if defined(XXH_DOXYGEN) /* don't include */ +/*! + * @brief An unsigned 64-bit integer. + * + * Not necessarily defined to `uint64_t` but functionally equivalent. + */ +typedef uint64_t XXH64_hash_t; +#elif !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# ifdef _AIX +# include +# else +# include +# endif + typedef uint64_t XXH64_hash_t; +#else +# include +# if defined(__LP64__) && ULONG_MAX == 0xFFFFFFFFFFFFFFFFULL + /* LP64 ABI says uint64_t is unsigned long */ + typedef unsigned long XXH64_hash_t; +# else + /* the following type must have a width of 64-bit */ + typedef unsigned long long XXH64_hash_t; +# endif +#endif + +/*! + * @} + * + * @defgroup XXH64_family XXH64 family + * @ingroup public + * @{ + * Contains functions used in the classic 64-bit xxHash algorithm. + * + * @note + * XXH3 provides competitive speed for both 32-bit and 64-bit systems, + * and offers true 64/128 bit hash results. + * It provides better speed for systems with vector processing capabilities. + */ + +/*! + * @brief Calculates the 64-bit hash of @p input using xxHash64. + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * @param seed The 64-bit seed to alter the hash's output predictably. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 64-bit xxHash64 value. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); + +/******* Streaming *******/ +#ifndef XXH_NO_STREAM +/*! + * @brief The opaque state struct for the XXH64 streaming API. + * + * @see XXH64_state_s for details. + * @see @ref streaming_example "Streaming Example" + */ +typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ + +/*! + * @brief Allocates an @ref XXH64_state_t. + * + * @return An allocated pointer of @ref XXH64_state_t on success. + * @return `NULL` on failure. + * + * @note Must be freed with XXH64_freeState(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_MALLOCF XXH64_state_t* XXH64_createState(void); + +/*! + * @brief Frees an @ref XXH64_state_t. + * + * @param statePtr A pointer to an @ref XXH64_state_t allocated with @ref XXH64_createState(). + * + * @return @ref XXH_OK. + * + * @note @p statePtr must be allocated with XXH64_createState(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); + +/*! + * @brief Copies one @ref XXH64_state_t to another. + * + * @param dst_state The state to copy to. + * @param src_state The state to copy from. + * @pre + * @p dst_state and @p src_state must not be `NULL` and must not overlap. + */ +XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dst_state, const XXH64_state_t* src_state); + +/*! + * @brief Resets an @ref XXH64_state_t to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note This function resets and seeds a state. Call it before @ref XXH64_update(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed); + +/*! + * @brief Consumes a block of @p input to an @ref XXH64_state_t. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note Call this to incrementally consume blocks of data. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH_NOESCAPE XXH64_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Returns the calculated hash value from an @ref XXH64_state_t. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated 64-bit xxHash64 value from that state. + * + * @note + * Calling XXH64_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_digest (XXH_NOESCAPE const XXH64_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ +/******* Canonical representation *******/ + +/*! + * @brief Canonical (big endian) representation of @ref XXH64_hash_t. + */ +typedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t; + +/*! + * @brief Converts an @ref XXH64_hash_t to a big endian @ref XXH64_canonical_t. + * + * @param dst The @ref XXH64_canonical_t pointer to be stored to. + * @param hash The @ref XXH64_hash_t to be converted. + * + * @pre + * @p dst must not be `NULL`. + * + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash); + +/*! + * @brief Converts an @ref XXH64_canonical_t to a native @ref XXH64_hash_t. + * + * @param src The @ref XXH64_canonical_t to convert. + * + * @pre + * @p src must not be `NULL`. + * + * @return The converted hash. + * + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src); + +#ifndef XXH_NO_XXH3 + +/*! + * @} + * ************************************************************************ + * @defgroup XXH3_family XXH3 family + * @ingroup public + * @{ + * + * XXH3 is a more recent hash algorithm featuring: + * - Improved speed for both small and large inputs + * - True 64-bit and 128-bit outputs + * - SIMD acceleration + * - Improved 32-bit viability + * + * Speed analysis methodology is explained here: + * + * https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html + * + * Compared to XXH64, expect XXH3 to run approximately + * ~2x faster on large inputs and >3x faster on small ones, + * exact differences vary depending on platform. + * + * XXH3's speed benefits greatly from SIMD and 64-bit arithmetic, + * but does not require it. + * Most 32-bit and 64-bit targets that can run XXH32 smoothly can run XXH3 + * at competitive speeds, even without vector support. Further details are + * explained in the implementation. + * + * XXH3 has a fast scalar implementation, but it also includes accelerated SIMD + * implementations for many common platforms: + * - AVX512 + * - AVX2 + * - SSE2 + * - ARM NEON + * - WebAssembly SIMD128 + * - POWER8 VSX + * - s390x ZVector + * This can be controlled via the @ref XXH_VECTOR macro, but it automatically + * selects the best version according to predefined macros. For the x86 family, an + * automatic runtime dispatcher is included separately in @ref xxh_x86dispatch.c. + * + * XXH3 implementation is portable: + * it has a generic C90 formulation that can be compiled on any platform, + * all implementations generate exactly the same hash value on all platforms. + * Starting from v0.8.0, it's also labelled "stable", meaning that + * any future version will also generate the same hash value. + * + * XXH3 offers 2 variants, _64bits and _128bits. + * + * When only 64 bits are needed, prefer invoking the _64bits variant, as it + * reduces the amount of mixing, resulting in faster speed on small inputs. + * It's also generally simpler to manipulate a scalar return type than a struct. + * + * The API supports one-shot hashing, streaming mode, and custom secrets. + */ + +/*! + * @ingroup tuning + * @brief Possible values for @ref XXH_VECTOR. + * + * Unless set explicitly, determined automatically. + */ +# define XXH_SCALAR 0 /*!< Portable scalar version */ +# define XXH_SSE2 1 /*!< SSE2 for Pentium 4, Opteron, all x86_64. */ +# define XXH_AVX2 2 /*!< AVX2 for Haswell and Bulldozer */ +# define XXH_AVX512 3 /*!< AVX512 for Skylake and Icelake */ +# define XXH_NEON 4 /*!< NEON for most ARMv7-A, all AArch64, and WASM SIMD128 */ +# define XXH_VSX 5 /*!< VSX and ZVector for POWER8/z13 (64-bit) */ +# define XXH_SVE 6 /*!< SVE for some ARMv8-A and ARMv9-A */ +# define XXH_LSX 7 /*!< LSX (128-bit SIMD) for LoongArch64 */ + + +/*-********************************************************************** +* XXH3 64-bit variant +************************************************************************/ + +/*! + * @brief Calculates 64-bit unseeded variant of XXH3 hash of @p input. + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 64-bit XXH3 hash value. + * + * @note + * This is equivalent to @ref XXH3_64bits_withSeed() with a seed of `0`, however + * it may have slightly better performance due to constant propagation of the + * defaults. + * + * @see + * XXH3_64bits_withSeed(), XXH3_64bits_withSecret(): other seeding variants + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Calculates 64-bit seeded variant of XXH3 hash of @p input. + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 64-bit XXH3 hash value. + * + * @note + * seed == 0 produces the same results as @ref XXH3_64bits(). + * + * This variant generates a custom secret on the fly based on default secret + * altered using the @p seed value. + * + * While this operation is decently fast, note that it's not completely free. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed); + +/*! + * The bare minimum size for a custom secret. + * + * @see + * XXH3_64bits_withSecret(), XXH3_64bits_reset_withSecret(), + * XXH3_128bits_withSecret(), XXH3_128bits_reset_withSecret(). + */ +#define XXH3_SECRET_SIZE_MIN 136 + +/*! + * @brief Calculates 64-bit variant of XXH3 with a custom "secret". + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @return The calculated 64-bit XXH3 hash value. + * + * @pre + * The memory between @p data and @p data + @p len must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p data may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * It's possible to provide any blob of bytes as a "secret" to generate the hash. + * This makes it more difficult for an external actor to prepare an intentional collision. + * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN). + * However, the quality of the secret impacts the dispersion of the hash algorithm. + * Therefore, the secret _must_ look like a bunch of random bytes. + * Avoid "trivial" or structured data such as repeated sequences or a text document. + * Whenever in doubt about the "randomness" of the blob of bytes, + * consider employing @ref XXH3_generateSecret() instead (see below). + * It will generate a proper high entropy secret derived from the blob of bytes. + * Another advantage of using XXH3_generateSecret() is that + * it guarantees that all bits within the initial blob of bytes + * will impact every bit of the output. + * This is not necessarily the case when using the blob of bytes directly + * because, when hashing _small_ inputs, only a portion of the secret is employed. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); + + +/******* Streaming *******/ +#ifndef XXH_NO_STREAM +/* + * Streaming requires state maintenance. + * This operation costs memory and CPU. + * As a consequence, streaming is slower than one-shot hashing. + * For better performance, prefer one-shot functions whenever applicable. + */ + +/*! + * @brief The opaque state struct for the XXH3 streaming API. + * + * @see XXH3_state_s for details. + * @see @ref streaming_example "Streaming Example" + */ +typedef struct XXH3_state_s XXH3_state_t; +XXH_PUBLIC_API XXH_MALLOCF XXH3_state_t* XXH3_createState(void); +XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr); + +/*! + * @brief Copies one @ref XXH3_state_t to another. + * + * @param dst_state The state to copy to. + * @param src_state The state to copy from. + * @pre + * @p dst_state and @p src_state must not be `NULL` and must not overlap. + */ +XXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state); + +/*! + * @brief Resets an @ref XXH3_state_t to begin a new hash. + * + * @param statePtr The state struct to reset. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret with default parameters. + * - Call this function before @ref XXH3_64bits_update(). + * - Digest will be equivalent to `XXH3_64bits()`. + * + * @see @ref streaming_example "Streaming Example" + * + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); + +/*! + * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret from `seed`. + * - Call this function before @ref XXH3_64bits_update(). + * - Digest will be equivalent to `XXH3_64bits_withSeed()`. + * + * @see @ref streaming_example "Streaming Example" + * + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); + +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * `secret` is referenced, it _must outlive_ the hash streaming session. + * + * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN, + * and the quality of produced hash values depends on secret's entropy + * (secret's content should look like a bunch of random bytes). + * When in doubt about the randomness of a candidate `secret`, + * consider employing `XXH3_generateSecret()` instead (see below). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); + +/*! + * @brief Consumes a block of @p input to an @ref XXH3_state_t. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note Call this to incrementally consume blocks of data. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Returns the calculated XXH3 64-bit hash value from an @ref XXH3_state_t. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated XXH3 64-bit hash value from that state. + * + * @note + * Calling XXH3_64bits_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ + +/* note : canonical representation of XXH3 is the same as XXH64 + * since they both produce XXH64_hash_t values */ + + +/*-********************************************************************** +* XXH3 128-bit variant +************************************************************************/ + +/*! + * @brief The return value from 128-bit hashes. + * + * Stored in little endian order, although the fields themselves are in native + * endianness. + */ +typedef struct { + XXH64_hash_t low64; /*!< `value & 0xFFFFFFFFFFFFFFFF` */ + XXH64_hash_t high64; /*!< `value >> 64` */ +} XXH128_hash_t; + +/*! + * @brief Calculates 128-bit unseeded variant of XXH3 of @p data. + * + * @param data The block of data to be hashed, at least @p length bytes in size. + * @param len The length of @p data, in bytes. + * + * @return The calculated 128-bit variant of XXH3 value. + * + * The 128-bit variant of XXH3 has more strength, but it has a bit of overhead + * for shorter inputs. + * + * This is equivalent to @ref XXH3_128bits_withSeed() with a seed of `0`, however + * it may have slightly better performance due to constant propagation of the + * defaults. + * + * @see XXH3_128bits_withSeed(), XXH3_128bits_withSecret(): other seeding variants + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* data, size_t len); +/*! @brief Calculates 128-bit seeded variant of XXH3 hash of @p data. + * + * @param data The block of data to be hashed, at least @p length bytes in size. + * @param len The length of @p data, in bytes. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @return The calculated 128-bit variant of XXH3 value. + * + * @note + * seed == 0 produces the same results as @ref XXH3_64bits(). + * + * This variant generates a custom secret on the fly based on default secret + * altered using the @p seed value. + * + * While this operation is decently fast, note that it's not completely free. + * + * @see XXH3_128bits(), XXH3_128bits_withSecret(): other seeding variants + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); +/*! + * @brief Calculates 128-bit variant of XXH3 with a custom "secret". + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @return The calculated 128-bit variant of XXH3 value. + * + * It's possible to provide any blob of bytes as a "secret" to generate the hash. + * This makes it more difficult for an external actor to prepare an intentional collision. + * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN). + * However, the quality of the secret impacts the dispersion of the hash algorithm. + * Therefore, the secret _must_ look like a bunch of random bytes. + * Avoid "trivial" or structured data such as repeated sequences or a text document. + * Whenever in doubt about the "randomness" of the blob of bytes, + * consider employing @ref XXH3_generateSecret() instead (see below). + * It will generate a proper high entropy secret derived from the blob of bytes. + * Another advantage of using XXH3_generateSecret() is that + * it guarantees that all bits within the initial blob of bytes + * will impact every bit of the output. + * This is not necessarily the case when using the blob of bytes directly + * because, when hashing _small_ inputs, only a portion of the secret is employed. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize); + +/******* Streaming *******/ +#ifndef XXH_NO_STREAM +/* + * Streaming requires state maintenance. + * This operation costs memory and CPU. + * As a consequence, streaming is slower than one-shot hashing. + * For better performance, prefer one-shot functions whenever applicable. + * + * XXH3_128bits uses the same XXH3_state_t as XXH3_64bits(). + * Use already declared XXH3_createState() and XXH3_freeState(). + * + * All reset and streaming functions have same meaning as their 64-bit counterpart. + */ + +/*! + * @brief Resets an @ref XXH3_state_t to begin a new hash. + * + * @param statePtr The state struct to reset. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret with default parameters. + * - Call it before @ref XXH3_128bits_update(). + * - Digest will be equivalent to `XXH3_128bits()`. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr); + +/*! + * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * - This function resets `statePtr` and generate a secret from `seed`. + * - Call it before @ref XXH3_128bits_update(). + * - Digest will be equivalent to `XXH3_128bits_withSeed()`. + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed); +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr The state struct to reset. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * `secret` is referenced, it _must outlive_ the hash streaming session. + * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN, + * and the quality of produced hash values depends on secret's entropy + * (secret's content should look like a bunch of random bytes). + * When in doubt about the randomness of a candidate `secret`, + * consider employing `XXH3_generateSecret()` instead (see below). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize); + +/*! + * @brief Consumes a block of @p input to an @ref XXH3_state_t. + * + * Call this to incrementally consume blocks of data. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @note + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + */ +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length); + +/*! + * @brief Returns the calculated XXH3 128-bit hash value from an @ref XXH3_state_t. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated XXH3 128-bit hash value from that state. + * + * @note + * Calling XXH3_128bits_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr); +#endif /* !XXH_NO_STREAM */ + +/* Following helper functions make it possible to compare XXH128_hast_t values. + * Since XXH128_hash_t is a structure, this capability is not offered by the language. + * Note: For better performance, these functions can be inlined using XXH_INLINE_ALL */ + +/*! + * @brief Check equality of two XXH128_hash_t values + * + * @param h1 The 128-bit hash value. + * @param h2 Another 128-bit hash value. + * + * @return `1` if `h1` and `h2` are equal. + * @return `0` if they are not. + */ +XXH_PUBLIC_API XXH_PUREF int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2); + +/*! + * @brief Compares two @ref XXH128_hash_t + * + * This comparator is compatible with stdlib's `qsort()`/`bsearch()`. + * + * @param h128_1 Left-hand side value + * @param h128_2 Right-hand side value + * + * @return >0 if @p h128_1 > @p h128_2 + * @return =0 if @p h128_1 == @p h128_2 + * @return <0 if @p h128_1 < @p h128_2 + */ +XXH_PUBLIC_API XXH_PUREF int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2); + + +/******* Canonical representation *******/ +typedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t; + + +/*! + * @brief Converts an @ref XXH128_hash_t to a big endian @ref XXH128_canonical_t. + * + * @param dst The @ref XXH128_canonical_t pointer to be stored to. + * @param hash The @ref XXH128_hash_t to be converted. + * + * @pre + * @p dst must not be `NULL`. + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash); + +/*! + * @brief Converts an @ref XXH128_canonical_t to a native @ref XXH128_hash_t. + * + * @param src The @ref XXH128_canonical_t to convert. + * + * @pre + * @p src must not be `NULL`. + * + * @return The converted hash. + * @see @ref canonical_representation_example "Canonical Representation Example" + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src); + + +#endif /* !XXH_NO_XXH3 */ +#endif /* XXH_NO_LONG_LONG */ + +/*! + * @} + */ +#endif /* XXHASH_H_5627135585666179 */ + + + +#if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) +#define XXHASH_H_STATIC_13879238742 +/* **************************************************************************** + * This section contains declarations which are not guaranteed to remain stable. + * They may change in future versions, becoming incompatible with a different + * version of the library. + * These declarations should only be used with static linking. + * Never use them in association with dynamic linking! + ***************************************************************************** */ + +/* + * These definitions are only present to allow static allocation + * of XXH states, on stack or in a struct, for example. + * Never **ever** access their members directly. + */ + +/*! + * @internal + * @brief Structure for XXH32 streaming API. + * + * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, + * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is + * an opaque type. This allows fields to safely be changed. + * + * Typedef'd to @ref XXH32_state_t. + * Do not access the members of this struct directly. + * @see XXH64_state_s, XXH3_state_s + */ +struct XXH32_state_s { + XXH32_hash_t total_len_32; /*!< Total length hashed, modulo 2^32 */ + XXH32_hash_t large_len; /*!< Whether the hash is >= 16 (handles @ref total_len_32 overflow) */ + XXH32_hash_t acc[4]; /*!< Accumulator lanes */ + unsigned char buffer[16]; /*!< Internal buffer for partial reads. */ + XXH32_hash_t bufferedSize; /*!< Amount of data in @ref buffer */ + XXH32_hash_t reserved; /*!< Reserved field. Do not read nor write to it. */ +}; /* typedef'd to XXH32_state_t */ + + +#ifndef XXH_NO_LONG_LONG /* defined when there is no 64-bit support */ + +/*! + * @internal + * @brief Structure for XXH64 streaming API. + * + * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, + * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is + * an opaque type. This allows fields to safely be changed. + * + * Typedef'd to @ref XXH64_state_t. + * Do not access the members of this struct directly. + * @see XXH32_state_s, XXH3_state_s + */ +struct XXH64_state_s { + XXH64_hash_t total_len; /*!< Total length hashed. This is always 64-bit. */ + XXH64_hash_t acc[4]; /*!< Accumulator lanes */ + unsigned char buffer[32]; /*!< Internal buffer for partial reads.. */ + XXH32_hash_t bufferedSize; /*!< Amount of data in @ref buffer */ + XXH32_hash_t reserved32; /*!< Reserved field, needed for padding anyways*/ + XXH64_hash_t reserved64; /*!< Reserved field. Do not read or write to it. */ +}; /* typedef'd to XXH64_state_t */ + +#ifndef XXH_NO_XXH3 + +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* >= C11 */ +# define XXH_ALIGN(n) _Alignas(n) +#elif defined(__cplusplus) && (__cplusplus >= 201103L) /* >= C++11 */ +/* In C++ alignas() is a keyword */ +# define XXH_ALIGN(n) alignas(n) +#elif defined(__GNUC__) +# define XXH_ALIGN(n) __attribute__ ((aligned(n))) +#elif defined(_MSC_VER) +# define XXH_ALIGN(n) __declspec(align(n)) +#else +# define XXH_ALIGN(n) /* disabled */ +#endif + +/* Old GCC versions only accept the attribute after the type in structures. */ +#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) /* C11+ */ \ + && ! (defined(__cplusplus) && (__cplusplus >= 201103L)) /* >= C++11 */ \ + && defined(__GNUC__) +# define XXH_ALIGN_MEMBER(align, type) type XXH_ALIGN(align) +#else +# define XXH_ALIGN_MEMBER(align, type) XXH_ALIGN(align) type +#endif + +/*! + * @brief The size of the internal XXH3 buffer. + * + * This is the optimal update size for incremental hashing. + * + * @see XXH3_64b_update(), XXH3_128b_update(). + */ +#define XXH3_INTERNALBUFFER_SIZE 256 + +/*! + * @internal + * @brief Default size of the secret buffer (and @ref XXH3_kSecret). + * + * This is the size used in @ref XXH3_kSecret and the seeded functions. + * + * Not to be confused with @ref XXH3_SECRET_SIZE_MIN. + */ +#define XXH3_SECRET_DEFAULT_SIZE 192 + +/*! + * @internal + * @brief Structure for XXH3 streaming API. + * + * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, + * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. + * Otherwise it is an opaque type. + * Never use this definition in combination with dynamic library. + * This allows fields to safely be changed in the future. + * + * @note ** This structure has a strict alignment requirement of 64 bytes!! ** + * Do not allocate this with `malloc()` or `new`, + * it will not be sufficiently aligned. + * Use @ref XXH3_createState() and @ref XXH3_freeState(), or stack allocation. + * + * Typedef'd to @ref XXH3_state_t. + * Do never access the members of this struct directly. + * + * @see XXH3_INITSTATE() for stack initialization. + * @see XXH3_createState(), XXH3_freeState(). + * @see XXH32_state_s, XXH64_state_s + */ +struct XXH3_state_s { + XXH_ALIGN_MEMBER(64, XXH64_hash_t acc[8]); + /*!< The 8 accumulators. See @ref XXH32_state_s::v and @ref XXH64_state_s::v */ + XXH_ALIGN_MEMBER(64, unsigned char customSecret[XXH3_SECRET_DEFAULT_SIZE]); + /*!< Used to store a custom secret generated from a seed. */ + XXH_ALIGN_MEMBER(64, unsigned char buffer[XXH3_INTERNALBUFFER_SIZE]); + /*!< The internal buffer. @see XXH32_state_s::mem32 */ + XXH32_hash_t bufferedSize; + /*!< The amount of memory in @ref buffer, @see XXH32_state_s::memsize */ + XXH32_hash_t useSeed; + /*!< Reserved field. Needed for padding on 64-bit. */ + size_t nbStripesSoFar; + /*!< Number or stripes processed. */ + XXH64_hash_t totalLen; + /*!< Total length hashed. 64-bit even on 32-bit targets. */ + size_t nbStripesPerBlock; + /*!< Number of stripes per block. */ + size_t secretLimit; + /*!< Size of @ref customSecret or @ref extSecret */ + XXH64_hash_t seed; + /*!< Seed for _withSeed variants. Must be zero otherwise, @see XXH3_INITSTATE() */ + XXH64_hash_t reserved64; + /*!< Reserved field. */ + const unsigned char* extSecret; + /*!< Reference to an external secret for the _withSecret variants, NULL + * for other variants. */ + /* note: there may be some padding at the end due to alignment on 64 bytes */ +}; /* typedef'd to XXH3_state_t */ + +#undef XXH_ALIGN_MEMBER + +/*! + * @brief Initializes a stack-allocated `XXH3_state_s`. + * + * When the @ref XXH3_state_t structure is merely emplaced on stack, + * it should be initialized with XXH3_INITSTATE() or a memset() + * in case its first reset uses XXH3_NNbits_reset_withSeed(). + * This init can be omitted if the first reset uses default or _withSecret mode. + * This operation isn't necessary when the state is created with XXH3_createState(). + * Note that this doesn't prepare the state for a streaming operation, + * it's still necessary to use XXH3_NNbits_reset*() afterwards. + */ +#define XXH3_INITSTATE(XXH3_state_ptr) \ + do { \ + XXH3_state_t* tmp_xxh3_state_ptr = (XXH3_state_ptr); \ + tmp_xxh3_state_ptr->seed = 0; \ + tmp_xxh3_state_ptr->extSecret = NULL; \ + } while(0) + + +/*! + * @brief Calculates the 128-bit hash of @p data using XXH3. + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param seed The 64-bit seed to alter the hash's output predictably. + * + * @pre + * The memory between @p data and @p data + @p len must be valid, + * readable, contiguous memory. However, if @p len is `0`, @p data may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 128-bit XXH3 value. + * + * @see @ref single_shot_example "Single Shot Example" for an example. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed); + + +/* === Experimental API === */ +/* Symbols defined below must be considered tied to a specific library version. */ + +/*! + * @brief Derive a high-entropy secret from any user-defined content, named customSeed. + * + * @param secretBuffer A writable buffer for derived high-entropy secret data. + * @param secretSize Size of secretBuffer, in bytes. Must be >= XXH3_SECRET_SIZE_MIN. + * @param customSeed A user-defined content. + * @param customSeedSize Size of customSeed, in bytes. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * The generated secret can be used in combination with `*_withSecret()` functions. + * The `_withSecret()` variants are useful to provide a higher level of protection + * than 64-bit seed, as it becomes much more difficult for an external actor to + * guess how to impact the calculation logic. + * + * The function accepts as input a custom seed of any length and any content, + * and derives from it a high-entropy secret of length @p secretSize into an + * already allocated buffer @p secretBuffer. + * + * The generated secret can then be used with any `*_withSecret()` variant. + * The functions @ref XXH3_128bits_withSecret(), @ref XXH3_64bits_withSecret(), + * @ref XXH3_128bits_reset_withSecret() and @ref XXH3_64bits_reset_withSecret() + * are part of this list. They all accept a `secret` parameter + * which must be large enough for implementation reasons (>= @ref XXH3_SECRET_SIZE_MIN) + * _and_ feature very high entropy (consist of random-looking bytes). + * These conditions can be a high bar to meet, so @ref XXH3_generateSecret() can + * be employed to ensure proper quality. + * + * @p customSeed can be anything. It can have any size, even small ones, + * and its content can be anything, even "poor entropy" sources such as a bunch + * of zeroes. The resulting `secret` will nonetheless provide all required qualities. + * + * @pre + * - @p secretSize must be >= @ref XXH3_SECRET_SIZE_MIN + * - When @p customSeedSize > 0, supplying NULL as customSeed is undefined behavior. + * + * Example code: + * @code{.c} + * #include + * #include + * #include + * #define XXH_STATIC_LINKING_ONLY // expose unstable API + * #include "xxhash.h" + * // Hashes argv[2] using the entropy from argv[1]. + * int main(int argc, char* argv[]) + * { + * char secret[XXH3_SECRET_SIZE_MIN]; + * if (argv != 3) { return 1; } + * XXH3_generateSecret(secret, sizeof(secret), argv[1], strlen(argv[1])); + * XXH64_hash_t h = XXH3_64bits_withSecret( + * argv[2], strlen(argv[2]), + * secret, sizeof(secret) + * ); + * printf("%016llx\n", (unsigned long long) h); + * } + * @endcode + */ +XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize); + +/*! + * @brief Generate the same secret as the _withSeed() variants. + * + * @param secretBuffer A writable buffer of @ref XXH3_SECRET_DEFAULT_SIZE bytes + * @param seed The 64-bit seed to alter the hash result predictably. + * + * The generated secret can be used in combination with + *`*_withSecret()` and `_withSecretandSeed()` variants. + * + * Example C++ `std::string` hash class: + * @code{.cpp} + * #include + * #define XXH_STATIC_LINKING_ONLY // expose unstable API + * #include "xxhash.h" + * // Slow, seeds each time + * class HashSlow { + * XXH64_hash_t seed; + * public: + * HashSlow(XXH64_hash_t s) : seed{s} {} + * size_t operator()(const std::string& x) const { + * return size_t{XXH3_64bits_withSeed(x.c_str(), x.length(), seed)}; + * } + * }; + * // Fast, caches the seeded secret for future uses. + * class HashFast { + * unsigned char secret[XXH3_SECRET_DEFAULT_SIZE]; + * public: + * HashFast(XXH64_hash_t s) { + * XXH3_generateSecret_fromSeed(secret, seed); + * } + * size_t operator()(const std::string& x) const { + * return size_t{ + * XXH3_64bits_withSecret(x.c_str(), x.length(), secret, sizeof(secret)) + * }; + * } + * }; + * @endcode + */ +XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed); + +/*! + * @brief Maximum size of "short" key in bytes. + */ +#define XXH3_MIDSIZE_MAX 240 + +/*! + * @brief Calculates 64/128-bit seeded variant of XXH3 hash of @p data. + * + * @param data The block of data to be hashed, at least @p len bytes in size. + * @param len The length of @p data, in bytes. + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed The 64-bit seed to alter the hash result predictably. + * + * These variants generate hash values using either: + * - @p seed for "short" keys (< @ref XXH3_MIDSIZE_MAX = 240 bytes) + * - @p secret for "large" keys (>= @ref XXH3_MIDSIZE_MAX). + * + * This generally benefits speed, compared to `_withSeed()` or `_withSecret()`. + * `_withSeed()` has to generate the secret on the fly for "large" keys. + * It's fast, but can be perceptible for "not so large" keys (< 1 KB). + * `_withSecret()` has to generate the masks on the fly for "small" keys, + * which requires more instructions than _withSeed() variants. + * Therefore, _withSecretandSeed variant combines the best of both worlds. + * + * When @p secret has been generated by XXH3_generateSecret_fromSeed(), + * this variant produces *exactly* the same results as `_withSeed()` variant, + * hence offering only a pure speed benefit on "large" input, + * by skipping the need to regenerate the secret for every large input. + * + * Another usage scenario is to hash the secret to a 64-bit hash value, + * for example with XXH3_64bits(), which then becomes the seed, + * and then employ both the seed and the secret in _withSecretandSeed(). + * On top of speed, an added benefit is that each bit in the secret + * has a 50% chance to swap each bit in the output, via its impact to the seed. + * + * This is not guaranteed when using the secret directly in "small data" scenarios, + * because only portions of the secret are employed for small data. + */ +XXH_PUBLIC_API XXH_PUREF XXH64_hash_t +XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* data, size_t len, + XXH_NOESCAPE const void* secret, size_t secretSize, + XXH64_hash_t seed); + +/*! + * @brief Calculates 128-bit seeded variant of XXH3 hash of @p data. + * + * @param data The memory segment to be hashed, at least @p len bytes in size. + * @param length The length of @p data, in bytes. + * @param secret The secret used to alter hash result predictably. + * @param secretSize The length of @p secret, in bytes (must be >= XXH3_SECRET_SIZE_MIN) + * @param seed64 The 64-bit seed to alter the hash result predictably. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @see XXH3_64bits_withSecretandSeed(): contract is the same. + */ +XXH_PUBLIC_API XXH_PUREF XXH128_hash_t +XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, + XXH_NOESCAPE const void* secret, size_t secretSize, + XXH64_hash_t seed64); + +#ifndef XXH_NO_STREAM +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed64 The 64-bit seed to alter the hash result predictably. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @see XXH3_64bits_withSecretandSeed(). Contract is identical. + */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, + XXH_NOESCAPE const void* secret, size_t secretSize, + XXH64_hash_t seed64); + +/*! + * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash. + * + * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). + * @param secret The secret data. + * @param secretSize The length of @p secret, in bytes. + * @param seed64 The 64-bit seed to alter the hash result predictably. + * + * @return @ref XXH_OK on success. + * @return @ref XXH_ERROR on failure. + * + * @see XXH3_64bits_withSecretandSeed(). Contract is identical. + * + * Note: there was a bug in an earlier version of this function (<= v0.8.2) + * that would make it generate an incorrect hash value + * when @p seed == 0 and @p length < XXH3_MIDSIZE_MAX + * and @p secret is different from XXH3_generateSecret_fromSeed(). + * As stated in the contract, the correct hash result must be + * the same as XXH3_128bits_withSeed() when @p length <= XXH3_MIDSIZE_MAX. + * Results generated by this older version are wrong, hence not comparable. + */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, + XXH_NOESCAPE const void* secret, size_t secretSize, + XXH64_hash_t seed64); + +#endif /* !XXH_NO_STREAM */ + +#endif /* !XXH_NO_XXH3 */ +#endif /* XXH_NO_LONG_LONG */ +#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) +# define XXH_IMPLEMENTATION +#endif + +#endif /* defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) */ + + +/* ======================================================================== */ +/* ======================================================================== */ +/* ======================================================================== */ + + +/*-********************************************************************** + * xxHash implementation + *-********************************************************************** + * xxHash's implementation used to be hosted inside xxhash.c. + * + * However, inlining requires implementation to be visible to the compiler, + * hence be included alongside the header. + * Previously, implementation was hosted inside xxhash.c, + * which was then #included when inlining was activated. + * This construction created issues with a few build and install systems, + * as it required xxhash.c to be stored in /include directory. + * + * xxHash implementation is now directly integrated within xxhash.h. + * As a consequence, xxhash.c is no longer needed in /include. + * + * xxhash.c is still available and is still useful. + * In a "normal" setup, when xxhash is not inlined, + * xxhash.h only exposes the prototypes and public symbols, + * while xxhash.c can be built into an object file xxhash.o + * which can then be linked into the final binary. + ************************************************************************/ + +#if ( defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) \ + || defined(XXH_IMPLEMENTATION) ) && !defined(XXH_IMPLEM_13a8737387) +# define XXH_IMPLEM_13a8737387 + +/* ************************************* +* Tuning parameters +***************************************/ + +/*! + * @defgroup tuning Tuning parameters + * @{ + * + * Various macros to control xxHash's behavior. + */ +#ifdef XXH_DOXYGEN +/*! + * @brief Define this to disable 64-bit code. + * + * Useful if only using the @ref XXH32_family and you have a strict C90 compiler. + */ +# define XXH_NO_LONG_LONG +# undef XXH_NO_LONG_LONG /* don't actually */ +/*! + * @brief Controls how unaligned memory is accessed. + * + * By default, access to unaligned memory is controlled by `memcpy()`, which is + * safe and portable. + * + * Unfortunately, on some target/compiler combinations, the generated assembly + * is sub-optimal. + * + * The below switch allow selection of a different access method + * in the search for improved performance. + * + * @par Possible options: + * + * - `XXH_FORCE_MEMORY_ACCESS=0` (default): `memcpy` + * @par + * Use `memcpy()`. Safe and portable. Note that most modern compilers will + * eliminate the function call and treat it as an unaligned access. + * + * - `XXH_FORCE_MEMORY_ACCESS=1`: `__attribute__((aligned(1)))` + * @par + * Depends on compiler extensions and is therefore not portable. + * This method is safe _if_ your compiler supports it, + * and *generally* as fast or faster than `memcpy`. + * + * - `XXH_FORCE_MEMORY_ACCESS=2`: Direct cast + * @par + * Casts directly and dereferences. This method doesn't depend on the + * compiler, but it violates the C standard as it directly dereferences an + * unaligned pointer. It can generate buggy code on targets which do not + * support unaligned memory accesses, but in some circumstances, it's the + * only known way to get the most performance. + * + * - `XXH_FORCE_MEMORY_ACCESS=3`: Byteshift + * @par + * Also portable. This can generate the best code on old compilers which don't + * inline small `memcpy()` calls, and it might also be faster on big-endian + * systems which lack a native byteswap instruction. However, some compilers + * will emit literal byteshifts even if the target supports unaligned access. + * + * + * @warning + * Methods 1 and 2 rely on implementation-defined behavior. Use these with + * care, as what works on one compiler/platform/optimization level may cause + * another to read garbage data or even crash. + * + * See https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html for details. + * + * Prefer these methods in priority order (0 > 3 > 1 > 2) + */ +# define XXH_FORCE_MEMORY_ACCESS 0 + +/*! + * @def XXH_SIZE_OPT + * @brief Controls how much xxHash optimizes for size. + * + * xxHash, when compiled, tends to result in a rather large binary size. This + * is mostly due to heavy usage to forced inlining and constant folding of the + * @ref XXH3_family to increase performance. + * + * However, some developers prefer size over speed. This option can + * significantly reduce the size of the generated code. When using the `-Os` + * or `-Oz` options on GCC or Clang, this is defined to 1 by default, + * otherwise it is defined to 0. + * + * Most of these size optimizations can be controlled manually. + * + * This is a number from 0-2. + * - `XXH_SIZE_OPT` == 0: Default. xxHash makes no size optimizations. Speed + * comes first. + * - `XXH_SIZE_OPT` == 1: Default for `-Os` and `-Oz`. xxHash is more + * conservative and disables hacks that increase code size. It implies the + * options @ref XXH_NO_INLINE_HINTS == 1, @ref XXH_FORCE_ALIGN_CHECK == 0, + * and @ref XXH3_NEON_LANES == 8 if they are not already defined. + * - `XXH_SIZE_OPT` == 2: xxHash tries to make itself as small as possible. + * Performance may cry. For example, the single shot functions just use the + * streaming API. + */ +# define XXH_SIZE_OPT 0 + +/*! + * @def XXH_FORCE_ALIGN_CHECK + * @brief If defined to non-zero, adds a special path for aligned inputs (XXH32() + * and XXH64() only). + * + * This is an important performance trick for architectures without decent + * unaligned memory access performance. + * + * It checks for input alignment, and when conditions are met, uses a "fast + * path" employing direct 32-bit/64-bit reads, resulting in _dramatically + * faster_ read speed. + * + * The check costs one initial branch per hash, which is generally negligible, + * but not zero. + * + * Moreover, it's not useful to generate an additional code path if memory + * access uses the same instruction for both aligned and unaligned + * addresses (e.g. x86 and aarch64). + * + * In these cases, the alignment check can be removed by setting this macro to 0. + * Then the code will always use unaligned memory access. + * Align check is automatically disabled on x86, x64, ARM64, and some ARM chips + * which are platforms known to offer good unaligned memory accesses performance. + * + * It is also disabled by default when @ref XXH_SIZE_OPT >= 1. + * + * This option does not affect XXH3 (only XXH32 and XXH64). + */ +# define XXH_FORCE_ALIGN_CHECK 0 + +/*! + * @def XXH_NO_INLINE_HINTS + * @brief When non-zero, sets all functions to `static`. + * + * By default, xxHash tries to force the compiler to inline almost all internal + * functions. + * + * This can usually improve performance due to reduced jumping and improved + * constant folding, but significantly increases the size of the binary which + * might not be favorable. + * + * Additionally, sometimes the forced inlining can be detrimental to performance, + * depending on the architecture. + * + * XXH_NO_INLINE_HINTS marks all internal functions as static, giving the + * compiler full control on whether to inline or not. + * + * When not optimizing (-O0), using `-fno-inline` with GCC or Clang, or if + * @ref XXH_SIZE_OPT >= 1, this will automatically be defined. + */ +# define XXH_NO_INLINE_HINTS 0 + +/*! + * @def XXH3_INLINE_SECRET + * @brief Determines whether to inline the XXH3 withSecret code. + * + * When the secret size is known, the compiler can improve the performance + * of XXH3_64bits_withSecret() and XXH3_128bits_withSecret(). + * + * However, if the secret size is not known, it doesn't have any benefit. This + * happens when xxHash is compiled into a global symbol. Therefore, if + * @ref XXH_INLINE_ALL is *not* defined, this will be defined to 0. + * + * Additionally, this defaults to 0 on GCC 12+, which has an issue with function pointers + * that are *sometimes* force inline on -Og, and it is impossible to automatically + * detect this optimization level. + */ +# define XXH3_INLINE_SECRET 0 + +/*! + * @def XXH32_ENDJMP + * @brief Whether to use a jump for `XXH32_finalize`. + * + * For performance, `XXH32_finalize` uses multiple branches in the finalizer. + * This is generally preferable for performance, + * but depending on exact architecture, a jmp may be preferable. + * + * This setting is only possibly making a difference for very small inputs. + */ +# define XXH32_ENDJMP 0 + +/*! + * @internal + * @brief Redefines old internal names. + * + * For compatibility with code that uses xxHash's internals before the names + * were changed to improve namespacing. There is no other reason to use this. + */ +# define XXH_OLD_NAMES +# undef XXH_OLD_NAMES /* don't actually use, it is ugly. */ + +/*! + * @def XXH_NO_STREAM + * @brief Disables the streaming API. + * + * When xxHash is not inlined and the streaming functions are not used, disabling + * the streaming functions can improve code size significantly, especially with + * the @ref XXH3_family which tends to make constant folded copies of itself. + */ +# define XXH_NO_STREAM +# undef XXH_NO_STREAM /* don't actually */ +#endif /* XXH_DOXYGEN */ +/*! + * @} + */ + +#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ + /* prefer __packed__ structures (method 1) for GCC + * < ARMv7 with unaligned access (e.g. Raspbian armhf) still uses byte shifting, so we use memcpy + * which for some reason does unaligned loads. */ +# if defined(__GNUC__) && !(defined(__ARM_ARCH) && __ARM_ARCH < 7 && defined(__ARM_FEATURE_UNALIGNED)) +# define XXH_FORCE_MEMORY_ACCESS 1 +# endif +#endif + +#ifndef XXH_SIZE_OPT + /* default to 1 for -Os or -Oz */ +# if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE_SIZE__) +# define XXH_SIZE_OPT 1 +# else +# define XXH_SIZE_OPT 0 +# endif +#endif + +#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ + /* don't check on sizeopt, x86, aarch64, or arm when unaligned access is available */ +# if XXH_SIZE_OPT >= 1 || \ + defined(__i386) || defined(__x86_64__) || defined(__aarch64__) || defined(__ARM_FEATURE_UNALIGNED) \ + || defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) || defined(_M_ARM) /* visual */ +# define XXH_FORCE_ALIGN_CHECK 0 +# else +# define XXH_FORCE_ALIGN_CHECK 1 +# endif +#endif + +#ifndef XXH_NO_INLINE_HINTS +# if XXH_SIZE_OPT >= 1 || defined(__NO_INLINE__) /* -O0, -fno-inline */ +# define XXH_NO_INLINE_HINTS 1 +# else +# define XXH_NO_INLINE_HINTS 0 +# endif +#endif + +#ifndef XXH3_INLINE_SECRET +# if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12) \ + || !defined(XXH_INLINE_ALL) +# define XXH3_INLINE_SECRET 0 +# else +# define XXH3_INLINE_SECRET 1 +# endif +#endif + +#ifndef XXH32_ENDJMP +/* generally preferable for performance */ +# define XXH32_ENDJMP 0 +#endif + +/*! + * @defgroup impl Implementation + * @{ + */ + + +/* ************************************* +* Includes & Memory related functions +***************************************/ +#if defined(XXH_NO_STREAM) +/* nothing */ +#elif defined(XXH_NO_STDLIB) + +/* When requesting to disable any mention of stdlib, + * the library loses the ability to invoked malloc / free. + * In practice, it means that functions like `XXH*_createState()` + * will always fail, and return NULL. + * This flag is useful in situations where + * xxhash.h is integrated into some kernel, embedded or limited environment + * without access to dynamic allocation. + */ + +static XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; } +static void XXH_free(void* p) { (void)p; } + +#else + +/* + * Modify the local functions below should you wish to use + * different memory routines for malloc() and free() + */ +#include + +/*! + * @internal + * @brief Modify this function to use a different routine than malloc(). + */ +static XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); } + +/*! + * @internal + * @brief Modify this function to use a different routine than free(). + */ +static void XXH_free(void* p) { free(p); } + +#endif /* XXH_NO_STDLIB */ + +#include + +/*! + * @internal + * @brief Modify this function to use a different routine than memcpy(). + */ +static void* XXH_memcpy(void* dest, const void* src, size_t size) +{ + return memcpy(dest,src,size); +} + +#include /* ULLONG_MAX */ + + +/* ************************************* +* Compiler Specific Options +***************************************/ +#ifdef _MSC_VER /* Visual Studio warning fix */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +#endif + +#if XXH_NO_INLINE_HINTS /* disable inlining hints */ +# if defined(__GNUC__) || defined(__clang__) +# define XXH_FORCE_INLINE static __attribute__((__unused__)) +# else +# define XXH_FORCE_INLINE static +# endif +# define XXH_NO_INLINE static +/* enable inlining hints */ +#elif defined(__GNUC__) || defined(__clang__) +# define XXH_FORCE_INLINE static __inline__ __attribute__((__always_inline__, __unused__)) +# define XXH_NO_INLINE static __attribute__((__noinline__)) +#elif defined(_MSC_VER) /* Visual Studio */ +# define XXH_FORCE_INLINE static __forceinline +# define XXH_NO_INLINE static __declspec(noinline) +#elif defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* C99 */ +# define XXH_FORCE_INLINE static inline +# define XXH_NO_INLINE static +#else +# define XXH_FORCE_INLINE static +# define XXH_NO_INLINE static +#endif + +#if defined(XXH_INLINE_ALL) +# define XXH_STATIC XXH_FORCE_INLINE +#else +# define XXH_STATIC static +#endif + +#if XXH3_INLINE_SECRET +# define XXH3_WITH_SECRET_INLINE XXH_FORCE_INLINE +#else +# define XXH3_WITH_SECRET_INLINE XXH_NO_INLINE +#endif + +#if ((defined(sun) || defined(__sun)) && __cplusplus) /* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */ +# define XXH_RESTRICT /* disable */ +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* >= C99 */ +# define XXH_RESTRICT restrict +#elif (defined (__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \ + || (defined (__clang__)) \ + || (defined (_MSC_VER) && (_MSC_VER >= 1400)) \ + || (defined (__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300)) +/* + * There are a LOT more compilers that recognize __restrict but this + * covers the major ones. + */ +# define XXH_RESTRICT __restrict +#else +# define XXH_RESTRICT /* disable */ +#endif + +/* ************************************* +* Debug +***************************************/ +/*! + * @ingroup tuning + * @def XXH_DEBUGLEVEL + * @brief Sets the debugging level. + * + * XXH_DEBUGLEVEL is expected to be defined externally, typically via the + * compiler's command line options. The value must be a number. + */ +#ifndef XXH_DEBUGLEVEL +# ifdef DEBUGLEVEL /* backwards compat */ +# define XXH_DEBUGLEVEL DEBUGLEVEL +# else +# define XXH_DEBUGLEVEL 0 +# endif +#endif + +#if (XXH_DEBUGLEVEL>=1) +# include /* note: can still be disabled with NDEBUG */ +# define XXH_ASSERT(c) assert(c) +#else +# if defined(__INTEL_COMPILER) +# define XXH_ASSERT(c) XXH_ASSUME((unsigned char) (c)) +# else +# define XXH_ASSERT(c) XXH_ASSUME(c) +# endif +#endif + +/* note: use after variable declarations */ +#ifndef XXH_STATIC_ASSERT +# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ +# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { _Static_assert((c),m); } while(0) +# elif defined(__cplusplus) && (__cplusplus >= 201103L) /* C++11 */ +# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { static_assert((c),m); } while(0) +# else +# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { struct xxh_sa { char x[(c) ? 1 : -1]; }; } while(0) +# endif +# define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE((c),#c) +#endif + +/*! + * @internal + * @def XXH_COMPILER_GUARD(var) + * @brief Used to prevent unwanted optimizations for @p var. + * + * It uses an empty GCC inline assembly statement with a register constraint + * which forces @p var into a general purpose register (eg eax, ebx, ecx + * on x86) and marks it as modified. + * + * This is used in a few places to avoid unwanted autovectorization (e.g. + * XXH32_round()). All vectorization we want is explicit via intrinsics, + * and _usually_ isn't wanted elsewhere. + * + * We also use it to prevent unwanted constant folding for AArch64 in + * XXH3_initCustomSecret_scalar(). + */ +#if defined(__GNUC__) || defined(__clang__) +# define XXH_COMPILER_GUARD(var) __asm__("" : "+r" (var)) +#else +# define XXH_COMPILER_GUARD(var) ((void)0) +#endif + +/* Specifically for NEON vectors which use the "w" constraint, on + * Clang. */ +#if defined(__clang__) && defined(__ARM_ARCH) && !defined(__wasm__) +# define XXH_COMPILER_GUARD_CLANG_NEON(var) __asm__("" : "+w" (var)) +#else +# define XXH_COMPILER_GUARD_CLANG_NEON(var) ((void)0) +#endif + +/* ************************************* +* Basic Types +***************************************/ +#if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# ifdef _AIX +# include +# else +# include +# endif + typedef uint8_t xxh_u8; +#else + typedef unsigned char xxh_u8; +#endif +typedef XXH32_hash_t xxh_u32; + +#ifdef XXH_OLD_NAMES +# warning "XXH_OLD_NAMES is planned to be removed starting v0.9. If the program depends on it, consider moving away from it by employing newer type names directly" +# define BYTE xxh_u8 +# define U8 xxh_u8 +# define U32 xxh_u32 +#endif + +/* *** Memory access *** */ + +/*! + * @internal + * @fn xxh_u32 XXH_read32(const void* ptr) + * @brief Reads an unaligned 32-bit integer from @p ptr in native endianness. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * + * @param ptr The pointer to read from. + * @return The 32-bit native endian integer from the bytes at @p ptr. + */ + +/*! + * @internal + * @fn xxh_u32 XXH_readLE32(const void* ptr) + * @brief Reads an unaligned 32-bit little endian integer from @p ptr. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * + * @param ptr The pointer to read from. + * @return The 32-bit little endian integer from the bytes at @p ptr. + */ + +/*! + * @internal + * @fn xxh_u32 XXH_readBE32(const void* ptr) + * @brief Reads an unaligned 32-bit big endian integer from @p ptr. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * + * @param ptr The pointer to read from. + * @return The 32-bit big endian integer from the bytes at @p ptr. + */ + +/*! + * @internal + * @fn xxh_u32 XXH_readLE32_align(const void* ptr, XXH_alignment align) + * @brief Like @ref XXH_readLE32(), but has an option for aligned reads. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * Note that when @ref XXH_FORCE_ALIGN_CHECK == 0, the @p align parameter is + * always @ref XXH_alignment::XXH_unaligned. + * + * @param ptr The pointer to read from. + * @param align Whether @p ptr is aligned. + * @pre + * If @p align == @ref XXH_alignment::XXH_aligned, @p ptr must be 4 byte + * aligned. + * @return The 32-bit little endian integer from the bytes at @p ptr. + */ + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) +/* + * Manual byteshift. Best for old compilers which don't inline memcpy. + * We actually directly use XXH_readLE32 and XXH_readBE32. + */ +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* + * Force direct memory access. Only works on CPU which support unaligned memory + * access in hardware. + */ +static xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; } + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* + * __attribute__((aligned(1))) is supported by gcc and clang. Originally the + * documentation claimed that it only increased the alignment, but actually it + * can decrease it on gcc, clang, and icc: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, + * https://gcc.godbolt.org/z/xYez1j67Y. + */ +#ifdef XXH_OLD_NAMES +typedef union { xxh_u32 u32; } __attribute__((__packed__)) unalign; +#endif +static xxh_u32 XXH_read32(const void* ptr) +{ + typedef __attribute__((__aligned__(1))) xxh_u32 xxh_unalign32; + return *((const xxh_unalign32*)ptr); +} + +#else + +/* + * Portable and safe solution. Generally efficient. + * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html + */ +static xxh_u32 XXH_read32(const void* memPtr) +{ + xxh_u32 val; + XXH_memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + + +/* *** Endianness *** */ + +/*! + * @ingroup tuning + * @def XXH_CPU_LITTLE_ENDIAN + * @brief Whether the target is little endian. + * + * Defined to 1 if the target is little endian, or 0 if it is big endian. + * It can be defined externally, for example on the compiler command line. + * + * If it is not defined, + * a runtime check (which is usually constant folded) is used instead. + * + * @note + * This is not necessarily defined to an integer constant. + * + * @see XXH_isLittleEndian() for the runtime check. + */ +#ifndef XXH_CPU_LITTLE_ENDIAN +/* + * Try to detect endianness automatically, to avoid the nonstandard behavior + * in `XXH_isLittleEndian()` + */ +# if defined(_WIN32) /* Windows is always little endian */ \ + || defined(__LITTLE_ENDIAN__) \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +# define XXH_CPU_LITTLE_ENDIAN 1 +# elif defined(__BIG_ENDIAN__) \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +# define XXH_CPU_LITTLE_ENDIAN 0 +# else +/*! + * @internal + * @brief Runtime check for @ref XXH_CPU_LITTLE_ENDIAN. + * + * Most compilers will constant fold this. + */ +static int XXH_isLittleEndian(void) +{ + /* + * Portable and well-defined behavior. + * Don't use static: it is detrimental to performance. + */ + const union { xxh_u32 u; xxh_u8 c[4]; } one = { 1 }; + return one.c[0]; +} +# define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian() +# endif +#endif + + + + +/* **************************************** +* Compiler-specific Functions and Macros +******************************************/ +#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +#ifdef __has_builtin +# define XXH_HAS_BUILTIN(x) __has_builtin(x) +#else +# define XXH_HAS_BUILTIN(x) 0 +#endif + + + +/* + * C23 and future versions have standard "unreachable()". + * Once it has been implemented reliably we can add it as an + * additional case: + * + * ``` + * #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) + * # include + * # ifdef unreachable + * # define XXH_UNREACHABLE() unreachable() + * # endif + * #endif + * ``` + * + * Note C++23 also has std::unreachable() which can be detected + * as follows: + * ``` + * #if defined(__cpp_lib_unreachable) && (__cpp_lib_unreachable >= 202202L) + * # include + * # define XXH_UNREACHABLE() std::unreachable() + * #endif + * ``` + * NB: `__cpp_lib_unreachable` is defined in the `` header. + * We don't use that as including `` in `extern "C"` blocks + * doesn't work on GCC12 + */ + +#if XXH_HAS_BUILTIN(__builtin_unreachable) +# define XXH_UNREACHABLE() __builtin_unreachable() + +#elif defined(_MSC_VER) +# define XXH_UNREACHABLE() __assume(0) + +#else +# define XXH_UNREACHABLE() +#endif + +#if XXH_HAS_BUILTIN(__builtin_assume) +# define XXH_ASSUME(c) __builtin_assume(c) +#else +# define XXH_ASSUME(c) if (!(c)) { XXH_UNREACHABLE(); } +#endif + +/*! + * @internal + * @def XXH_rotl32(x,r) + * @brief 32-bit rotate left. + * + * @param x The 32-bit integer to be rotated. + * @param r The number of bits to rotate. + * @pre + * @p r > 0 && @p r < 32 + * @note + * @p x and @p r may be evaluated multiple times. + * @return The rotated result. + */ +#if !defined(NO_CLANG_BUILTIN) && XXH_HAS_BUILTIN(__builtin_rotateleft32) \ + && XXH_HAS_BUILTIN(__builtin_rotateleft64) +# define XXH_rotl32 __builtin_rotateleft32 +# define XXH_rotl64 __builtin_rotateleft64 +#elif XXH_HAS_BUILTIN(__builtin_stdc_rotate_left) +# define XXH_rotl32 __builtin_stdc_rotate_left +# define XXH_rotl64 __builtin_stdc_rotate_left +/* Note: although _rotl exists for minGW (GCC under windows), performance seems poor */ +#elif defined(_MSC_VER) +# define XXH_rotl32(x,r) _rotl(x,r) +# define XXH_rotl64(x,r) _rotl64(x,r) +#else +# define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) +# define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r)))) +#endif + +/*! + * @internal + * @fn xxh_u32 XXH_swap32(xxh_u32 x) + * @brief A 32-bit byteswap. + * + * @param x The 32-bit integer to byteswap. + * @return @p x, byteswapped. + */ +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap32 _byteswap_ulong +#elif XXH_GCC_VERSION >= 403 +# define XXH_swap32 __builtin_bswap32 +#else +static xxh_u32 XXH_swap32 (xxh_u32 x) +{ + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff ); +} +#endif + + +/* *************************** +* Memory reads +*****************************/ + +/*! + * @internal + * @brief Enum to indicate whether a pointer is aligned. + */ +typedef enum { + XXH_aligned, /*!< Aligned */ + XXH_unaligned /*!< Possibly unaligned */ +} XXH_alignment; + +/* + * XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. + * + * This is ideal for older compilers which don't inline memcpy. + */ +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) + +XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[0] + | ((xxh_u32)bytePtr[1] << 8) + | ((xxh_u32)bytePtr[2] << 16) + | ((xxh_u32)bytePtr[3] << 24); +} + +XXH_FORCE_INLINE xxh_u32 XXH_readBE32(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[3] + | ((xxh_u32)bytePtr[2] << 8) + | ((xxh_u32)bytePtr[1] << 16) + | ((xxh_u32)bytePtr[0] << 24); +} + +#else +XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); +} + +static xxh_u32 XXH_readBE32(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); +} +#endif + +XXH_FORCE_INLINE xxh_u32 +XXH_readLE32_align(const void* ptr, XXH_alignment align) +{ + if (align==XXH_unaligned) { + return XXH_readLE32(ptr); + } else { + return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u32*)ptr : XXH_swap32(*(const xxh_u32*)ptr); + } +} + + +/* ************************************* +* Misc +***************************************/ +/*! @ingroup public */ +XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } + + +/* ******************************************************************* +* 32-bit hash functions +*********************************************************************/ +/*! + * @} + * @defgroup XXH32_impl XXH32 implementation + * @ingroup impl + * + * Details on the XXH32 implementation. + * @{ + */ + /* #define instead of static const, to be used as initializers */ +#define XXH_PRIME32_1 0x9E3779B1U /*!< 0b10011110001101110111100110110001 */ +#define XXH_PRIME32_2 0x85EBCA77U /*!< 0b10000101111010111100101001110111 */ +#define XXH_PRIME32_3 0xC2B2AE3DU /*!< 0b11000010101100101010111000111101 */ +#define XXH_PRIME32_4 0x27D4EB2FU /*!< 0b00100111110101001110101100101111 */ +#define XXH_PRIME32_5 0x165667B1U /*!< 0b00010110010101100110011110110001 */ + +#ifdef XXH_OLD_NAMES +# define PRIME32_1 XXH_PRIME32_1 +# define PRIME32_2 XXH_PRIME32_2 +# define PRIME32_3 XXH_PRIME32_3 +# define PRIME32_4 XXH_PRIME32_4 +# define PRIME32_5 XXH_PRIME32_5 +#endif + +/*! + * @internal + * @brief Normal stripe processing routine. + * + * This shuffles the bits so that any bit from @p input impacts several bits in + * @p acc. + * + * @param acc The accumulator lane. + * @param input The stripe of input to mix. + * @return The mixed accumulator lane. + */ +static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input) +{ + acc += input * XXH_PRIME32_2; + acc = XXH_rotl32(acc, 13); + acc *= XXH_PRIME32_1; +#if (defined(__SSE4_1__) || defined(__aarch64__) || defined(__wasm_simd128__)) && !defined(XXH_ENABLE_AUTOVECTORIZE) + /* + * UGLY HACK: + * A compiler fence is used to prevent GCC and Clang from + * autovectorizing the XXH32 loop (pragmas and attributes don't work for some + * reason) without globally disabling SSE4.1. + * + * The reason we want to avoid vectorization is because despite working on + * 4 integers at a time, there are multiple factors slowing XXH32 down on + * SSE4: + * - There's a ridiculous amount of lag from pmulld (10 cycles of latency on + * newer chips!) making it slightly slower to multiply four integers at + * once compared to four integers independently. Even when pmulld was + * fastest, Sandy/Ivy Bridge, it is still not worth it to go into SSE + * just to multiply unless doing a long operation. + * + * - Four instructions are required to rotate, + * movqda tmp, v // not required with VEX encoding + * pslld tmp, 13 // tmp <<= 13 + * psrld v, 19 // x >>= 19 + * por v, tmp // x |= tmp + * compared to one for scalar: + * roll v, 13 // reliably fast across the board + * shldl v, v, 13 // Sandy Bridge and later prefer this for some reason + * + * - Instruction level parallelism is actually more beneficial here because + * the SIMD actually serializes this operation: While v1 is rotating, v2 + * can load data, while v3 can multiply. SSE forces them to operate + * together. + * + * This is also enabled on AArch64, as Clang is *very aggressive* in vectorizing + * the loop. NEON is only faster on the A53, and with the newer cores, it is less + * than half the speed. + * + * Additionally, this is used on WASM SIMD128 because it JITs to the same + * SIMD instructions and has the same issue. + */ + XXH_COMPILER_GUARD(acc); +#endif + return acc; +} + +/*! + * @internal + * @brief Mixes all bits to finalize the hash. + * + * The final mix ensures that all input bits have a chance to impact any bit in + * the output digest, resulting in an unbiased distribution. + * + * @param hash The hash to avalanche. + * @return The avalanched hash. + */ +static xxh_u32 XXH32_avalanche(xxh_u32 hash) +{ + hash ^= hash >> 15; + hash *= XXH_PRIME32_2; + hash ^= hash >> 13; + hash *= XXH_PRIME32_3; + hash ^= hash >> 16; + return hash; +} + +#define XXH_get32bits(p) XXH_readLE32_align(p, align) + +/*! + * @internal + * @brief Sets up the initial accumulator state for XXH32(). + */ +XXH_FORCE_INLINE void +XXH32_initAccs(xxh_u32 *acc, xxh_u32 seed) +{ + XXH_ASSERT(acc != NULL); + acc[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2; + acc[1] = seed + XXH_PRIME32_2; + acc[2] = seed + 0; + acc[3] = seed - XXH_PRIME32_1; +} + +/*! + * @internal + * @brief Consumes a block of data for XXH32(). + * + * @return the end input pointer. + */ +XXH_FORCE_INLINE const xxh_u8 * +XXH32_consumeLong( + xxh_u32 *XXH_RESTRICT acc, + xxh_u8 const *XXH_RESTRICT input, + size_t len, + XXH_alignment align +) +{ + const xxh_u8* const bEnd = input + len; + const xxh_u8* const limit = bEnd - 15; + XXH_ASSERT(acc != NULL); + XXH_ASSERT(input != NULL); + XXH_ASSERT(len >= 16); + do { + acc[0] = XXH32_round(acc[0], XXH_get32bits(input)); input += 4; + acc[1] = XXH32_round(acc[1], XXH_get32bits(input)); input += 4; + acc[2] = XXH32_round(acc[2], XXH_get32bits(input)); input += 4; + acc[3] = XXH32_round(acc[3], XXH_get32bits(input)); input += 4; + } while (input < limit); + + return input; +} + +/*! + * @internal + * @brief Merges the accumulator lanes together for XXH32() + */ +XXH_FORCE_INLINE XXH_PUREF xxh_u32 +XXH32_mergeAccs(const xxh_u32 *acc) +{ + XXH_ASSERT(acc != NULL); + return XXH_rotl32(acc[0], 1) + XXH_rotl32(acc[1], 7) + + XXH_rotl32(acc[2], 12) + XXH_rotl32(acc[3], 18); +} + +/*! + * @internal + * @brief Processes the last 0-15 bytes of @p ptr. + * + * There may be up to 15 bytes remaining to consume from the input. + * This final stage will digest them to ensure that all input bytes are present + * in the final mix. + * + * @param hash The hash to finalize. + * @param ptr The pointer to the remaining input. + * @param len The remaining length, modulo 16. + * @param align Whether @p ptr is aligned. + * @return The finalized hash. + * @see XXH64_finalize(). + */ +static XXH_PUREF xxh_u32 +XXH32_finalize(xxh_u32 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) +{ +#define XXH_PROCESS1 do { \ + hash += (*ptr++) * XXH_PRIME32_5; \ + hash = XXH_rotl32(hash, 11) * XXH_PRIME32_1; \ +} while (0) + +#define XXH_PROCESS4 do { \ + hash += XXH_get32bits(ptr) * XXH_PRIME32_3; \ + ptr += 4; \ + hash = XXH_rotl32(hash, 17) * XXH_PRIME32_4; \ +} while (0) + + if (ptr==NULL) XXH_ASSERT(len == 0); + + /* Compact rerolled version; generally faster */ + if (!XXH32_ENDJMP) { + len &= 15; + while (len >= 4) { + XXH_PROCESS4; + len -= 4; + } + while (len > 0) { + XXH_PROCESS1; + --len; + } + return XXH32_avalanche(hash); + } else { + switch(len&15) /* or switch(bEnd - p) */ { + case 12: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 8: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 4: XXH_PROCESS4; + return XXH32_avalanche(hash); + + case 13: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 9: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 5: XXH_PROCESS4; + XXH_PROCESS1; + return XXH32_avalanche(hash); + + case 14: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 10: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 6: XXH_PROCESS4; + XXH_PROCESS1; + XXH_PROCESS1; + return XXH32_avalanche(hash); + + case 15: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 11: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 7: XXH_PROCESS4; + XXH_FALLTHROUGH; /* fallthrough */ + case 3: XXH_PROCESS1; + XXH_FALLTHROUGH; /* fallthrough */ + case 2: XXH_PROCESS1; + XXH_FALLTHROUGH; /* fallthrough */ + case 1: XXH_PROCESS1; + XXH_FALLTHROUGH; /* fallthrough */ + case 0: return XXH32_avalanche(hash); + } + XXH_ASSERT(0); + return hash; /* reaching this point is deemed impossible */ + } +} + +#ifdef XXH_OLD_NAMES +# define PROCESS1 XXH_PROCESS1 +# define PROCESS4 XXH_PROCESS4 +#else +# undef XXH_PROCESS1 +# undef XXH_PROCESS4 +#endif + +/*! + * @internal + * @brief The implementation for @ref XXH32(). + * + * @param input , len , seed Directly passed from @ref XXH32(). + * @param align Whether @p input is aligned. + * @return The calculated hash. + */ +XXH_FORCE_INLINE XXH_PUREF xxh_u32 +XXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment align) +{ + xxh_u32 h32; + + if (input==NULL) XXH_ASSERT(len == 0); + + if (len>=16) { + xxh_u32 acc[4]; + XXH32_initAccs(acc, seed); + + input = XXH32_consumeLong(acc, input, len, align); + + h32 = XXH32_mergeAccs(acc); + } else { + h32 = seed + XXH_PRIME32_5; + } + + h32 += (xxh_u32)len; + + return XXH32_finalize(h32, input, len&15, align); +} + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t seed) +{ +#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH32_state_t state; + XXH32_reset(&state, seed); + XXH32_update(&state, (const xxh_u8*)input, len); + return XXH32_digest(&state); +#else + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ + return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); + } } + + return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); +#endif +} + + + +/******* Hash streaming *******/ +#ifndef XXH_NO_STREAM +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) +{ + return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); +} +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) +{ + XXH_memcpy(dstState, srcState, sizeof(*dstState)); +} + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t seed) +{ + XXH_ASSERT(statePtr != NULL); + memset(statePtr, 0, sizeof(*statePtr)); + XXH32_initAccs(statePtr->acc, seed); + return XXH_OK; +} + + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH_errorcode +XXH32_update(XXH32_state_t* state, const void* input, size_t len) +{ + if (input==NULL) { + XXH_ASSERT(len == 0); + return XXH_OK; + } + + state->total_len_32 += (XXH32_hash_t)len; + state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16)); + + XXH_ASSERT(state->bufferedSize < sizeof(state->buffer)); + if (len < sizeof(state->buffer) - state->bufferedSize) { /* fill in tmp buffer */ + XXH_memcpy(state->buffer + state->bufferedSize, input, len); + state->bufferedSize += (XXH32_hash_t)len; + return XXH_OK; + } + + { const xxh_u8* xinput = (const xxh_u8*)input; + const xxh_u8* const bEnd = xinput + len; + + if (state->bufferedSize) { /* non-empty buffer: complete first */ + XXH_memcpy(state->buffer + state->bufferedSize, xinput, sizeof(state->buffer) - state->bufferedSize); + xinput += sizeof(state->buffer) - state->bufferedSize; + /* then process one round */ + (void)XXH32_consumeLong(state->acc, state->buffer, sizeof(state->buffer), XXH_aligned); + state->bufferedSize = 0; + } + + XXH_ASSERT(xinput <= bEnd); + if ((size_t)(bEnd - xinput) >= sizeof(state->buffer)) { + /* Process the remaining data */ + xinput = XXH32_consumeLong(state->acc, xinput, (size_t)(bEnd - xinput), XXH_unaligned); + } + + if (xinput < bEnd) { + /* Copy the leftover to the tmp buffer */ + XXH_memcpy(state->buffer, xinput, (size_t)(bEnd-xinput)); + state->bufferedSize = (unsigned)(bEnd-xinput); + } + } + + return XXH_OK; +} + + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state) +{ + xxh_u32 h32; + + if (state->large_len) { + h32 = XXH32_mergeAccs(state->acc); + } else { + h32 = state->acc[2] /* == seed */ + XXH_PRIME32_5; + } + + h32 += state->total_len_32; + + return XXH32_finalize(h32, state->buffer, state->bufferedSize, XXH_aligned); +} +#endif /* !XXH_NO_STREAM */ + +/******* Canonical representation *******/ + +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); + XXH_memcpy(dst, &hash, sizeof(*dst)); +} +/*! @ingroup XXH32_family */ +XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) +{ + return XXH_readBE32(src); +} + + +#ifndef XXH_NO_LONG_LONG + +/* ******************************************************************* +* 64-bit hash functions +*********************************************************************/ +/*! + * @} + * @ingroup impl + * @{ + */ +/******* Memory access *******/ + +typedef XXH64_hash_t xxh_u64; + +#ifdef XXH_OLD_NAMES +# define U64 xxh_u64 +#endif + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) +/* + * Manual byteshift. Best for old compilers which don't inline memcpy. + * We actually directly use XXH_readLE64 and XXH_readBE64. + */ +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ +static xxh_u64 XXH_read64(const void* memPtr) +{ + return *(const xxh_u64*) memPtr; +} + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* + * __attribute__((aligned(1))) is supported by gcc and clang. Originally the + * documentation claimed that it only increased the alignment, but actually it + * can decrease it on gcc, clang, and icc: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502, + * https://gcc.godbolt.org/z/xYez1j67Y. + */ +#ifdef XXH_OLD_NAMES +typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((__packed__)) unalign64; +#endif +static xxh_u64 XXH_read64(const void* ptr) +{ + typedef __attribute__((__aligned__(1))) xxh_u64 xxh_unalign64; + return *((const xxh_unalign64*)ptr); +} + +#else + +/* + * Portable and safe solution. Generally efficient. + * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html + */ +static xxh_u64 XXH_read64(const void* memPtr) +{ + xxh_u64 val; + XXH_memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap64 _byteswap_uint64 +#elif XXH_GCC_VERSION >= 403 +# define XXH_swap64 __builtin_bswap64 +#else +static xxh_u64 XXH_swap64(xxh_u64 x) +{ + return ((x << 56) & 0xff00000000000000ULL) | + ((x << 40) & 0x00ff000000000000ULL) | + ((x << 24) & 0x0000ff0000000000ULL) | + ((x << 8) & 0x000000ff00000000ULL) | + ((x >> 8) & 0x00000000ff000000ULL) | + ((x >> 24) & 0x0000000000ff0000ULL) | + ((x >> 40) & 0x000000000000ff00ULL) | + ((x >> 56) & 0x00000000000000ffULL); +} +#endif + + +/* XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. */ +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) + +XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[0] + | ((xxh_u64)bytePtr[1] << 8) + | ((xxh_u64)bytePtr[2] << 16) + | ((xxh_u64)bytePtr[3] << 24) + | ((xxh_u64)bytePtr[4] << 32) + | ((xxh_u64)bytePtr[5] << 40) + | ((xxh_u64)bytePtr[6] << 48) + | ((xxh_u64)bytePtr[7] << 56); +} + +XXH_FORCE_INLINE xxh_u64 XXH_readBE64(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[7] + | ((xxh_u64)bytePtr[6] << 8) + | ((xxh_u64)bytePtr[5] << 16) + | ((xxh_u64)bytePtr[4] << 24) + | ((xxh_u64)bytePtr[3] << 32) + | ((xxh_u64)bytePtr[2] << 40) + | ((xxh_u64)bytePtr[1] << 48) + | ((xxh_u64)bytePtr[0] << 56); +} + +#else +XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); +} + +static xxh_u64 XXH_readBE64(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); +} +#endif + +XXH_FORCE_INLINE xxh_u64 +XXH_readLE64_align(const void* ptr, XXH_alignment align) +{ + if (align==XXH_unaligned) + return XXH_readLE64(ptr); + else + return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u64*)ptr : XXH_swap64(*(const xxh_u64*)ptr); +} + + +/******* xxh64 *******/ +/*! + * @} + * @defgroup XXH64_impl XXH64 implementation + * @ingroup impl + * + * Details on the XXH64 implementation. + * @{ + */ +/* #define rather that static const, to be used as initializers */ +#define XXH_PRIME64_1 0x9E3779B185EBCA87ULL /*!< 0b1001111000110111011110011011000110000101111010111100101010000111 */ +#define XXH_PRIME64_2 0xC2B2AE3D27D4EB4FULL /*!< 0b1100001010110010101011100011110100100111110101001110101101001111 */ +#define XXH_PRIME64_3 0x165667B19E3779F9ULL /*!< 0b0001011001010110011001111011000110011110001101110111100111111001 */ +#define XXH_PRIME64_4 0x85EBCA77C2B2AE63ULL /*!< 0b1000010111101011110010100111011111000010101100101010111001100011 */ +#define XXH_PRIME64_5 0x27D4EB2F165667C5ULL /*!< 0b0010011111010100111010110010111100010110010101100110011111000101 */ + +#ifdef XXH_OLD_NAMES +# define PRIME64_1 XXH_PRIME64_1 +# define PRIME64_2 XXH_PRIME64_2 +# define PRIME64_3 XXH_PRIME64_3 +# define PRIME64_4 XXH_PRIME64_4 +# define PRIME64_5 XXH_PRIME64_5 +#endif + +/*! @copydoc XXH32_round */ +static xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input) +{ + acc += input * XXH_PRIME64_2; + acc = XXH_rotl64(acc, 31); + acc *= XXH_PRIME64_1; +#if (defined(__AVX512F__)) && !defined(XXH_ENABLE_AUTOVECTORIZE) + /* + * DISABLE AUTOVECTORIZATION: + * A compiler fence is used to prevent GCC and Clang from + * autovectorizing the XXH64 loop (pragmas and attributes don't work for some + * reason) without globally disabling AVX512. + * + * Autovectorization of XXH64 tends to be detrimental, + * though the exact outcome may change depending on exact cpu and compiler version. + * For information, it has been reported as detrimental for Skylake-X, + * but possibly beneficial for Zen4. + * + * The default is to disable auto-vectorization, + * but you can select to enable it instead using `XXH_ENABLE_AUTOVECTORIZE` build variable. + */ + XXH_COMPILER_GUARD(acc); +#endif + return acc; +} + +static xxh_u64 XXH64_mergeRound(xxh_u64 acc, xxh_u64 val) +{ + val = XXH64_round(0, val); + acc ^= val; + acc = acc * XXH_PRIME64_1 + XXH_PRIME64_4; + return acc; +} + +/*! @copydoc XXH32_avalanche */ +static xxh_u64 XXH64_avalanche(xxh_u64 hash) +{ + hash ^= hash >> 33; + hash *= XXH_PRIME64_2; + hash ^= hash >> 29; + hash *= XXH_PRIME64_3; + hash ^= hash >> 32; + return hash; +} + + +#define XXH_get64bits(p) XXH_readLE64_align(p, align) + +/*! + * @internal + * @brief Sets up the initial accumulator state for XXH64(). + */ +XXH_FORCE_INLINE void +XXH64_initAccs(xxh_u64 *acc, xxh_u64 seed) +{ + XXH_ASSERT(acc != NULL); + acc[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2; + acc[1] = seed + XXH_PRIME64_2; + acc[2] = seed + 0; + acc[3] = seed - XXH_PRIME64_1; +} + +/*! + * @internal + * @brief Consumes a block of data for XXH64(). + * + * @return the end input pointer. + */ +XXH_FORCE_INLINE const xxh_u8 * +XXH64_consumeLong( + xxh_u64 *XXH_RESTRICT acc, + xxh_u8 const *XXH_RESTRICT input, + size_t len, + XXH_alignment align +) +{ + const xxh_u8* const bEnd = input + len; + const xxh_u8* const limit = bEnd - 31; + XXH_ASSERT(acc != NULL); + XXH_ASSERT(input != NULL); + XXH_ASSERT(len >= 32); + do { + /* reroll on 32-bit */ + if (sizeof(void *) < sizeof(xxh_u64)) { + size_t i; + for (i = 0; i < 4; i++) { + acc[i] = XXH64_round(acc[i], XXH_get64bits(input)); + input += 8; + } + } else { + acc[0] = XXH64_round(acc[0], XXH_get64bits(input)); input += 8; + acc[1] = XXH64_round(acc[1], XXH_get64bits(input)); input += 8; + acc[2] = XXH64_round(acc[2], XXH_get64bits(input)); input += 8; + acc[3] = XXH64_round(acc[3], XXH_get64bits(input)); input += 8; + } + } while (input < limit); + + return input; +} + +/*! + * @internal + * @brief Merges the accumulator lanes together for XXH64() + */ +XXH_FORCE_INLINE XXH_PUREF xxh_u64 +XXH64_mergeAccs(const xxh_u64 *acc) +{ + XXH_ASSERT(acc != NULL); + { + xxh_u64 h64 = XXH_rotl64(acc[0], 1) + XXH_rotl64(acc[1], 7) + + XXH_rotl64(acc[2], 12) + XXH_rotl64(acc[3], 18); + /* reroll on 32-bit */ + if (sizeof(void *) < sizeof(xxh_u64)) { + size_t i; + for (i = 0; i < 4; i++) { + h64 = XXH64_mergeRound(h64, acc[i]); + } + } else { + h64 = XXH64_mergeRound(h64, acc[0]); + h64 = XXH64_mergeRound(h64, acc[1]); + h64 = XXH64_mergeRound(h64, acc[2]); + h64 = XXH64_mergeRound(h64, acc[3]); + } + return h64; + } +} + +/*! + * @internal + * @brief Processes the last 0-31 bytes of @p ptr. + * + * There may be up to 31 bytes remaining to consume from the input. + * This final stage will digest them to ensure that all input bytes are present + * in the final mix. + * + * @param hash The hash to finalize. + * @param ptr The pointer to the remaining input. + * @param len The remaining length, modulo 32. + * @param align Whether @p ptr is aligned. + * @return The finalized hash + * @see XXH32_finalize(). + */ +XXH_STATIC XXH_PUREF xxh_u64 +XXH64_finalize(xxh_u64 hash, const xxh_u8* ptr, size_t len, XXH_alignment align) +{ + if (ptr==NULL) XXH_ASSERT(len == 0); + len &= 31; + while (len >= 8) { + xxh_u64 const k1 = XXH64_round(0, XXH_get64bits(ptr)); + ptr += 8; + hash ^= k1; + hash = XXH_rotl64(hash,27) * XXH_PRIME64_1 + XXH_PRIME64_4; + len -= 8; + } + if (len >= 4) { + hash ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1; + ptr += 4; + hash = XXH_rotl64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3; + len -= 4; + } + while (len > 0) { + hash ^= (*ptr++) * XXH_PRIME64_5; + hash = XXH_rotl64(hash, 11) * XXH_PRIME64_1; + --len; + } + return XXH64_avalanche(hash); +} + +#ifdef XXH_OLD_NAMES +# define PROCESS1_64 XXH_PROCESS1_64 +# define PROCESS4_64 XXH_PROCESS4_64 +# define PROCESS8_64 XXH_PROCESS8_64 +#else +# undef XXH_PROCESS1_64 +# undef XXH_PROCESS4_64 +# undef XXH_PROCESS8_64 +#endif + +/*! + * @internal + * @brief The implementation for @ref XXH64(). + * + * @param input , len , seed Directly passed from @ref XXH64(). + * @param align Whether @p input is aligned. + * @return The calculated hash. + */ +XXH_FORCE_INLINE XXH_PUREF xxh_u64 +XXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment align) +{ + xxh_u64 h64; + if (input==NULL) XXH_ASSERT(len == 0); + + if (len>=32) { /* Process a large block of data */ + xxh_u64 acc[4]; + XXH64_initAccs(acc, seed); + + input = XXH64_consumeLong(acc, input, len, align); + + h64 = XXH64_mergeAccs(acc); + } else { + h64 = seed + XXH_PRIME64_5; + } + + h64 += (xxh_u64) len; + + return XXH64_finalize(h64, input, len, align); +} + + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH64_hash_t XXH64 (XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) +{ +#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH64_state_t state; + XXH64_reset(&state, seed); + XXH64_update(&state, (const xxh_u8*)input, len); + return XXH64_digest(&state); +#else + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ + return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); + } } + + return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); + +#endif +} + +/******* Hash Streaming *******/ +#ifndef XXH_NO_STREAM +/*! @ingroup XXH64_family*/ +XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) +{ + return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); +} +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dstState, const XXH64_state_t* srcState) +{ + XXH_memcpy(dstState, srcState, sizeof(*dstState)); +} + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed) +{ + XXH_ASSERT(statePtr != NULL); + memset(statePtr, 0, sizeof(*statePtr)); + XXH64_initAccs(statePtr->acc, seed); + return XXH_OK; +} + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH_errorcode +XXH64_update (XXH_NOESCAPE XXH64_state_t* state, XXH_NOESCAPE const void* input, size_t len) +{ + if (input==NULL) { + XXH_ASSERT(len == 0); + return XXH_OK; + } + + state->total_len += len; + + XXH_ASSERT(state->bufferedSize <= sizeof(state->buffer)); + if (len < sizeof(state->buffer) - state->bufferedSize) { /* fill in tmp buffer */ + XXH_memcpy(state->buffer + state->bufferedSize, input, len); + state->bufferedSize += (XXH32_hash_t)len; + return XXH_OK; + } + + { const xxh_u8* xinput = (const xxh_u8*)input; + const xxh_u8* const bEnd = xinput + len; + + if (state->bufferedSize) { /* non-empty buffer => complete first */ + XXH_memcpy(state->buffer + state->bufferedSize, xinput, sizeof(state->buffer) - state->bufferedSize); + xinput += sizeof(state->buffer) - state->bufferedSize; + /* and process one round */ + (void)XXH64_consumeLong(state->acc, state->buffer, sizeof(state->buffer), XXH_aligned); + state->bufferedSize = 0; + } + + XXH_ASSERT(xinput <= bEnd); + if ((size_t)(bEnd - xinput) >= sizeof(state->buffer)) { + /* Process the remaining data */ + xinput = XXH64_consumeLong(state->acc, xinput, (size_t)(bEnd - xinput), XXH_unaligned); + } + + if (xinput < bEnd) { + /* Copy the leftover to the tmp buffer */ + XXH_memcpy(state->buffer, xinput, (size_t)(bEnd-xinput)); + state->bufferedSize = (unsigned)(bEnd-xinput); + } + } + + return XXH_OK; +} + + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH64_hash_t XXH64_digest(XXH_NOESCAPE const XXH64_state_t* state) +{ + xxh_u64 h64; + + if (state->total_len >= 32) { + h64 = XXH64_mergeAccs(state->acc); + } else { + h64 = state->acc[2] /*seed*/ + XXH_PRIME64_5; + } + + h64 += (xxh_u64) state->total_len; + + return XXH64_finalize(h64, state->buffer, (size_t)state->total_len, XXH_aligned); +} +#endif /* !XXH_NO_STREAM */ + +/******* Canonical representation *******/ + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); + XXH_memcpy(dst, &hash, sizeof(*dst)); +} + +/*! @ingroup XXH64_family */ +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src) +{ + return XXH_readBE64(src); +} + +#ifndef XXH_NO_XXH3 + +/* ********************************************************************* +* XXH3 +* New generation hash designed for speed on small keys and vectorization +************************************************************************ */ +/*! + * @} + * @defgroup XXH3_impl XXH3 implementation + * @ingroup impl + * @{ + */ + +/* === Compiler specifics === */ + + +#if (defined(__GNUC__) && (__GNUC__ >= 3)) \ + || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) \ + || defined(__clang__) +# define XXH_likely(x) __builtin_expect(x, 1) +# define XXH_unlikely(x) __builtin_expect(x, 0) +#else +# define XXH_likely(x) (x) +# define XXH_unlikely(x) (x) +#endif + +#ifndef XXH_HAS_INCLUDE +# ifdef __has_include +/* + * Not defined as XXH_HAS_INCLUDE(x) (function-like) because + * this causes segfaults in Apple Clang 4.2 (on Mac OS X 10.7 Lion) + */ +# define XXH_HAS_INCLUDE __has_include +# else +# define XXH_HAS_INCLUDE(x) 0 +# endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +# if defined(__ARM_FEATURE_SVE) +# include +# endif +# if defined(__ARM_NEON__) || defined(__ARM_NEON) \ + || (defined(_M_ARM) && _M_ARM >= 7) \ + || defined(_M_ARM64) || defined(_M_ARM64EC) \ + || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE()) /* WASM SIMD128 via SIMDe */ +# define inline __inline__ /* circumvent a clang bug */ +# include +# undef inline +# elif defined(__AVX2__) +# include +# elif defined(__SSE2__) +# include +# elif defined(__loongarch_sx) +# include +# endif +#endif + +#if defined(_MSC_VER) +# include +#endif + +/* + * One goal of XXH3 is to make it fast on both 32-bit and 64-bit, while + * remaining a true 64-bit/128-bit hash function. + * + * This is done by prioritizing a subset of 64-bit operations that can be + * emulated without too many steps on the average 32-bit machine. + * + * For example, these two lines seem similar, and run equally fast on 64-bit: + * + * xxh_u64 x; + * x ^= (x >> 47); // good + * x ^= (x >> 13); // bad + * + * However, to a 32-bit machine, there is a major difference. + * + * x ^= (x >> 47) looks like this: + * + * x.lo ^= (x.hi >> (47 - 32)); + * + * while x ^= (x >> 13) looks like this: + * + * // note: funnel shifts are not usually cheap. + * x.lo ^= (x.lo >> 13) | (x.hi << (32 - 13)); + * x.hi ^= (x.hi >> 13); + * + * The first one is significantly faster than the second, simply because the + * shift is larger than 32. This means: + * - All the bits we need are in the upper 32 bits, so we can ignore the lower + * 32 bits in the shift. + * - The shift result will always fit in the lower 32 bits, and therefore, + * we can ignore the upper 32 bits in the xor. + * + * Thanks to this optimization, XXH3 only requires these features to be efficient: + * + * - Usable unaligned access + * - A 32-bit or 64-bit ALU + * - If 32-bit, a decent ADC instruction + * - A 32 or 64-bit multiply with a 64-bit result + * - For the 128-bit variant, a decent byteswap helps short inputs. + * + * The first two are already required by XXH32, and almost all 32-bit and 64-bit + * platforms which can run XXH32 can run XXH3 efficiently. + * + * Thumb-1, the classic 16-bit only subset of ARM's instruction set, is one + * notable exception. + * + * First of all, Thumb-1 lacks support for the UMULL instruction which + * performs the important long multiply. This means numerous __aeabi_lmul + * calls. + * + * Second of all, the 8 functional registers are just not enough. + * Setup for __aeabi_lmul, byteshift loads, pointers, and all arithmetic need + * Lo registers, and this shuffling results in thousands more MOVs than A32. + * + * A32 and T32 don't have this limitation. They can access all 14 registers, + * do a 32->64 multiply with UMULL, and the flexible operand allowing free + * shifts is helpful, too. + * + * Therefore, we do a quick sanity check. + * + * If compiling Thumb-1 for a target which supports ARM instructions, we will + * emit a warning, as it is not a "sane" platform to compile for. + * + * Usually, if this happens, it is because of an accident and you probably need + * to specify -march, as you likely meant to compile for a newer architecture. + * + * Credit: large sections of the vectorial and asm source code paths + * have been contributed by @easyaspi314 + */ +#if defined(__thumb__) && !defined(__thumb2__) && defined(__ARM_ARCH_ISA_ARM) +# warning "XXH3 is highly inefficient without ARM or Thumb-2." +#endif + +/* ========================================== + * Vectorization detection + * ========================================== */ + +#ifdef XXH_DOXYGEN +/*! + * @ingroup tuning + * @brief Overrides the vectorization implementation chosen for XXH3. + * + * Can be defined to 0 to disable SIMD or any of the values mentioned in + * @ref XXH_VECTOR_TYPE. + * + * If this is not defined, it uses predefined macros to determine the best + * implementation. + */ +# define XXH_VECTOR XXH_SCALAR +/*! + * @ingroup tuning + * @brief Selects the minimum alignment for XXH3's accumulators. + * + * When using SIMD, this should match the alignment required for said vector + * type, so, for example, 32 for AVX2. + * + * Default: Auto detected. + */ +# define XXH_ACC_ALIGN 8 +#endif + +/* Actual definition */ +#ifndef XXH_DOXYGEN +#endif + +#ifndef XXH_VECTOR /* can be defined on command line */ +# if defined(__ARM_FEATURE_SVE) +# define XXH_VECTOR XXH_SVE +# elif ( \ + defined(__ARM_NEON__) || defined(__ARM_NEON) /* gcc */ \ + || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) /* msvc */ \ + || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE()) /* wasm simd128 via SIMDe */ \ + ) && ( \ + defined(_WIN32) || defined(__LITTLE_ENDIAN__) /* little endian only */ \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \ + ) +# define XXH_VECTOR XXH_NEON +# elif defined(__AVX512F__) +# define XXH_VECTOR XXH_AVX512 +# elif defined(__AVX2__) +# define XXH_VECTOR XXH_AVX2 +# elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2)) +# define XXH_VECTOR XXH_SSE2 +# elif (defined(__PPC64__) && defined(__POWER8_VECTOR__)) \ + || (defined(__s390x__) && defined(__VEC__)) \ + && defined(__GNUC__) /* TODO: IBM XL */ +# define XXH_VECTOR XXH_VSX +# elif defined(__loongarch_sx) +# define XXH_VECTOR XXH_LSX +# else +# define XXH_VECTOR XXH_SCALAR +# endif +#endif + +/* __ARM_FEATURE_SVE is only supported by GCC & Clang. */ +#if (XXH_VECTOR == XXH_SVE) && !defined(__ARM_FEATURE_SVE) +# ifdef _MSC_VER +# pragma warning(once : 4606) +# else +# warning "__ARM_FEATURE_SVE isn't supported. Use SCALAR instead." +# endif +# undef XXH_VECTOR +# define XXH_VECTOR XXH_SCALAR +#endif + +/* + * Controls the alignment of the accumulator, + * for compatibility with aligned vector loads, which are usually faster. + */ +#ifndef XXH_ACC_ALIGN +# if defined(XXH_X86DISPATCH) +# define XXH_ACC_ALIGN 64 /* for compatibility with avx512 */ +# elif XXH_VECTOR == XXH_SCALAR /* scalar */ +# define XXH_ACC_ALIGN 8 +# elif XXH_VECTOR == XXH_SSE2 /* sse2 */ +# define XXH_ACC_ALIGN 16 +# elif XXH_VECTOR == XXH_AVX2 /* avx2 */ +# define XXH_ACC_ALIGN 32 +# elif XXH_VECTOR == XXH_NEON /* neon */ +# define XXH_ACC_ALIGN 16 +# elif XXH_VECTOR == XXH_VSX /* vsx */ +# define XXH_ACC_ALIGN 16 +# elif XXH_VECTOR == XXH_AVX512 /* avx512 */ +# define XXH_ACC_ALIGN 64 +# elif XXH_VECTOR == XXH_SVE /* sve */ +# define XXH_ACC_ALIGN 64 +# elif XXH_VECTOR == XXH_LSX /* lsx */ +# define XXH_ACC_ALIGN 64 +# endif +#endif + +#if defined(XXH_X86DISPATCH) || XXH_VECTOR == XXH_SSE2 \ + || XXH_VECTOR == XXH_AVX2 || XXH_VECTOR == XXH_AVX512 +# define XXH_SEC_ALIGN XXH_ACC_ALIGN +#elif XXH_VECTOR == XXH_SVE +# define XXH_SEC_ALIGN XXH_ACC_ALIGN +#else +# define XXH_SEC_ALIGN 8 +#endif + +#if defined(__GNUC__) || defined(__clang__) +# define XXH_ALIASING __attribute__((__may_alias__)) +#else +# define XXH_ALIASING /* nothing */ +#endif + +/* + * UGLY HACK: + * GCC usually generates the best code with -O3 for xxHash. + * + * However, when targeting AVX2, it is overzealous in its unrolling resulting + * in code roughly 3/4 the speed of Clang. + * + * There are other issues, such as GCC splitting _mm256_loadu_si256 into + * _mm_loadu_si128 + _mm256_inserti128_si256. This is an optimization which + * only applies to Sandy and Ivy Bridge... which don't even support AVX2. + * + * That is why when compiling the AVX2 version, it is recommended to use either + * -O2 -mavx2 -march=haswell + * or + * -O2 -mavx2 -mno-avx256-split-unaligned-load + * for decent performance, or to use Clang instead. + * + * Fortunately, we can control the first one with a pragma that forces GCC into + * -O2, but the other one we can't control without "failed to inline always + * inline function due to target mismatch" warnings. + */ +#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \ + && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ + && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */ +# pragma GCC push_options +# pragma GCC optimize("-O2") +#endif + +#if XXH_VECTOR == XXH_NEON + +/* + * UGLY HACK: While AArch64 GCC on Linux does not seem to care, on macOS, GCC -O3 + * optimizes out the entire hashLong loop because of the aliasing violation. + * + * However, GCC is also inefficient at load-store optimization with vld1q/vst1q, + * so the only option is to mark it as aliasing. + */ +typedef uint64x2_t xxh_aliasing_uint64x2_t XXH_ALIASING; + +/*! + * @internal + * @brief `vld1q_u64` but faster and alignment-safe. + * + * On AArch64, unaligned access is always safe, but on ARMv7-a, it is only + * *conditionally* safe (`vld1` has an alignment bit like `movdq[ua]` in x86). + * + * GCC for AArch64 sees `vld1q_u8` as an intrinsic instead of a load, so it + * prohibits load-store optimizations. Therefore, a direct dereference is used. + * + * Otherwise, `vld1q_u8` is used with `vreinterpretq_u8_u64` to do a safe + * unaligned load. + */ +#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) +XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) /* silence -Wcast-align */ +{ + return *(xxh_aliasing_uint64x2_t const *)ptr; +} +#else +XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) +{ + return vreinterpretq_u64_u8(vld1q_u8((uint8_t const*)ptr)); +} +#endif + +/*! + * @internal + * @brief `vmlal_u32` on low and high halves of a vector. + * + * This is a workaround for AArch64 GCC < 11 which implemented arm_neon.h with + * inline assembly and were therefore incapable of merging the `vget_{low, high}_u32` + * with `vmlal_u32`. + */ +#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 11 +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + /* Inline assembly is the only way */ + __asm__("umlal %0.2d, %1.2s, %2.2s" : "+w" (acc) : "w" (lhs), "w" (rhs)); + return acc; +} +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + /* This intrinsic works as expected */ + return vmlal_high_u32(acc, lhs, rhs); +} +#else +/* Portable intrinsic versions */ +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + return vmlal_u32(acc, vget_low_u32(lhs), vget_low_u32(rhs)); +} +/*! @copydoc XXH_vmlal_low_u32 + * Assume the compiler converts this to vmlal_high_u32 on aarch64 */ +XXH_FORCE_INLINE uint64x2_t +XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs) +{ + return vmlal_u32(acc, vget_high_u32(lhs), vget_high_u32(rhs)); +} +#endif + +/*! + * @ingroup tuning + * @brief Controls the NEON to scalar ratio for XXH3 + * + * This can be set to 2, 4, 6, or 8. + * + * ARM Cortex CPUs are _very_ sensitive to how their pipelines are used. + * + * For example, the Cortex-A73 can dispatch 3 micro-ops per cycle, but only 2 of those + * can be NEON. If you are only using NEON instructions, you are only using 2/3 of the CPU + * bandwidth. + * + * This is even more noticeable on the more advanced cores like the Cortex-A76 which + * can dispatch 8 micro-ops per cycle, but still only 2 NEON micro-ops at once. + * + * Therefore, to make the most out of the pipeline, it is beneficial to run 6 NEON lanes + * and 2 scalar lanes, which is chosen by default. + * + * This does not apply to Apple processors or 32-bit processors, which run better with + * full NEON. These will default to 8. Additionally, size-optimized builds run 8 lanes. + * + * This change benefits CPUs with large micro-op buffers without negatively affecting + * most other CPUs: + * + * | Chipset | Dispatch type | NEON only | 6:2 hybrid | Diff. | + * |:----------------------|:--------------------|----------:|-----------:|------:| + * | Snapdragon 730 (A76) | 2 NEON/8 micro-ops | 8.8 GB/s | 10.1 GB/s | ~16% | + * | Snapdragon 835 (A73) | 2 NEON/3 micro-ops | 5.1 GB/s | 5.3 GB/s | ~5% | + * | Marvell PXA1928 (A53) | In-order dual-issue | 1.9 GB/s | 1.9 GB/s | 0% | + * | Apple M1 | 4 NEON/8 micro-ops | 37.3 GB/s | 36.1 GB/s | ~-3% | + * + * It also seems to fix some bad codegen on GCC, making it almost as fast as clang. + * + * When using WASM SIMD128, if this is 2 or 6, SIMDe will scalarize 2 of the lanes meaning + * it effectively becomes worse 4. + * + * @see XXH3_accumulate_512_neon() + */ +# ifndef XXH3_NEON_LANES +# if (defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) \ + && !defined(__APPLE__) && XXH_SIZE_OPT <= 0 +# define XXH3_NEON_LANES 6 +# else +# define XXH3_NEON_LANES XXH_ACC_NB +# endif +# endif +#endif /* XXH_VECTOR == XXH_NEON */ + +/* + * VSX and Z Vector helpers. + * + * This is very messy, and any pull requests to clean this up are welcome. + * + * There are a lot of problems with supporting VSX and s390x, due to + * inconsistent intrinsics, spotty coverage, and multiple endiannesses. + */ +#if XXH_VECTOR == XXH_VSX +/* Annoyingly, these headers _may_ define three macros: `bool`, `vector`, + * and `pixel`. This is a problem for obvious reasons. + * + * These keywords are unnecessary; the spec literally says they are + * equivalent to `__bool`, `__vector`, and `__pixel` and may be undef'd + * after including the header. + * + * We use pragma push_macro/pop_macro to keep the namespace clean. */ +# pragma push_macro("bool") +# pragma push_macro("vector") +# pragma push_macro("pixel") +/* silence potential macro redefined warnings */ +# undef bool +# undef vector +# undef pixel + +# if defined(__s390x__) +# include +# else +# include +# endif + +/* Restore the original macro values, if applicable. */ +# pragma pop_macro("pixel") +# pragma pop_macro("vector") +# pragma pop_macro("bool") + +typedef __vector unsigned long long xxh_u64x2; +typedef __vector unsigned char xxh_u8x16; +typedef __vector unsigned xxh_u32x4; + +/* + * UGLY HACK: Similar to aarch64 macOS GCC, s390x GCC has the same aliasing issue. + */ +typedef xxh_u64x2 xxh_aliasing_u64x2 XXH_ALIASING; + +# ifndef XXH_VSX_BE +# if defined(__BIG_ENDIAN__) \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +# define XXH_VSX_BE 1 +# elif defined(__VEC_ELEMENT_REG_ORDER__) && __VEC_ELEMENT_REG_ORDER__ == __ORDER_BIG_ENDIAN__ +# warning "-maltivec=be is not recommended. Please use native endianness." +# define XXH_VSX_BE 1 +# else +# define XXH_VSX_BE 0 +# endif +# endif /* !defined(XXH_VSX_BE) */ + +# if XXH_VSX_BE +# if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__)) +# define XXH_vec_revb vec_revb +# else +/*! + * A polyfill for POWER9's vec_revb(). + */ +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val) +{ + xxh_u8x16 const vByteSwap = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; + return vec_perm(val, val, vByteSwap); +} +# endif +# endif /* XXH_VSX_BE */ + +/*! + * Performs an unaligned vector load and byte swaps it on big endian. + */ +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_loadu(const void *ptr) +{ + xxh_u64x2 ret; + XXH_memcpy(&ret, ptr, sizeof(xxh_u64x2)); +# if XXH_VSX_BE + ret = XXH_vec_revb(ret); +# endif + return ret; +} + +/* + * vec_mulo and vec_mule are very problematic intrinsics on PowerPC + * + * These intrinsics weren't added until GCC 8, despite existing for a while, + * and they are endian dependent. Also, their meaning swap depending on version. + * */ +# if defined(__s390x__) + /* s390x is always big endian, no issue on this platform */ +# define XXH_vec_mulo vec_mulo +# define XXH_vec_mule vec_mule +# elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw) && !defined(__ibmxl__) +/* Clang has a better way to control this, we can just use the builtin which doesn't swap. */ + /* The IBM XL Compiler (which defined __clang__) only implements the vec_* operations */ +# define XXH_vec_mulo __builtin_altivec_vmulouw +# define XXH_vec_mule __builtin_altivec_vmuleuw +# else +/* gcc needs inline assembly */ +/* Adapted from https://github.com/google/highwayhash/blob/master/highwayhash/hh_vsx.h. */ +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mulo(xxh_u32x4 a, xxh_u32x4 b) +{ + xxh_u64x2 result; + __asm__("vmulouw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); + return result; +} +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b) +{ + xxh_u64x2 result; + __asm__("vmuleuw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); + return result; +} +# endif /* XXH_vec_mulo, XXH_vec_mule */ +#endif /* XXH_VECTOR == XXH_VSX */ + +#if XXH_VECTOR == XXH_SVE +#define ACCRND(acc, offset) \ +do { \ + svuint64_t input_vec = svld1_u64(mask, xinput + offset); \ + svuint64_t secret_vec = svld1_u64(mask, xsecret + offset); \ + svuint64_t mixed = sveor_u64_x(mask, secret_vec, input_vec); \ + svuint64_t swapped = svtbl_u64(input_vec, kSwap); \ + svuint64_t mixed_lo = svextw_u64_x(mask, mixed); \ + svuint64_t mixed_hi = svlsr_n_u64_x(mask, mixed, 32); \ + svuint64_t mul = svmad_u64_x(mask, mixed_lo, mixed_hi, swapped); \ + acc = svadd_u64_x(mask, acc, mul); \ +} while (0) +#endif /* XXH_VECTOR == XXH_SVE */ + +/* prefetch + * can be disabled, by declaring XXH_NO_PREFETCH build macro */ +#if defined(XXH_NO_PREFETCH) +# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ +#else +# if XXH_SIZE_OPT >= 1 +# define XXH_PREFETCH(ptr) (void)(ptr) +# elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) /* _mm_prefetch() not defined outside of x86/x64 */ +# include /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ +# define XXH_PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) +# elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) +# define XXH_PREFETCH(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) +# else +# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ +# endif +#endif /* XXH_NO_PREFETCH */ + + +/* ========================================== + * XXH3 default settings + * ========================================== */ + +#define XXH_SECRET_DEFAULT_SIZE 192 /* minimum XXH3_SECRET_SIZE_MIN */ + +#if (XXH_SECRET_DEFAULT_SIZE < XXH3_SECRET_SIZE_MIN) +# error "default keyset is not large enough" +#endif + +/*! Pseudorandom secret taken directly from FARSH. */ +XXH_ALIGN(64) static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = { + 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c, + 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f, + 0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21, + 0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c, + 0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3, + 0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8, + 0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d, + 0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64, + 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb, + 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e, + 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce, + 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e, +}; + +static const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL; /*!< 0b0001011001010110011001111001000110011110001101110111100111111001 */ +static const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL; /*!< 0b1001111110110010000111000110010100011110100110001101111100100101 */ + +#ifdef XXH_OLD_NAMES +# define kSecret XXH3_kSecret +#endif + +#ifdef XXH_DOXYGEN +/*! + * @brief Calculates a 32-bit to 64-bit long multiply. + * + * Implemented as a macro. + * + * Wraps `__emulu` on MSVC x86 because it tends to call `__allmul` when it doesn't + * need to (but it shouldn't need to anyways, it is about 7 instructions to do + * a 64x64 multiply...). Since we know that this will _always_ emit `MULL`, we + * use that instead of the normal method. + * + * If you are compiling for platforms like Thumb-1 and don't have a better option, + * you may also want to write your own long multiply routine here. + * + * @param x, y Numbers to be multiplied + * @return 64-bit product of the low 32 bits of @p x and @p y. + */ +XXH_FORCE_INLINE xxh_u64 +XXH_mult32to64(xxh_u64 x, xxh_u64 y) +{ + return (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF); +} +#elif defined(_MSC_VER) && defined(_M_IX86) +# define XXH_mult32to64(x, y) __emulu((unsigned)(x), (unsigned)(y)) +#else +/* + * Downcast + upcast is usually better than masking on older compilers like + * GCC 4.2 (especially 32-bit ones), all without affecting newer compilers. + * + * The other method, (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF), will AND both operands + * and perform a full 64x64 multiply -- entirely redundant on 32-bit. + */ +# define XXH_mult32to64(x, y) ((xxh_u64)(xxh_u32)(x) * (xxh_u64)(xxh_u32)(y)) +#endif + +/*! + * @brief Calculates a 64->128-bit long multiply. + * + * Uses `__uint128_t` and `_umul128` if available, otherwise uses a scalar + * version. + * + * @param lhs , rhs The 64-bit integers to be multiplied + * @return The 128-bit result represented in an @ref XXH128_hash_t. + */ +static XXH128_hash_t +XXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs) +{ + /* + * GCC/Clang __uint128_t method. + * + * On most 64-bit targets, GCC and Clang define a __uint128_t type. + * This is usually the best way as it usually uses a native long 64-bit + * multiply, such as MULQ on x86_64 or MUL + UMULH on aarch64. + * + * Usually. + * + * Despite being a 32-bit platform, Clang (and emscripten) define this type + * despite not having the arithmetic for it. This results in a laggy + * compiler builtin call which calculates a full 128-bit multiply. + * In that case it is best to use the portable one. + * https://github.com/Cyan4973/xxHash/issues/211#issuecomment-515575677 + */ +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__wasm__) \ + && defined(__SIZEOF_INT128__) \ + || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128) + + __uint128_t const product = (__uint128_t)lhs * (__uint128_t)rhs; + XXH128_hash_t r128; + r128.low64 = (xxh_u64)(product); + r128.high64 = (xxh_u64)(product >> 64); + return r128; + + /* + * MSVC for x64's _umul128 method. + * + * xxh_u64 _umul128(xxh_u64 Multiplier, xxh_u64 Multiplicand, xxh_u64 *HighProduct); + * + * This compiles to single operand MUL on x64. + */ +#elif (defined(_M_X64) || defined(_M_IA64)) && !defined(_M_ARM64EC) + +#ifndef _MSC_VER +# pragma intrinsic(_umul128) +#endif + xxh_u64 product_high; + xxh_u64 const product_low = _umul128(lhs, rhs, &product_high); + XXH128_hash_t r128; + r128.low64 = product_low; + r128.high64 = product_high; + return r128; + + /* + * MSVC for ARM64's __umulh method. + * + * This compiles to the same MUL + UMULH as GCC/Clang's __uint128_t method. + */ +#elif defined(_M_ARM64) || defined(_M_ARM64EC) + +#ifndef _MSC_VER +# pragma intrinsic(__umulh) +#endif + XXH128_hash_t r128; + r128.low64 = lhs * rhs; + r128.high64 = __umulh(lhs, rhs); + return r128; + +#else + /* + * Portable scalar method. Optimized for 32-bit and 64-bit ALUs. + * + * This is a fast and simple grade school multiply, which is shown below + * with base 10 arithmetic instead of base 0x100000000. + * + * 9 3 // D2 lhs = 93 + * x 7 5 // D2 rhs = 75 + * ---------- + * 1 5 // D2 lo_lo = (93 % 10) * (75 % 10) = 15 + * 4 5 | // D2 hi_lo = (93 / 10) * (75 % 10) = 45 + * 2 1 | // D2 lo_hi = (93 % 10) * (75 / 10) = 21 + * + 6 3 | | // D2 hi_hi = (93 / 10) * (75 / 10) = 63 + * --------- + * 2 7 | // D2 cross = (15 / 10) + (45 % 10) + 21 = 27 + * + 6 7 | | // D2 upper = (27 / 10) + (45 / 10) + 63 = 67 + * --------- + * 6 9 7 5 // D4 res = (27 * 10) + (15 % 10) + (67 * 100) = 6975 + * + * The reasons for adding the products like this are: + * 1. It avoids manual carry tracking. Just like how + * (9 * 9) + 9 + 9 = 99, the same applies with this for UINT64_MAX. + * This avoids a lot of complexity. + * + * 2. It hints for, and on Clang, compiles to, the powerful UMAAL + * instruction available in ARM's Digital Signal Processing extension + * in 32-bit ARMv6 and later, which is shown below: + * + * void UMAAL(xxh_u32 *RdLo, xxh_u32 *RdHi, xxh_u32 Rn, xxh_u32 Rm) + * { + * xxh_u64 product = (xxh_u64)*RdLo * (xxh_u64)*RdHi + Rn + Rm; + * *RdLo = (xxh_u32)(product & 0xFFFFFFFF); + * *RdHi = (xxh_u32)(product >> 32); + * } + * + * This instruction was designed for efficient long multiplication, and + * allows this to be calculated in only 4 instructions at speeds + * comparable to some 64-bit ALUs. + * + * 3. It isn't terrible on other platforms. Usually this will be a couple + * of 32-bit ADD/ADCs. + */ + + /* First calculate all of the cross products. */ + xxh_u64 const lo_lo = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF); + xxh_u64 const hi_lo = XXH_mult32to64(lhs >> 32, rhs & 0xFFFFFFFF); + xxh_u64 const lo_hi = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs >> 32); + xxh_u64 const hi_hi = XXH_mult32to64(lhs >> 32, rhs >> 32); + + /* Now add the products together. These will never overflow. */ + xxh_u64 const cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi; + xxh_u64 const upper = (hi_lo >> 32) + (cross >> 32) + hi_hi; + xxh_u64 const lower = (cross << 32) | (lo_lo & 0xFFFFFFFF); + + XXH128_hash_t r128; + r128.low64 = lower; + r128.high64 = upper; + return r128; +#endif +} + +/*! + * @brief Calculates a 64-bit to 128-bit multiply, then XOR folds it. + * + * The reason for the separate function is to prevent passing too many structs + * around by value. This will hopefully inline the multiply, but we don't force it. + * + * @param lhs , rhs The 64-bit integers to multiply + * @return The low 64 bits of the product XOR'd by the high 64 bits. + * @see XXH_mult64to128() + */ +static xxh_u64 +XXH3_mul128_fold64(xxh_u64 lhs, xxh_u64 rhs) +{ + XXH128_hash_t product = XXH_mult64to128(lhs, rhs); + return product.low64 ^ product.high64; +} + +/*! Seems to produce slightly better code on GCC for some reason. */ +XXH_FORCE_INLINE XXH_CONSTF xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift) +{ + XXH_ASSERT(0 <= shift && shift < 64); + return v64 ^ (v64 >> shift); +} + +/* + * This is a fast avalanche stage, + * suitable when input bits are already partially mixed + */ +static XXH64_hash_t XXH3_avalanche(xxh_u64 h64) +{ + h64 = XXH_xorshift64(h64, 37); + h64 *= PRIME_MX1; + h64 = XXH_xorshift64(h64, 32); + return h64; +} + +/* + * This is a stronger avalanche, + * inspired by Pelle Evensen's rrmxmx + * preferable when input has not been previously mixed + */ +static XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len) +{ + /* this mix is inspired by Pelle Evensen's rrmxmx */ + h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24); + h64 *= PRIME_MX2; + h64 ^= (h64 >> 35) + len ; + h64 *= PRIME_MX2; + return XXH_xorshift64(h64, 28); +} + + +/* ========================================== + * Short keys + * ========================================== + * One of the shortcomings of XXH32 and XXH64 was that their performance was + * sub-optimal on short lengths. It used an iterative algorithm which strongly + * favored lengths that were a multiple of 4 or 8. + * + * Instead of iterating over individual inputs, we use a set of single shot + * functions which piece together a range of lengths and operate in constant time. + * + * Additionally, the number of multiplies has been significantly reduced. This + * reduces latency, especially when emulating 64-bit multiplies on 32-bit. + * + * Depending on the platform, this may or may not be faster than XXH32, but it + * is almost guaranteed to be faster than XXH64. + */ + +/* + * At very short lengths, there isn't enough input to fully hide secrets, or use + * the entire secret. + * + * There is also only a limited amount of mixing we can do before significantly + * impacting performance. + * + * Therefore, we use different sections of the secret and always mix two secret + * samples with an XOR. This should have no effect on performance on the + * seedless or withSeed variants because everything _should_ be constant folded + * by modern compilers. + * + * The XOR mixing hides individual parts of the secret and increases entropy. + * + * This adds an extra layer of strength for custom secrets. + */ +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_1to3_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(1 <= len && len <= 3); + XXH_ASSERT(secret != NULL); + /* + * len = 1: combined = { input[0], 0x01, input[0], input[0] } + * len = 2: combined = { input[1], 0x02, input[0], input[1] } + * len = 3: combined = { input[2], 0x03, input[0], input[1] } + */ + { xxh_u8 const c1 = input[0]; + xxh_u8 const c2 = input[len >> 1]; + xxh_u8 const c3 = input[len - 1]; + xxh_u32 const combined = ((xxh_u32)c1 << 16) | ((xxh_u32)c2 << 24) + | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); + xxh_u64 const bitflip = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; + xxh_u64 const keyed = (xxh_u64)combined ^ bitflip; + return XXH64_avalanche(keyed); + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_4to8_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(4 <= len && len <= 8); + seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; + { xxh_u32 const input1 = XXH_readLE32(input); + xxh_u32 const input2 = XXH_readLE32(input + len - 4); + xxh_u64 const bitflip = (XXH_readLE64(secret+8) ^ XXH_readLE64(secret+16)) - seed; + xxh_u64 const input64 = input2 + (((xxh_u64)input1) << 32); + xxh_u64 const keyed = input64 ^ bitflip; + return XXH3_rrmxmx(keyed, len); + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_9to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(9 <= len && len <= 16); + { xxh_u64 const bitflip1 = (XXH_readLE64(secret+24) ^ XXH_readLE64(secret+32)) + seed; + xxh_u64 const bitflip2 = (XXH_readLE64(secret+40) ^ XXH_readLE64(secret+48)) - seed; + xxh_u64 const input_lo = XXH_readLE64(input) ^ bitflip1; + xxh_u64 const input_hi = XXH_readLE64(input + len - 8) ^ bitflip2; + xxh_u64 const acc = len + + XXH_swap64(input_lo) + input_hi + + XXH3_mul128_fold64(input_lo, input_hi); + return XXH3_avalanche(acc); + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_0to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(len <= 16); + { if (XXH_likely(len > 8)) return XXH3_len_9to16_64b(input, len, secret, seed); + if (XXH_likely(len >= 4)) return XXH3_len_4to8_64b(input, len, secret, seed); + if (len) return XXH3_len_1to3_64b(input, len, secret, seed); + return XXH64_avalanche(seed ^ (XXH_readLE64(secret+56) ^ XXH_readLE64(secret+64))); + } +} + +/* + * DISCLAIMER: There are known *seed-dependent* multicollisions here due to + * multiplication by zero, affecting hashes of lengths 17 to 240. + * + * However, they are very unlikely. + * + * Keep this in mind when using the unseeded XXH3_64bits() variant: As with all + * unseeded non-cryptographic hashes, it does not attempt to defend itself + * against specially crafted inputs, only random inputs. + * + * Compared to classic UMAC where a 1 in 2^31 chance of 4 consecutive bytes + * cancelling out the secret is taken an arbitrary number of times (addressed + * in XXH3_accumulate_512), this collision is very unlikely with random inputs + * and/or proper seeding: + * + * This only has a 1 in 2^63 chance of 8 consecutive bytes cancelling out, in a + * function that is only called up to 16 times per hash with up to 240 bytes of + * input. + * + * This is not too bad for a non-cryptographic hash function, especially with + * only 64 bit outputs. + * + * The 128-bit variant (which trades some speed for strength) is NOT affected + * by this, although it is always a good idea to use a proper seed if you care + * about strength. + */ +XXH_FORCE_INLINE xxh_u64 XXH3_mix16B(const xxh_u8* XXH_RESTRICT input, + const xxh_u8* XXH_RESTRICT secret, xxh_u64 seed64) +{ +#if defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ + && defined(__i386__) && defined(__SSE2__) /* x86 + SSE2 */ \ + && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable like XXH32 hack */ + /* + * UGLY HACK: + * GCC for x86 tends to autovectorize the 128-bit multiply, resulting in + * slower code. + * + * By forcing seed64 into a register, we disrupt the cost model and + * cause it to scalarize. See `XXH32_round()` + * + * FIXME: Clang's output is still _much_ faster -- On an AMD Ryzen 3600, + * XXH3_64bits @ len=240 runs at 4.6 GB/s with Clang 9, but 3.3 GB/s on + * GCC 9.2, despite both emitting scalar code. + * + * GCC generates much better scalar code than Clang for the rest of XXH3, + * which is why finding a more optimal codepath is an interest. + */ + XXH_COMPILER_GUARD(seed64); +#endif + { xxh_u64 const input_lo = XXH_readLE64(input); + xxh_u64 const input_hi = XXH_readLE64(input+8); + return XXH3_mul128_fold64( + input_lo ^ (XXH_readLE64(secret) + seed64), + input_hi ^ (XXH_readLE64(secret+8) - seed64) + ); + } +} + +/* For mid range keys, XXH3 uses a Mum-hash variant. */ +XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(16 < len && len <= 128); + + { xxh_u64 acc = len * XXH_PRIME64_1; +#if XXH_SIZE_OPT >= 1 + /* Smaller and cleaner, but slightly slower. */ + unsigned int i = (unsigned int)(len - 1) / 32; + do { + acc += XXH3_mix16B(input+16 * i, secret+32*i, seed); + acc += XXH3_mix16B(input+len-16*(i+1), secret+32*i+16, seed); + } while (i-- != 0); +#else + if (len > 32) { + if (len > 64) { + if (len > 96) { + acc += XXH3_mix16B(input+48, secret+96, seed); + acc += XXH3_mix16B(input+len-64, secret+112, seed); + } + acc += XXH3_mix16B(input+32, secret+64, seed); + acc += XXH3_mix16B(input+len-48, secret+80, seed); + } + acc += XXH3_mix16B(input+16, secret+32, seed); + acc += XXH3_mix16B(input+len-32, secret+48, seed); + } + acc += XXH3_mix16B(input+0, secret+0, seed); + acc += XXH3_mix16B(input+len-16, secret+16, seed); +#endif + return XXH3_avalanche(acc); + } +} + +XXH_NO_INLINE XXH_PUREF XXH64_hash_t +XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); + + #define XXH3_MIDSIZE_STARTOFFSET 3 + #define XXH3_MIDSIZE_LASTOFFSET 17 + + { xxh_u64 acc = len * XXH_PRIME64_1; + xxh_u64 acc_end; + unsigned int const nbRounds = (unsigned int)len / 16; + unsigned int i; + XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); + for (i=0; i<8; i++) { + acc += XXH3_mix16B(input+(16*i), secret+(16*i), seed); + } + /* last bytes */ + acc_end = XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed); + XXH_ASSERT(nbRounds >= 8); + acc = XXH3_avalanche(acc); +#if defined(__clang__) /* Clang */ \ + && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ + && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ + /* + * UGLY HACK: + * Clang for ARMv7-A tries to vectorize this loop, similar to GCC x86. + * In everywhere else, it uses scalar code. + * + * For 64->128-bit multiplies, even if the NEON was 100% optimal, it + * would still be slower than UMAAL (see XXH_mult64to128). + * + * Unfortunately, Clang doesn't handle the long multiplies properly and + * converts them to the nonexistent "vmulq_u64" intrinsic, which is then + * scalarized into an ugly mess of VMOV.32 instructions. + * + * This mess is difficult to avoid without turning autovectorization + * off completely, but they are usually relatively minor and/or not + * worth it to fix. + * + * This loop is the easiest to fix, as unlike XXH32, this pragma + * _actually works_ because it is a loop vectorization instead of an + * SLP vectorization. + */ + #pragma clang loop vectorize(disable) +#endif + for (i=8 ; i < nbRounds; i++) { + /* + * Prevents clang for unrolling the acc loop and interleaving with this one. + */ + XXH_COMPILER_GUARD(acc); + acc_end += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed); + } + return XXH3_avalanche(acc + acc_end); + } +} + + +/* ======= Long Keys ======= */ + +#define XXH_STRIPE_LEN 64 +#define XXH_SECRET_CONSUME_RATE 8 /* nb of secret bytes consumed at each accumulation */ +#define XXH_ACC_NB (XXH_STRIPE_LEN / sizeof(xxh_u64)) + +#ifdef XXH_OLD_NAMES +# define STRIPE_LEN XXH_STRIPE_LEN +# define ACC_NB XXH_ACC_NB +#endif + +#ifndef XXH_PREFETCH_DIST +# ifdef __clang__ +# define XXH_PREFETCH_DIST 320 +# else +# if (XXH_VECTOR == XXH_AVX512) +# define XXH_PREFETCH_DIST 512 +# else +# define XXH_PREFETCH_DIST 384 +# endif +# endif /* __clang__ */ +#endif /* XXH_PREFETCH_DIST */ + +/* + * These macros are to generate an XXH3_accumulate() function. + * The two arguments select the name suffix and target attribute. + * + * The name of this symbol is XXH3_accumulate_() and it calls + * XXH3_accumulate_512_(). + * + * It may be useful to hand implement this function if the compiler fails to + * optimize the inline function. + */ +#define XXH3_ACCUMULATE_TEMPLATE(name) \ +void \ +XXH3_accumulate_##name(xxh_u64* XXH_RESTRICT acc, \ + const xxh_u8* XXH_RESTRICT input, \ + const xxh_u8* XXH_RESTRICT secret, \ + size_t nbStripes) \ +{ \ + size_t n; \ + for (n = 0; n < nbStripes; n++ ) { \ + const xxh_u8* const in = input + n*XXH_STRIPE_LEN; \ + XXH_PREFETCH(in + XXH_PREFETCH_DIST); \ + XXH3_accumulate_512_##name( \ + acc, \ + in, \ + secret + n*XXH_SECRET_CONSUME_RATE); \ + } \ +} + + +XXH_FORCE_INLINE void XXH_writeLE64(void* dst, xxh_u64 v64) +{ + if (!XXH_CPU_LITTLE_ENDIAN) v64 = XXH_swap64(v64); + XXH_memcpy(dst, &v64, sizeof(v64)); +} + +/* Several intrinsic functions below are supposed to accept __int64 as argument, + * as documented in https://software.intel.com/sites/landingpage/IntrinsicsGuide/ . + * However, several environments do not define __int64 type, + * requiring a workaround. + */ +#if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) + typedef int64_t xxh_i64; +#else + /* the following type must have a width of 64-bit */ + typedef long long xxh_i64; +#endif + + +/* + * XXH3_accumulate_512 is the tightest loop for long inputs, and it is the most optimized. + * + * It is a hardened version of UMAC, based off of FARSH's implementation. + * + * This was chosen because it adapts quite well to 32-bit, 64-bit, and SIMD + * implementations, and it is ridiculously fast. + * + * We harden it by mixing the original input to the accumulators as well as the product. + * + * This means that in the (relatively likely) case of a multiply by zero, the + * original input is preserved. + * + * On 128-bit inputs, we swap 64-bit pairs when we add the input to improve + * cross-pollination, as otherwise the upper and lower halves would be + * essentially independent. + * + * This doesn't matter on 64-bit hashes since they all get merged together in + * the end, so we skip the extra step. + * + * Both XXH3_64bits and XXH3_128bits use this subroutine. + */ + +#if (XXH_VECTOR == XXH_AVX512) \ + || (defined(XXH_DISPATCH_AVX512) && XXH_DISPATCH_AVX512 != 0) + +#ifndef XXH_TARGET_AVX512 +# define XXH_TARGET_AVX512 /* disable attribute target */ +#endif + +XXH_FORCE_INLINE XXH_TARGET_AVX512 void +XXH3_accumulate_512_avx512(void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + __m512i* const xacc = (__m512i *) acc; + XXH_ASSERT((((size_t)acc) & 63) == 0); + XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); + + { + /* data_vec = input[0]; */ + __m512i const data_vec = _mm512_loadu_si512 (input); + /* key_vec = secret[0]; */ + __m512i const key_vec = _mm512_loadu_si512 (secret); + /* data_key = data_vec ^ key_vec; */ + __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m512i const data_key_lo = _mm512_srli_epi64 (data_key, 32); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m512i const product = _mm512_mul_epu32 (data_key, data_key_lo); + /* xacc[0] += swap(data_vec); */ + __m512i const data_swap = _mm512_shuffle_epi32(data_vec, (_MM_PERM_ENUM)_MM_SHUFFLE(1, 0, 3, 2)); + __m512i const sum = _mm512_add_epi64(*xacc, data_swap); + /* xacc[0] += product; */ + *xacc = _mm512_add_epi64(product, sum); + } +} +XXH_FORCE_INLINE XXH_TARGET_AVX512 XXH3_ACCUMULATE_TEMPLATE(avx512) + +/* + * XXH3_scrambleAcc: Scrambles the accumulators to improve mixing. + * + * Multiplication isn't perfect, as explained by Google in HighwayHash: + * + * // Multiplication mixes/scrambles bytes 0-7 of the 64-bit result to + * // varying degrees. In descending order of goodness, bytes + * // 3 4 2 5 1 6 0 7 have quality 228 224 164 160 100 96 36 32. + * // As expected, the upper and lower bytes are much worse. + * + * Source: https://github.com/google/highwayhash/blob/0aaf66b/highwayhash/hh_avx2.h#L291 + * + * Since our algorithm uses a pseudorandom secret to add some variance into the + * mix, we don't need to (or want to) mix as often or as much as HighwayHash does. + * + * This isn't as tight as XXH3_accumulate, but still written in SIMD to avoid + * extraction. + * + * Both XXH3_64bits and XXH3_128bits use this subroutine. + */ + +XXH_FORCE_INLINE XXH_TARGET_AVX512 void +XXH3_scrambleAcc_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 63) == 0); + XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); + { __m512i* const xacc = (__m512i*) acc; + const __m512i prime32 = _mm512_set1_epi32((int)XXH_PRIME32_1); + + /* xacc[0] ^= (xacc[0] >> 47) */ + __m512i const acc_vec = *xacc; + __m512i const shifted = _mm512_srli_epi64 (acc_vec, 47); + /* xacc[0] ^= secret; */ + __m512i const key_vec = _mm512_loadu_si512 (secret); + __m512i const data_key = _mm512_ternarylogic_epi32(key_vec, acc_vec, shifted, 0x96 /* key_vec ^ acc_vec ^ shifted */); + + /* xacc[0] *= XXH_PRIME32_1; */ + __m512i const data_key_hi = _mm512_srli_epi64 (data_key, 32); + __m512i const prod_lo = _mm512_mul_epu32 (data_key, prime32); + __m512i const prod_hi = _mm512_mul_epu32 (data_key_hi, prime32); + *xacc = _mm512_add_epi64(prod_lo, _mm512_slli_epi64(prod_hi, 32)); + } +} + +XXH_FORCE_INLINE XXH_TARGET_AVX512 void +XXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 63) == 0); + XXH_STATIC_ASSERT(XXH_SEC_ALIGN == 64); + XXH_ASSERT(((size_t)customSecret & 63) == 0); + (void)(&XXH_writeLE64); + { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m512i); + __m512i const seed_pos = _mm512_set1_epi64((xxh_i64)seed64); + __m512i const seed = _mm512_mask_sub_epi64(seed_pos, 0xAA, _mm512_set1_epi8(0), seed_pos); + + const __m512i* const src = (const __m512i*) ((const void*) XXH3_kSecret); + __m512i* const dest = ( __m512i*) customSecret; + int i; + XXH_ASSERT(((size_t)src & 63) == 0); /* control alignment */ + XXH_ASSERT(((size_t)dest & 63) == 0); + for (i=0; i < nbRounds; ++i) { + dest[i] = _mm512_add_epi64(_mm512_load_si512(src + i), seed); + } } +} + +#endif + +#if (XXH_VECTOR == XXH_AVX2) \ + || (defined(XXH_DISPATCH_AVX2) && XXH_DISPATCH_AVX2 != 0) + +#ifndef XXH_TARGET_AVX2 +# define XXH_TARGET_AVX2 /* disable attribute target */ +#endif + +XXH_FORCE_INLINE XXH_TARGET_AVX2 void +XXH3_accumulate_512_avx2( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 31) == 0); + { __m256i* const xacc = (__m256i *) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ + const __m256i* const xinput = (const __m256i *) input; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ + const __m256i* const xsecret = (const __m256i *) secret; + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { + /* data_vec = xinput[i]; */ + __m256i const data_vec = _mm256_loadu_si256 (xinput+i); + /* key_vec = xsecret[i]; */ + __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); + /* data_key = data_vec ^ key_vec; */ + __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m256i const data_key_lo = _mm256_srli_epi64 (data_key, 32); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m256i const product = _mm256_mul_epu32 (data_key, data_key_lo); + /* xacc[i] += swap(data_vec); */ + __m256i const data_swap = _mm256_shuffle_epi32(data_vec, _MM_SHUFFLE(1, 0, 3, 2)); + __m256i const sum = _mm256_add_epi64(xacc[i], data_swap); + /* xacc[i] += product; */ + xacc[i] = _mm256_add_epi64(product, sum); + } } +} +XXH_FORCE_INLINE XXH_TARGET_AVX2 XXH3_ACCUMULATE_TEMPLATE(avx2) + +XXH_FORCE_INLINE XXH_TARGET_AVX2 void +XXH3_scrambleAcc_avx2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 31) == 0); + { __m256i* const xacc = (__m256i*) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ + const __m256i* const xsecret = (const __m256i *) secret; + const __m256i prime32 = _mm256_set1_epi32((int)XXH_PRIME32_1); + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { + /* xacc[i] ^= (xacc[i] >> 47) */ + __m256i const acc_vec = xacc[i]; + __m256i const shifted = _mm256_srli_epi64 (acc_vec, 47); + __m256i const data_vec = _mm256_xor_si256 (acc_vec, shifted); + /* xacc[i] ^= xsecret; */ + __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); + __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); + + /* xacc[i] *= XXH_PRIME32_1; */ + __m256i const data_key_hi = _mm256_srli_epi64 (data_key, 32); + __m256i const prod_lo = _mm256_mul_epu32 (data_key, prime32); + __m256i const prod_hi = _mm256_mul_epu32 (data_key_hi, prime32); + xacc[i] = _mm256_add_epi64(prod_lo, _mm256_slli_epi64(prod_hi, 32)); + } + } +} + +XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_initCustomSecret_avx2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 31) == 0); + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE / sizeof(__m256i)) == 6); + XXH_STATIC_ASSERT(XXH_SEC_ALIGN <= 64); + (void)(&XXH_writeLE64); + XXH_PREFETCH(customSecret); + { __m256i const seed = _mm256_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64, (xxh_i64)(0U - seed64), (xxh_i64)seed64); + + const __m256i* const src = (const __m256i*) ((const void*) XXH3_kSecret); + __m256i* dest = ( __m256i*) customSecret; + +# if defined(__GNUC__) || defined(__clang__) + /* + * On GCC & Clang, marking 'dest' as modified will cause the compiler: + * - do not extract the secret from sse registers in the internal loop + * - use less common registers, and avoid pushing these reg into stack + */ + XXH_COMPILER_GUARD(dest); +# endif + XXH_ASSERT(((size_t)src & 31) == 0); /* control alignment */ + XXH_ASSERT(((size_t)dest & 31) == 0); + + /* GCC -O2 need unroll loop manually */ + dest[0] = _mm256_add_epi64(_mm256_load_si256(src+0), seed); + dest[1] = _mm256_add_epi64(_mm256_load_si256(src+1), seed); + dest[2] = _mm256_add_epi64(_mm256_load_si256(src+2), seed); + dest[3] = _mm256_add_epi64(_mm256_load_si256(src+3), seed); + dest[4] = _mm256_add_epi64(_mm256_load_si256(src+4), seed); + dest[5] = _mm256_add_epi64(_mm256_load_si256(src+5), seed); + } +} + +#endif + +/* x86dispatch always generates SSE2 */ +#if (XXH_VECTOR == XXH_SSE2) || defined(XXH_X86DISPATCH) + +#ifndef XXH_TARGET_SSE2 +# define XXH_TARGET_SSE2 /* disable attribute target */ +#endif + +XXH_FORCE_INLINE XXH_TARGET_SSE2 void +XXH3_accumulate_512_sse2( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + /* SSE2 is just a half-scale version of the AVX2 version. */ + XXH_ASSERT((((size_t)acc) & 15) == 0); + { __m128i* const xacc = (__m128i *) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ + const __m128i* const xinput = (const __m128i *) input; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ + const __m128i* const xsecret = (const __m128i *) secret; + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { + /* data_vec = xinput[i]; */ + __m128i const data_vec = _mm_loadu_si128 (xinput+i); + /* key_vec = xsecret[i]; */ + __m128i const key_vec = _mm_loadu_si128 (xsecret+i); + /* data_key = data_vec ^ key_vec; */ + __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m128i const data_key_lo = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m128i const product = _mm_mul_epu32 (data_key, data_key_lo); + /* xacc[i] += swap(data_vec); */ + __m128i const data_swap = _mm_shuffle_epi32(data_vec, _MM_SHUFFLE(1,0,3,2)); + __m128i const sum = _mm_add_epi64(xacc[i], data_swap); + /* xacc[i] += product; */ + xacc[i] = _mm_add_epi64(product, sum); + } } +} +XXH_FORCE_INLINE XXH_TARGET_SSE2 XXH3_ACCUMULATE_TEMPLATE(sse2) + +XXH_FORCE_INLINE XXH_TARGET_SSE2 void +XXH3_scrambleAcc_sse2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + { __m128i* const xacc = (__m128i*) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ + const __m128i* const xsecret = (const __m128i *) secret; + const __m128i prime32 = _mm_set1_epi32((int)XXH_PRIME32_1); + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { + /* xacc[i] ^= (xacc[i] >> 47) */ + __m128i const acc_vec = xacc[i]; + __m128i const shifted = _mm_srli_epi64 (acc_vec, 47); + __m128i const data_vec = _mm_xor_si128 (acc_vec, shifted); + /* xacc[i] ^= xsecret[i]; */ + __m128i const key_vec = _mm_loadu_si128 (xsecret+i); + __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); + + /* xacc[i] *= XXH_PRIME32_1; */ + __m128i const data_key_hi = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); + __m128i const prod_lo = _mm_mul_epu32 (data_key, prime32); + __m128i const prod_hi = _mm_mul_epu32 (data_key_hi, prime32); + xacc[i] = _mm_add_epi64(prod_lo, _mm_slli_epi64(prod_hi, 32)); + } + } +} + +XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_initCustomSecret_sse2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); + (void)(&XXH_writeLE64); + { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m128i); + +# if defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER < 1900 + /* MSVC 32bit mode does not support _mm_set_epi64x before 2015 */ + XXH_ALIGN(16) const xxh_i64 seed64x2[2] = { (xxh_i64)seed64, (xxh_i64)(0U - seed64) }; + __m128i const seed = _mm_load_si128((__m128i const*)seed64x2); +# else + __m128i const seed = _mm_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64); +# endif + int i; + + const void* const src16 = XXH3_kSecret; + __m128i* dst16 = (__m128i*) customSecret; +# if defined(__GNUC__) || defined(__clang__) + /* + * On GCC & Clang, marking 'dest' as modified will cause the compiler: + * - do not extract the secret from sse registers in the internal loop + * - use less common registers, and avoid pushing these reg into stack + */ + XXH_COMPILER_GUARD(dst16); +# endif + XXH_ASSERT(((size_t)src16 & 15) == 0); /* control alignment */ + XXH_ASSERT(((size_t)dst16 & 15) == 0); + + for (i=0; i < nbRounds; ++i) { + dst16[i] = _mm_add_epi64(_mm_load_si128((const __m128i *)src16+i), seed); + } } +} + +#endif + +#if (XXH_VECTOR == XXH_NEON) + +/* forward declarations for the scalar routines */ +XXH_FORCE_INLINE void +XXH3_scalarRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT input, + void const* XXH_RESTRICT secret, size_t lane); + +XXH_FORCE_INLINE void +XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, + void const* XXH_RESTRICT secret, size_t lane); + +/*! + * @internal + * @brief The bulk processing loop for NEON and WASM SIMD128. + * + * The NEON code path is actually partially scalar when running on AArch64. This + * is to optimize the pipelining and can have up to 15% speedup depending on the + * CPU, and it also mitigates some GCC codegen issues. + * + * @see XXH3_NEON_LANES for configuring this and details about this optimization. + * + * NEON's 32-bit to 64-bit long multiply takes a half vector of 32-bit + * integers instead of the other platforms which mask full 64-bit vectors, + * so the setup is more complicated than just shifting right. + * + * Additionally, there is an optimization for 4 lanes at once noted below. + * + * Since, as stated, the most optimal amount of lanes for Cortexes is 6, + * there needs to be *three* versions of the accumulate operation used + * for the remaining 2 lanes. + * + * WASM's SIMD128 uses SIMDe's arm_neon.h polyfill because the intrinsics overlap + * nearly perfectly. + */ + +XXH_FORCE_INLINE void +XXH3_accumulate_512_neon( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + XXH_STATIC_ASSERT(XXH3_NEON_LANES > 0 && XXH3_NEON_LANES <= XXH_ACC_NB && XXH3_NEON_LANES % 2 == 0); + { /* GCC for darwin arm64 does not like aliasing here */ + xxh_aliasing_uint64x2_t* const xacc = (xxh_aliasing_uint64x2_t*) acc; + /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */ + uint8_t const* xinput = (const uint8_t *) input; + uint8_t const* xsecret = (const uint8_t *) secret; + + size_t i; +#ifdef __wasm_simd128__ + /* + * On WASM SIMD128, Clang emits direct address loads when XXH3_kSecret + * is constant propagated, which results in it converting it to this + * inside the loop: + * + * a = v128.load(XXH3_kSecret + 0 + $secret_offset, offset = 0) + * b = v128.load(XXH3_kSecret + 16 + $secret_offset, offset = 0) + * ... + * + * This requires a full 32-bit address immediate (and therefore a 6 byte + * instruction) as well as an add for each offset. + * + * Putting an asm guard prevents it from folding (at the cost of losing + * the alignment hint), and uses the free offset in `v128.load` instead + * of adding secret_offset each time which overall reduces code size by + * about a kilobyte and improves performance. + */ + XXH_COMPILER_GUARD(xsecret); +#endif + /* Scalar lanes use the normal scalarRound routine */ + for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { + XXH3_scalarRound(acc, input, secret, i); + } + i = 0; + /* 4 NEON lanes at a time. */ + for (; i+1 < XXH3_NEON_LANES / 2; i+=2) { + /* data_vec = xinput[i]; */ + uint64x2_t data_vec_1 = XXH_vld1q_u64(xinput + (i * 16)); + uint64x2_t data_vec_2 = XXH_vld1q_u64(xinput + ((i+1) * 16)); + /* key_vec = xsecret[i]; */ + uint64x2_t key_vec_1 = XXH_vld1q_u64(xsecret + (i * 16)); + uint64x2_t key_vec_2 = XXH_vld1q_u64(xsecret + ((i+1) * 16)); + /* data_swap = swap(data_vec) */ + uint64x2_t data_swap_1 = vextq_u64(data_vec_1, data_vec_1, 1); + uint64x2_t data_swap_2 = vextq_u64(data_vec_2, data_vec_2, 1); + /* data_key = data_vec ^ key_vec; */ + uint64x2_t data_key_1 = veorq_u64(data_vec_1, key_vec_1); + uint64x2_t data_key_2 = veorq_u64(data_vec_2, key_vec_2); + + /* + * If we reinterpret the 64x2 vectors as 32x4 vectors, we can use a + * de-interleave operation for 4 lanes in 1 step with `vuzpq_u32` to + * get one vector with the low 32 bits of each lane, and one vector + * with the high 32 bits of each lane. + * + * The intrinsic returns a double vector because the original ARMv7-a + * instruction modified both arguments in place. AArch64 and SIMD128 emit + * two instructions from this intrinsic. + * + * [ dk11L | dk11H | dk12L | dk12H ] -> [ dk11L | dk12L | dk21L | dk22L ] + * [ dk21L | dk21H | dk22L | dk22H ] -> [ dk11H | dk12H | dk21H | dk22H ] + */ + uint32x4x2_t unzipped = vuzpq_u32( + vreinterpretq_u32_u64(data_key_1), + vreinterpretq_u32_u64(data_key_2) + ); + /* data_key_lo = data_key & 0xFFFFFFFF */ + uint32x4_t data_key_lo = unzipped.val[0]; + /* data_key_hi = data_key >> 32 */ + uint32x4_t data_key_hi = unzipped.val[1]; + /* + * Then, we can split the vectors horizontally and multiply which, as for most + * widening intrinsics, have a variant that works on both high half vectors + * for free on AArch64. A similar instruction is available on SIMD128. + * + * sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi + */ + uint64x2_t sum_1 = XXH_vmlal_low_u32(data_swap_1, data_key_lo, data_key_hi); + uint64x2_t sum_2 = XXH_vmlal_high_u32(data_swap_2, data_key_lo, data_key_hi); + /* + * Clang reorders + * a += b * c; // umlal swap.2d, dkl.2s, dkh.2s + * c += a; // add acc.2d, acc.2d, swap.2d + * to + * c += a; // add acc.2d, acc.2d, swap.2d + * c += b * c; // umlal acc.2d, dkl.2s, dkh.2s + * + * While it would make sense in theory since the addition is faster, + * for reasons likely related to umlal being limited to certain NEON + * pipelines, this is worse. A compiler guard fixes this. + */ + XXH_COMPILER_GUARD_CLANG_NEON(sum_1); + XXH_COMPILER_GUARD_CLANG_NEON(sum_2); + /* xacc[i] = acc_vec + sum; */ + xacc[i] = vaddq_u64(xacc[i], sum_1); + xacc[i+1] = vaddq_u64(xacc[i+1], sum_2); + } + /* Operate on the remaining NEON lanes 2 at a time. */ + for (; i < XXH3_NEON_LANES / 2; i++) { + /* data_vec = xinput[i]; */ + uint64x2_t data_vec = XXH_vld1q_u64(xinput + (i * 16)); + /* key_vec = xsecret[i]; */ + uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16)); + /* acc_vec_2 = swap(data_vec) */ + uint64x2_t data_swap = vextq_u64(data_vec, data_vec, 1); + /* data_key = data_vec ^ key_vec; */ + uint64x2_t data_key = veorq_u64(data_vec, key_vec); + /* For two lanes, just use VMOVN and VSHRN. */ + /* data_key_lo = data_key & 0xFFFFFFFF; */ + uint32x2_t data_key_lo = vmovn_u64(data_key); + /* data_key_hi = data_key >> 32; */ + uint32x2_t data_key_hi = vshrn_n_u64(data_key, 32); + /* sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi; */ + uint64x2_t sum = vmlal_u32(data_swap, data_key_lo, data_key_hi); + /* Same Clang workaround as before */ + XXH_COMPILER_GUARD_CLANG_NEON(sum); + /* xacc[i] = acc_vec + sum; */ + xacc[i] = vaddq_u64 (xacc[i], sum); + } + } +} +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(neon) + +XXH_FORCE_INLINE void +XXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + + { xxh_aliasing_uint64x2_t* xacc = (xxh_aliasing_uint64x2_t*) acc; + uint8_t const* xsecret = (uint8_t const*) secret; + + size_t i; + /* WASM uses operator overloads and doesn't need these. */ +#ifndef __wasm_simd128__ + /* { prime32_1, prime32_1 } */ + uint32x2_t const kPrimeLo = vdup_n_u32(XXH_PRIME32_1); + /* { 0, prime32_1, 0, prime32_1 } */ + uint32x4_t const kPrimeHi = vreinterpretq_u32_u64(vdupq_n_u64((xxh_u64)XXH_PRIME32_1 << 32)); +#endif + + /* AArch64 uses both scalar and neon at the same time */ + for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) { + XXH3_scalarScrambleRound(acc, secret, i); + } + for (i=0; i < XXH3_NEON_LANES / 2; i++) { + /* xacc[i] ^= (xacc[i] >> 47); */ + uint64x2_t acc_vec = xacc[i]; + uint64x2_t shifted = vshrq_n_u64(acc_vec, 47); + uint64x2_t data_vec = veorq_u64(acc_vec, shifted); + + /* xacc[i] ^= xsecret[i]; */ + uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16)); + uint64x2_t data_key = veorq_u64(data_vec, key_vec); + /* xacc[i] *= XXH_PRIME32_1 */ +#ifdef __wasm_simd128__ + /* SIMD128 has multiply by u64x2, use it instead of expanding and scalarizing */ + xacc[i] = data_key * XXH_PRIME32_1; +#else + /* + * Expanded version with portable NEON intrinsics + * + * lo(x) * lo(y) + (hi(x) * lo(y) << 32) + * + * prod_hi = hi(data_key) * lo(prime) << 32 + * + * Since we only need 32 bits of this multiply a trick can be used, reinterpreting the vector + * as a uint32x4_t and multiplying by { 0, prime, 0, prime } to cancel out the unwanted bits + * and avoid the shift. + */ + uint32x4_t prod_hi = vmulq_u32 (vreinterpretq_u32_u64(data_key), kPrimeHi); + /* Extract low bits for vmlal_u32 */ + uint32x2_t data_key_lo = vmovn_u64(data_key); + /* xacc[i] = prod_hi + lo(data_key) * XXH_PRIME32_1; */ + xacc[i] = vmlal_u32(vreinterpretq_u64_u32(prod_hi), data_key_lo, kPrimeLo); +#endif + } + } +} +#endif + +#if (XXH_VECTOR == XXH_VSX) + +XXH_FORCE_INLINE void +XXH3_accumulate_512_vsx( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + /* presumed aligned */ + xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc; + xxh_u8 const* const xinput = (xxh_u8 const*) input; /* no alignment restriction */ + xxh_u8 const* const xsecret = (xxh_u8 const*) secret; /* no alignment restriction */ + xxh_u64x2 const v32 = { 32, 32 }; + size_t i; + for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { + /* data_vec = xinput[i]; */ + xxh_u64x2 const data_vec = XXH_vec_loadu(xinput + 16*i); + /* key_vec = xsecret[i]; */ + xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i); + xxh_u64x2 const data_key = data_vec ^ key_vec; + /* shuffled = (data_key << 32) | (data_key >> 32); */ + xxh_u32x4 const shuffled = (xxh_u32x4)vec_rl(data_key, v32); + /* product = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)shuffled & 0xFFFFFFFF); */ + xxh_u64x2 const product = XXH_vec_mulo((xxh_u32x4)data_key, shuffled); + /* acc_vec = xacc[i]; */ + xxh_u64x2 acc_vec = xacc[i]; + acc_vec += product; + + /* swap high and low halves */ +#ifdef __s390x__ + acc_vec += vec_permi(data_vec, data_vec, 2); +#else + acc_vec += vec_xxpermdi(data_vec, data_vec, 2); +#endif + xacc[i] = acc_vec; + } +} +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(vsx) + +XXH_FORCE_INLINE void +XXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + + { xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc; + const xxh_u8* const xsecret = (const xxh_u8*) secret; + /* constants */ + xxh_u64x2 const v32 = { 32, 32 }; + xxh_u64x2 const v47 = { 47, 47 }; + xxh_u32x4 const prime = { XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1 }; + size_t i; + for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { + /* xacc[i] ^= (xacc[i] >> 47); */ + xxh_u64x2 const acc_vec = xacc[i]; + xxh_u64x2 const data_vec = acc_vec ^ (acc_vec >> v47); + + /* xacc[i] ^= xsecret[i]; */ + xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i); + xxh_u64x2 const data_key = data_vec ^ key_vec; + + /* xacc[i] *= XXH_PRIME32_1 */ + /* prod_lo = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)prime & 0xFFFFFFFF); */ + xxh_u64x2 const prod_even = XXH_vec_mule((xxh_u32x4)data_key, prime); + /* prod_hi = ((xxh_u64x2)data_key >> 32) * ((xxh_u64x2)prime >> 32); */ + xxh_u64x2 const prod_odd = XXH_vec_mulo((xxh_u32x4)data_key, prime); + xacc[i] = prod_odd + (prod_even << v32); + } } +} + +#endif + +#if (XXH_VECTOR == XXH_SVE) + +XXH_FORCE_INLINE void +XXH3_accumulate_512_sve( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + uint64_t *xacc = (uint64_t *)acc; + const uint64_t *xinput = (const uint64_t *)(const void *)input; + const uint64_t *xsecret = (const uint64_t *)(const void *)secret; + svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1); + uint64_t element_count = svcntd(); + if (element_count >= 8) { + svbool_t mask = svptrue_pat_b64(SV_VL8); + svuint64_t vacc = svld1_u64(mask, xacc); + ACCRND(vacc, 0); + svst1_u64(mask, xacc, vacc); + } else if (element_count == 2) { /* sve128 */ + svbool_t mask = svptrue_pat_b64(SV_VL2); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 2); + svuint64_t acc2 = svld1_u64(mask, xacc + 4); + svuint64_t acc3 = svld1_u64(mask, xacc + 6); + ACCRND(acc0, 0); + ACCRND(acc1, 2); + ACCRND(acc2, 4); + ACCRND(acc3, 6); + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 2, acc1); + svst1_u64(mask, xacc + 4, acc2); + svst1_u64(mask, xacc + 6, acc3); + } else { + svbool_t mask = svptrue_pat_b64(SV_VL4); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 4); + ACCRND(acc0, 0); + ACCRND(acc1, 4); + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 4, acc1); + } +} + +XXH_FORCE_INLINE void +XXH3_accumulate_sve(xxh_u64* XXH_RESTRICT acc, + const xxh_u8* XXH_RESTRICT input, + const xxh_u8* XXH_RESTRICT secret, + size_t nbStripes) +{ + if (nbStripes != 0) { + uint64_t *xacc = (uint64_t *)acc; + const uint64_t *xinput = (const uint64_t *)(const void *)input; + const uint64_t *xsecret = (const uint64_t *)(const void *)secret; + svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1); + uint64_t element_count = svcntd(); + if (element_count >= 8) { + svbool_t mask = svptrue_pat_b64(SV_VL8); + svuint64_t vacc = svld1_u64(mask, xacc + 0); + do { + /* svprfd(svbool_t, void *, enum svfprop); */ + svprfd(mask, xinput + 128, SV_PLDL1STRM); + ACCRND(vacc, 0); + xinput += 8; + xsecret += 1; + nbStripes--; + } while (nbStripes != 0); + + svst1_u64(mask, xacc + 0, vacc); + } else if (element_count == 2) { /* sve128 */ + svbool_t mask = svptrue_pat_b64(SV_VL2); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 2); + svuint64_t acc2 = svld1_u64(mask, xacc + 4); + svuint64_t acc3 = svld1_u64(mask, xacc + 6); + do { + svprfd(mask, xinput + 128, SV_PLDL1STRM); + ACCRND(acc0, 0); + ACCRND(acc1, 2); + ACCRND(acc2, 4); + ACCRND(acc3, 6); + xinput += 8; + xsecret += 1; + nbStripes--; + } while (nbStripes != 0); + + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 2, acc1); + svst1_u64(mask, xacc + 4, acc2); + svst1_u64(mask, xacc + 6, acc3); + } else { + svbool_t mask = svptrue_pat_b64(SV_VL4); + svuint64_t acc0 = svld1_u64(mask, xacc + 0); + svuint64_t acc1 = svld1_u64(mask, xacc + 4); + do { + svprfd(mask, xinput + 128, SV_PLDL1STRM); + ACCRND(acc0, 0); + ACCRND(acc1, 4); + xinput += 8; + xsecret += 1; + nbStripes--; + } while (nbStripes != 0); + + svst1_u64(mask, xacc + 0, acc0); + svst1_u64(mask, xacc + 4, acc1); + } + } +} + +#endif + +#if (XXH_VECTOR == XXH_LSX) +#define _LSX_SHUFFLE(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w)) + +XXH_FORCE_INLINE void +XXH3_accumulate_512_lsx( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + { + __m128i* const xacc = (__m128i *) acc; + const __m128i* const xinput = (const __m128i *) input; + const __m128i* const xsecret = (const __m128i *) secret; + + for (size_t i = 0; i < XXH_STRIPE_LEN / sizeof(__m128i); i++) { + /* data_vec = xinput[i]; */ + __m128i const data_vec = __lsx_vld(xinput + i, 0); + /* key_vec = xsecret[i]; */ + __m128i const key_vec = __lsx_vld(xsecret + i, 0); + /* data_key = data_vec ^ key_vec; */ + __m128i const data_key = __lsx_vxor_v(data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m128i const data_key_lo = __lsx_vsrli_d(data_key, 32); + // __m128i const data_key_lo = __lsx_vsrli_d(data_key, 32); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m128i const product = __lsx_vmulwev_d_wu(data_key, data_key_lo); + /* xacc[i] += swap(data_vec); */ + __m128i const data_swap = __lsx_vshuf4i_w(data_vec, _LSX_SHUFFLE(1, 0, 3, 2)); + __m128i const sum = __lsx_vadd_d(xacc[i], data_swap); + /* xacc[i] += product; */ + xacc[i] = __lsx_vadd_d(product, sum); + } + } +} +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(lsx) + +XXH_FORCE_INLINE void +XXH3_scrambleAcc_lsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + { + __m128i* const xacc = (__m128i*) acc; + const __m128i* const xsecret = (const __m128i *) secret; + const __m128i prime32 = __lsx_vreplgr2vr_w((int)XXH_PRIME32_1); + + for (size_t i = 0; i < XXH_STRIPE_LEN / sizeof(__m128i); i++) { + /* xacc[i] ^= (xacc[i] >> 47) */ + __m128i const acc_vec = xacc[i]; + __m128i const shifted = __lsx_vsrli_d(acc_vec, 47); + __m128i const data_vec = __lsx_vxor_v(acc_vec, shifted); + /* xacc[i] ^= xsecret[i]; */ + __m128i const key_vec = __lsx_vld(xsecret + i, 0); + __m128i const data_key = __lsx_vxor_v(data_vec, key_vec); + + /* xacc[i] *= XXH_PRIME32_1; */ + __m128i const data_key_hi = __lsx_vsrli_d(data_key, 32); + __m128i const prod_lo = __lsx_vmulwev_d_wu(data_key, prime32); + __m128i const prod_hi = __lsx_vmulwev_d_wu(data_key_hi, prime32); + xacc[i] = __lsx_vadd_d(prod_lo, __lsx_vslli_d(prod_hi, 32)); + } + } +} + +#endif + +/* scalar variants - universal */ + +#if defined(__aarch64__) && (defined(__GNUC__) || defined(__clang__)) +/* + * In XXH3_scalarRound(), GCC and Clang have a similar codegen issue, where they + * emit an excess mask and a full 64-bit multiply-add (MADD X-form). + * + * While this might not seem like much, as AArch64 is a 64-bit architecture, only + * big Cortex designs have a full 64-bit multiplier. + * + * On the little cores, the smaller 32-bit multiplier is used, and full 64-bit + * multiplies expand to 2-3 multiplies in microcode. This has a major penalty + * of up to 4 latency cycles and 2 stall cycles in the multiply pipeline. + * + * Thankfully, AArch64 still provides the 32-bit long multiply-add (UMADDL) which does + * not have this penalty and does the mask automatically. + */ +XXH_FORCE_INLINE xxh_u64 +XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc) +{ + xxh_u64 ret; + /* note: %x = 64-bit register, %w = 32-bit register */ + __asm__("umaddl %x0, %w1, %w2, %x3" : "=r" (ret) : "r" (lhs), "r" (rhs), "r" (acc)); + return ret; +} +#else +XXH_FORCE_INLINE xxh_u64 +XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc) +{ + return XXH_mult32to64((xxh_u32)lhs, (xxh_u32)rhs) + acc; +} +#endif + +/*! + * @internal + * @brief Scalar round for @ref XXH3_accumulate_512_scalar(). + * + * This is extracted to its own function because the NEON path uses a combination + * of NEON and scalar. + */ +XXH_FORCE_INLINE void +XXH3_scalarRound(void* XXH_RESTRICT acc, + void const* XXH_RESTRICT input, + void const* XXH_RESTRICT secret, + size_t lane) +{ + xxh_u64* xacc = (xxh_u64*) acc; + xxh_u8 const* xinput = (xxh_u8 const*) input; + xxh_u8 const* xsecret = (xxh_u8 const*) secret; + XXH_ASSERT(lane < XXH_ACC_NB); + XXH_ASSERT(((size_t)acc & (XXH_ACC_ALIGN-1)) == 0); + { + xxh_u64 const data_val = XXH_readLE64(xinput + lane * 8); + xxh_u64 const data_key = data_val ^ XXH_readLE64(xsecret + lane * 8); + xacc[lane ^ 1] += data_val; /* swap adjacent lanes */ + xacc[lane] = XXH_mult32to64_add64(data_key /* & 0xFFFFFFFF */, data_key >> 32, xacc[lane]); + } +} + +/*! + * @internal + * @brief Processes a 64 byte block of data using the scalar path. + */ +XXH_FORCE_INLINE void +XXH3_accumulate_512_scalar(void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + size_t i; + /* ARM GCC refuses to unroll this loop, resulting in a 24% slowdown on ARMv6. */ +#if defined(__GNUC__) && !defined(__clang__) \ + && (defined(__arm__) || defined(__thumb2__)) \ + && defined(__ARM_FEATURE_UNALIGNED) /* no unaligned access just wastes bytes */ \ + && XXH_SIZE_OPT <= 0 +# pragma GCC unroll 8 +#endif + for (i=0; i < XXH_ACC_NB; i++) { + XXH3_scalarRound(acc, input, secret, i); + } +} +XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(scalar) + +/*! + * @internal + * @brief Scalar scramble step for @ref XXH3_scrambleAcc_scalar(). + * + * This is extracted to its own function because the NEON path uses a combination + * of NEON and scalar. + */ +XXH_FORCE_INLINE void +XXH3_scalarScrambleRound(void* XXH_RESTRICT acc, + void const* XXH_RESTRICT secret, + size_t lane) +{ + xxh_u64* const xacc = (xxh_u64*) acc; /* presumed aligned */ + const xxh_u8* const xsecret = (const xxh_u8*) secret; /* no alignment restriction */ + XXH_ASSERT((((size_t)acc) & (XXH_ACC_ALIGN-1)) == 0); + XXH_ASSERT(lane < XXH_ACC_NB); + { + xxh_u64 const key64 = XXH_readLE64(xsecret + lane * 8); + xxh_u64 acc64 = xacc[lane]; + acc64 = XXH_xorshift64(acc64, 47); + acc64 ^= key64; + acc64 *= XXH_PRIME32_1; + xacc[lane] = acc64; + } +} + +/*! + * @internal + * @brief Scrambles the accumulators after a large chunk has been read + */ +XXH_FORCE_INLINE void +XXH3_scrambleAcc_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + size_t i; + for (i=0; i < XXH_ACC_NB; i++) { + XXH3_scalarScrambleRound(acc, secret, i); + } +} + +XXH_FORCE_INLINE void +XXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + /* + * We need a separate pointer for the hack below, + * which requires a non-const pointer. + * Any decent compiler will optimize this out otherwise. + */ + const xxh_u8* kSecretPtr = XXH3_kSecret; + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); + +#if defined(__GNUC__) && defined(__aarch64__) + /* + * UGLY HACK: + * GCC and Clang generate a bunch of MOV/MOVK pairs for aarch64, and they are + * placed sequentially, in order, at the top of the unrolled loop. + * + * While MOVK is great for generating constants (2 cycles for a 64-bit + * constant compared to 4 cycles for LDR), it fights for bandwidth with + * the arithmetic instructions. + * + * I L S + * MOVK + * MOVK + * MOVK + * MOVK + * ADD + * SUB STR + * STR + * By forcing loads from memory (as the asm line causes the compiler to assume + * that XXH3_kSecretPtr has been changed), the pipelines are used more + * efficiently: + * I L S + * LDR + * ADD LDR + * SUB STR + * STR + * + * See XXH3_NEON_LANES for details on the pipsline. + * + * XXH3_64bits_withSeed, len == 256, Snapdragon 835 + * without hack: 2654.4 MB/s + * with hack: 3202.9 MB/s + */ + XXH_COMPILER_GUARD(kSecretPtr); +#endif + { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / 16; + int i; + for (i=0; i < nbRounds; i++) { + /* + * The asm hack causes the compiler to assume that kSecretPtr aliases with + * customSecret, and on aarch64, this prevented LDP from merging two + * loads together for free. Putting the loads together before the stores + * properly generates LDP. + */ + xxh_u64 lo = XXH_readLE64(kSecretPtr + 16*i) + seed64; + xxh_u64 hi = XXH_readLE64(kSecretPtr + 16*i + 8) - seed64; + XXH_writeLE64((xxh_u8*)customSecret + 16*i, lo); + XXH_writeLE64((xxh_u8*)customSecret + 16*i + 8, hi); + } } +} + + +typedef void (*XXH3_f_accumulate)(xxh_u64* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, size_t); +typedef void (*XXH3_f_scrambleAcc)(void* XXH_RESTRICT, const void*); +typedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64); + + +#if (XXH_VECTOR == XXH_AVX512) + +#define XXH3_accumulate_512 XXH3_accumulate_512_avx512 +#define XXH3_accumulate XXH3_accumulate_avx512 +#define XXH3_scrambleAcc XXH3_scrambleAcc_avx512 +#define XXH3_initCustomSecret XXH3_initCustomSecret_avx512 + +#elif (XXH_VECTOR == XXH_AVX2) + +#define XXH3_accumulate_512 XXH3_accumulate_512_avx2 +#define XXH3_accumulate XXH3_accumulate_avx2 +#define XXH3_scrambleAcc XXH3_scrambleAcc_avx2 +#define XXH3_initCustomSecret XXH3_initCustomSecret_avx2 + +#elif (XXH_VECTOR == XXH_SSE2) + +#define XXH3_accumulate_512 XXH3_accumulate_512_sse2 +#define XXH3_accumulate XXH3_accumulate_sse2 +#define XXH3_scrambleAcc XXH3_scrambleAcc_sse2 +#define XXH3_initCustomSecret XXH3_initCustomSecret_sse2 + +#elif (XXH_VECTOR == XXH_NEON) + +#define XXH3_accumulate_512 XXH3_accumulate_512_neon +#define XXH3_accumulate XXH3_accumulate_neon +#define XXH3_scrambleAcc XXH3_scrambleAcc_neon +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#elif (XXH_VECTOR == XXH_VSX) + +#define XXH3_accumulate_512 XXH3_accumulate_512_vsx +#define XXH3_accumulate XXH3_accumulate_vsx +#define XXH3_scrambleAcc XXH3_scrambleAcc_vsx +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#elif (XXH_VECTOR == XXH_SVE) +#define XXH3_accumulate_512 XXH3_accumulate_512_sve +#define XXH3_accumulate XXH3_accumulate_sve +#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#elif (XXH_VECTOR == XXH_LSX) +#define XXH3_accumulate_512 XXH3_accumulate_512_lsx +#define XXH3_accumulate XXH3_accumulate_lsx +#define XXH3_scrambleAcc XXH3_scrambleAcc_lsx +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#else /* scalar */ + +#define XXH3_accumulate_512 XXH3_accumulate_512_scalar +#define XXH3_accumulate XXH3_accumulate_scalar +#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#endif + +#if XXH_SIZE_OPT >= 1 /* don't do SIMD for initialization */ +# undef XXH3_initCustomSecret +# define XXH3_initCustomSecret XXH3_initCustomSecret_scalar +#endif + +XXH_FORCE_INLINE void +XXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc, + const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + size_t const nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE; + size_t const block_len = XXH_STRIPE_LEN * nbStripesPerBlock; + size_t const nb_blocks = (len - 1) / block_len; + + size_t n; + + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); + + for (n = 0; n < nb_blocks; n++) { + f_acc(acc, input + n*block_len, secret, nbStripesPerBlock); + f_scramble(acc, secret + secretSize - XXH_STRIPE_LEN); + } + + /* last partial block */ + XXH_ASSERT(len > XXH_STRIPE_LEN); + { size_t const nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN; + XXH_ASSERT(nbStripes <= (secretSize / XXH_SECRET_CONSUME_RATE)); + f_acc(acc, input + nb_blocks*block_len, secret, nbStripes); + + /* last stripe */ + { const xxh_u8* const p = input + len - XXH_STRIPE_LEN; +#define XXH_SECRET_LASTACC_START 7 /* not aligned on 8, last secret is different from acc & scrambler */ + XXH3_accumulate_512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START); + } } +} + +XXH_FORCE_INLINE xxh_u64 +XXH3_mix2Accs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret) +{ + return XXH3_mul128_fold64( + acc[0] ^ XXH_readLE64(secret), + acc[1] ^ XXH_readLE64(secret+8) ); +} + +static XXH_PUREF XXH64_hash_t +XXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 start) +{ + xxh_u64 result64 = start; + size_t i = 0; + + for (i = 0; i < 4; i++) { + result64 += XXH3_mix2Accs(acc+2*i, secret + 16*i); +#if defined(__clang__) /* Clang */ \ + && (defined(__arm__) || defined(__thumb__)) /* ARMv7 */ \ + && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ + && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ + /* + * UGLY HACK: + * Prevent autovectorization on Clang ARMv7-a. Exact same problem as + * the one in XXH3_len_129to240_64b. Speeds up shorter keys > 240b. + * XXH3_64bits, len == 256, Snapdragon 835: + * without hack: 2063.7 MB/s + * with hack: 2560.7 MB/s + */ + XXH_COMPILER_GUARD(result64); +#endif + } + + return XXH3_avalanche(result64); +} + +/* do not align on 8, so that the secret is different from the accumulator */ +#define XXH_SECRET_MERGEACCS_START 11 + +static XXH_PUREF XXH64_hash_t +XXH3_finalizeLong_64b(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 len) +{ + return XXH3_mergeAccs(acc, secret + XXH_SECRET_MERGEACCS_START, len * XXH_PRIME64_1); +} + +#define XXH3_INIT_ACC { XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \ + XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 } + +XXH_FORCE_INLINE XXH64_hash_t +XXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len, + const void* XXH_RESTRICT secret, size_t secretSize, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; + + XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, (const xxh_u8*)secret, secretSize, f_acc, f_scramble); + + /* converge into final hash */ + XXH_STATIC_ASSERT(sizeof(acc) == 64); + XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); + return XXH3_finalizeLong_64b(acc, (const xxh_u8*)secret, (xxh_u64)len); +} + +/* + * It's important for performance to transmit secret's size (when it's static) + * so that the compiler can properly optimize the vectorized loop. + * This makes a big performance difference for "medium" keys (<1 KB) when using AVX instruction set. + * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE + * breaks -Og, this is XXH_NO_INLINE. + */ +XXH3_WITH_SECRET_INLINE XXH64_hash_t +XXH3_hashLong_64b_withSecret(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; + return XXH3_hashLong_64b_internal(input, len, secret, secretLen, XXH3_accumulate, XXH3_scrambleAcc); +} + +/* + * It's preferable for performance that XXH3_hashLong is not inlined, + * as it results in a smaller function for small data, easier to the instruction cache. + * Note that inside this no_inline function, we do inline the internal loop, + * and provide a statically defined secret size to allow optimization of vector loop. + */ +XXH_NO_INLINE XXH_PUREF XXH64_hash_t +XXH3_hashLong_64b_default(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate, XXH3_scrambleAcc); +} + +/* + * XXH3_hashLong_64b_withSeed(): + * Generate a custom key based on alteration of default XXH3_kSecret with the seed, + * and then use this key for long mode hashing. + * + * This operation is decently fast but nonetheless costs a little bit of time. + * Try to avoid it whenever possible (typically when seed==0). + * + * It's important for performance that XXH3_hashLong is not inlined. Not sure + * why (uop cache maybe?), but the difference is large and easily measurable. + */ +XXH_FORCE_INLINE XXH64_hash_t +XXH3_hashLong_64b_withSeed_internal(const void* input, size_t len, + XXH64_hash_t seed, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble, + XXH3_f_initCustomSecret f_initSec) +{ +#if XXH_SIZE_OPT <= 0 + if (seed == 0) + return XXH3_hashLong_64b_internal(input, len, + XXH3_kSecret, sizeof(XXH3_kSecret), + f_acc, f_scramble); +#endif + { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; + f_initSec(secret, seed); + return XXH3_hashLong_64b_internal(input, len, secret, sizeof(secret), + f_acc, f_scramble); + } +} + +/* + * It's important for performance that XXH3_hashLong is not inlined. + */ +XXH_NO_INLINE XXH64_hash_t +XXH3_hashLong_64b_withSeed(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + return XXH3_hashLong_64b_withSeed_internal(input, len, seed, + XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret); +} + + +typedef XXH64_hash_t (*XXH3_hashLong64_f)(const void* XXH_RESTRICT, size_t, + XXH64_hash_t, const xxh_u8* XXH_RESTRICT, size_t); + +XXH_FORCE_INLINE XXH64_hash_t +XXH3_64bits_internal(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, + XXH3_hashLong64_f f_hashLong) +{ + XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); + /* + * If an action is to be taken if `secretLen` condition is not respected, + * it should be done here. + * For now, it's a contract pre-condition. + * Adding a check and a branch here would cost performance at every hash. + * Also, note that function signature doesn't offer room to return an error. + */ + if (len <= 16) + return XXH3_len_0to16_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); + if (len <= 128) + return XXH3_len_17to128_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + if (len <= XXH3_MIDSIZE_MAX) + return XXH3_len_129to240_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + return f_hashLong(input, len, seed64, (const xxh_u8*)secret, secretLen); +} + + +/* === Public entry point === */ + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length) +{ + return XXH3_64bits_internal(input, length, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t +XXH3_64bits_withSecret(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize) +{ + return XXH3_64bits_internal(input, length, 0, secret, secretSize, XXH3_hashLong_64b_withSecret); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t +XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed) +{ + return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed); +} + +XXH_PUBLIC_API XXH64_hash_t +XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) +{ + if (length <= XXH3_MIDSIZE_MAX) + return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); + return XXH3_hashLong_64b_withSecret(input, length, seed, (const xxh_u8*)secret, secretSize); +} + + +/* === XXH3 streaming === */ +#ifndef XXH_NO_STREAM +/* + * Malloc's a pointer that is always aligned to @align. + * + * This must be freed with `XXH_alignedFree()`. + * + * malloc typically guarantees 16 byte alignment on 64-bit systems and 8 byte + * alignment on 32-bit. This isn't enough for the 32 byte aligned loads in AVX2 + * or on 32-bit, the 16 byte aligned loads in SSE2 and NEON. + * + * This underalignment previously caused a rather obvious crash which went + * completely unnoticed due to XXH3_createState() not actually being tested. + * Credit to RedSpah for noticing this bug. + * + * The alignment is done manually: Functions like posix_memalign or _mm_malloc + * are avoided: To maintain portability, we would have to write a fallback + * like this anyways, and besides, testing for the existence of library + * functions without relying on external build tools is impossible. + * + * The method is simple: Overallocate, manually align, and store the offset + * to the original behind the returned pointer. + * + * Align must be a power of 2 and 8 <= align <= 128. + */ +static XXH_MALLOCF void* XXH_alignedMalloc(size_t s, size_t align) +{ + XXH_ASSERT(align <= 128 && align >= 8); /* range check */ + XXH_ASSERT((align & (align-1)) == 0); /* power of 2 */ + XXH_ASSERT(s != 0 && s < (s + align)); /* empty/overflow */ + { /* Overallocate to make room for manual realignment and an offset byte */ + xxh_u8* base = (xxh_u8*)XXH_malloc(s + align); + if (base != NULL) { + /* + * Get the offset needed to align this pointer. + * + * Even if the returned pointer is aligned, there will always be + * at least one byte to store the offset to the original pointer. + */ + size_t offset = align - ((size_t)base & (align - 1)); /* base % align */ + /* Add the offset for the now-aligned pointer */ + xxh_u8* ptr = base + offset; + + XXH_ASSERT((size_t)ptr % align == 0); + + /* Store the offset immediately before the returned pointer. */ + ptr[-1] = (xxh_u8)offset; + return ptr; + } + return NULL; + } +} +/* + * Frees an aligned pointer allocated by XXH_alignedMalloc(). Don't pass + * normal malloc'd pointers, XXH_alignedMalloc has a specific data layout. + */ +static void XXH_alignedFree(void* p) +{ + if (p != NULL) { + xxh_u8* ptr = (xxh_u8*)p; + /* Get the offset byte we added in XXH_malloc. */ + xxh_u8 offset = ptr[-1]; + /* Free the original malloc'd pointer */ + xxh_u8* base = ptr - offset; + XXH_free(base); + } +} +/*! @ingroup XXH3_family */ +/*! + * @brief Allocate an @ref XXH3_state_t. + * + * @return An allocated pointer of @ref XXH3_state_t on success. + * @return `NULL` on failure. + * + * @note Must be freed with XXH3_freeState(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void) +{ + XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64); + if (state==NULL) return NULL; + XXH3_INITSTATE(state); + return state; +} + +/*! @ingroup XXH3_family */ +/*! + * @brief Frees an @ref XXH3_state_t. + * + * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState(). + * + * @return @ref XXH_OK. + * + * @note Must be allocated with XXH3_createState(). + * + * @see @ref streaming_example "Streaming Example" + */ +XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr) +{ + XXH_alignedFree(statePtr); + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API void +XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state) +{ + XXH_memcpy(dst_state, src_state, sizeof(*dst_state)); +} + +static void +XXH3_reset_internal(XXH3_state_t* statePtr, + XXH64_hash_t seed, + const void* secret, size_t secretSize) +{ + size_t const initStart = offsetof(XXH3_state_t, bufferedSize); + size_t const initLength = offsetof(XXH3_state_t, nbStripesPerBlock) - initStart; + XXH_ASSERT(offsetof(XXH3_state_t, nbStripesPerBlock) > initStart); + XXH_ASSERT(statePtr != NULL); + /* set members from bufferedSize to nbStripesPerBlock (excluded) to 0 */ + memset((char*)statePtr + initStart, 0, initLength); + statePtr->acc[0] = XXH_PRIME32_3; + statePtr->acc[1] = XXH_PRIME64_1; + statePtr->acc[2] = XXH_PRIME64_2; + statePtr->acc[3] = XXH_PRIME64_3; + statePtr->acc[4] = XXH_PRIME64_4; + statePtr->acc[5] = XXH_PRIME32_2; + statePtr->acc[6] = XXH_PRIME64_5; + statePtr->acc[7] = XXH_PRIME32_1; + statePtr->seed = seed; + statePtr->useSeed = (seed != 0); + statePtr->extSecret = (const unsigned char*)secret; + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); + statePtr->secretLimit = secretSize - XXH_STRIPE_LEN; + statePtr->nbStripesPerBlock = statePtr->secretLimit / XXH_SECRET_CONSUME_RATE; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr) +{ + if (statePtr == NULL) return XXH_ERROR; + XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE); + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize) +{ + if (statePtr == NULL) return XXH_ERROR; + XXH3_reset_internal(statePtr, 0, secret, secretSize); + if (secret == NULL) return XXH_ERROR; + if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed) +{ + if (statePtr == NULL) return XXH_ERROR; + if (seed==0) return XXH3_64bits_reset(statePtr); + if ((seed != statePtr->seed) || (statePtr->extSecret != NULL)) + XXH3_initCustomSecret(statePtr->customSecret, seed); + XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE); + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64) +{ + if (statePtr == NULL) return XXH_ERROR; + if (secret == NULL) return XXH_ERROR; + if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; + XXH3_reset_internal(statePtr, seed64, secret, secretSize); + statePtr->useSeed = 1; /* always, even if seed64==0 */ + return XXH_OK; +} + +/*! + * @internal + * @brief Processes a large input for XXH3_update() and XXH3_digest_long(). + * + * Unlike XXH3_hashLong_internal_loop(), this can process data that overlaps a block. + * + * @param acc Pointer to the 8 accumulator lanes + * @param nbStripesSoFarPtr In/out pointer to the number of leftover stripes in the block* + * @param nbStripesPerBlock Number of stripes in a block + * @param input Input pointer + * @param nbStripes Number of stripes to process + * @param secret Secret pointer + * @param secretLimit Offset of the last block in @p secret + * @param f_acc Pointer to an XXH3_accumulate implementation + * @param f_scramble Pointer to an XXH3_scrambleAcc implementation + * @return Pointer past the end of @p input after processing + */ +XXH_FORCE_INLINE const xxh_u8 * +XXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc, + size_t* XXH_RESTRICT nbStripesSoFarPtr, size_t nbStripesPerBlock, + const xxh_u8* XXH_RESTRICT input, size_t nbStripes, + const xxh_u8* XXH_RESTRICT secret, size_t secretLimit, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + const xxh_u8* initialSecret = secret + *nbStripesSoFarPtr * XXH_SECRET_CONSUME_RATE; + /* Process full blocks */ + if (nbStripes >= (nbStripesPerBlock - *nbStripesSoFarPtr)) { + /* Process the initial partial block... */ + size_t nbStripesThisIter = nbStripesPerBlock - *nbStripesSoFarPtr; + + do { + /* Accumulate and scramble */ + f_acc(acc, input, initialSecret, nbStripesThisIter); + f_scramble(acc, secret + secretLimit); + input += nbStripesThisIter * XXH_STRIPE_LEN; + nbStripes -= nbStripesThisIter; + /* Then continue the loop with the full block size */ + nbStripesThisIter = nbStripesPerBlock; + initialSecret = secret; + } while (nbStripes >= nbStripesPerBlock); + *nbStripesSoFarPtr = 0; + } + /* Process a partial block */ + if (nbStripes > 0) { + f_acc(acc, input, initialSecret, nbStripes); + input += nbStripes * XXH_STRIPE_LEN; + *nbStripesSoFarPtr += nbStripes; + } + /* Return end pointer */ + return input; +} + +#ifndef XXH3_STREAM_USE_STACK +# if XXH_SIZE_OPT <= 0 && !defined(__clang__) /* clang doesn't need additional stack space */ +# define XXH3_STREAM_USE_STACK 1 +# endif +#endif +/* + * Both XXH3_64bits_update and XXH3_128bits_update use this routine. + */ +XXH_FORCE_INLINE XXH_errorcode +XXH3_update(XXH3_state_t* XXH_RESTRICT const state, + const xxh_u8* XXH_RESTRICT input, size_t len, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + if (input==NULL) { + XXH_ASSERT(len == 0); + return XXH_OK; + } + + XXH_ASSERT(state != NULL); + { const xxh_u8* const bEnd = input + len; + const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; +#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1 + /* For some reason, gcc and MSVC seem to suffer greatly + * when operating accumulators directly into state. + * Operating into stack space seems to enable proper optimization. + * clang, on the other hand, doesn't seem to need this trick */ + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[8]; + XXH_memcpy(acc, state->acc, sizeof(acc)); +#else + xxh_u64* XXH_RESTRICT const acc = state->acc; +#endif + state->totalLen += len; + XXH_ASSERT(state->bufferedSize <= XXH3_INTERNALBUFFER_SIZE); + + /* small input : just fill in tmp buffer */ + if (len <= XXH3_INTERNALBUFFER_SIZE - state->bufferedSize) { + XXH_memcpy(state->buffer + state->bufferedSize, input, len); + state->bufferedSize += (XXH32_hash_t)len; + return XXH_OK; + } + + /* total input is now > XXH3_INTERNALBUFFER_SIZE */ + #define XXH3_INTERNALBUFFER_STRIPES (XXH3_INTERNALBUFFER_SIZE / XXH_STRIPE_LEN) + XXH_STATIC_ASSERT(XXH3_INTERNALBUFFER_SIZE % XXH_STRIPE_LEN == 0); /* clean multiple */ + + /* + * Internal buffer is partially filled (always, except at beginning) + * Complete it, then consume it. + */ + if (state->bufferedSize) { + size_t const loadSize = XXH3_INTERNALBUFFER_SIZE - state->bufferedSize; + XXH_memcpy(state->buffer + state->bufferedSize, input, loadSize); + input += loadSize; + XXH3_consumeStripes(acc, + &state->nbStripesSoFar, state->nbStripesPerBlock, + state->buffer, XXH3_INTERNALBUFFER_STRIPES, + secret, state->secretLimit, + f_acc, f_scramble); + state->bufferedSize = 0; + } + XXH_ASSERT(input < bEnd); + if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) { + size_t nbStripes = (size_t)(bEnd - 1 - input) / XXH_STRIPE_LEN; + input = XXH3_consumeStripes(acc, + &state->nbStripesSoFar, state->nbStripesPerBlock, + input, nbStripes, + secret, state->secretLimit, + f_acc, f_scramble); + XXH_memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN); + + } + /* Some remaining input (always) : buffer it */ + XXH_ASSERT(input < bEnd); + XXH_ASSERT(bEnd - input <= XXH3_INTERNALBUFFER_SIZE); + XXH_ASSERT(state->bufferedSize == 0); + XXH_memcpy(state->buffer, input, (size_t)(bEnd-input)); + state->bufferedSize = (XXH32_hash_t)(bEnd-input); +#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1 + /* save stack accumulators into state */ + XXH_memcpy(state->acc, acc, sizeof(acc)); +#endif + } + + return XXH_OK; +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) +{ + return XXH3_update(state, (const xxh_u8*)input, len, + XXH3_accumulate, XXH3_scrambleAcc); +} + + +XXH_FORCE_INLINE void +XXH3_digest_long (XXH64_hash_t* acc, + const XXH3_state_t* state, + const unsigned char* secret) +{ + xxh_u8 lastStripe[XXH_STRIPE_LEN]; + const xxh_u8* lastStripePtr; + + /* + * Digest on a local copy. This way, the state remains unaltered, and it can + * continue ingesting more input afterwards. + */ + XXH_memcpy(acc, state->acc, sizeof(state->acc)); + if (state->bufferedSize >= XXH_STRIPE_LEN) { + /* Consume remaining stripes then point to remaining data in buffer */ + size_t const nbStripes = (state->bufferedSize - 1) / XXH_STRIPE_LEN; + size_t nbStripesSoFar = state->nbStripesSoFar; + XXH3_consumeStripes(acc, + &nbStripesSoFar, state->nbStripesPerBlock, + state->buffer, nbStripes, + secret, state->secretLimit, + XXH3_accumulate, XXH3_scrambleAcc); + lastStripePtr = state->buffer + state->bufferedSize - XXH_STRIPE_LEN; + } else { /* bufferedSize < XXH_STRIPE_LEN */ + /* Copy to temp buffer */ + size_t const catchupSize = XXH_STRIPE_LEN - state->bufferedSize; + XXH_ASSERT(state->bufferedSize > 0); /* there is always some input buffered */ + XXH_memcpy(lastStripe, state->buffer + sizeof(state->buffer) - catchupSize, catchupSize); + XXH_memcpy(lastStripe + catchupSize, state->buffer, state->bufferedSize); + lastStripePtr = lastStripe; + } + /* Last stripe */ + XXH3_accumulate_512(acc, + lastStripePtr, + secret + state->secretLimit - XXH_SECRET_LASTACC_START); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* state) +{ + const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; + if (state->totalLen > XXH3_MIDSIZE_MAX) { + XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; + XXH3_digest_long(acc, state, secret); + return XXH3_finalizeLong_64b(acc, secret, (xxh_u64)state->totalLen); + } + /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */ + if (state->useSeed) + return XXH3_64bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); + return XXH3_64bits_withSecret(state->buffer, (size_t)(state->totalLen), + secret, state->secretLimit + XXH_STRIPE_LEN); +} +#endif /* !XXH_NO_STREAM */ + + +/* ========================================== + * XXH3 128 bits (a.k.a XXH128) + * ========================================== + * XXH3's 128-bit variant has better mixing and strength than the 64-bit variant, + * even without counting the significantly larger output size. + * + * For example, extra steps are taken to avoid the seed-dependent collisions + * in 17-240 byte inputs (See XXH3_mix16B and XXH128_mix32B). + * + * This strength naturally comes at the cost of some speed, especially on short + * lengths. Note that longer hashes are about as fast as the 64-bit version + * due to it using only a slight modification of the 64-bit loop. + * + * XXH128 is also more oriented towards 64-bit machines. It is still extremely + * fast for a _128-bit_ hash on 32-bit (it usually clears XXH64). + */ + +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_1to3_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + /* A doubled version of 1to3_64b with different constants. */ + XXH_ASSERT(input != NULL); + XXH_ASSERT(1 <= len && len <= 3); + XXH_ASSERT(secret != NULL); + /* + * len = 1: combinedl = { input[0], 0x01, input[0], input[0] } + * len = 2: combinedl = { input[1], 0x02, input[0], input[1] } + * len = 3: combinedl = { input[2], 0x03, input[0], input[1] } + */ + { xxh_u8 const c1 = input[0]; + xxh_u8 const c2 = input[len >> 1]; + xxh_u8 const c3 = input[len - 1]; + xxh_u32 const combinedl = ((xxh_u32)c1 <<16) | ((xxh_u32)c2 << 24) + | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); + xxh_u32 const combinedh = XXH_rotl32(XXH_swap32(combinedl), 13); + xxh_u64 const bitflipl = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; + xxh_u64 const bitfliph = (XXH_readLE32(secret+8) ^ XXH_readLE32(secret+12)) - seed; + xxh_u64 const keyed_lo = (xxh_u64)combinedl ^ bitflipl; + xxh_u64 const keyed_hi = (xxh_u64)combinedh ^ bitfliph; + XXH128_hash_t h128; + h128.low64 = XXH64_avalanche(keyed_lo); + h128.high64 = XXH64_avalanche(keyed_hi); + return h128; + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(4 <= len && len <= 8); + seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; + { xxh_u32 const input_lo = XXH_readLE32(input); + xxh_u32 const input_hi = XXH_readLE32(input + len - 4); + xxh_u64 const input_64 = input_lo + ((xxh_u64)input_hi << 32); + xxh_u64 const bitflip = (XXH_readLE64(secret+16) ^ XXH_readLE64(secret+24)) + seed; + xxh_u64 const keyed = input_64 ^ bitflip; + + /* Shift len to the left to ensure it is even, this avoids even multiplies. */ + XXH128_hash_t m128 = XXH_mult64to128(keyed, XXH_PRIME64_1 + (len << 2)); + + m128.high64 += (m128.low64 << 1); + m128.low64 ^= (m128.high64 >> 3); + + m128.low64 = XXH_xorshift64(m128.low64, 35); + m128.low64 *= PRIME_MX2; + m128.low64 = XXH_xorshift64(m128.low64, 28); + m128.high64 = XXH3_avalanche(m128.high64); + return m128; + } +} + +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(9 <= len && len <= 16); + { xxh_u64 const bitflipl = (XXH_readLE64(secret+32) ^ XXH_readLE64(secret+40)) - seed; + xxh_u64 const bitfliph = (XXH_readLE64(secret+48) ^ XXH_readLE64(secret+56)) + seed; + xxh_u64 const input_lo = XXH_readLE64(input); + xxh_u64 input_hi = XXH_readLE64(input + len - 8); + XXH128_hash_t m128 = XXH_mult64to128(input_lo ^ input_hi ^ bitflipl, XXH_PRIME64_1); + /* + * Put len in the middle of m128 to ensure that the length gets mixed to + * both the low and high bits in the 128x64 multiply below. + */ + m128.low64 += (xxh_u64)(len - 1) << 54; + input_hi ^= bitfliph; + /* + * Add the high 32 bits of input_hi to the high 32 bits of m128, then + * add the long product of the low 32 bits of input_hi and XXH_PRIME32_2 to + * the high 64 bits of m128. + * + * The best approach to this operation is different on 32-bit and 64-bit. + */ + if (sizeof(void *) < sizeof(xxh_u64)) { /* 32-bit */ + /* + * 32-bit optimized version, which is more readable. + * + * On 32-bit, it removes an ADC and delays a dependency between the two + * halves of m128.high64, but it generates an extra mask on 64-bit. + */ + m128.high64 += (input_hi & 0xFFFFFFFF00000000ULL) + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2); + } else { + /* + * 64-bit optimized (albeit more confusing) version. + * + * Uses some properties of addition and multiplication to remove the mask: + * + * Let: + * a = input_hi.lo = (input_hi & 0x00000000FFFFFFFF) + * b = input_hi.hi = (input_hi & 0xFFFFFFFF00000000) + * c = XXH_PRIME32_2 + * + * a + (b * c) + * Inverse Property: x + y - x == y + * a + (b * (1 + c - 1)) + * Distributive Property: x * (y + z) == (x * y) + (x * z) + * a + (b * 1) + (b * (c - 1)) + * Identity Property: x * 1 == x + * a + b + (b * (c - 1)) + * + * Substitute a, b, and c: + * input_hi.hi + input_hi.lo + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) + * + * Since input_hi.hi + input_hi.lo == input_hi, we get this: + * input_hi + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) + */ + m128.high64 += input_hi + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2 - 1); + } + /* m128 ^= XXH_swap64(m128 >> 64); */ + m128.low64 ^= XXH_swap64(m128.high64); + + { /* 128x64 multiply: h128 = m128 * XXH_PRIME64_2; */ + XXH128_hash_t h128 = XXH_mult64to128(m128.low64, XXH_PRIME64_2); + h128.high64 += m128.high64 * XXH_PRIME64_2; + + h128.low64 = XXH3_avalanche(h128.low64); + h128.high64 = XXH3_avalanche(h128.high64); + return h128; + } } +} + +/* + * Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN + */ +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_0to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(len <= 16); + { if (len > 8) return XXH3_len_9to16_128b(input, len, secret, seed); + if (len >= 4) return XXH3_len_4to8_128b(input, len, secret, seed); + if (len) return XXH3_len_1to3_128b(input, len, secret, seed); + { XXH128_hash_t h128; + xxh_u64 const bitflipl = XXH_readLE64(secret+64) ^ XXH_readLE64(secret+72); + xxh_u64 const bitfliph = XXH_readLE64(secret+80) ^ XXH_readLE64(secret+88); + h128.low64 = XXH64_avalanche(seed ^ bitflipl); + h128.high64 = XXH64_avalanche( seed ^ bitfliph); + return h128; + } } +} + +/* + * A bit slower than XXH3_mix16B, but handles multiply by zero better. + */ +XXH_FORCE_INLINE XXH128_hash_t +XXH128_mix32B(XXH128_hash_t acc, const xxh_u8* input_1, const xxh_u8* input_2, + const xxh_u8* secret, XXH64_hash_t seed) +{ + acc.low64 += XXH3_mix16B (input_1, secret+0, seed); + acc.low64 ^= XXH_readLE64(input_2) + XXH_readLE64(input_2 + 8); + acc.high64 += XXH3_mix16B (input_2, secret+16, seed); + acc.high64 ^= XXH_readLE64(input_1) + XXH_readLE64(input_1 + 8); + return acc; +} + + +XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(16 < len && len <= 128); + + { XXH128_hash_t acc; + acc.low64 = len * XXH_PRIME64_1; + acc.high64 = 0; + +#if XXH_SIZE_OPT >= 1 + { + /* Smaller, but slightly slower. */ + unsigned int i = (unsigned int)(len - 1) / 32; + do { + acc = XXH128_mix32B(acc, input+16*i, input+len-16*(i+1), secret+32*i, seed); + } while (i-- != 0); + } +#else + if (len > 32) { + if (len > 64) { + if (len > 96) { + acc = XXH128_mix32B(acc, input+48, input+len-64, secret+96, seed); + } + acc = XXH128_mix32B(acc, input+32, input+len-48, secret+64, seed); + } + acc = XXH128_mix32B(acc, input+16, input+len-32, secret+32, seed); + } + acc = XXH128_mix32B(acc, input, input+len-16, secret, seed); +#endif + { XXH128_hash_t h128; + h128.low64 = acc.low64 + acc.high64; + h128.high64 = (acc.low64 * XXH_PRIME64_1) + + (acc.high64 * XXH_PRIME64_4) + + ((len - seed) * XXH_PRIME64_2); + h128.low64 = XXH3_avalanche(h128.low64); + h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); + return h128; + } + } +} + +XXH_NO_INLINE XXH_PUREF XXH128_hash_t +XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); + + { XXH128_hash_t acc; + unsigned i; + acc.low64 = len * XXH_PRIME64_1; + acc.high64 = 0; + /* + * We set as `i` as offset + 32. We do this so that unchanged + * `len` can be used as upper bound. This reaches a sweet spot + * where both x86 and aarch64 get simple agen and good codegen + * for the loop. + */ + for (i = 32; i < 160; i += 32) { + acc = XXH128_mix32B(acc, + input + i - 32, + input + i - 16, + secret + i - 32, + seed); + } + acc.low64 = XXH3_avalanche(acc.low64); + acc.high64 = XXH3_avalanche(acc.high64); + /* + * NB: `i <= len` will duplicate the last 32-bytes if + * len % 32 was zero. This is an unfortunate necessity to keep + * the hash result stable. + */ + for (i=160; i <= len; i += 32) { + acc = XXH128_mix32B(acc, + input + i - 32, + input + i - 16, + secret + XXH3_MIDSIZE_STARTOFFSET + i - 160, + seed); + } + /* last bytes */ + acc = XXH128_mix32B(acc, + input + len - 16, + input + len - 32, + secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16, + (XXH64_hash_t)0 - seed); + + { XXH128_hash_t h128; + h128.low64 = acc.low64 + acc.high64; + h128.high64 = (acc.low64 * XXH_PRIME64_1) + + (acc.high64 * XXH_PRIME64_4) + + ((len - seed) * XXH_PRIME64_2); + h128.low64 = XXH3_avalanche(h128.low64); + h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); + return h128; + } + } +} + +static XXH_PUREF XXH128_hash_t +XXH3_finalizeLong_128b(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, xxh_u64 len) +{ + XXH128_hash_t h128; + h128.low64 = XXH3_finalizeLong_64b(acc, secret, len); + h128.high64 = XXH3_mergeAccs(acc, secret + secretSize + - XXH_STRIPE_LEN - XXH_SECRET_MERGEACCS_START, + ~(len * XXH_PRIME64_2)); + return h128; +} + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble) +{ + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; + + XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, secret, secretSize, f_acc, f_scramble); + + /* converge into final hash */ + XXH_STATIC_ASSERT(sizeof(acc) == 64); + XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); + return XXH3_finalizeLong_128b(acc, secret, secretSize, (xxh_u64)len); +} + +/* + * It's important for performance that XXH3_hashLong() is not inlined. + */ +XXH_NO_INLINE XXH_PUREF XXH128_hash_t +XXH3_hashLong_128b_default(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, + const void* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), + XXH3_accumulate, XXH3_scrambleAcc); +} + +/* + * It's important for performance to pass @p secretLen (when it's static) + * to the compiler, so that it can properly optimize the vectorized loop. + * + * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE + * breaks -Og, this is XXH_NO_INLINE. + */ +XXH3_WITH_SECRET_INLINE XXH128_hash_t +XXH3_hashLong_128b_withSecret(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, + const void* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; + return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, secretLen, + XXH3_accumulate, XXH3_scrambleAcc); +} + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_hashLong_128b_withSeed_internal(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, + XXH3_f_accumulate f_acc, + XXH3_f_scrambleAcc f_scramble, + XXH3_f_initCustomSecret f_initSec) +{ + if (seed64 == 0) + return XXH3_hashLong_128b_internal(input, len, + XXH3_kSecret, sizeof(XXH3_kSecret), + f_acc, f_scramble); + { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; + f_initSec(secret, seed64); + return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, sizeof(secret), + f_acc, f_scramble); + } +} + +/* + * It's important for performance that XXH3_hashLong is not inlined. + */ +XXH_NO_INLINE XXH128_hash_t +XXH3_hashLong_128b_withSeed(const void* input, size_t len, + XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + return XXH3_hashLong_128b_withSeed_internal(input, len, seed64, + XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret); +} + +typedef XXH128_hash_t (*XXH3_hashLong128_f)(const void* XXH_RESTRICT, size_t, + XXH64_hash_t, const void* XXH_RESTRICT, size_t); + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_128bits_internal(const void* input, size_t len, + XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, + XXH3_hashLong128_f f_hl128) +{ + XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); + /* + * If an action is to be taken if `secret` conditions are not respected, + * it should be done here. + * For now, it's a contract pre-condition. + * Adding a check and a branch here would cost performance at every hash. + */ + if (len <= 16) + return XXH3_len_0to16_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); + if (len <= 128) + return XXH3_len_17to128_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + if (len <= XXH3_MIDSIZE_MAX) + return XXH3_len_129to240_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + return f_hl128(input, len, seed64, secret, secretLen); +} + + +/* === Public XXH128 API === */ + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* input, size_t len) +{ + return XXH3_128bits_internal(input, len, 0, + XXH3_kSecret, sizeof(XXH3_kSecret), + XXH3_hashLong_128b_default); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH3_128bits_withSecret(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize) +{ + return XXH3_128bits_internal(input, len, 0, + (const xxh_u8*)secret, secretSize, + XXH3_hashLong_128b_withSecret); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH3_128bits_withSeed(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_128bits_internal(input, len, seed, + XXH3_kSecret, sizeof(XXH3_kSecret), + XXH3_hashLong_128b_withSeed); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) +{ + if (len <= XXH3_MIDSIZE_MAX) + return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL); + return XXH3_hashLong_128b_withSecret(input, len, seed, secret, secretSize); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH128(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_128bits_withSeed(input, len, seed); +} + + +/* === XXH3 128-bit streaming === */ +#ifndef XXH_NO_STREAM +/* + * All initialization and update functions are identical to 64-bit streaming variant. + * The only difference is the finalization routine. + */ + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr) +{ + return XXH3_64bits_reset(statePtr); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize) +{ + return XXH3_64bits_reset_withSecret(statePtr, secret, secretSize); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed) +{ + return XXH3_64bits_reset_withSeed(statePtr, seed); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed) +{ + return XXH3_64bits_reset_withSecretandSeed(statePtr, secret, secretSize, seed); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len) +{ + return XXH3_64bits_update(state, input, len); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* state) +{ + const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; + if (state->totalLen > XXH3_MIDSIZE_MAX) { + XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; + XXH3_digest_long(acc, state, secret); + XXH_ASSERT(state->secretLimit + XXH_STRIPE_LEN >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); + return XXH3_finalizeLong_128b(acc, secret, state->secretLimit + XXH_STRIPE_LEN, (xxh_u64)state->totalLen); + } + /* len <= XXH3_MIDSIZE_MAX : short code */ + if (state->useSeed) + return XXH3_128bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); + return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen), + secret, state->secretLimit + XXH_STRIPE_LEN); +} +#endif /* !XXH_NO_STREAM */ +/* 128-bit utility functions */ + +#include /* memcmp, memcpy */ + +/* return : 1 is equal, 0 if different */ +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2) +{ + /* note : XXH128_hash_t is compact, it has no padding byte */ + return !(memcmp(&h1, &h2, sizeof(h1))); +} + +/* This prototype is compatible with stdlib's qsort(). + * @return : >0 if *h128_1 > *h128_2 + * <0 if *h128_1 < *h128_2 + * =0 if *h128_1 == *h128_2 */ +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2) +{ + XXH128_hash_t const h1 = *(const XXH128_hash_t*)h128_1; + XXH128_hash_t const h2 = *(const XXH128_hash_t*)h128_2; + int const hcmp = (h1.high64 > h2.high64) - (h2.high64 > h1.high64); + /* note : bets that, in most cases, hash values are different */ + if (hcmp) return hcmp; + return (h1.low64 > h2.low64) - (h2.low64 > h1.low64); +} + + +/*====== Canonical representation ======*/ +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API void +XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH128_canonical_t) == sizeof(XXH128_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) { + hash.high64 = XXH_swap64(hash.high64); + hash.low64 = XXH_swap64(hash.low64); + } + XXH_memcpy(dst, &hash.high64, sizeof(hash.high64)); + XXH_memcpy((char*)dst + sizeof(hash.high64), &hash.low64, sizeof(hash.low64)); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src) +{ + XXH128_hash_t h; + h.high64 = XXH_readBE64(src); + h.low64 = XXH_readBE64(src->digest + 8); + return h; +} + + + +/* ========================================== + * Secret generators + * ========================================== + */ +#define XXH_MIN(x, y) (((x) > (y)) ? (y) : (x)) + +XXH_FORCE_INLINE void XXH3_combine16(void* dst, XXH128_hash_t h128) +{ + XXH_writeLE64( dst, XXH_readLE64(dst) ^ h128.low64 ); + XXH_writeLE64( (char*)dst+8, XXH_readLE64((char*)dst+8) ^ h128.high64 ); +} + +/*! @ingroup XXH3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize) +{ +#if (XXH_DEBUGLEVEL >= 1) + XXH_ASSERT(secretBuffer != NULL); + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); +#else + /* production mode, assert() are disabled */ + if (secretBuffer == NULL) return XXH_ERROR; + if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; +#endif + + if (customSeedSize == 0) { + customSeed = XXH3_kSecret; + customSeedSize = XXH_SECRET_DEFAULT_SIZE; + } +#if (XXH_DEBUGLEVEL >= 1) + XXH_ASSERT(customSeed != NULL); +#else + if (customSeed == NULL) return XXH_ERROR; +#endif + + /* Fill secretBuffer with a copy of customSeed - repeat as needed */ + { size_t pos = 0; + while (pos < secretSize) { + size_t const toCopy = XXH_MIN((secretSize - pos), customSeedSize); + memcpy((char*)secretBuffer + pos, customSeed, toCopy); + pos += toCopy; + } } + + { size_t const nbSeg16 = secretSize / 16; + size_t n; + XXH128_canonical_t scrambler; + XXH128_canonicalFromHash(&scrambler, XXH128(customSeed, customSeedSize, 0)); + for (n=0; n -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "COMP_ERR" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "COMP_ERR" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -585,7 +585,7 @@ Display version information and exit\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ibd2sdi.1 b/man/ibd2sdi.1 index 1441efce70c5..15ce9197c7f0 100644 --- a/man/ibd2sdi.1 +++ b/man/ibd2sdi.1 @@ -2,12 +2,12 @@ .\" Title: ibd2sdi .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "IBD2SDI" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "IBD2SDI" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -796,7 +796,7 @@ ibd2sdi \-\-skip\-pretty \&.\&./data/test/t1\&.ibd .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/innochecksum.1 b/man/innochecksum.1 index 29943afda6d0..5ba2cdc6cc05 100644 --- a/man/innochecksum.1 +++ b/man/innochecksum.1 @@ -2,12 +2,12 @@ .\" Title: innochecksum .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "INNOCHECKSUM" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "INNOCHECKSUM" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1377,7 +1377,7 @@ innochecksum\&.exe ibdata3 .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/lz4_decompress.1 b/man/lz4_decompress.1 index 4823025843ed..20cdd37f5278 100644 --- a/man/lz4_decompress.1 +++ b/man/lz4_decompress.1 @@ -2,12 +2,12 @@ .\" Title: lz4_decompress .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "LZ4_DECOMPRESS" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "LZ4_DECOMPRESS" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -120,7 +120,7 @@ zlib_decompress(1)\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/my_print_defaults.1 b/man/my_print_defaults.1 index 159b0d360506..a19619cdb8bf 100644 --- a/man/my_print_defaults.1 +++ b/man/my_print_defaults.1 @@ -2,12 +2,12 @@ .\" Title: my_print_defaults .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MY_PRINT_DEFAULTS" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MY_PRINT_DEFAULTS" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -221,7 +221,7 @@ Display version information and exit\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/myisam_ftdump.1 b/man/myisam_ftdump.1 index 99db4a6367a6..8c54e50d354f 100644 --- a/man/myisam_ftdump.1 +++ b/man/myisam_ftdump.1 @@ -2,12 +2,12 @@ .\" Title: myisam_ftdump .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYISAM_FTDUMP" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYISAM_FTDUMP" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -304,7 +304,7 @@ Verbose mode\&. Print more output about what the program does\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/myisamchk.1 b/man/myisamchk.1 index 9adf9b0aa6be..0b0b341a9c24 100644 --- a/man/myisamchk.1 +++ b/man/myisamchk.1 @@ -2,12 +2,12 @@ .\" Title: myisamchk .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYISAMCHK" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYISAMCHK" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -2945,7 +2945,7 @@ instead of .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/myisamlog.1 b/man/myisamlog.1 index e90d04bb1668..9effa98bb454 100644 --- a/man/myisamlog.1 +++ b/man/myisamlog.1 @@ -2,12 +2,12 @@ .\" Title: myisamlog .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYISAMLOG" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYISAMLOG" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -240,7 +240,7 @@ Display version information\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/myisampack.1 b/man/myisampack.1 index 7f8ec3c1f7e5..5bb2f64a42dc 100644 --- a/man/myisampack.1 +++ b/man/myisampack.1 @@ -2,12 +2,12 @@ .\" Title: myisampack .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYISAMPACK" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYISAMPACK" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -966,7 +966,7 @@ option to .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysql.1 b/man/mysql.1 index dfe7593585b0..4f1b6ff57690 100644 --- a/man/mysql.1 +++ b/man/mysql.1 @@ -2,12 +2,12 @@ .\" Title: mysql .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQL" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQL" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -6488,7 +6488,7 @@ command)\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysql.server.1 b/man/mysql.server.1 index 326ece2ea785..ff548491e1b8 100644 --- a/man/mysql.server.1 +++ b/man/mysql.server.1 @@ -2,12 +2,12 @@ .\" Title: mysql.server .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQL\&.SERVER" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQL\&.SERVER" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -415,7 +415,7 @@ exits with an error\&. The default value is 900\&. A value of 0 means not to wai .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysql_config.1 b/man/mysql_config.1 index 89d91cb3b50f..4c25605a1840 100644 --- a/man/mysql_config.1 +++ b/man/mysql_config.1 @@ -2,12 +2,12 @@ .\" Title: mysql_config .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQL_CONFIG" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQL_CONFIG" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -245,7 +245,7 @@ gcc \-o progname progname\&.o `mysql_config \-\-libs` .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysql_config_editor.1 b/man/mysql_config_editor.1 index 906bd741b1be..1d6bddad965a 100644 --- a/man/mysql_config_editor.1 +++ b/man/mysql_config_editor.1 @@ -2,12 +2,12 @@ .\" Title: mysql_config_editor .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQL_CONFIG_EDITOR" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQL_CONFIG_EDITOR" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1132,7 +1132,7 @@ to disable it\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysql_migrate_keyring.1 b/man/mysql_migrate_keyring.1 index 105d933d560d..8072807fe85f 100644 --- a/man/mysql_migrate_keyring.1 +++ b/man/mysql_migrate_keyring.1 @@ -2,12 +2,12 @@ .\" Title: mysql_migrate_keyring .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQL_MIGRATE_KEYRING" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQL_MIGRATE_KEYRING" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1102,7 +1102,7 @@ Display version information and exit\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysql_secure_installation.1 b/man/mysql_secure_installation.1 index 56782d61798b..d907e2c2e08b 100644 --- a/man/mysql_secure_installation.1 +++ b/man/mysql_secure_installation.1 @@ -2,12 +2,12 @@ .\" Title: mysql_secure_installation .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQL_SECURE_INSTALLATION" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQL_SECURE_INSTALLATION" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -792,7 +792,7 @@ The user name of the MySQL account to use for connecting to the server\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysql_ssl_rsa_setup.1 b/man/mysql_ssl_rsa_setup.1 index 6763fb56ab15..8b5e2d65c108 100644 --- a/man/mysql_ssl_rsa_setup.1 +++ b/man/mysql_ssl_rsa_setup.1 @@ -2,12 +2,12 @@ .\" Title: mysql_ssl_rsa_setup .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQL_SSL_RSA_SETUP" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQL_SSL_RSA_SETUP" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -545,7 +545,7 @@ Display version information and exit\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysql_tzinfo_to_sql.1 b/man/mysql_tzinfo_to_sql.1 index 06cf5e2f9c75..3f0a28808b34 100644 --- a/man/mysql_tzinfo_to_sql.1 +++ b/man/mysql_tzinfo_to_sql.1 @@ -2,12 +2,12 @@ .\" Title: mysql_tzinfo_to_sql .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQL_TZINFO_TO_SQL" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQL_TZINFO_TO_SQL" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -120,7 +120,7 @@ After running .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysql_upgrade.1 b/man/mysql_upgrade.1 index 3a58e0a449e4..739953fefc38 100644 --- a/man/mysql_upgrade.1 +++ b/man/mysql_upgrade.1 @@ -2,12 +2,12 @@ .\" Title: mysql_upgrade .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQL_UPGRADE" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQL_UPGRADE" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1890,7 +1890,7 @@ This option was added in MySQL 8\&.0\&.18\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqladmin.1 b/man/mysqladmin.1 index dc3beb81546e..ac3c66bb184f 100644 --- a/man/mysqladmin.1 +++ b/man/mysqladmin.1 @@ -2,12 +2,12 @@ .\" Title: mysqladmin .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLADMIN" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQLADMIN" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -2322,7 +2322,7 @@ This option was added in MySQL 8\&.0\&.18\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqlbinlog.1 b/man/mysqlbinlog.1 index 4be489a3aa2a..cb6c72472384 100644 --- a/man/mysqlbinlog.1 +++ b/man/mysqlbinlog.1 @@ -2,12 +2,12 @@ .\" Title: mysqlbinlog .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLBINLOG" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQLBINLOG" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -4437,7 +4437,7 @@ specifies a nonzero server ID\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqlcheck.1 b/man/mysqlcheck.1 index 396311393f2e..8ebc8e922e0a 100644 --- a/man/mysqlcheck.1 +++ b/man/mysqlcheck.1 @@ -2,12 +2,12 @@ .\" Title: mysqlcheck .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLCHECK" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQLCHECK" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -2081,7 +2081,7 @@ This option was added in MySQL 8\&.0\&.18\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqld.8 b/man/mysqld.8 index 8f2e18382197..ac2b79649e97 100644 --- a/man/mysqld.8 +++ b/man/mysqld.8 @@ -2,12 +2,12 @@ .\" Title: mysqld .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLD" "8" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQLD" "8" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -80,7 +80,7 @@ Chapter\ \&2, Installing MySQL\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqld_multi.1 b/man/mysqld_multi.1 index 3b505f1fab1b..e18d273c91ad 100644 --- a/man/mysqld_multi.1 +++ b/man/mysqld_multi.1 @@ -2,12 +2,12 @@ .\" Title: mysqld_multi .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLD_MULTI" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQLD_MULTI" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -963,7 +963,7 @@ Section\ \&6.2.2.2, \(lqUsing Option Files\(rq\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqld_safe.1 b/man/mysqld_safe.1 index 1e6b78dd179e..9114c9929e36 100644 --- a/man/mysqld_safe.1 +++ b/man/mysqld_safe.1 @@ -2,12 +2,12 @@ .\" Title: mysqld_safe .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLD_SAFE" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQLD_SAFE" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1404,7 +1404,7 @@ Section\ \&7.4.2.8, \(lqError Logging to the System Log\(rq\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqldump.1 b/man/mysqldump.1 index 14699add66b6..abe21310ba29 100644 --- a/man/mysqldump.1 +++ b/man/mysqldump.1 @@ -2,12 +2,12 @@ .\" Title: mysqldump .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLDUMP" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQLDUMP" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -5334,7 +5334,7 @@ for a workaround\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqldumpslow.1 b/man/mysqldumpslow.1 index 215e6e336ad6..5bd387ffd849 100644 --- a/man/mysqldumpslow.1 +++ b/man/mysqldumpslow.1 @@ -2,12 +2,12 @@ .\" Title: mysqldumpslow .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLDUMPSLOW" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQLDUMPSLOW" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -411,7 +411,7 @@ Verbose mode\&. Print more information about what the program does\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqlimport.1 b/man/mysqlimport.1 index 288531ef6f78..9858d7fa1ad4 100644 --- a/man/mysqlimport.1 +++ b/man/mysqlimport.1 @@ -2,12 +2,12 @@ .\" Title: mysqlimport .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLIMPORT" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQLIMPORT" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1935,7 +1935,7 @@ $> \fBmysql \-e \*(AqSELECT * FROM imptest\*(Aq test\fR .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqlpump.1 b/man/mysqlpump.1 index 8b5fea6e716c..34e5a8e4c11b 100644 --- a/man/mysqlpump.1 +++ b/man/mysqlpump.1 @@ -2,12 +2,12 @@ .\" Title: mysqlpump .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLPUMP" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQLPUMP" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -3918,7 +3918,7 @@ mysqlpump mysql user db \&.\&.\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqlrouter.1 b/man/mysqlrouter.1 index 81d6e17f9073..c9dd0aaa8fb6 100644 --- a/man/mysqlrouter.1 +++ b/man/mysqlrouter.1 @@ -2,12 +2,12 @@ .\" Title: mysqlrouter .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/12/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Router .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLROUTER" "1" "12/12/2024" "MySQL 8\&.0" "MySQL Router" +.TH "MYSQLROUTER" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Router" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -96,7 +96,7 @@ Displays the version number and related information of the application, and exit .\} .nf $> \fBmysqlrouter \-\-version\fR -MySQL Router v8\&.0\&.40 on Linux (64\-bit) (GPL community edition) +MySQL Router v8\&.0\&.41 on Linux (64\-bit) (GPL community edition) .fi .if n \{\ .RE @@ -385,6 +385,62 @@ This option is not available on Windows\&. .sp -1 .IP \(bu 2.3 .\} +\fB\-\-core\-file\fR +.TS +allbox tab(:); +lB l +lB l +lB l +lB l. +T{ +Command-Line Format +T}:T{ +--core-file[={0|1}] +T} +T{ +Introduced +T}:T{ +8.0.31 +T} +T{ +Type +T}:T{ +Boolean +T} +T{ +Default Value +T}:T{ +0 +T} +.TE +.sp 1 +Write a core file if +\fBmysqlrouter\fR +dies\&. The name and location of the core file is system dependent\&. On Linux, a core file named +core\&.\fIpid\fR +is written to the current working directory of the process\&. +\fIpid\fR +represents the process ID of the server process\&. On macOS, a core file named +core\&.\fIpid\fR +is written to the +/cores +directory, if the process has the +com\&.apple\&.security\&.get\-task\-allow +entitlement\&. On Solaris, use the +\fBcoreadm\fR +command to specify where to write the core file and how to name it\&. On Windows, a minidump file named +mysqlrouter\&.\fI{pid}\fR\&.dmp +is written to the current working directory of the process\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} \fB\-\-directory \fR\fB\fIdir_path\fR\fR, \fB\-d \fR\fB\fIdir_path\fR\fR .TS @@ -3087,7 +3143,7 @@ at bootstrap\&. It defaults to 8443\&. Availability of the port is not checked\& .SH "COPYRIGHT" .br .PP -Copyright \(co 2006, 2024, Oracle and/or its affiliates. +Copyright \(co 2006, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqlrouter_keyring.1 b/man/mysqlrouter_keyring.1 index 746951ce24ee..fe1bc8861209 100644 --- a/man/mysqlrouter_keyring.1 +++ b/man/mysqlrouter_keyring.1 @@ -2,12 +2,12 @@ .\" Title: mysqlrouter_keyring .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/12/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Router .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLROUTER_KEYRING" "1" "12/12/2024" "MySQL 8\&.0" "MySQL Router" +.TH "MYSQLROUTER_KEYRING" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Router" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -209,7 +209,7 @@ $> mysqlrouter_keyring master\-key\-rename \-\-master\-key\-file=mysqlrouter\&.k .SH "COPYRIGHT" .br .PP -Copyright \(co 2006, 2024, Oracle and/or its affiliates. +Copyright \(co 2006, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqlrouter_passwd.1 b/man/mysqlrouter_passwd.1 index 56a525390b93..faa70430ef19 100644 --- a/man/mysqlrouter_passwd.1 +++ b/man/mysqlrouter_passwd.1 @@ -2,12 +2,12 @@ .\" Title: mysqlrouter_passwd .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/12/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Router .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLROUTER_PASSWD" "1" "12/12/2024" "MySQL 8\&.0" "MySQL Router" +.TH "MYSQLROUTER_PASSWD" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Router" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -91,7 +91,7 @@ Options .SH "COPYRIGHT" .br .PP -Copyright \(co 2006, 2024, Oracle and/or its affiliates. +Copyright \(co 2006, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqlrouter_plugin_info.1 b/man/mysqlrouter_plugin_info.1 index d746ff821d27..ee4f5a483609 100644 --- a/man/mysqlrouter_plugin_info.1 +++ b/man/mysqlrouter_plugin_info.1 @@ -2,12 +2,12 @@ .\" Title: mysqlrouter_plugin_info .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/12/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Router .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLROUTER_PLUGIN_INFO" "1" "12/12/2024" "MySQL 8\&.0" "MySQL Router" +.TH "MYSQLROUTER_PLUGIN_INFO" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Router" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -56,7 +56,7 @@ Print plugin information: Display this help and exit\&. $> mysqlrouter_plugin_info \-\-version MySQL Router Ver 8\&.0\&.37 for Linux on x86_64 (MySQL Community \- GPL) -Copyright (c) 2015, 2024, Oracle and/or its affiliates\&. +Copyright (c) 2015, 2025, Oracle and/or its affiliates\&. Oracle is a registered trademark of Oracle Corporation and/or its affiliates\&. Other names may be trademarks of their respective owners\&. @@ -94,7 +94,7 @@ $> mysqlrouter_plugin_info /usr/lib64/mysqlrouter/routing\&.so routing .SH "COPYRIGHT" .br .PP -Copyright \(co 2006, 2024, Oracle and/or its affiliates. +Copyright \(co 2006, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqlshow.1 b/man/mysqlshow.1 index b4718160572a..cc9e36096397 100644 --- a/man/mysqlshow.1 +++ b/man/mysqlshow.1 @@ -2,12 +2,12 @@ .\" Title: mysqlshow .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLSHOW" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQLSHOW" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1625,7 +1625,7 @@ This option was added in MySQL 8\&.0\&.18\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/mysqlslap.1 b/man/mysqlslap.1 index 910f2b5755fd..feaa2d55eadd 100644 --- a/man/mysqlslap.1 +++ b/man/mysqlslap.1 @@ -2,12 +2,12 @@ .\" Title: mysqlslap .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "MYSQLSLAP" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "MYSQLSLAP" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -2485,7 +2485,7 @@ This option was added in MySQL 8\&.0\&.18\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_blob_tool.1 b/man/ndb_blob_tool.1 index d553fc54394f..0700ba4a2cfb 100644 --- a/man/ndb_blob_tool.1 +++ b/man/ndb_blob_tool.1 @@ -2,12 +2,12 @@ .\" Title: ndb_blob_tool .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_BLOB_TOOL" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_BLOB_TOOL" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1227,7 +1227,7 @@ Section\ \&13.7, \(lqData Type Storage Requirements\(rq, for more information\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_config.1 b/man/ndb_config.1 index 5db0407aec14..d9a1f9c0361a 100644 --- a/man/ndb_config.1 +++ b/man/ndb_config.1 @@ -2,12 +2,12 @@ .\" Title: ndb_config .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_CONFIG" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_CONFIG" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -2290,7 +2290,7 @@ option\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_delete_all.1 b/man/ndb_delete_all.1 index 60e9db95d065..cea36fad85a4 100644 --- a/man/ndb_delete_all.1 +++ b/man/ndb_delete_all.1 @@ -2,12 +2,12 @@ .\" Title: ndb_delete_all .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_DELETE_ALL" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_DELETE_ALL" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -993,7 +993,7 @@ testing library\&. This dependency has been removed in NDB 8\&.0, eliminating th .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_desc.1 b/man/ndb_desc.1 index 2a0446a966d2..b873968385aa 100644 --- a/man/ndb_desc.1 +++ b/man/ndb_desc.1 @@ -2,12 +2,12 @@ .\" Title: ndb_desc .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_DESC" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_DESC" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1505,7 +1505,7 @@ Table indexes listed in the output are ordered by ID\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_drop_index.1 b/man/ndb_drop_index.1 index c74ea5fb1cf0..7b68add86a96 100644 --- a/man/ndb_drop_index.1 +++ b/man/ndb_drop_index.1 @@ -2,12 +2,12 @@ .\" Title: ndb_drop_index .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_DROP_INDEX" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_DROP_INDEX" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -946,7 +946,7 @@ ndb_drop_table(1)) to drop the table\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_drop_table.1 b/man/ndb_drop_table.1 index 384b2df4ae72..724af6bd9784 100644 --- a/man/ndb_drop_table.1 +++ b/man/ndb_drop_table.1 @@ -2,12 +2,12 @@ .\" Title: ndb_drop_table .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_DROP_TABLE" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_DROP_TABLE" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -888,7 +888,7 @@ Display version information and exit\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_error_reporter.1 b/man/ndb_error_reporter.1 index 055ed530b2e2..2f326dfb265e 100644 --- a/man/ndb_error_reporter.1 +++ b/man/ndb_error_reporter.1 @@ -2,12 +2,12 @@ .\" Title: ndb_error_reporter .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_ERROR_REPORTER" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_ERROR_REPORTER" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -278,7 +278,7 @@ Skip all nodes belong to the node group having the supplied node group ID\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_import.1 b/man/ndb_import.1 index a08e642e2288..8ff44ef11180 100644 --- a/man/ndb_import.1 +++ b/man/ndb_import.1 @@ -2,12 +2,12 @@ .\" Title: ndb_import .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_IMPORT" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_IMPORT" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -3373,7 +3373,7 @@ option\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_index_stat.1 b/man/ndb_index_stat.1 index 0db7437225c4..a05abace6892 100644 --- a/man/ndb_index_stat.1 +++ b/man/ndb_index_stat.1 @@ -2,12 +2,12 @@ .\" Title: ndb_index_stat .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_INDEX_STAT" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_INDEX_STAT" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1622,7 +1622,7 @@ ndb_index_stat system options)\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_mgm.1 b/man/ndb_mgm.1 index cd91f509391d..73a30b41e8c8 100644 --- a/man/ndb_mgm.1 +++ b/man/ndb_mgm.1 @@ -2,12 +2,12 @@ .\" Title: ndb_mgm .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_MGM" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_MGM" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1111,7 +1111,7 @@ Section\ \&25.6.1, \(lqCommands in the NDB Cluster Management Client\(rq\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_mgmd.8 b/man/ndb_mgmd.8 index 6e9ce29b725d..6007112524b0 100644 --- a/man/ndb_mgmd.8 +++ b/man/ndb_mgmd.8 @@ -2,12 +2,12 @@ .\" Title: ndb_mgmd .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_MGMD" "8" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_MGMD" "8" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -2036,7 +2036,7 @@ is the process ID file used when running the management server as a daemon\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_move_data.1 b/man/ndb_move_data.1 index 5e21f47b55e6..466312e0e574 100644 --- a/man/ndb_move_data.1 +++ b/man/ndb_move_data.1 @@ -2,12 +2,12 @@ .\" Title: ndb_move_data .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_MOVE_DATA" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_MOVE_DATA" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1169,7 +1169,7 @@ Display version information and exit\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_perror.1 b/man/ndb_perror.1 index c6332080378c..f65082c49230 100644 --- a/man/ndb_perror.1 +++ b/man/ndb_perror.1 @@ -2,12 +2,12 @@ .\" Title: ndb_perror .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_PERROR" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_PERROR" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -560,7 +560,7 @@ Verbose output; disable with .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_print_backup_file.1 b/man/ndb_print_backup_file.1 index 97e3dc97a1cc..985eb2e35186 100644 --- a/man/ndb_print_backup_file.1 +++ b/man/ndb_print_backup_file.1 @@ -2,12 +2,12 @@ .\" Title: ndb_print_backup_file .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_PRINT_BACKUP_FILE" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_PRINT_BACKUP_FILE" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1171,7 +1171,7 @@ Display version information and exit\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_print_file.1 b/man/ndb_print_file.1 index 4d6a10dfc9af..f3b97c2cae2c 100644 --- a/man/ndb_print_file.1 +++ b/man/ndb_print_file.1 @@ -2,12 +2,12 @@ .\" Title: ndb_print_file .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_PRINT_FILE" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_PRINT_FILE" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -366,7 +366,7 @@ Section\ \&25.6.11, \(lqNDB Cluster Disk Data Tables\(rq\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_print_frag_file.1 b/man/ndb_print_frag_file.1 index fd9103f91971..ce96b6ae35b6 100644 --- a/man/ndb_print_frag_file.1 +++ b/man/ndb_print_frag_file.1 @@ -2,12 +2,12 @@ .\" Title: ndb_print_frag_file .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_PRINT_FRAG_FILE" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_PRINT_FRAG_FILE" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -117,7 +117,7 @@ LcpNo[1]: maxGciCompleted: 0 maxGciStarted: 0 lcpId: 0 lcpStatus: invalid .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_print_schema_file.1 b/man/ndb_print_schema_file.1 index 77817962f9ef..e2add56df079 100644 --- a/man/ndb_print_schema_file.1 +++ b/man/ndb_print_schema_file.1 @@ -2,12 +2,12 @@ .\" Title: ndb_print_schema_file .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_PRINT_SCHEMA_FILE" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_PRINT_SCHEMA_FILE" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -67,7 +67,7 @@ None\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_print_sys_file.1 b/man/ndb_print_sys_file.1 index af1e7d6b164f..b0059056cbe1 100644 --- a/man/ndb_print_sys_file.1 +++ b/man/ndb_print_sys_file.1 @@ -2,12 +2,12 @@ .\" Title: ndb_print_sys_file .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_PRINT_SYS_FILE" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_PRINT_SYS_FILE" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -70,7 +70,7 @@ None\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_redo_log_reader.1 b/man/ndb_redo_log_reader.1 index 5ea1c7605eea..2557827a17d9 100644 --- a/man/ndb_redo_log_reader.1 +++ b/man/ndb_redo_log_reader.1 @@ -2,12 +2,12 @@ .\" Title: ndb_redo_log_reader .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_REDO_LOG_READER" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_REDO_LOG_READER" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -648,7 +648,7 @@ must be run on a cluster data node, since it accesses the data node file system .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_restore.1 b/man/ndb_restore.1 index 33cf2d74f7ff..bf5555fecfb3 100644 --- a/man/ndb_restore.1 +++ b/man/ndb_restore.1 @@ -2,12 +2,12 @@ .\" Title: ndb_restore .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_RESTORE" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_RESTORE" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1199,9 +1199,9 @@ It is not possible to restore a backup made from a newer version of NDB Cluster \fBndb_restore\fR from the newer NDB Cluster version to do so\&. .sp -For example, to restore a cluster backup taken from a cluster running NDB Cluster 8\&.0\&.41 to a cluster running NDB Cluster 7\&.6\&.33, you must use the +For example, to restore a cluster backup taken from a cluster running NDB Cluster 8\&.0\&.42 to a cluster running NDB Cluster 7\&.6\&.34, you must use the \fBndb_restore\fR -that comes with the NDB Cluster 7\&.6\&.33 distribution\&. +that comes with the NDB Cluster 7\&.6\&.34 distribution\&. .sp .5v .RE For more rapid restoration, the data may be restored in parallel, provided that there is a sufficient number of cluster connections available\&. That is, when restoring to multiple nodes in parallel, you must have an @@ -5669,7 +5669,7 @@ binary supplied with the older version of the NDB Cluster software\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_secretsfile_reader.1 b/man/ndb_secretsfile_reader.1 index 15322a39ee43..46561f661d39 100644 --- a/man/ndb_secretsfile_reader.1 +++ b/man/ndb_secretsfile_reader.1 @@ -2,12 +2,12 @@ .\" Title: ndb_secretsfile_reader .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_SECRETSFILE_READER" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_SECRETSFILE_READER" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -526,7 +526,7 @@ was added in NDB 8\&.0\&.31\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_select_all.1 b/man/ndb_select_all.1 index a2c87f637397..47ec87e0005b 100644 --- a/man/ndb_select_all.1 +++ b/man/ndb_select_all.1 @@ -2,12 +2,12 @@ .\" Title: ndb_select_all .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_SELECT_ALL" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_SELECT_ALL" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1334,7 +1334,7 @@ GCI id name breed DISK_REF .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_select_count.1 b/man/ndb_select_count.1 index 68b4ad06c4a6..8847a3583b45 100644 --- a/man/ndb_select_count.1 +++ b/man/ndb_select_count.1 @@ -2,12 +2,12 @@ .\" Title: ndb_select_count .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_SELECT_COUNT" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_SELECT_COUNT" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -888,7 +888,7 @@ $> \fB\&./ndb_select_count \-c localhost \-d ctest1 fish dogs\fR .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_show_tables.1 b/man/ndb_show_tables.1 index 4876d6ee2aea..d5fd7da20b16 100644 --- a/man/ndb_show_tables.1 +++ b/man/ndb_show_tables.1 @@ -2,12 +2,12 @@ .\" Title: ndb_show_tables .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_SHOW_TABLES" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_SHOW_TABLES" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1060,7 +1060,7 @@ testing library\&. This dependency has been removed, eliminating the extraneous .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_size.pl.1 b/man/ndb_size.pl.1 index 3ea3c5d90da0..044101e33fcf 100644 --- a/man/ndb_size.pl.1 +++ b/man/ndb_size.pl.1 @@ -2,12 +2,12 @@ .\" Title: ndb_size.pl .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_SIZE\&.PL" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_SIZE\&.PL" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -410,7 +410,7 @@ required per table and table row\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_top.1 b/man/ndb_top.1 index 001007e220cc..1703c53a388c 100644 --- a/man/ndb_top.1 +++ b/man/ndb_top.1 @@ -2,12 +2,12 @@ .\" Title: ndb_top .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_TOP" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_TOP" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1052,7 +1052,7 @@ also shows spin times for threads, displayed in green\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndb_waiter.1 b/man/ndb_waiter.1 index 33b663b73dda..f3ed3865f0a2 100644 --- a/man/ndb_waiter.1 +++ b/man/ndb_waiter.1 @@ -2,12 +2,12 @@ .\" Title: ndb_waiter .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDB_WAITER" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDB_WAITER" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1382,7 +1382,7 @@ testing library\&. This dependency has been removed, eliminating the extraneous .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndbd.8 b/man/ndbd.8 index 7ee37cf01c5f..01ef872fc94e 100644 --- a/man/ndbd.8 +++ b/man/ndbd.8 @@ -2,12 +2,12 @@ .\" Title: ndbd .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDBD" "8" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDBD" "8" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1955,7 +1955,7 @@ Section\ \&25.2.7, \(lqKnown Limitations of NDB Cluster\(rq\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndbinfo_select_all.1 b/man/ndbinfo_select_all.1 index b45b94bbb7ec..23ba111c5074 100644 --- a/man/ndbinfo_select_all.1 +++ b/man/ndbinfo_select_all.1 @@ -2,12 +2,12 @@ .\" Title: ndbinfo_select_all .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDBINFO_SELECT_ALL" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDBINFO_SELECT_ALL" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1188,7 +1188,7 @@ table_info .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndbmtd.8 b/man/ndbmtd.8 index 9bc4099cfae4..28d29977b50b 100644 --- a/man/ndbmtd.8 +++ b/man/ndbmtd.8 @@ -2,12 +2,12 @@ .\" Title: ndbmtd .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDBMTD" "8" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDBMTD" "8" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -193,7 +193,7 @@ concurrently on different data nodes in the same NDB Cluster\&. However, such co .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/ndbxfrm.1 b/man/ndbxfrm.1 index 56ba8a2dc848..bdeffc567e12 100644 --- a/man/ndbxfrm.1 +++ b/man/ndbxfrm.1 @@ -2,12 +2,12 @@ .\" Title: ndbxfrm .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "NDBXFRM" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "NDBXFRM" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -1395,7 +1395,7 @@ are the old and new passwords, respectively; both of these must be quoted\&. The .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/perror.1 b/man/perror.1 index ec9fbd394e2a..7a11f30f1c1e 100644 --- a/man/perror.1 +++ b/man/perror.1 @@ -2,12 +2,12 @@ .\" Title: perror .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "PERROR" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "PERROR" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -172,7 +172,7 @@ Display version information and exit\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/man/zlib_decompress.1 b/man/zlib_decompress.1 index 9a489b7f9edf..a0f3e5a1163b 100644 --- a/man/zlib_decompress.1 +++ b/man/zlib_decompress.1 @@ -2,12 +2,12 @@ .\" Title: zlib_decompress .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 12/13/2024 +.\" Date: 03/13/2025 .\" Manual: MySQL Database System .\" Source: MySQL 8.0 .\" Language: English .\" -.TH "ZLIB_DECOMPRESS" "1" "12/13/2024" "MySQL 8\&.0" "MySQL Database System" +.TH "ZLIB_DECOMPRESS" "1" "03/13/2025" "MySQL 8\&.0" "MySQL Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -120,7 +120,7 @@ lz4_decompress(1)\&. .SH "COPYRIGHT" .br .PP -Copyright \(co 1997, 2024, Oracle and/or its affiliates. +Copyright \(co 1997, 2025, Oracle and/or its affiliates. .PP This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. .PP diff --git a/mysql-test/r/explain_dml.result b/mysql-test/r/explain_dml.result index 1798eb9a66f2..6c9120e6fefb 100644 --- a/mysql-test/r/explain_dml.result +++ b/mysql-test/r/explain_dml.result @@ -95,12 +95,12 @@ Warning 3005 INSERT DELAYED is no longer supported. The statement was converted Note 1003 insert ignore into `test`.`t1` PARTITION (`p0`,`p1`) (`test`.`t1`.`c1`,`test`.`t1`.`c2`) /* select#1 */ select `test`.`t2`.`c1` AS `c1`,'a' AS `a` from `test`.`t2` on duplicate key update `test`.`t1`.`c2` = 'c' EXPLAIN INSERT INTO t1 PARTITION(p0, p1) -SET c1 = (SELECT c1 from t2); +SET c1 = (SELECT c1 from t2 LIMIT 1); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 INSERT t1 p0_subp0,p0_subp1,p1_subp6,p1_subp7 ALL NULL NULL NULL NULL NULL NULL NULL +1 INSERT t1 p1_subp6 ALL NULL NULL NULL NULL NULL NULL NULL 2 SUBQUERY t2 NULL ALL NULL NULL NULL NULL 3 100.00 NULL Warnings: -Note 1003 insert into `test`.`t1` PARTITION (`p0`,`p1`) (`test`.`t1`.`c1`) values ((/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2`)) +Note 1003 insert into `test`.`t1` PARTITION (`p0`,`p1`) (`test`.`t1`.`c1`) values ((/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2` limit 1)) EXPLAIN REPLACE LOW_PRIORITY INTO t1 PARTITION(p0, p1) (c1, c2) VALUES (1, 'a'), (2, 'b'); @@ -119,12 +119,12 @@ Warning 3005 REPLACE DELAYED is no longer supported. The statement was converted Note 1003 replace into `test`.`t1` PARTITION (`p0`,`p1`) (`test`.`t1`.`c1`,`test`.`t1`.`c2`) /* select#1 */ select `test`.`t2`.`c1` AS `c1`,'a' AS `a` from `test`.`t2` EXPLAIN REPLACE INTO t1 PARTITION(p0, p1) -SET c1 = (SELECT c1 from t2); +SET c1 = (SELECT c1 from t2 LIMIT 1); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 REPLACE t1 p0_subp0,p0_subp1,p1_subp6,p1_subp7 ALL NULL NULL NULL NULL NULL NULL NULL +1 REPLACE t1 p1_subp6 ALL NULL NULL NULL NULL NULL NULL NULL 2 SUBQUERY t2 NULL ALL NULL NULL NULL NULL 3 100.00 NULL Warnings: -Note 1003 replace into `test`.`t1` PARTITION (`p0`,`p1`) (`test`.`t1`.`c1`) values ((/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2`)) +Note 1003 replace into `test`.`t1` PARTITION (`p0`,`p1`) (`test`.`t1`.`c1`) values ((/* select#2 */ select `test`.`t2`.`c1` from `test`.`t2` limit 1)) EXPLAIN FORMAT=TRADITIONAL FOR QUERY 'DELETE FROM t3 WHERE c1 > 0' id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 DELETE t3 NULL ALL NULL NULL NULL NULL 3 100.00 Using where diff --git a/mysql-test/r/group_by_fd_no_prot.result b/mysql-test/r/group_by_fd_no_prot.result index d5104e392ea1..408a69746284 100644 --- a/mysql-test/r/group_by_fd_no_prot.result +++ b/mysql-test/r/group_by_fd_no_prot.result @@ -2221,7 +2221,7 @@ id select_type table partitions type possible_keys key key_len ref rows filtered 2 DEPENDENT SUBQUERY t3 NULL index NULL b 15 NULL 1 100.00 Using where; Not exists; Using index; Using join buffer (hash join) Warnings: Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1 -Note 1003 /* select#1 */ select (/* select#2 */ select 2 from `test`.`t2` anti join (`test`.`t3`) on((1 = 1)) where true) AS `col` from `test`.`t1` group by `test`.`t1`.`a` +Note 1003 /* select#1 */ select (/* select#2 */ select 2 from `test`.`t2` anti join (`test`.`t3`) on(true) where true) AS `col` from `test`.`t1` group by `test`.`t1`.`a` explain select (select 2 from t2 where exists(select 1 from t3 where t1.b)) as col from t1 group by t1.a; ERROR 42000: Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.t1.b' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by explain select (select 2 from t2 where not exists(select 1 from t3 where t1.b)) as col from t1 group by t1.a; diff --git a/mysql-test/r/group_by_fd_ps_prot.result b/mysql-test/r/group_by_fd_ps_prot.result index c8c691fadf89..f5e3983c63cf 100644 --- a/mysql-test/r/group_by_fd_ps_prot.result +++ b/mysql-test/r/group_by_fd_ps_prot.result @@ -1577,7 +1577,7 @@ id select_type table partitions type possible_keys key key_len ref rows filtered 2 DEPENDENT SUBQUERY t3 NULL index NULL b 15 NULL 1 100.00 Using where; Not exists; Using index; Using join buffer (hash join) Warnings: Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1 -Note 1003 /* select#1 */ select (/* select#2 */ select 2 from `test`.`t2` anti join (`test`.`t3`) on((1 = 1)) where true) AS `col` from `test`.`t1` group by `test`.`t1`.`a` +Note 1003 /* select#1 */ select (/* select#2 */ select 2 from `test`.`t2` anti join (`test`.`t3`) on(true) where true) AS `col` from `test`.`t1` group by `test`.`t1`.`a` explain select (select 2 from t2 where exists(select 1 from t3 where t1.b)) as col from t1 group by t1.a; ERROR 42000: Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.t1.b' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by explain select (select 2 from t2 where not exists(select 1 from t3 where t1.b)) as col from t1 group by t1.a; diff --git a/mysql-test/r/mysqldump-tablespace-escape.result b/mysql-test/r/mysqldump-tablespace-escape.result index 5c4b3c117210..d923710a114e 100644 --- a/mysql-test/r/mysqldump-tablespace-escape.result +++ b/mysql-test/r/mysqldump-tablespace-escape.result @@ -2,7 +2,78 @@ # Bug#36816986 - MySQL Shell command injection # CREATE DATABASE bug36816986; +USE bug36816986; -- Run mysqldump with tablespace_injection_test. The test injected string must be found: Pattern found. +The ` must be escaped: +Pattern found. DROP DATABASE bug36816986; + +####################################### + +# +# Bug#37607195 - fprintf_string not using the actual quote parameter +# +CREATE DATABASE bug37607195; +USE bug37607195; +Create a bunch of tables with numerous ` ' " \n etc. +SET @@sql_mode='ANSI_QUOTES,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; +CREATE TABLE "custo`mers" ( +"customer'_id" INT AUTO_INCREMENT PRIMARY KEY, +"fir`st_`na`me" VARCHAR(50) NOT NULL, +"last_'name" VARCHAR(50) NOT NULL, +"em`ail" VARCHAR(100) UNIQUE NOT NULL, +`pho"\ne` VARCHAR(15), +"created'_'at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +"updated'_'at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); +CREATE TABLE "prod'ucts" ( +"product`_`id" INT AUTO_INCREMENT PRIMARY KEY, +"product'_`name" VARCHAR(100) NOT NULL, +"descri`p`t`i`o`n" TEXT, +"pr'i'ce" DECIMAL(10, 2) NOT NULL CHECK ("pr'i'ce" >= 0), +`stock"_"qua\ntity` INT DEFAULT 0, +`created'_'at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +`updated"_'at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +INDEX ("product'_`name") +); +CREATE TABLE "orders" ( +"order_id" INT AUTO_INCREMENT PRIMARY KEY, +"customer_id" INT NOT NULL, +"order_date" TIMESTAMP DEFAULT CURRENT_TIMESTAMP, +"status" ENUM('Pending', 'Completed', 'Cancelled') NOT NULL, +"total\n" DECIMAL(10, 2) NOT NULL CHECK ("total\n" >= 0), +FOREIGN KEY (customer_id) REFERENCES "custo`mers"("customer'_id") ON DELETE CASCADE, +INDEX (order_date) +); +CREATE TABLE `'order'_'items'` ( +`order'_'item_id` INT AUTO_INCREMENT PRIMARY KEY, +`'order'_'id'` INT NOT NULL, +`product'_'id` INT NOT NULL, +`qua\ntity` INT NOT NULL CHECK (`qua\ntity` > 0), +`p'rice` DECIMAL(10,2) NOT NULL CHECK (`p'rice` >= 0), +FOREIGN KEY (`'order'_'id'`) REFERENCES "orders"(order_id) ON DELETE CASCADE, +FOREIGN KEY (`product'_'id`) REFERENCES "prod'ucts"("product`_`id") ON DELETE CASCADE, +UNIQUE KEY (`'order'_'id'`, `product'_'id`) +); +# Table 1: `'order'_'items'` +# `qua\ntity` must be escaped +Pattern found. +# Table 2: "custo`mers" +# "custo`mers" must be escaped +Pattern found. +# `pho"\ne` must be escaped +Pattern found. +# Table 3: "orders" +# `total\n` must be escaped +Pattern found. +# FOREIGN KEY (`customer_id`) REFERENCES must be escaped +Pattern found. +# Table 4: `prod'ucts` +# "descri`p`t`i`o`n" TEXT must be escaped +Pattern found. +# `stock"_"qua\ntity` must be escaped +Pattern found. +SET @@sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; +DROP DATABASE bug37607195; diff --git a/mysql-test/r/partition_locking.result b/mysql-test/r/partition_locking.result index f25120f5dd85..9c41e99d035a 100644 --- a/mysql-test/r/partition_locking.result +++ b/mysql-test/r/partition_locking.result @@ -4784,7 +4784,7 @@ FLUSH STATUS; EXPLAIN INSERT INTO t2 VALUES ((SELECT max(a) FROM t1), (SELECT min(a) FROM t1)); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 INSERT t2 p0,p1,p2 ALL NULL NULL NULL NULL # NULL NULL +1 INSERT t2 p2 ALL NULL NULL NULL NULL # NULL NULL 3 SUBQUERY t1 p0,p1,p2 ALL NULL NULL NULL NULL # 100.00 NULL 2 SUBQUERY t1 p0,p1,p2 ALL NULL NULL NULL NULL # 100.00 NULL Warnings: @@ -4792,6 +4792,9 @@ Note 1003 insert into `test`.`t2` values ((/* select#2 */ select max(`test`.`t1` VARIABLE_NAME VARIABLE_VALUE Handler_commit 1 Handler_external_lock 6 +Handler_read_first 3 +Handler_read_key 3 +Handler_read_rnd_next 8 # I.e. No lock pruning possible FLUSH STATUS; INSERT INTO t2 VALUES ((SELECT a FROM t1 WHERE a = 1), @@ -4809,7 +4812,7 @@ FLUSH STATUS; EXPLAIN INSERT INTO t2 VALUES ((SELECT a FROM t1 WHERE a = 1), (SELECT b FROM t1 WHERE a = 2)); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 INSERT t2 p0,p1,p2 ALL NULL NULL NULL NULL # NULL NULL +1 INSERT t2 p1 ALL NULL NULL NULL NULL # NULL NULL 3 SUBQUERY t1 p2 ALL NULL NULL NULL NULL # 25.00 Using where 2 SUBQUERY t1 p1 ALL NULL NULL NULL NULL # 25.00 Using where Warnings: @@ -4817,6 +4820,9 @@ Note 1003 insert into `test`.`t2` values ((/* select#2 */ select `test`.`t1`.`a` VARIABLE_NAME VARIABLE_VALUE Handler_commit 1 Handler_external_lock 6 +Handler_read_first 1 +Handler_read_key 1 +Handler_read_rnd_next 4 # I.e. No lock pruning possible on insert table SELECT * FROM t2 ORDER BY a, b; a b @@ -5024,9 +5030,9 @@ Handler_read_next 12 UNLOCK TABLES; EXPLAIN SELECT * FROM t2 WHERE a = sf_a_from_t1b_d('1'); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 p1 const PRIMARY PRIMARY 4 const # 100.00 NULL +1 SIMPLE t2 p0,p1,p2 eq_ref PRIMARY PRIMARY 4 const # 100.00 Using where Warnings: -Note 1003 /* select#1 */ select '1' AS `a`,'1' AS `b` from `test`.`t2` where true +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` = (`sf_a_from_t1b_d`('1'))) FLUSH STATUS; START TRANSACTION; SELECT * FROM t2 WHERE a = sf_a_from_t1b_d('1'); @@ -5080,9 +5086,9 @@ Handler_read_next 12 UNLOCK TABLES; EXPLAIN SELECT * FROM t2 WHERE a = 7 + sf_a_from_t1b_d('1'); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 p2 const PRIMARY PRIMARY 4 const # 100.00 NULL +1 SIMPLE t2 p0,p1,p2 eq_ref PRIMARY PRIMARY 4 const # 100.00 Using where Warnings: -Note 1003 /* select#1 */ select '8' AS `a`,'8' AS `b` from `test`.`t2` where true +Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` = ((7 + `sf_a_from_t1b_d`('1')))) FLUSH STATUS; START TRANSACTION; SELECT * FROM t2 WHERE a = 7 + sf_a_from_t1b_d('1'); @@ -5132,9 +5138,9 @@ Handler_read_next 7 UNLOCK TABLES; EXPLAIN SELECT * FROM t2 WHERE a = sf_a_from_t1b_d('1') AND a = 2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL # NULL Impossible WHERE +1 SIMPLE t2 p2 const PRIMARY PRIMARY 4 const # 100.00 NULL Warnings: -Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where false +Note 1003 /* select#1 */ select '2' AS `a`,'2' AS `b` from `test`.`t2` where ((2 = `sf_a_from_t1b_d`('1'))) FLUSH STATUS; START TRANSACTION; SELECT * FROM t2 WHERE a = sf_a_from_t1b_d('1') AND a = 2; @@ -5316,9 +5322,9 @@ Handler_read_next 12 UNLOCK TABLES; EXPLAIN SELECT sf_add_1(a) - 1, sf_add_hello(b) FROM t2 WHERE a = sf_a_from_t1b_d('1'); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 p1 const PRIMARY PRIMARY 4 const # 100.00 NULL +1 SIMPLE t2 p0,p1,p2 eq_ref PRIMARY PRIMARY 4 const # 100.00 Using where Warnings: -Note 1003 /* select#1 */ select (`sf_add_1`('1') - 1) AS `sf_add_1(a) - 1`,`sf_add_hello`('1') AS `sf_add_hello(b)` from `test`.`t2` where true +Note 1003 /* select#1 */ select (`sf_add_1`(`test`.`t2`.`a`) - 1) AS `sf_add_1(a) - 1`,`sf_add_hello`(`test`.`t2`.`b`) AS `sf_add_hello(b)` from `test`.`t2` where (`test`.`t2`.`a` = (`sf_a_from_t1b_d`('1'))) FLUSH STATUS; START TRANSACTION; SELECT sf_add_1(a) - 1, sf_add_hello(b) FROM t2 WHERE a = sf_a_from_t1b_d('1'); @@ -5372,9 +5378,9 @@ Handler_read_next 12 UNLOCK TABLES; EXPLAIN SELECT sf_add_1(a) - 1, sf_add_hello(b) FROM t2 WHERE a = 7 + sf_a_from_t1b_d('1'); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 p2 const PRIMARY PRIMARY 4 const # 100.00 NULL +1 SIMPLE t2 p0,p1,p2 eq_ref PRIMARY PRIMARY 4 const # 100.00 Using where Warnings: -Note 1003 /* select#1 */ select (`sf_add_1`('8') - 1) AS `sf_add_1(a) - 1`,`sf_add_hello`('8') AS `sf_add_hello(b)` from `test`.`t2` where true +Note 1003 /* select#1 */ select (`sf_add_1`(`test`.`t2`.`a`) - 1) AS `sf_add_1(a) - 1`,`sf_add_hello`(`test`.`t2`.`b`) AS `sf_add_hello(b)` from `test`.`t2` where (`test`.`t2`.`a` = ((7 + `sf_a_from_t1b_d`('1')))) FLUSH STATUS; START TRANSACTION; SELECT sf_add_1(a) - 1, sf_add_hello(b) FROM t2 WHERE a = 7 + sf_a_from_t1b_d('1'); @@ -5424,9 +5430,9 @@ Handler_read_next 7 UNLOCK TABLES; EXPLAIN SELECT sf_add_1(a) - 1, sf_add_hello(b) FROM t2 WHERE a = sf_a_from_t1b_d('1') AND a = 2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL # NULL Impossible WHERE +1 SIMPLE t2 p2 const PRIMARY PRIMARY 4 const # 100.00 NULL Warnings: -Note 1003 /* select#1 */ select (`sf_add_1`(`test`.`t2`.`a`) - 1) AS `sf_add_1(a) - 1`,`sf_add_hello`(`test`.`t2`.`b`) AS `sf_add_hello(b)` from `test`.`t2` where false +Note 1003 /* select#1 */ select (`sf_add_1`('2') - 1) AS `sf_add_1(a) - 1`,`sf_add_hello`('2') AS `sf_add_hello(b)` from `test`.`t2` where ((2 = `sf_a_from_t1b_d`('1'))) FLUSH STATUS; START TRANSACTION; SELECT sf_add_1(a) - 1, sf_add_hello(b) FROM t2 WHERE a = sf_a_from_t1b_d('1') AND a = 2; @@ -5646,7 +5652,7 @@ ROLLBACK; UNLOCK TABLES; EXPLAIN UPDATE t2 SET b = CONCAT('+', b) WHERE a = sf_a_from_t1b_d('1'); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 UPDATE t2 p1 range PRIMARY PRIMARY 4 const # 100.00 Using where +1 UPDATE t2 p0,p1,p2 index NULL PRIMARY 4 NULL # 100.00 Using where Warnings: Note 1003 update `test`.`t2` set `test`.`t2`.`b` = concat('+',`test`.`t2`.`b`) where (`test`.`t2`.`a` = `sf_a_from_t1b_d`('1')) FLUSH STATUS; @@ -5728,7 +5734,7 @@ ROLLBACK; UNLOCK TABLES; EXPLAIN UPDATE t2 SET b = CONCAT('+', b) WHERE a = 7 + sf_a_from_t1b_d('1'); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 UPDATE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where +1 UPDATE t2 p0,p1,p2 index NULL PRIMARY 4 NULL # 100.00 Using where Warnings: Note 1003 update `test`.`t2` set `test`.`t2`.`b` = concat('+',`test`.`t2`.`b`) where (`test`.`t2`.`a` = (7 + `sf_a_from_t1b_d`('1'))) FLUSH STATUS; @@ -5802,9 +5808,9 @@ ROLLBACK; UNLOCK TABLES; EXPLAIN UPDATE t2 SET b = CONCAT('+', b) WHERE a = sf_a_from_t1b_d('1') AND a = 2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 UPDATE NULL NULL NULL NULL NULL NULL NULL # NULL Impossible WHERE +1 UPDATE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where Warnings: -Note 1003 update `test`.`t2` set `test`.`t2`.`b` = concat('+',`test`.`t2`.`b`) where () +Note 1003 update `test`.`t2` set `test`.`t2`.`b` = concat('+',`test`.`t2`.`b`) where ((`test`.`t2`.`a` = 2) and (2 = `sf_a_from_t1b_d`('1'))) FLUSH STATUS; START TRANSACTION; UPDATE t2 SET b = CONCAT('+', b) WHERE a = sf_a_from_t1b_d('1') AND a = 2; @@ -6058,7 +6064,7 @@ ROLLBACK; UNLOCK TABLES; EXPLAIN UPDATE t2 SET b = sf_add_hello(b) WHERE a = sf_a_from_t1b_d('1'); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 UPDATE t2 p1 range PRIMARY PRIMARY 4 const # 100.00 Using where +1 UPDATE t2 p0,p1,p2 index NULL PRIMARY 4 NULL # 100.00 Using where Warnings: Note 1003 update `test`.`t2` set `test`.`t2`.`b` = `sf_add_hello`(`test`.`t2`.`b`) where (`test`.`t2`.`a` = `sf_a_from_t1b_d`('1')) FLUSH STATUS; @@ -6140,7 +6146,7 @@ ROLLBACK; UNLOCK TABLES; EXPLAIN UPDATE t2 SET b = sf_add_hello(b) WHERE a = 7 + sf_a_from_t1b_d('1'); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 UPDATE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where +1 UPDATE t2 p0,p1,p2 index NULL PRIMARY 4 NULL # 100.00 Using where Warnings: Note 1003 update `test`.`t2` set `test`.`t2`.`b` = `sf_add_hello`(`test`.`t2`.`b`) where (`test`.`t2`.`a` = (7 + `sf_a_from_t1b_d`('1'))) FLUSH STATUS; @@ -6214,9 +6220,9 @@ ROLLBACK; UNLOCK TABLES; EXPLAIN UPDATE t2 SET b = sf_add_hello(b) WHERE a = sf_a_from_t1b_d('1') AND a = 2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 UPDATE NULL NULL NULL NULL NULL NULL NULL # NULL Impossible WHERE +1 UPDATE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where Warnings: -Note 1003 update `test`.`t2` set `test`.`t2`.`b` = `sf_add_hello`(`test`.`t2`.`b`) where () +Note 1003 update `test`.`t2` set `test`.`t2`.`b` = `sf_add_hello`(`test`.`t2`.`b`) where ((`test`.`t2`.`a` = 2) and (2 = `sf_a_from_t1b_d`('1'))) FLUSH STATUS; START TRANSACTION; UPDATE t2 SET b = sf_add_hello(b) WHERE a = sf_a_from_t1b_d('1') AND a = 2; @@ -6476,7 +6482,7 @@ ROLLBACK; UNLOCK TABLES; EXPLAIN UPDATE t2 SET a = sf_add_1(a) + 4 WHERE a = sf_a_from_t1b_d('1'); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 UPDATE t2 p1 range PRIMARY PRIMARY 4 const # 100.00 Using where +1 UPDATE t2 p0,p1,p2 index NULL PRIMARY 4 NULL # 100.00 Using where; Using temporary Warnings: Note 1003 update `test`.`t2` set `test`.`t2`.`a` = (`sf_add_1`(`test`.`t2`.`a`) + 4) where (`test`.`t2`.`a` = `sf_a_from_t1b_d`('1')) FLUSH STATUS; @@ -6562,7 +6568,7 @@ ROLLBACK; UNLOCK TABLES; EXPLAIN UPDATE t2 SET a = sf_add_1(a) + 4 WHERE a = 7 + sf_a_from_t1b_d('1'); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 UPDATE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where +1 UPDATE t2 p0,p1,p2 index NULL PRIMARY 4 NULL # 100.00 Using where; Using temporary Warnings: Note 1003 update `test`.`t2` set `test`.`t2`.`a` = (`sf_add_1`(`test`.`t2`.`a`) + 4) where (`test`.`t2`.`a` = (7 + `sf_a_from_t1b_d`('1'))) FLUSH STATUS; @@ -6638,9 +6644,9 @@ ROLLBACK; UNLOCK TABLES; EXPLAIN UPDATE t2 SET a = sf_add_1(a) + 4 WHERE a = sf_a_from_t1b_d('1') AND a = 2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 UPDATE NULL NULL NULL NULL NULL NULL NULL # NULL Impossible WHERE +1 UPDATE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where Warnings: -Note 1003 update `test`.`t2` set `test`.`t2`.`a` = (`sf_add_1`(`test`.`t2`.`a`) + 4) where () +Note 1003 update `test`.`t2` set `test`.`t2`.`a` = (`sf_add_1`(`test`.`t2`.`a`) + 4) where ((`test`.`t2`.`a` = 2) and (2 = `sf_a_from_t1b_d`('1'))) FLUSH STATUS; START TRANSACTION; UPDATE t2 SET a = sf_add_1(a) + 4 WHERE a = sf_a_from_t1b_d('1') AND a = 2; @@ -6893,7 +6899,7 @@ ROLLBACK; UNLOCK TABLES; EXPLAIN DELETE FROM t2 WHERE a = sf_a_from_t1b_d('1'); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 DELETE t2 p1 range PRIMARY PRIMARY 4 const # 100.00 Using where +1 DELETE t2 p0,p1,p2 ALL NULL NULL NULL NULL # 100.00 Using where Warnings: Note 1003 delete from `test`.`t2` where (`test`.`t2`.`a` = `sf_a_from_t1b_d`('1')) FLUSH STATUS; @@ -6971,7 +6977,7 @@ ROLLBACK; UNLOCK TABLES; EXPLAIN DELETE FROM t2 WHERE a = 7 + sf_a_from_t1b_d('1'); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 DELETE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where +1 DELETE t2 p0,p1,p2 ALL NULL NULL NULL NULL # 100.00 Using where Warnings: Note 1003 delete from `test`.`t2` where (`test`.`t2`.`a` = (7 + `sf_a_from_t1b_d`('1'))) FLUSH STATUS; @@ -7043,9 +7049,9 @@ ROLLBACK; UNLOCK TABLES; EXPLAIN DELETE FROM t2 WHERE a = sf_a_from_t1b_d('1') AND a = 2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 DELETE NULL NULL NULL NULL NULL NULL NULL # NULL Impossible WHERE +1 DELETE t2 p2 range PRIMARY PRIMARY 4 const # 100.00 Using where Warnings: -Note 1003 delete from `test`.`t2` where () +Note 1003 delete from `test`.`t2` where ((`test`.`t2`.`a` = 2) and (2 = `sf_a_from_t1b_d`('1'))) FLUSH STATUS; START TRANSACTION; DELETE FROM t2 WHERE a = sf_a_from_t1b_d('1') AND a = 2; diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result index 1f80c52cffa5..8f1f2b0d1123 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -6327,3 +6327,116 @@ c1 c2 SELECT * from t2 WHERE c2 NOT IN ((SELECT c0 FROM t1 LIMIT 1),null); c1 c2 DROP TABLE t1, t2; +# +# Bug#37397306 - looks like not use pruning when it inserts with now() function in 8.0 +# +CREATE TABLE t1 ( +f1 DATETIME NOT NULL, +f2 INT NOT NULL, +f3 DATE NOT NULL, +PRIMARY KEY (f1,f2) +) +PARTITION BY RANGE COLUMNS(f1) +( +PARTITION p01 VALUES LESS THAN ('1975-12-31 10:21:55'), +PARTITION p02 VALUES LESS THAN ('1976-12-31 10:21:55'), +PARTITION p03 VALUES LESS THAN ('2090-12-31 10:21:55') +); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +SET TIMESTAMP=UNIX_TIMESTAMP('2019-03-11 12:00:00'); +EXPLAIN INSERT INTO t1 (f1,f2,f3) VALUES (now(),10001,'1976-11-31'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 INSERT t1 p03 ALL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 insert into `test`.`t1` (`test`.`t1`.`f1`,`test`.`t1`.`f2`,`test`.`t1`.`f3`) values (now(),10001,'1976-11-31') +SET TIMESTAMP=UNIX_TIMESTAMP('1975-03-11 12:00:00'); +EXPLAIN INSERT INTO t1 (f1,f2,f3) VALUES (now(),10001,'2000-11-31'); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 INSERT t1 p01 ALL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 insert into `test`.`t1` (`test`.`t1`.`f1`,`test`.`t1`.`f2`,`test`.`t1`.`f3`) values (now(),10001,'2000-11-31') +SET TIMESTAMP=DEFAULT; +DROP TABLE t1; +CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER) +PARTITION BY RANGE (a) +( +PARTITION p1 VALUES LESS THAN (10), +PARTITION p2 VALUES LESS THAN MAXVALUE +); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +set @a=1,@b=22; +EXPLAIN INSERT INTO t1(a,b) VALUES (@a,@b); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 INSERT t1 p1 ALL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 insert into `test`.`t1` (`test`.`t1`.`a`,`test`.`t1`.`b`) values ((@`a`),(@`b`)) +EXPLAIN INSERT INTO t1 VALUES (@a, 1), (@b, 2); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 INSERT t1 p1,p2 ALL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 insert into `test`.`t1` values ((@`a`),1),((@`b`),2) +set @a=11,@b=22; +EXPLAIN INSERT INTO t1(a,b) VALUES (@a,@b); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 INSERT t1 p2 ALL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 insert into `test`.`t1` (`test`.`t1`.`a`,`test`.`t1`.`b`) values ((@`a`),(@`b`)) +EXPLAIN INSERT INTO t1 VALUES (@a, 1), (@b, 2); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 INSERT t1 p2 ALL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 insert into `test`.`t1` values ((@`a`),1),((@`b`),2) +PREPARE s from "EXPLAIN INSERT INTO t1(a,b) VALUES (?,?)"; +set @a=1,@b=22; +EXECUTE s USING @a,@b; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 INSERT t1 p1 ALL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 insert into `test`.`t1` (`test`.`t1`.`a`,`test`.`t1`.`b`) values (?,?) +set @a=11,@b=22; +EXECUTE s USING @a,@b; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 INSERT t1 p2 ALL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 insert into `test`.`t1` (`test`.`t1`.`a`,`test`.`t1`.`b`) values (?,?) +PREPARE p from "EXPLAIN INSERT INTO t1(a,b) VALUES (?,1), (?,2)"; +set @a=1,@b=22; +EXECUTE p USING @a,@b; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 INSERT t1 p1,p2 ALL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 insert into `test`.`t1` (`test`.`t1`.`a`,`test`.`t1`.`b`) values (?,1),(?,2) +set @a=11,@b=22; +EXECUTE p USING @a,@b; +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 INSERT t1 p2 ALL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 insert into `test`.`t1` (`test`.`t1`.`a`,`test`.`t1`.`b`) values (?,1),(?,2) +DROP TABLE t1; +CREATE TABLE t1 ( +id INT PRIMARY KEY, +f1 FLOAT +) +PARTITION BY RANGE (id) +( +PARTITION p0 VALUES LESS THAN (10), +PARTITION p1 VALUES LESS THAN MAXVALUE +); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +EXPLAIN INSERT INTO t1 (id, f1) VALUES (1,RAND()); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 INSERT t1 p0 ALL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 insert into `test`.`t1` (`test`.`t1`.`id`,`test`.`t1`.`f1`) values (1,rand()) +EXPLAIN INSERT INTO t1 VALUES (20,RAND()); +id select_type table partitions type possible_keys key key_len ref rows filtered Extra +1 INSERT t1 p1 ALL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 insert into `test`.`t1` values (20,rand()) +DROP TABLE t1; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index f6a4657f82d6..a7e413ef53c0 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6377,9 +6377,9 @@ Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = 1) EXPLAIN SELECT * FROM t1 WHERE c1=f1(); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using index +1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using where; Using index Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = `f1`()) +Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = (`f1`())) EXPLAIN SELECT * FROM v1 WHERE c1=1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using index @@ -6387,14 +6387,14 @@ Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = 1) EXPLAIN SELECT * FROM v1 WHERE c1=f1(); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using index +1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using where; Using index Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = `f1`()) +Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = (`f1`())) EXPLAIN SELECT * FROM t1 WHERE c1=f2(10); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using index +1 SIMPLE t1 NULL ref c1 c1 5 const 1 100.00 Using where; Using index Warnings: -Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = `f2`(10)) +Note 1003 /* select#1 */ select `test`.`t1`.`c1` AS `c1` from `test`.`t1` where (`test`.`t1`.`c1` = (`f2`(10))) EXPLAIN SELECT * FROM t1 WHERE c1=f2(c1); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL index NULL c1 5 NULL 5 20.00 Using where; Using index diff --git a/mysql-test/r/subquery_sj_all.result b/mysql-test/r/subquery_sj_all.result index 59f39c67c269..6e366d3a7c8d 100644 --- a/mysql-test/r/subquery_sj_all.result +++ b/mysql-test/r/subquery_sj_all.result @@ -7774,7 +7774,7 @@ WHERE 1 IN(SELECT 1 FROM t4))); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 9 100.00 NULL -1 SIMPLE NULL const 4 const 1 100.00 NULL +1 SIMPLE NULL const 8 const 1 100.00 NULL 2 MATERIALIZED t2 NULL ALL NULL NULL NULL NULL 9 100.00 NULL 2 MATERIALIZED t3 NULL ALL NULL NULL NULL NULL 9 100.00 Using join buffer (hash join) 2 MATERIALIZED t4 NULL ALL NULL NULL NULL NULL 9 100.00 Using join buffer (hash join) diff --git a/mysql-test/r/subquery_sj_all_bka.result b/mysql-test/r/subquery_sj_all_bka.result index 6ad39c3178f8..7f2001eba122 100644 --- a/mysql-test/r/subquery_sj_all_bka.result +++ b/mysql-test/r/subquery_sj_all_bka.result @@ -7776,7 +7776,7 @@ WHERE 1 IN(SELECT 1 FROM t4))); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 9 100.00 NULL -1 SIMPLE NULL const 4 const 1 100.00 NULL +1 SIMPLE NULL const 8 const 1 100.00 NULL 2 MATERIALIZED t2 NULL ALL NULL NULL NULL NULL 9 100.00 NULL 2 MATERIALIZED t3 NULL ALL NULL NULL NULL NULL 9 100.00 Using join buffer (hash join) 2 MATERIALIZED t4 NULL ALL NULL NULL NULL NULL 9 100.00 Using join buffer (hash join) diff --git a/mysql-test/r/subquery_sj_all_bka_nobnl.result b/mysql-test/r/subquery_sj_all_bka_nobnl.result index 6d36ded29b48..ca17e208fabb 100644 --- a/mysql-test/r/subquery_sj_all_bka_nobnl.result +++ b/mysql-test/r/subquery_sj_all_bka_nobnl.result @@ -7774,7 +7774,7 @@ WHERE 1 IN(SELECT 1 FROM t4))); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 9 100.00 NULL -1 SIMPLE NULL const 4 const 1 100.00 NULL +1 SIMPLE NULL const 8 const 1 100.00 NULL 2 MATERIALIZED t2 NULL ALL NULL NULL NULL NULL 9 100.00 NULL 2 MATERIALIZED t3 NULL ALL NULL NULL NULL NULL 9 100.00 NULL 2 MATERIALIZED t4 NULL ALL NULL NULL NULL NULL 9 100.00 NULL diff --git a/mysql-test/r/subquery_sj_mat.result b/mysql-test/r/subquery_sj_mat.result index b6bd0ce22b28..33971a0a9c41 100644 --- a/mysql-test/r/subquery_sj_mat.result +++ b/mysql-test/r/subquery_sj_mat.result @@ -7977,7 +7977,7 @@ WHERE 1 IN(SELECT 1 FROM t3)); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL -1 SIMPLE NULL const 4 const 1 100.00 NULL +1 SIMPLE NULL const 8 const 1 100.00 NULL 2 MATERIALIZED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 MATERIALIZED t3 NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (hash join) Warnings: @@ -8016,7 +8016,7 @@ WHERE 1 IN(SELECT 1 FROM t4))); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 9 100.00 NULL -1 SIMPLE NULL const 4 const 1 100.00 NULL +1 SIMPLE NULL const 8 const 1 100.00 NULL 2 MATERIALIZED t2 NULL ALL NULL NULL NULL NULL 9 100.00 NULL 2 MATERIALIZED t3 NULL ALL NULL NULL NULL NULL 9 100.00 Using join buffer (hash join) 2 MATERIALIZED t4 NULL ALL NULL NULL NULL NULL 9 100.00 Using join buffer (hash join) @@ -13188,9 +13188,8 @@ Table Op Msg_type Msg_text test.t1 analyze status OK EXPLAIN SELECT 1 FROM t1 WHERE EXISTS(SELECT 1) IN (SELECT 1 FROM t1); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 1 100.00 NULL -1 PRIMARY NULL const 4 const 1 100.00 NULL -3 MATERIALIZED t1 NULL ALL NULL NULL NULL NULL 1 100.00 NULL +1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 1 100.00 Start temporary +1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 1 100.00 End temporary; Using join buffer (hash join) 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` semi join (`test`.`t1`) where true diff --git a/mysql-test/r/subquery_sj_mat_bka.result b/mysql-test/r/subquery_sj_mat_bka.result index a088f33597ef..35295db692e5 100644 --- a/mysql-test/r/subquery_sj_mat_bka.result +++ b/mysql-test/r/subquery_sj_mat_bka.result @@ -7978,7 +7978,7 @@ WHERE 1 IN(SELECT 1 FROM t3)); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL -1 SIMPLE NULL const 4 const 1 100.00 NULL +1 SIMPLE NULL const 8 const 1 100.00 NULL 2 MATERIALIZED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 MATERIALIZED t3 NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (hash join) Warnings: @@ -8017,7 +8017,7 @@ WHERE 1 IN(SELECT 1 FROM t4))); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 9 100.00 NULL -1 SIMPLE NULL const 4 const 1 100.00 NULL +1 SIMPLE NULL const 8 const 1 100.00 NULL 2 MATERIALIZED t2 NULL ALL NULL NULL NULL NULL 9 100.00 NULL 2 MATERIALIZED t3 NULL ALL NULL NULL NULL NULL 9 100.00 Using join buffer (hash join) 2 MATERIALIZED t4 NULL ALL NULL NULL NULL NULL 9 100.00 Using join buffer (hash join) @@ -13189,9 +13189,8 @@ Table Op Msg_type Msg_text test.t1 analyze status OK EXPLAIN SELECT 1 FROM t1 WHERE EXISTS(SELECT 1) IN (SELECT 1 FROM t1); id select_type table partitions type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 1 100.00 NULL -1 PRIMARY NULL const 4 const 1 100.00 NULL -3 MATERIALIZED t1 NULL ALL NULL NULL NULL NULL 1 100.00 NULL +1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 1 100.00 Start temporary +1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 1 100.00 End temporary; Using join buffer (hash join) 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` semi join (`test`.`t1`) where true diff --git a/mysql-test/r/subquery_sj_mat_bka_nobnl.result b/mysql-test/r/subquery_sj_mat_bka_nobnl.result index 7378907ce8a8..61f2f6f9c0a4 100644 --- a/mysql-test/r/subquery_sj_mat_bka_nobnl.result +++ b/mysql-test/r/subquery_sj_mat_bka_nobnl.result @@ -7977,7 +7977,7 @@ WHERE 1 IN(SELECT 1 FROM t3)); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL -1 SIMPLE NULL const 4 const 1 100.00 NULL +1 SIMPLE NULL const 8 const 1 100.00 NULL 2 MATERIALIZED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 MATERIALIZED t3 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: @@ -8016,7 +8016,7 @@ WHERE 1 IN(SELECT 1 FROM t4))); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 9 100.00 NULL -1 SIMPLE NULL const 4 const 1 100.00 NULL +1 SIMPLE NULL const 8 const 1 100.00 NULL 2 MATERIALIZED t2 NULL ALL NULL NULL NULL NULL 9 100.00 NULL 2 MATERIALIZED t3 NULL ALL NULL NULL NULL NULL 9 100.00 NULL 2 MATERIALIZED t4 NULL ALL NULL NULL NULL NULL 9 100.00 NULL @@ -13185,8 +13185,7 @@ test.t1 analyze status OK EXPLAIN SELECT 1 FROM t1 WHERE EXISTS(SELECT 1) IN (SELECT 1 FROM t1); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 1 100.00 NULL -1 PRIMARY NULL const 4 const 1 100.00 NULL -3 MATERIALIZED t1 NULL ALL NULL NULL NULL NULL 1 100.00 NULL +1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 1 100.00 Start temporary; End temporary 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 /* select#1 */ select 1 AS `1` from `test`.`t1` semi join (`test`.`t1`) where true diff --git a/mysql-test/suite/group_replication/r/gr_partial_trx_in_applier_relay_log.result b/mysql-test/suite/group_replication/r/gr_partial_trx_in_applier_relay_log.result index f0164955ed30..db5ac970ac1f 100644 --- a/mysql-test/suite/group_replication/r/gr_partial_trx_in_applier_relay_log.result +++ b/mysql-test/suite/group_replication/r/gr_partial_trx_in_applier_relay_log.result @@ -39,6 +39,7 @@ INSERT INTO t1 values (12); SET GLOBAL DEBUG="-d,stop_applier_channel_after_reading_write_rows_log_event"; include/stop_group_replication.inc include/start_group_replication.inc +include/assert.inc [Certifier broadcast thread must be running] ######################################################################## # 5. On M1: Insert another tuple and do a diff tables with other nodes. # (just to check that everything is working fine). diff --git a/mysql-test/suite/group_replication/t/gr_partial_trx_in_applier_relay_log.test b/mysql-test/suite/group_replication/t/gr_partial_trx_in_applier_relay_log.test index 17d2c2de96b5..d43baed7a994 100644 --- a/mysql-test/suite/group_replication/t/gr_partial_trx_in_applier_relay_log.test +++ b/mysql-test/suite/group_replication/t/gr_partial_trx_in_applier_relay_log.test @@ -92,6 +92,10 @@ SET GLOBAL DEBUG="-d,stop_applier_channel_after_reading_write_rows_log_event"; --let $wait_timeout=120 --source include/start_group_replication.inc +--let $assert_text= Certifier broadcast thread must be running +--let $assert_cond= [SELECT COUNT(*) FROM performance_schema.threads WHERE name = "thread/group_rpl/THD_certifier_broadcast"] = 1 +--source include/assert.inc + --echo ######################################################################## --echo # 5. On M1: Insert another tuple and do a diff tables with other nodes. --echo # (just to check that everything is working fine). diff --git a/mysql-test/suite/innodb/r/cross_ddl_partition_tables.result b/mysql-test/suite/innodb/r/cross_ddl_partition_tables.result new file mode 100644 index 000000000000..c4f0976bdaa9 --- /dev/null +++ b/mysql-test/suite/innodb/r/cross_ddl_partition_tables.result @@ -0,0 +1,37 @@ +# Create database and tables +CREATE DATABASE testdb; +USE testdb; +CREATE TABLE t1 ( id int ); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +CREATE TABLE t2 ( id int ); +INSERT INTO t2 SELECT * FROM t1; +CREATE TABLE t3 ( +id INT +) +PARTITION BY RANGE (id) ( +PARTITION p0 VALUES LESS THAN (1000), +PARTITION p1 VALUES LESS THAN (2000), +PARTITION p2 VALUES LESS THAN (3000) +); +INSERT INTO t3 VALUES (800); +INSERT INTO t3 VALUES (1500); +INSERT INTO t3 VALUES (2300); +BEGIN; +SELECT COUNT(*) FROM t1; +COUNT(*) +32 +# Alter the partition table. +ALTER TABLE testdb.t3 ADD COLUMN name varchar(10); +# SELECT COUNT(*) must fail as the table definition is changed. +SELECT COUNT(*) FROM testdb.t3; +ERROR HY000: Table definition has changed, please retry transaction +# SELECT * must fail as the table definition is changed. +SELECT * FROM testdb.t3; +ERROR HY000: Table definition has changed, please retry transaction +# Clean up +DROP DATABASE testdb; diff --git a/mysql-test/suite/innodb/r/innodb_dirty_pages_at_shutdown.result b/mysql-test/suite/innodb/r/innodb_dirty_pages_at_shutdown.result new file mode 100644 index 000000000000..3eea91735658 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_dirty_pages_at_shutdown.result @@ -0,0 +1,13 @@ +CREATE TABLE t1 (c1 INT); +INSERT INTO t1 VALUES (1); +call mtr.add_suppression("\\[InnoDB\\] \\[FATAL\\] Page still fixed or dirty at shutdown."); +call mtr.add_suppression("\\[InnoDB\\] Assertion failure.*ib::fatal triggered"); +call mtr.add_suppression("Attempting backtrace"); +SET GLOBAL DEBUG="+d,simulate_dirty_page_at_shutdown"; +# Shutdown the server +# Search the server error logs for the FATAL message +Pattern "Page still fixed or dirty at shutdown" found +# Start the server +# restart +SET GLOBAL DEBUG="-d,simulate_dirty_page_at_shutdown"; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/instant_max_column_crash.result b/mysql-test/suite/innodb/r/instant_max_column_crash.result index bd1a0ae2716e..b139fadcd66d 100644 --- a/mysql-test/suite/innodb/r/instant_max_column_crash.result +++ b/mysql-test/suite/innodb/r/instant_max_column_crash.result @@ -2,1078 +2,54 @@ # Bug: #34378513 : Assertion failure: dict0mem.h:2482:pos < n_def thread 140243300361984 # # Create table with 1017 columns -CREATE TABLE tb1 ( -col_1 INT DEFAULT NULL, -col_2 INT DEFAULT NULL, -col_3 INT DEFAULT NULL, -col_4 INT DEFAULT NULL, -col_5 INT DEFAULT NULL, -col_6 INT DEFAULT NULL, -col_7 INT DEFAULT NULL, -col_8 INT DEFAULT NULL, -col_9 INT DEFAULT NULL, -col_10 INT DEFAULT NULL, -col_11 INT DEFAULT NULL, -col_12 INT DEFAULT NULL, -col_13 INT DEFAULT NULL, -col_14 INT DEFAULT NULL, -col_15 INT DEFAULT NULL, -col_16 INT DEFAULT NULL, -col_17 INT DEFAULT NULL, -col_18 INT DEFAULT NULL, -col_19 INT DEFAULT NULL, -col_20 INT DEFAULT NULL, -col_21 INT DEFAULT NULL, -col_22 INT DEFAULT NULL, -col_23 INT DEFAULT NULL, -col_24 INT DEFAULT NULL, -col_25 INT DEFAULT NULL, -col_26 INT DEFAULT NULL, -col_27 INT DEFAULT NULL, -col_28 INT DEFAULT NULL, -col_29 INT DEFAULT NULL, -col_30 INT DEFAULT NULL, -col_31 INT DEFAULT NULL, -col_32 INT DEFAULT NULL, -col_33 INT DEFAULT NULL, -col_34 INT DEFAULT NULL, -col_35 INT DEFAULT NULL, -col_36 INT DEFAULT NULL, -col_37 INT DEFAULT NULL, -col_38 INT DEFAULT NULL, -col_39 INT DEFAULT NULL, -col_40 INT DEFAULT NULL, -col_41 INT DEFAULT NULL, -col_42 INT DEFAULT NULL, -col_43 INT DEFAULT NULL, -col_44 INT DEFAULT NULL, -col_45 INT DEFAULT NULL, -col_46 INT DEFAULT NULL, -col_47 INT DEFAULT NULL, -col_48 INT DEFAULT NULL, -col_49 INT DEFAULT NULL, -col_50 INT DEFAULT NULL, -col_51 INT DEFAULT NULL, -col_52 INT DEFAULT NULL, -col_53 INT DEFAULT NULL, -col_54 INT DEFAULT NULL, -col_55 INT DEFAULT NULL, -col_56 INT DEFAULT NULL, -col_57 INT DEFAULT NULL, -col_58 INT DEFAULT NULL, -col_59 INT DEFAULT NULL, -col_60 INT DEFAULT NULL, -col_61 INT DEFAULT NULL, -col_62 INT DEFAULT NULL, -col_63 INT DEFAULT NULL, -col_64 INT DEFAULT NULL, -col_65 INT DEFAULT NULL, -col_66 INT DEFAULT NULL, -col_67 INT DEFAULT NULL, -col_68 INT DEFAULT NULL, -col_69 INT DEFAULT NULL, -col_70 INT DEFAULT NULL, -col_71 INT DEFAULT NULL, -col_72 INT DEFAULT NULL, -col_73 INT DEFAULT NULL, -col_74 INT DEFAULT NULL, -col_75 INT DEFAULT NULL, -col_76 INT DEFAULT NULL, -col_77 INT DEFAULT NULL, -col_78 INT DEFAULT NULL, -col_79 INT DEFAULT NULL, -col_80 INT DEFAULT NULL, -col_81 INT DEFAULT NULL, -col_82 INT DEFAULT NULL, -col_83 INT DEFAULT NULL, -col_84 INT DEFAULT NULL, -col_85 INT DEFAULT NULL, -col_86 INT DEFAULT NULL, -col_87 INT DEFAULT NULL, -col_88 INT DEFAULT NULL, -col_89 INT DEFAULT NULL, -col_90 INT DEFAULT NULL, -col_91 INT DEFAULT NULL, -col_92 INT DEFAULT NULL, -col_93 INT DEFAULT NULL, -col_94 INT DEFAULT NULL, -col_95 INT DEFAULT NULL, -col_96 INT DEFAULT NULL, -col_97 INT DEFAULT NULL, -col_98 INT DEFAULT NULL, -col_99 INT DEFAULT NULL, -col_100 INT DEFAULT NULL, -col_101 INT DEFAULT NULL, -col_102 INT DEFAULT NULL, -col_103 INT DEFAULT NULL, -col_104 INT DEFAULT NULL, -col_105 INT DEFAULT NULL, -col_106 INT DEFAULT NULL, -col_107 INT DEFAULT NULL, -col_108 INT DEFAULT NULL, -col_109 INT DEFAULT NULL, -col_110 INT DEFAULT NULL, -col_111 INT DEFAULT NULL, -col_112 INT DEFAULT NULL, -col_113 INT DEFAULT NULL, -col_114 INT DEFAULT NULL, -col_115 INT DEFAULT NULL, -col_116 INT DEFAULT NULL, -col_117 INT DEFAULT NULL, -col_118 INT DEFAULT NULL, -col_119 INT DEFAULT NULL, -col_120 INT DEFAULT NULL, -col_121 INT DEFAULT NULL, -col_122 INT DEFAULT NULL, -col_123 INT DEFAULT NULL, -col_124 INT DEFAULT NULL, -col_125 INT DEFAULT NULL, -col_126 INT DEFAULT NULL, -col_127 INT DEFAULT NULL, -col_128 INT DEFAULT NULL, -col_129 INT DEFAULT NULL, -col_130 INT DEFAULT NULL, -col_131 INT DEFAULT NULL, -col_132 INT DEFAULT NULL, -col_133 INT DEFAULT NULL, -col_134 INT DEFAULT NULL, -col_135 INT DEFAULT NULL, -col_136 INT DEFAULT NULL, -col_137 INT DEFAULT NULL, -col_138 INT DEFAULT NULL, -col_139 INT DEFAULT NULL, -col_140 INT DEFAULT NULL, -col_141 INT DEFAULT NULL, -col_142 INT DEFAULT NULL, -col_143 INT DEFAULT NULL, -col_144 INT DEFAULT NULL, -col_145 INT DEFAULT NULL, -col_146 INT DEFAULT NULL, -col_147 INT DEFAULT NULL, -col_148 INT DEFAULT NULL, -col_149 INT DEFAULT NULL, -col_150 INT DEFAULT NULL, -col_151 INT DEFAULT NULL, -col_152 INT DEFAULT NULL, -col_153 INT DEFAULT NULL, -col_154 INT DEFAULT NULL, -col_155 INT DEFAULT NULL, -col_156 INT DEFAULT NULL, -col_157 INT DEFAULT NULL, -col_158 INT DEFAULT NULL, -col_159 INT DEFAULT NULL, -col_160 INT DEFAULT NULL, -col_161 INT DEFAULT NULL, -col_162 INT DEFAULT NULL, -col_163 INT DEFAULT NULL, -col_164 INT DEFAULT NULL, -col_165 INT DEFAULT NULL, -col_166 INT DEFAULT NULL, -col_167 INT DEFAULT NULL, -col_168 INT DEFAULT NULL, -col_169 INT DEFAULT NULL, -col_170 INT DEFAULT NULL, -col_171 INT DEFAULT NULL, -col_172 INT DEFAULT NULL, -col_173 INT DEFAULT NULL, -col_174 INT DEFAULT NULL, -col_175 INT DEFAULT NULL, -col_176 INT DEFAULT NULL, -col_177 INT DEFAULT NULL, -col_178 INT DEFAULT NULL, -col_179 INT DEFAULT NULL, -col_180 INT DEFAULT NULL, -col_181 INT DEFAULT NULL, -col_182 INT DEFAULT NULL, -col_183 INT DEFAULT NULL, -col_184 INT DEFAULT NULL, -col_185 INT DEFAULT NULL, -col_186 INT DEFAULT NULL, -col_187 INT DEFAULT NULL, -col_188 INT DEFAULT NULL, -col_189 INT DEFAULT NULL, -col_190 INT DEFAULT NULL, -col_191 INT DEFAULT NULL, -col_192 INT DEFAULT NULL, -col_193 INT DEFAULT NULL, -col_194 INT DEFAULT NULL, -col_195 INT DEFAULT NULL, -col_196 INT DEFAULT NULL, -col_197 INT DEFAULT NULL, -col_198 INT DEFAULT NULL, -col_199 INT DEFAULT NULL, -col_200 INT DEFAULT NULL, -col_201 INT DEFAULT NULL, -col_202 INT DEFAULT NULL, -col_203 INT DEFAULT NULL, -col_204 INT DEFAULT NULL, -col_205 INT DEFAULT NULL, -col_206 INT DEFAULT NULL, -col_207 INT DEFAULT NULL, -col_208 INT DEFAULT NULL, -col_209 INT DEFAULT NULL, -col_210 INT DEFAULT NULL, -col_211 INT DEFAULT NULL, -col_212 INT DEFAULT NULL, -col_213 INT DEFAULT NULL, -col_214 INT DEFAULT NULL, -col_215 INT DEFAULT NULL, -col_216 INT DEFAULT NULL, -col_217 INT DEFAULT NULL, -col_218 INT DEFAULT NULL, -col_219 INT DEFAULT NULL, -col_220 INT DEFAULT NULL, -col_221 INT DEFAULT NULL, -col_222 INT DEFAULT NULL, -col_223 INT DEFAULT NULL, -col_224 INT DEFAULT NULL, -col_225 INT DEFAULT NULL, -col_226 INT DEFAULT NULL, -col_227 INT DEFAULT NULL, -col_228 INT DEFAULT NULL, -col_229 INT DEFAULT NULL, -col_230 INT DEFAULT NULL, -col_231 INT DEFAULT NULL, -col_232 INT DEFAULT NULL, -col_233 INT DEFAULT NULL, -col_234 INT DEFAULT NULL, -col_235 INT DEFAULT NULL, -col_236 INT DEFAULT NULL, -col_237 INT DEFAULT NULL, -col_238 INT DEFAULT NULL, -col_239 INT DEFAULT NULL, -col_240 INT DEFAULT NULL, -col_241 INT DEFAULT NULL, -col_242 INT DEFAULT NULL, -col_243 INT DEFAULT NULL, -col_244 INT DEFAULT NULL, -col_245 INT DEFAULT NULL, -col_246 INT DEFAULT NULL, -col_247 INT DEFAULT NULL, -col_248 INT DEFAULT NULL, -col_249 INT DEFAULT NULL, -col_250 INT DEFAULT NULL, -col_251 INT DEFAULT NULL, -col_252 INT DEFAULT NULL, -col_253 INT DEFAULT NULL, -col_254 INT DEFAULT NULL, -col_255 INT DEFAULT NULL, -col_256 INT DEFAULT NULL, -col_257 INT DEFAULT NULL, -col_258 INT DEFAULT NULL, -col_259 INT DEFAULT NULL, -col_260 INT DEFAULT NULL, -col_261 INT DEFAULT NULL, -col_262 INT DEFAULT NULL, -col_263 INT DEFAULT NULL, -col_264 INT DEFAULT NULL, -col_265 INT DEFAULT NULL, -col_266 INT DEFAULT NULL, -col_267 INT DEFAULT NULL, -col_268 INT DEFAULT NULL, -col_269 INT DEFAULT NULL, -col_270 INT DEFAULT NULL, -col_271 INT DEFAULT NULL, -col_272 INT DEFAULT NULL, -col_273 INT DEFAULT NULL, -col_274 INT DEFAULT NULL, -col_275 INT DEFAULT NULL, -col_276 INT DEFAULT NULL, -col_277 INT DEFAULT NULL, -col_278 INT DEFAULT NULL, -col_279 INT DEFAULT NULL, -col_280 INT DEFAULT NULL, -col_281 INT DEFAULT NULL, -col_282 INT DEFAULT NULL, -col_283 INT DEFAULT NULL, -col_284 INT DEFAULT NULL, -col_285 INT DEFAULT NULL, -col_286 INT DEFAULT NULL, -col_287 INT DEFAULT NULL, -col_288 INT DEFAULT NULL, -col_289 INT DEFAULT NULL, -col_290 INT DEFAULT NULL, -col_291 INT DEFAULT NULL, -col_292 INT DEFAULT NULL, -col_293 INT DEFAULT NULL, -col_294 INT DEFAULT NULL, -col_295 INT DEFAULT NULL, -col_296 INT DEFAULT NULL, -col_297 INT DEFAULT NULL, -col_298 INT DEFAULT NULL, -col_299 INT DEFAULT NULL, -col_300 INT DEFAULT NULL, -col_301 INT DEFAULT NULL, -col_302 INT DEFAULT NULL, -col_303 INT DEFAULT NULL, -col_304 INT DEFAULT NULL, -col_305 INT DEFAULT NULL, -col_306 INT DEFAULT NULL, -col_307 INT DEFAULT NULL, -col_308 INT DEFAULT NULL, -col_309 INT DEFAULT NULL, -col_310 INT DEFAULT NULL, -col_311 INT DEFAULT NULL, -col_312 INT DEFAULT NULL, -col_313 INT DEFAULT NULL, -col_314 INT DEFAULT NULL, -col_315 INT DEFAULT NULL, -col_316 INT DEFAULT NULL, -col_317 INT DEFAULT NULL, -col_318 INT DEFAULT NULL, -col_319 INT DEFAULT NULL, -col_320 INT DEFAULT NULL, -col_321 INT DEFAULT NULL, -col_322 INT DEFAULT NULL, -col_323 INT DEFAULT NULL, -col_324 INT DEFAULT NULL, -col_325 INT DEFAULT NULL, -col_326 INT DEFAULT NULL, -col_327 INT DEFAULT NULL, -col_328 INT DEFAULT NULL, -col_329 INT DEFAULT NULL, -col_330 INT DEFAULT NULL, -col_331 INT DEFAULT NULL, -col_332 INT DEFAULT NULL, -col_333 INT DEFAULT NULL, -col_334 INT DEFAULT NULL, -col_335 INT DEFAULT NULL, -col_336 INT DEFAULT NULL, -col_337 INT DEFAULT NULL, -col_338 INT DEFAULT NULL, -col_339 INT DEFAULT NULL, -col_340 INT DEFAULT NULL, -col_341 INT DEFAULT NULL, -col_342 INT DEFAULT NULL, -col_343 INT DEFAULT NULL, -col_344 INT DEFAULT NULL, -col_345 INT DEFAULT NULL, -col_346 INT DEFAULT NULL, -col_347 INT DEFAULT NULL, -col_348 INT DEFAULT NULL, -col_349 INT DEFAULT NULL, -col_350 INT DEFAULT NULL, -col_351 INT DEFAULT NULL, -col_352 INT DEFAULT NULL, -col_353 INT DEFAULT NULL, -col_354 INT DEFAULT NULL, -col_355 INT DEFAULT NULL, -col_356 INT DEFAULT NULL, -col_357 INT DEFAULT NULL, -col_358 INT DEFAULT NULL, -col_359 INT DEFAULT NULL, -col_360 INT DEFAULT NULL, -col_361 INT DEFAULT NULL, -col_362 INT DEFAULT NULL, -col_363 INT DEFAULT NULL, -col_364 INT DEFAULT NULL, -col_365 INT DEFAULT NULL, -col_366 INT DEFAULT NULL, -col_367 INT DEFAULT NULL, -col_368 INT DEFAULT NULL, -col_369 INT DEFAULT NULL, -col_370 INT DEFAULT NULL, -col_371 INT DEFAULT NULL, -col_372 INT DEFAULT NULL, -col_373 INT DEFAULT NULL, -col_374 INT DEFAULT NULL, -col_375 INT DEFAULT NULL, -col_376 INT DEFAULT NULL, -col_377 INT DEFAULT NULL, -col_378 INT DEFAULT NULL, -col_379 INT DEFAULT NULL, -col_380 INT DEFAULT NULL, -col_381 INT DEFAULT NULL, -col_382 INT DEFAULT NULL, -col_383 INT DEFAULT NULL, -col_384 INT DEFAULT NULL, -col_385 INT DEFAULT NULL, -col_386 INT DEFAULT NULL, -col_387 INT DEFAULT NULL, -col_388 INT DEFAULT NULL, -col_389 INT DEFAULT NULL, -col_390 INT DEFAULT NULL, -col_391 INT DEFAULT NULL, -col_392 INT DEFAULT NULL, -col_393 INT DEFAULT NULL, -col_394 INT DEFAULT NULL, -col_395 INT DEFAULT NULL, -col_396 INT DEFAULT NULL, -col_397 INT DEFAULT NULL, -col_398 INT DEFAULT NULL, -col_399 INT DEFAULT NULL, -col_400 INT DEFAULT NULL, -col_401 INT DEFAULT NULL, -col_402 INT DEFAULT NULL, -col_403 INT DEFAULT NULL, -col_404 INT DEFAULT NULL, -col_405 INT DEFAULT NULL, -col_406 INT DEFAULT NULL, -col_407 INT DEFAULT NULL, -col_408 INT DEFAULT NULL, -col_409 INT DEFAULT NULL, -col_410 INT DEFAULT NULL, -col_411 INT DEFAULT NULL, -col_412 INT DEFAULT NULL, -col_413 INT DEFAULT NULL, -col_414 INT DEFAULT NULL, -col_415 INT DEFAULT NULL, -col_416 INT DEFAULT NULL, -col_417 INT DEFAULT NULL, -col_418 INT DEFAULT NULL, -col_419 INT DEFAULT NULL, -col_420 INT DEFAULT NULL, -col_421 INT DEFAULT NULL, -col_422 INT DEFAULT NULL, -col_423 INT DEFAULT NULL, -col_424 INT DEFAULT NULL, -col_425 INT DEFAULT NULL, -col_426 INT DEFAULT NULL, -col_427 INT DEFAULT NULL, -col_428 INT DEFAULT NULL, -col_429 INT DEFAULT NULL, -col_430 INT DEFAULT NULL, -col_431 INT DEFAULT NULL, -col_432 INT DEFAULT NULL, -col_433 INT DEFAULT NULL, -col_434 INT DEFAULT NULL, -col_435 INT DEFAULT NULL, -col_436 INT DEFAULT NULL, -col_437 INT DEFAULT NULL, -col_438 INT DEFAULT NULL, -col_439 INT DEFAULT NULL, -col_440 INT DEFAULT NULL, -col_441 INT DEFAULT NULL, -col_442 INT DEFAULT NULL, -col_443 INT DEFAULT NULL, -col_444 INT DEFAULT NULL, -col_445 INT DEFAULT NULL, -col_446 INT DEFAULT NULL, -col_447 INT DEFAULT NULL, -col_448 INT DEFAULT NULL, -col_449 INT DEFAULT NULL, -col_450 INT DEFAULT NULL, -col_451 INT DEFAULT NULL, -col_452 INT DEFAULT NULL, -col_453 INT DEFAULT NULL, -col_454 INT DEFAULT NULL, -col_455 INT DEFAULT NULL, -col_456 INT DEFAULT NULL, -col_457 INT DEFAULT NULL, -col_458 INT DEFAULT NULL, -col_459 INT DEFAULT NULL, -col_460 INT DEFAULT NULL, -col_461 INT DEFAULT NULL, -col_462 INT DEFAULT NULL, -col_463 INT DEFAULT NULL, -col_464 INT DEFAULT NULL, -col_465 INT DEFAULT NULL, -col_466 INT DEFAULT NULL, -col_467 INT DEFAULT NULL, -col_468 INT DEFAULT NULL, -col_469 INT DEFAULT NULL, -col_470 INT DEFAULT NULL, -col_471 INT DEFAULT NULL, -col_472 INT DEFAULT NULL, -col_473 INT DEFAULT NULL, -col_474 INT DEFAULT NULL, -col_475 INT DEFAULT NULL, -col_476 INT DEFAULT NULL, -col_477 INT DEFAULT NULL, -col_478 INT DEFAULT NULL, -col_479 INT DEFAULT NULL, -col_480 INT DEFAULT NULL, -col_481 INT DEFAULT NULL, -col_482 INT DEFAULT NULL, -col_483 INT DEFAULT NULL, -col_484 INT DEFAULT NULL, -col_485 INT DEFAULT NULL, -col_486 INT DEFAULT NULL, -col_487 INT DEFAULT NULL, -col_488 INT DEFAULT NULL, -col_489 INT DEFAULT NULL, -col_490 INT DEFAULT NULL, -col_491 INT DEFAULT NULL, -col_492 INT DEFAULT NULL, -col_493 INT DEFAULT NULL, -col_494 INT DEFAULT NULL, -col_495 INT DEFAULT NULL, -col_496 INT DEFAULT NULL, -col_497 INT DEFAULT NULL, -col_498 INT DEFAULT NULL, -col_499 INT DEFAULT NULL, -col_500 INT DEFAULT NULL, -col_501 INT DEFAULT NULL, -col_502 INT DEFAULT NULL, -col_503 INT DEFAULT NULL, -col_504 INT DEFAULT NULL, -col_505 INT DEFAULT NULL, -col_506 INT DEFAULT NULL, -col_507 INT DEFAULT NULL, -col_508 INT DEFAULT NULL, -col_509 INT DEFAULT NULL, -col_510 INT DEFAULT NULL, -col_511 INT DEFAULT NULL, -col_512 INT DEFAULT NULL, -col_513 INT DEFAULT NULL, -col_514 INT DEFAULT NULL, -col_515 INT DEFAULT NULL, -col_516 INT DEFAULT NULL, -col_517 INT DEFAULT NULL, -col_518 INT DEFAULT NULL, -col_519 INT DEFAULT NULL, -col_520 INT DEFAULT NULL, -col_521 INT DEFAULT NULL, -col_522 INT DEFAULT NULL, -col_523 INT DEFAULT NULL, -col_524 INT DEFAULT NULL, -col_525 INT DEFAULT NULL, -col_526 INT DEFAULT NULL, -col_527 INT DEFAULT NULL, -col_528 INT DEFAULT NULL, -col_529 INT DEFAULT NULL, -col_530 INT DEFAULT NULL, -col_531 INT DEFAULT NULL, -col_532 INT DEFAULT NULL, -col_533 INT DEFAULT NULL, -col_534 INT DEFAULT NULL, -col_535 INT DEFAULT NULL, -col_536 INT DEFAULT NULL, -col_537 INT DEFAULT NULL, -col_538 INT DEFAULT NULL, -col_539 INT DEFAULT NULL, -col_540 INT DEFAULT NULL, -col_541 INT DEFAULT NULL, -col_542 INT DEFAULT NULL, -col_543 INT DEFAULT NULL, -col_544 INT DEFAULT NULL, -col_545 INT DEFAULT NULL, -col_546 INT DEFAULT NULL, -col_547 INT DEFAULT NULL, -col_548 INT DEFAULT NULL, -col_549 INT DEFAULT NULL, -col_550 INT DEFAULT NULL, -col_551 INT DEFAULT NULL, -col_552 INT DEFAULT NULL, -col_553 INT DEFAULT NULL, -col_554 INT DEFAULT NULL, -col_555 INT DEFAULT NULL, -col_556 INT DEFAULT NULL, -col_557 INT DEFAULT NULL, -col_558 INT DEFAULT NULL, -col_559 INT DEFAULT NULL, -col_560 INT DEFAULT NULL, -col_561 INT DEFAULT NULL, -col_562 INT DEFAULT NULL, -col_563 INT DEFAULT NULL, -col_564 INT DEFAULT NULL, -col_565 INT DEFAULT NULL, -col_566 INT DEFAULT NULL, -col_567 INT DEFAULT NULL, -col_568 INT DEFAULT NULL, -col_569 INT DEFAULT NULL, -col_570 INT DEFAULT NULL, -col_571 INT DEFAULT NULL, -col_572 INT DEFAULT NULL, -col_573 INT DEFAULT NULL, -col_574 INT DEFAULT NULL, -col_575 INT DEFAULT NULL, -col_576 INT DEFAULT NULL, -col_577 INT DEFAULT NULL, -col_578 INT DEFAULT NULL, -col_579 INT DEFAULT NULL, -col_580 INT DEFAULT NULL, -col_581 INT DEFAULT NULL, -col_582 INT DEFAULT NULL, -col_583 INT DEFAULT NULL, -col_584 INT DEFAULT NULL, -col_585 INT DEFAULT NULL, -col_586 INT DEFAULT NULL, -col_587 INT DEFAULT NULL, -col_588 INT DEFAULT NULL, -col_589 INT DEFAULT NULL, -col_590 INT DEFAULT NULL, -col_591 INT DEFAULT NULL, -col_592 INT DEFAULT NULL, -col_593 INT DEFAULT NULL, -col_594 INT DEFAULT NULL, -col_595 INT DEFAULT NULL, -col_596 INT DEFAULT NULL, -col_597 INT DEFAULT NULL, -col_598 INT DEFAULT NULL, -col_599 INT DEFAULT NULL, -col_600 INT DEFAULT NULL, -col_601 INT DEFAULT NULL, -col_602 INT DEFAULT NULL, -col_603 INT DEFAULT NULL, -col_604 INT DEFAULT NULL, -col_605 INT DEFAULT NULL, -col_606 INT DEFAULT NULL, -col_607 INT DEFAULT NULL, -col_608 INT DEFAULT NULL, -col_609 INT DEFAULT NULL, -col_610 INT DEFAULT NULL, -col_611 INT DEFAULT NULL, -col_612 INT DEFAULT NULL, -col_613 INT DEFAULT NULL, -col_614 INT DEFAULT NULL, -col_615 INT DEFAULT NULL, -col_616 INT DEFAULT NULL, -col_617 INT DEFAULT NULL, -col_618 INT DEFAULT NULL, -col_619 INT DEFAULT NULL, -col_620 INT DEFAULT NULL, -col_621 INT DEFAULT NULL, -col_622 INT DEFAULT NULL, -col_623 INT DEFAULT NULL, -col_624 INT DEFAULT NULL, -col_625 INT DEFAULT NULL, -col_626 INT DEFAULT NULL, -col_627 INT DEFAULT NULL, -col_628 INT DEFAULT NULL, -col_629 INT DEFAULT NULL, -col_630 INT DEFAULT NULL, -col_631 INT DEFAULT NULL, -col_632 INT DEFAULT NULL, -col_633 INT DEFAULT NULL, -col_634 INT DEFAULT NULL, -col_635 INT DEFAULT NULL, -col_636 INT DEFAULT NULL, -col_637 INT DEFAULT NULL, -col_638 INT DEFAULT NULL, -col_639 INT DEFAULT NULL, -col_640 INT DEFAULT NULL, -col_641 INT DEFAULT NULL, -col_642 INT DEFAULT NULL, -col_643 INT DEFAULT NULL, -col_644 INT DEFAULT NULL, -col_645 INT DEFAULT NULL, -col_646 INT DEFAULT NULL, -col_647 INT DEFAULT NULL, -col_648 INT DEFAULT NULL, -col_649 INT DEFAULT NULL, -col_650 INT DEFAULT NULL, -col_651 INT DEFAULT NULL, -col_652 INT DEFAULT NULL, -col_653 INT DEFAULT NULL, -col_654 INT DEFAULT NULL, -col_655 INT DEFAULT NULL, -col_656 INT DEFAULT NULL, -col_657 INT DEFAULT NULL, -col_658 INT DEFAULT NULL, -col_659 INT DEFAULT NULL, -col_660 INT DEFAULT NULL, -col_661 INT DEFAULT NULL, -col_662 INT DEFAULT NULL, -col_663 INT DEFAULT NULL, -col_664 INT DEFAULT NULL, -col_665 INT DEFAULT NULL, -col_666 INT DEFAULT NULL, -col_667 INT DEFAULT NULL, -col_668 INT DEFAULT NULL, -col_669 INT DEFAULT NULL, -col_670 INT DEFAULT NULL, -col_671 INT DEFAULT NULL, -col_672 INT DEFAULT NULL, -col_673 INT DEFAULT NULL, -col_674 INT DEFAULT NULL, -col_675 INT DEFAULT NULL, -col_676 INT DEFAULT NULL, -col_677 INT DEFAULT NULL, -col_678 INT DEFAULT NULL, -col_679 INT DEFAULT NULL, -col_680 INT DEFAULT NULL, -col_681 INT DEFAULT NULL, -col_682 INT DEFAULT NULL, -col_683 INT DEFAULT NULL, -col_684 INT DEFAULT NULL, -col_685 INT DEFAULT NULL, -col_686 INT DEFAULT NULL, -col_687 INT DEFAULT NULL, -col_688 INT DEFAULT NULL, -col_689 INT DEFAULT NULL, -col_690 INT DEFAULT NULL, -col_691 INT DEFAULT NULL, -col_692 INT DEFAULT NULL, -col_693 INT DEFAULT NULL, -col_694 INT DEFAULT NULL, -col_695 INT DEFAULT NULL, -col_696 INT DEFAULT NULL, -col_697 INT DEFAULT NULL, -col_698 INT DEFAULT NULL, -col_699 INT DEFAULT NULL, -col_700 INT DEFAULT NULL, -col_701 INT DEFAULT NULL, -col_702 INT DEFAULT NULL, -col_703 INT DEFAULT NULL, -col_704 INT DEFAULT NULL, -col_705 INT DEFAULT NULL, -col_706 INT DEFAULT NULL, -col_707 INT DEFAULT NULL, -col_708 INT DEFAULT NULL, -col_709 INT DEFAULT NULL, -col_710 INT DEFAULT NULL, -col_711 INT DEFAULT NULL, -col_712 INT DEFAULT NULL, -col_713 INT DEFAULT NULL, -col_714 INT DEFAULT NULL, -col_715 INT DEFAULT NULL, -col_716 INT DEFAULT NULL, -col_717 INT DEFAULT NULL, -col_718 INT DEFAULT NULL, -col_719 INT DEFAULT NULL, -col_720 INT DEFAULT NULL, -col_721 INT DEFAULT NULL, -col_722 INT DEFAULT NULL, -col_723 INT DEFAULT NULL, -col_724 INT DEFAULT NULL, -col_725 INT DEFAULT NULL, -col_726 INT DEFAULT NULL, -col_727 INT DEFAULT NULL, -col_728 INT DEFAULT NULL, -col_729 INT DEFAULT NULL, -col_730 INT DEFAULT NULL, -col_731 INT DEFAULT NULL, -col_732 INT DEFAULT NULL, -col_733 INT DEFAULT NULL, -col_734 INT DEFAULT NULL, -col_735 INT DEFAULT NULL, -col_736 INT DEFAULT NULL, -col_737 INT DEFAULT NULL, -col_738 INT DEFAULT NULL, -col_739 INT DEFAULT NULL, -col_740 INT DEFAULT NULL, -col_741 INT DEFAULT NULL, -col_742 INT DEFAULT NULL, -col_743 INT DEFAULT NULL, -col_744 INT DEFAULT NULL, -col_745 INT DEFAULT NULL, -col_746 INT DEFAULT NULL, -col_747 INT DEFAULT NULL, -col_748 INT DEFAULT NULL, -col_749 INT DEFAULT NULL, -col_750 INT DEFAULT NULL, -col_751 INT DEFAULT NULL, -col_752 INT DEFAULT NULL, -col_753 INT DEFAULT NULL, -col_754 INT DEFAULT NULL, -col_755 INT DEFAULT NULL, -col_756 INT DEFAULT NULL, -col_757 INT DEFAULT NULL, -col_758 INT DEFAULT NULL, -col_759 INT DEFAULT NULL, -col_760 INT DEFAULT NULL, -col_761 INT DEFAULT NULL, -col_762 INT DEFAULT NULL, -col_763 INT DEFAULT NULL, -col_764 INT DEFAULT NULL, -col_765 INT DEFAULT NULL, -col_766 INT DEFAULT NULL, -col_767 INT DEFAULT NULL, -col_768 INT DEFAULT NULL, -col_769 INT DEFAULT NULL, -col_770 INT DEFAULT NULL, -col_771 INT DEFAULT NULL, -col_772 INT DEFAULT NULL, -col_773 INT DEFAULT NULL, -col_774 INT DEFAULT NULL, -col_775 INT DEFAULT NULL, -col_776 INT DEFAULT NULL, -col_777 INT DEFAULT NULL, -col_778 INT DEFAULT NULL, -col_779 INT DEFAULT NULL, -col_780 INT DEFAULT NULL, -col_781 INT DEFAULT NULL, -col_782 INT DEFAULT NULL, -col_783 INT DEFAULT NULL, -col_784 INT DEFAULT NULL, -col_785 INT DEFAULT NULL, -col_786 INT DEFAULT NULL, -col_787 INT DEFAULT NULL, -col_788 INT DEFAULT NULL, -col_789 INT DEFAULT NULL, -col_790 INT DEFAULT NULL, -col_791 INT DEFAULT NULL, -col_792 INT DEFAULT NULL, -col_793 INT DEFAULT NULL, -col_794 INT DEFAULT NULL, -col_795 INT DEFAULT NULL, -col_796 INT DEFAULT NULL, -col_797 INT DEFAULT NULL, -col_798 INT DEFAULT NULL, -col_799 INT DEFAULT NULL, -col_800 INT DEFAULT NULL, -col_801 INT DEFAULT NULL, -col_802 INT DEFAULT NULL, -col_803 INT DEFAULT NULL, -col_804 INT DEFAULT NULL, -col_805 INT DEFAULT NULL, -col_806 INT DEFAULT NULL, -col_807 INT DEFAULT NULL, -col_808 INT DEFAULT NULL, -col_809 INT DEFAULT NULL, -col_810 INT DEFAULT NULL, -col_811 INT DEFAULT NULL, -col_812 INT DEFAULT NULL, -col_813 INT DEFAULT NULL, -col_814 INT DEFAULT NULL, -col_815 INT DEFAULT NULL, -col_816 INT DEFAULT NULL, -col_817 INT DEFAULT NULL, -col_818 INT DEFAULT NULL, -col_819 INT DEFAULT NULL, -col_820 INT DEFAULT NULL, -col_821 INT DEFAULT NULL, -col_822 INT DEFAULT NULL, -col_823 INT DEFAULT NULL, -col_824 INT DEFAULT NULL, -col_825 INT DEFAULT NULL, -col_826 INT DEFAULT NULL, -col_827 INT DEFAULT NULL, -col_828 INT DEFAULT NULL, -col_829 INT DEFAULT NULL, -col_830 INT DEFAULT NULL, -col_831 INT DEFAULT NULL, -col_832 INT DEFAULT NULL, -col_833 INT DEFAULT NULL, -col_834 INT DEFAULT NULL, -col_835 INT DEFAULT NULL, -col_836 INT DEFAULT NULL, -col_837 INT DEFAULT NULL, -col_838 INT DEFAULT NULL, -col_839 INT DEFAULT NULL, -col_840 INT DEFAULT NULL, -col_841 INT DEFAULT NULL, -col_842 INT DEFAULT NULL, -col_843 INT DEFAULT NULL, -col_844 INT DEFAULT NULL, -col_845 INT DEFAULT NULL, -col_846 INT DEFAULT NULL, -col_847 INT DEFAULT NULL, -col_848 INT DEFAULT NULL, -col_849 INT DEFAULT NULL, -col_850 INT DEFAULT NULL, -col_851 INT DEFAULT NULL, -col_852 INT DEFAULT NULL, -col_853 INT DEFAULT NULL, -col_854 INT DEFAULT NULL, -col_855 INT DEFAULT NULL, -col_856 INT DEFAULT NULL, -col_857 INT DEFAULT NULL, -col_858 INT DEFAULT NULL, -col_859 INT DEFAULT NULL, -col_860 INT DEFAULT NULL, -col_861 INT DEFAULT NULL, -col_862 INT DEFAULT NULL, -col_863 INT DEFAULT NULL, -col_864 INT DEFAULT NULL, -col_865 INT DEFAULT NULL, -col_866 INT DEFAULT NULL, -col_867 INT DEFAULT NULL, -col_868 INT DEFAULT NULL, -col_869 INT DEFAULT NULL, -col_870 INT DEFAULT NULL, -col_871 INT DEFAULT NULL, -col_872 INT DEFAULT NULL, -col_873 INT DEFAULT NULL, -col_874 INT DEFAULT NULL, -col_875 INT DEFAULT NULL, -col_876 INT DEFAULT NULL, -col_877 INT DEFAULT NULL, -col_878 INT DEFAULT NULL, -col_879 INT DEFAULT NULL, -col_880 INT DEFAULT NULL, -col_881 INT DEFAULT NULL, -col_882 INT DEFAULT NULL, -col_883 INT DEFAULT NULL, -col_884 INT DEFAULT NULL, -col_885 INT DEFAULT NULL, -col_886 INT DEFAULT NULL, -col_887 INT DEFAULT NULL, -col_888 INT DEFAULT NULL, -col_889 INT DEFAULT NULL, -col_890 INT DEFAULT NULL, -col_891 INT DEFAULT NULL, -col_892 INT DEFAULT NULL, -col_893 INT DEFAULT NULL, -col_894 INT DEFAULT NULL, -col_895 INT DEFAULT NULL, -col_896 INT DEFAULT NULL, -col_897 INT DEFAULT NULL, -col_898 INT DEFAULT NULL, -col_899 INT DEFAULT NULL, -col_900 INT DEFAULT NULL, -col_901 INT DEFAULT NULL, -col_902 INT DEFAULT NULL, -col_903 INT DEFAULT NULL, -col_904 INT DEFAULT NULL, -col_905 INT DEFAULT NULL, -col_906 INT DEFAULT NULL, -col_907 INT DEFAULT NULL, -col_908 INT DEFAULT NULL, -col_909 INT DEFAULT NULL, -col_910 INT DEFAULT NULL, -col_911 INT DEFAULT NULL, -col_912 INT DEFAULT NULL, -col_913 INT DEFAULT NULL, -col_914 INT DEFAULT NULL, -col_915 INT DEFAULT NULL, -col_916 INT DEFAULT NULL, -col_917 INT DEFAULT NULL, -col_918 INT DEFAULT NULL, -col_919 INT DEFAULT NULL, -col_920 INT DEFAULT NULL, -col_921 INT DEFAULT NULL, -col_922 INT DEFAULT NULL, -col_923 INT DEFAULT NULL, -col_924 INT DEFAULT NULL, -col_925 INT DEFAULT NULL, -col_926 INT DEFAULT NULL, -col_927 INT DEFAULT NULL, -col_928 INT DEFAULT NULL, -col_929 INT DEFAULT NULL, -col_930 INT DEFAULT NULL, -col_931 INT DEFAULT NULL, -col_932 INT DEFAULT NULL, -col_933 INT DEFAULT NULL, -col_934 INT DEFAULT NULL, -col_935 INT DEFAULT NULL, -col_936 INT DEFAULT NULL, -col_937 INT DEFAULT NULL, -col_938 INT DEFAULT NULL, -col_939 INT DEFAULT NULL, -col_940 INT DEFAULT NULL, -col_941 INT DEFAULT NULL, -col_942 INT DEFAULT NULL, -col_943 INT DEFAULT NULL, -col_944 INT DEFAULT NULL, -col_945 INT DEFAULT NULL, -col_946 INT DEFAULT NULL, -col_947 INT DEFAULT NULL, -col_948 INT DEFAULT NULL, -col_949 INT DEFAULT NULL, -col_950 INT DEFAULT NULL, -col_951 INT DEFAULT NULL, -col_952 INT DEFAULT NULL, -col_953 INT DEFAULT NULL, -col_954 INT DEFAULT NULL, -col_955 INT DEFAULT NULL, -col_956 INT DEFAULT NULL, -col_957 INT DEFAULT NULL, -col_958 INT DEFAULT NULL, -col_959 INT DEFAULT NULL, -col_960 INT DEFAULT NULL, -col_961 INT DEFAULT NULL, -col_962 INT DEFAULT NULL, -col_963 INT DEFAULT NULL, -col_964 INT DEFAULT NULL, -col_965 INT DEFAULT NULL, -col_966 INT DEFAULT NULL, -col_967 INT DEFAULT NULL, -col_968 INT DEFAULT NULL, -col_969 INT DEFAULT NULL, -col_970 INT DEFAULT NULL, -col_971 INT DEFAULT NULL, -col_972 INT DEFAULT NULL, -col_973 INT DEFAULT NULL, -col_974 INT DEFAULT NULL, -col_975 INT DEFAULT NULL, -col_976 INT DEFAULT NULL, -col_977 INT DEFAULT NULL, -col_978 INT DEFAULT NULL, -col_979 INT DEFAULT NULL, -col_980 INT DEFAULT NULL, -col_981 INT DEFAULT NULL, -col_982 INT DEFAULT NULL, -col_983 INT DEFAULT NULL, -col_984 INT DEFAULT NULL, -col_985 INT DEFAULT NULL, -col_986 INT DEFAULT NULL, -col_987 INT DEFAULT NULL, -col_988 INT DEFAULT NULL, -col_989 INT DEFAULT NULL, -col_990 INT DEFAULT NULL, -col_991 INT DEFAULT NULL, -col_992 INT DEFAULT NULL, -col_993 INT DEFAULT NULL, -col_994 INT DEFAULT NULL, -col_995 INT DEFAULT NULL, -col_996 INT DEFAULT NULL, -col_997 INT DEFAULT NULL, -col_998 INT DEFAULT NULL, -col_999 INT DEFAULT NULL, -col_1000 INT DEFAULT NULL, -col_1001 INT DEFAULT NULL, -col_1002 INT DEFAULT NULL, -col_1003 INT DEFAULT NULL, -col_1004 INT DEFAULT NULL, -col_1005 INT DEFAULT NULL, -col_1006 INT DEFAULT NULL, -col_1007 INT DEFAULT NULL, -col_1008 INT DEFAULT NULL, -col_1009 INT DEFAULT NULL, -col_1010 INT DEFAULT NULL, -col_1011 INT DEFAULT NULL, -col_1012 INT DEFAULT NULL, -col_1013 INT DEFAULT NULL, -col_1014 INT DEFAULT NULL, -col_1015 INT DEFAULT NULL, -col_1016 INT DEFAULT NULL, -col_last INT DEFAULT NULL) ENGINE=InnoDB; +call create_table("tb1", 1017); # Generate row version -INSERT INTO tb1 (col_last) VALUES (1); +INSERT INTO tb1 (col_1017) VALUES (1); # Keep a copy for other scenarios CREATE TABLE t1 AS SELECT * FROM tb1; CREATE TABLE t2 AS SELECT * FROM tb1; CREATE TABLE t3 AS SELECT * FROM tb1; CREATE TABLE t4 AS SELECT * FROM tb1; + +# 1017 (user cols) + 3 (system cols) = 1020 (MAX_FIELDS_ALLOWED) + ######################################## # Scenario 1: ADD/DROP single column: ######################################## -# REC_MAX_N_FIELDS = 1023 -- max number of fields allowed. -# Step 1. DROP - ADD columns until (n_def + < REC_MAX_N_FIELDS) -# Current: n_def = 1020 ( + 3(DB_ROW_ID + DB_TRX_ID + DB_ROLL_PTR) + ) +# Current: n_def = (user columns + system columns + n_drop_cols) # Current: n_def = 1020 (1017 + 3 + 0) -ALTER TABLE tb1 DROP COLUMN col_last, ALGORITHM=INSTANT; +# ----------------------------------------------------------------------- +# DROP - ADD columns till (n_def + n_col_added < MAX_FIELDS_ALLOWED) +# ----------------------------------------------------------------------- +# DROP COLUMN should pass +ALTER TABLE tb1 DROP COLUMN col_1017, ALGORITHM=INSTANT; # Current: n_def = 1020 (1016 + 3 + 1) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS 1 1019 1016 1017 1017 -ALTER TABLE tb1 ADD COLUMN col_last INT, ALGORITHM=INSTANT; -# Current: n_def = 1021 (1017 + 3 + 1) -ALTER TABLE tb1 DROP COLUMN col_last, ALGORITHM=INSTANT; -# Current: n_def = 1021 (1016 + 3 + 2) -ALTER TABLE tb1 ADD COLUMN col_last INT, ALGORITHM=INSTANT; -# Current: n_def = 1022 (1017 + 3 + 2) -ALTER TABLE tb1 DROP COLUMN col_last, ALGORITHM=INSTANT; -# Current: n_def = 1022 (1016 + 3 + 3) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; -TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -5 1019 1016 1017 1019 -# Step 2. Test that ADD with ALGORITHM=INSTANT is no longer allowed: -# Current: n_def = 1022 (1016 + 3 + 3) -# If we ADD 1 column: n_def = 1023 (1017 + 3 + 3) becomes REC_MAX_N_FIELDS -- not allowed -ALTER TABLE tb1 ADD COLUMN col_last INT, ALGORITHM=INSTANT; +# ADD COLUMN should fail +ALTER TABLE tb1 ADD COLUMN col_1017 INT, ALGORITHM=INSTANT; ERROR HY000: Column can't be added to 'test/tb1' with ALGORITHM=INSTANT anymore. Please try ALGORITHM=INPLACE/COPY. -# Current: n_def = 1022 (1016 + 3 + 3) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; -TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -5 1019 1016 1017 1019 -# Note that we can still DROP columns with INSTANT: +# DROP COLUMN should still pass ALTER TABLE tb1 DROP COLUMN col_1016, ALGORITHM=INSTANT; -# Current: n_def = 1022 (1015 + 3 + 4) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; +# Current: n_def = 1020 (1015 + 3 + 2) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -6 1018 1015 1017 1019 -# But we cannot ADD any more columns with INSTANT: -# If we ADD 1 column: n_def = 1023 (1016 + 3 + 4) becomes REC_MAX_N_FIELDS -- not allowed -ALTER TABLE tb1 ADD COLUMN col_1016 INT, ALGORITHM=INSTANT; +2 1018 1015 1017 1017 +# ADD COLUMN should still fail +ALTER TABLE tb1 ADD COLUMN col_1017 INT, ALGORITHM=INSTANT; ERROR HY000: Column can't be added to 'test/tb1' with ALGORITHM=INSTANT anymore. Please try ALGORITHM=INPLACE/COPY. -# Step 3. Verify that ADD is possible without specifying ALGORITHM (should fallback to INPLACE) -ALTER TABLE tb1 ADD COLUMN col_last INT; +# ----------------------------------------------------------------------- +# Verify that ADD is possible without specifying ALGORITHM +# (should fallback to INPLACE) +# ----------------------------------------------------------------------- # Table is rebuilt when ALGORITHM=INPLACE is used (internally) -# Current: n_def = 1017 (1017) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; +ALTER TABLE tb1 ADD COLUMN col_1017 INT; +# Current: n_def = 1019 (1016 + 3) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS 0 1019 1016 1016 1016 # Cleanup @@ -1081,152 +57,215 @@ DROP TABLE tb1; ######################################## # Scenario 2: ADD/DROP two columns: ######################################## -# REC_MAX_N_FIELDS = 1023 -- max number of fields allowed. -# Step 1. DROP - ADD columns until (n_def + < REC_MAX_N_FIELDS) -# Current: n_def = 1020 ( + 3(DB_ROW_ID + DB_TRX_ID + DB_ROLL_PTR) + ) +# Current: n_def = (user columns + system columns + n_drop_cols) # Current: n_def = 1020 (1017 + 3 + 0) -ALTER TABLE t1 DROP COLUMN col_last, DROP COLUMN col_1016, ALGORITHM=INSTANT; +# ----------------------------------------------------------------------- +# DROP - ADD columns till (n_def + n_col_added < MAX_FIELDS_ALLOWED) +# ----------------------------------------------------------------------- +# DROP COLUMN for 2 columns should pass +ALTER TABLE t1 +DROP COLUMN col_1017, +DROP COLUMN col_1016, +ALGORITHM=INSTANT; # Current: n_def = 1020 (1015 + 3 + 2) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS 1 1018 1015 1017 1017 -ALTER TABLE t1 ADD COLUMN col_last INT, ADD COLUMN col_1016 INT, ALGORITHM=INSTANT; -# Current: n_def = 1022 (1017 + 3 + 2) -ALTER TABLE t1 DROP COLUMN col_last, DROP COLUMN col_1016, ALGORITHM=INSTANT; -# Current: n_def = 1022 (1015 + 3 + 4) -# Step 2. Test that ADD with ALGORITHM=INSTANT is no longer allowed: -# Current: n_def = 1022 (1015 + 3 + 4) -# If we ADD 2 columns: n_def = 1024 (1017 + 3 + 4) becomes > REC_MAX_N_FIELDS -- not allowed -ALTER TABLE t1 ADD COLUMN col_last INT, ADD COLUMN col_1016 INT, ALGORITHM=INSTANT; +# ADD COLUMN should fail +ALTER TABLE t1 +ADD COLUMN col_1017 INT, +ADD COLUMN col_1016 INT, +ALGORITHM=INSTANT; ERROR HY000: Column can't be added to 'test/t1' with ALGORITHM=INSTANT anymore. Please try ALGORITHM=INPLACE/COPY. -# Current: n_def = 1022 (1015 + 3 + 4) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; -TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -3 1018 1015 1017 1019 -# If we ADD 1 column: n_def = 1023 (1016 + 3 + 4) becomes REC_MAX_N_FIELDS -- not allowed -ALTER TABLE t1 ADD COLUMN col_last INT, ALGORITHM=INSTANT; -ERROR HY000: Column can't be added to 'test/t1' with ALGORITHM=INSTANT anymore. Please try ALGORITHM=INPLACE/COPY. -# Current: n_def = 1022 (1015 + 3 + 4) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; -TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -3 1018 1015 1017 1019 -# Note that we can still DROP columns with INSTANT: -ALTER TABLE t1 DROP COLUMN col_1015, DROP COLUMN col_1014, ALGORITHM=INSTANT; -# Current: n_def = 1022 (1013 + 3 + 6) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; +# DROP COLUMN for 2 columns should still pass +ALTER TABLE t1 +DROP COLUMN col_1015, +DROP COLUMN col_1014, +ALGORITHM=INSTANT; +# Current: n_def = 1020 (1013 + 3 + 4) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -4 1016 1013 1017 1019 -# But we cannot ADD any more columns with INSTANT: -# If we ADD 1 column: n_def = 1023 (1014 + 3 + 6) becomes REC_MAX_N_FIELDS -- not allowed -ALTER TABLE t1 ADD COLUMN col_1015 INT, ALGORITHM=INSTANT; +2 1016 1013 1017 1017 +# ADD COLUMN should still fail +ALTER TABLE t1 +ADD COLUMN col_1017 INT, +ADD COLUMN col_1016 INT, +ALGORITHM=INSTANT; ERROR HY000: Column can't be added to 'test/t1' with ALGORITHM=INSTANT anymore. Please try ALGORITHM=INPLACE/COPY. -# Current: n_def = 1022 (1013 + 3 + 6) -# Step 3. Verify that ADD is possible without specifying ALGORITHM (should fallback to INPLACE) -ALTER TABLE t1 ADD COLUMN col_1014 INT, ADD COLUMN col_1015 INT, ADD COLUMN col_1016 INT, ADD COLUMN col_last INT; +# ----------------------------------------------------------------------- +# Verify that ADD is possible without specifying ALGORITHM +# (should fallback to INPLACE) +# ----------------------------------------------------------------------- # Table is rebuilt when ALGORITHM=INPLACE is used (internally) -# Current: n_def = 1017 (1017) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; +ALTER TABLE t1 +ADD COLUMN col_1017 INT, +ADD COLUMN col_1016 INT; +# Current: n_def = 1018 (1015 + 3) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -0 1020 1017 1017 1017 +0 1018 1015 1015 1015 # Cleanup DROP TABLE t1; ######################################## # Scenario 3: ADD/DROP multiple columns: ######################################## -# REC_MAX_N_FIELDS = 1023 -- max number of fields allowed. -# ADD/DROP multiple columns and look for failures -# Current: n_def = 1020 ( + 3(DB_ROW_ID + DB_TRX_ID + DB_ROLL_PTR) + ) +# Current: n_def = (user columns + system columns + n_drop_cols) # Current: n_def = 1020 (1017 + 3 + 0) -ALTER TABLE t2 DROP COLUMN col_1016, DROP COLUMN col_1015, DROP COLUMN col_1014, DROP COLUMN col_1013, DROP COLUMN col_1012, DROP COLUMN col_1011, ALGORITHM=INSTANT; +# ----------------------------------------------------------------------- +# ADD/DROP multiple columns and look for failures +# ----------------------------------------------------------------------- +# DROP multiple columns should pass +ALTER TABLE t2 +DROP COLUMN col_1016, +DROP COLUMN col_1015, +DROP COLUMN col_1014, +DROP COLUMN col_1013, +DROP COLUMN col_1012, +DROP COLUMN col_1011, +ALGORITHM=INSTANT; # Current: n_def = 1020 (1011 + 3 + 6) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t2"; +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t2"; TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS 1 1014 1011 1017 1017 -ALTER TABLE t2 ADD COLUMN col_1011 INT, DROP COLUMN col_1010, ADD COLUMN col_1012 INT, ADD COLUMN col_1013 INT, DROP COLUMN col_1009, DROP COLUMN col_1008, ADD COLUMN col_1014 INT, ALGORITHM=INSTANT; +# ADD COLUMN should fail +ALTER TABLE t2 +ADD COLUMN col_1011 INT, +DROP COLUMN col_1010, +ADD COLUMN col_1012 INT, +ADD COLUMN col_1013 INT, +DROP COLUMN col_1009, +DROP COLUMN col_1008, +ADD COLUMN col_1014 INT, +ALGORITHM=INSTANT; ERROR HY000: Column can't be added to 'test/t2' with ALGORITHM=INSTANT anymore. Please try ALGORITHM=INPLACE/COPY. -# If operation was successful: n_def = 1027 (1015 + 3 + 9) > REC_MAX_N_FIELDS -# Current: n_def = 1020 (1011 + 3 + 6) -ALTER TABLE t2 ADD COLUMN col_1015 INT, ADD COLUMN col_1016 INT, DROP COLUMN col_1010, ALGORITHM=INSTANT; -# Current: n_def = 1022 (1012 + 3 + 7) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t2"; -TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -2 1015 1012 1017 1019 +# ----------------------------------------------------------------------- # Fallback to inplace for failed query -ALTER TABLE t2 ADD COLUMN col_1011 INT, DROP COLUMN col_1007, ADD COLUMN col_1012 INT, ADD COLUMN col_1013 INT, DROP COLUMN col_1009, DROP COLUMN col_1008, ADD COLUMN col_1014 INT; -# Current: n_def = 1017 (1017) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t2"; +# ----------------------------------------------------------------------- +ALTER TABLE t2 +ADD COLUMN col_1011 INT, +DROP COLUMN col_1010, +ADD COLUMN col_1012 INT, +ADD COLUMN col_1013 INT, +DROP COLUMN col_1009, +DROP COLUMN col_1008, +ADD COLUMN col_1014 INT; +# Current: n_def = 1018 (1015 + 3 + 0) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t2"; TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -0 1016 1013 1013 1013 +0 1015 1012 1012 1012 # Cleanup DROP TABLE t2; ######################################## # Scenario 4: With other ALTER operations: ######################################## -# REC_MAX_N_FIELDS = 1023 -- max number of fields allowed. -# ADD/DROP with other ALTER operations -# Current: n_def = 1020 ( + 3(DB_ROW_ID + DB_TRX_ID + DB_ROLL_PTR) + ) +# Current: n_def = (user columns + system columns + n_drop_cols) # Current: n_def = 1020 (1017 + 3 + 0) -ALTER TABLE t3 DROP COLUMN col_1016, DROP COLUMN col_1015, DROP COLUMN col_1014, DROP COLUMN col_1013, DROP COLUMN col_1012, DROP COLUMN col_1011, DROP COLUMN col_1010, DROP COLUMN col_1009, ALGORITHM=INSTANT; +# ----------------------------------------------------------------------- +# ADD/DROP with other ALTER operations +# ----------------------------------------------------------------------- +# DROP COLUMN should pass +ALTER TABLE t3 +DROP COLUMN col_1016, +DROP COLUMN col_1015, +DROP COLUMN col_1014, +DROP COLUMN col_1013, +DROP COLUMN col_1012, +DROP COLUMN col_1011, +DROP COLUMN col_1010, +DROP COLUMN col_1009, +ALGORITHM=INSTANT; Current: n_def = 1020 (1009 + 3 + 8) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS 1 1012 1009 1017 1017 -ALTER TABLE t3 ADD COLUMN col_1009 INT, RENAME COLUMN col_last TO col_1017, RENAME COLUMN col_1007 TO col_1007_new, ADD COLUMN col_1011 INT, DROP COLUMN col_1008, ALGORITHM=INSTANT; -Current: n_def = 1022 (1010 + 3 + 9) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; -TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -2 1013 1010 1017 1019 +# ADD COLUMN with other operations should fail +ALTER TABLE t3 +ADD COLUMN col_1009 INT, +RENAME COLUMN col_1017 TO col_10177, +RENAME COLUMN col_1007 TO col_1007_new, +DROP COLUMN col_1008, +ALGORITHM=INSTANT; +ERROR HY000: Column can't be added to 'test/t3' with ALGORITHM=INSTANT anymore. Please try ALGORITHM=INPLACE/COPY. +# ADD COLUMN should fail ALTER TABLE t3 ADD COLUMN col_1010 INT, ALGORITHM=INSTANT; ERROR HY000: Column can't be added to 'test/t3' with ALGORITHM=INSTANT anymore. Please try ALGORITHM=INPLACE/COPY. -Current: n_def = 1022 (1010 + 3 + 9) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; -TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -2 1013 1010 1017 1019 -Similarly single column add/drop will fail -ALTER TABLE t3 ADD COLUMN col_1010 INT, DROP COLUMN col_1009, ALGORITHM=INSTANT; +# Similarly single column add/drop will fail +ALTER TABLE t3 ADD COLUMN col_1010 INT, DROP COLUMN col_1008, ALGORITHM=INSTANT; ERROR HY000: Column can't be added to 'test/t3' with ALGORITHM=INSTANT anymore. Please try ALGORITHM=INPLACE/COPY. -Current: n_def = 1022 (1010 + 3 + 9) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; -TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -2 1013 1010 1017 1019 -Fallback to inplace for failed query +# ----------------------------------------------------------------------- +# Fallback to inplace for failed query +# ----------------------------------------------------------------------- +# ADD COLUMN should fallback to INPLACE and should pass ALTER TABLE t3 ADD COLUMN col_1010 INT; -Current: n_def = 1017 (1017) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; +Current: n_def = 1013 (1010 + 3 + 0) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -0 1014 1011 1011 1011 +0 1013 1010 1010 1010 # Cleanup DROP TABLE t3; ######################################## # Scenario 5: ADD/DROP few columns: ######################################## -# REC_MAX_N_FIELDS = 1023 -- max number of fields allowed. -# ADD/DROP few columns together -# Current: n_def = 1020 ( + 3(DB_ROW_ID + DB_TRX_ID + DB_ROLL_PTR) + ) +# Current: n_def = (user columns + system columns + n_drop_cols) # Current: n_def = 1020 (1017 + 3 + 0) -ALTER TABLE t4 DROP COLUMN col_1016, DROP COLUMN col_1015, DROP COLUMN col_1014, DROP COLUMN col_1013, DROP COLUMN col_1012, DROP COLUMN col_1011, DROP COLUMN col_1010, DROP COLUMN col_1009, ALGORITHM=INSTANT; +# ----------------------------------------------------------------------- +# ADD/DROP few columns together +# ----------------------------------------------------------------------- +# DROP COLUMN should pass +ALTER TABLE t4 +DROP COLUMN col_1016, +DROP COLUMN col_1015, +DROP COLUMN col_1014, +DROP COLUMN col_1013, +DROP COLUMN col_1012, +DROP COLUMN col_1011, +DROP COLUMN col_1010, +DROP COLUMN col_1009, +ALGORITHM=INSTANT; Current: n_def = 1020 (1009 + 3 + 8) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t4"; +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t4"; TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS 1 1012 1009 1017 1017 -ALTER TABLE t4 ADD COLUMN col_1016 INT, DROP COLUMN col_1008, ALGORITHM=INSTANT; -Current: n_def = 1021 (1009 + 3 + 9) -ALTER TABLE t4 ADD COLUMN col_1015 INT, DROP COLUMN col_1007, DROP COLUMN col_1006, ALGORITHM=INSTANT; -Current: n_def = 1022 (1008 + 3 + 11) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t4"; -TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -3 1011 1008 1017 1019 -ALTER TABLE t4 ADD COLUMN col_1014 INT, ADD COLUMN col_1013 INT, DROP COLUMN col_1005, ALGORITHM=INSTANT; +# ADD COLUMN should fail +ALTER TABLE t4 +ADD COLUMN col_1016 INT, +DROP COLUMN col_1008, +ALGORITHM=INSTANT; ERROR HY000: Column can't be added to 'test/t4' with ALGORITHM=INSTANT anymore. Please try ALGORITHM=INPLACE/COPY. -Current: n_def = 1022 (1008 + 3 + 11) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t4"; -TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -3 1011 1008 1017 1019 -Fallback to inplace for failed query -ALTER TABLE t4 ADD COLUMN col_1014 INT, ADD COLUMN col_1013 INT, DROP COLUMN col_1005; -Current: n_def = 1009 (1008 + 2 - 1 ) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t4"; +# ADD COLUMN should fail +ALTER TABLE t4 +ADD COLUMN col_1015 INT, +DROP COLUMN col_1007, +DROP COLUMN col_1006, +ALGORITHM=INSTANT; +ERROR HY000: Column can't be added to 'test/t4' with ALGORITHM=INSTANT anymore. Please try ALGORITHM=INPLACE/COPY. +# ADD COLUMN should fail +ALTER TABLE t4 +ADD COLUMN col_1014 INT, +ADD COLUMN col_1013 INT, +DROP COLUMN col_1005, +ALGORITHM=INSTANT; +ERROR HY000: Column can't be added to 'test/t4' with ALGORITHM=INSTANT anymore. Please try ALGORITHM=INPLACE/COPY. +# ----------------------------------------------------------------------- +# Fallback to inplace for failed query +# ----------------------------------------------------------------------- +ALTER TABLE t4 +ADD COLUMN col_1014 INT, +ADD COLUMN col_1013 INT, +DROP COLUMN col_1005; +Current: n_def = 1013 (1010 + 3 + 0) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t4"; TOTAL_ROW_VERSIONS N_COLS CURRENT_COLUMN_COUNTS INITIAL_COLUMN_COUNTS TOTAL_COLUMN_COUNTS -0 1012 1009 1009 1009 +0 1013 1010 1010 1010 # Cleanup DROP TABLE t4; +DROP PROCEDURE create_table; diff --git a/mysql-test/suite/innodb/r/partition_upgrade_5727_mac_lctn_2_debug.result b/mysql-test/suite/innodb/r/partition_upgrade_5727_mac_lctn_2_debug.result index 38e2e275c4f5..1c376076131f 100644 --- a/mysql-test/suite/innodb/r/partition_upgrade_5727_mac_lctn_2_debug.result +++ b/mysql-test/suite/innodb/r/partition_upgrade_5727_mac_lctn_2_debug.result @@ -302,7 +302,7 @@ test/table_part_cap_6#p#p1 Single test/table_part_cap_6#p#p2 Single test/table_part_cap_6#p#p3 Single test/table_part_cap_6#p#p4 Single -test/table_part_NOPART_CAP_7 General +test/table_part_nopart_cap_7 General test/table_part_sub_1#p#part_1#sp#part_1sp0 Single test/table_part_sub_1#p#part_1#sp#part_1sp1 Single test/table_part_sub_1#p#part_2#sp#part_2sp0 Single @@ -1386,7 +1386,7 @@ test/table_part_cap_6#p#p1 Single test/table_part_cap_6#p#p2 Single test/table_part_cap_6#p#p3 Single test/table_part_cap_6#p#p4 Single -test/table_part_NOPART_CAP_7 General +test/table_part_nopart_cap_7 General test/table_part_sub_1#p#part_1#sp#part_1sp0 Single test/table_part_sub_1#p#part_1#sp#part_1sp1 Single test/table_part_sub_1#p#part_2#sp#part_2sp0 Single diff --git a/mysql-test/suite/innodb/r/partition_upgrade_5727_win_lctn_2_debug.result b/mysql-test/suite/innodb/r/partition_upgrade_5727_win_lctn_2_debug.result index 0e644121aa35..1b2cc4805fde 100644 --- a/mysql-test/suite/innodb/r/partition_upgrade_5727_win_lctn_2_debug.result +++ b/mysql-test/suite/innodb/r/partition_upgrade_5727_win_lctn_2_debug.result @@ -302,7 +302,7 @@ test/table_part_cap_6#p#p1 Single test/table_part_cap_6#p#p2 Single test/table_part_cap_6#p#p3 Single test/table_part_cap_6#p#p4 Single -test/table_part_NOPART_CAP_7 General +test/table_part_nopart_cap_7 General test/table_part_sub_1#p#part_1#sp#part_1sp0 Single test/table_part_sub_1#p#part_1#sp#part_1sp1 Single test/table_part_sub_1#p#part_2#sp#part_2sp0 Single @@ -1386,7 +1386,7 @@ test/table_part_cap_6#p#p1 Single test/table_part_cap_6#p#p2 Single test/table_part_cap_6#p#p3 Single test/table_part_cap_6#p#p4 Single -test/table_part_NOPART_CAP_7 General +test/table_part_nopart_cap_7 General test/table_part_sub_1#p#part_1#sp#part_1sp0 Single test/table_part_sub_1#p#part_1#sp#part_1sp1 Single test/table_part_sub_1#p#part_2#sp#part_2sp0 Single diff --git a/mysql-test/suite/innodb/t/cross_ddl_partition_tables.test b/mysql-test/suite/innodb/t/cross_ddl_partition_tables.test new file mode 100644 index 000000000000..bd6d50747fcc --- /dev/null +++ b/mysql-test/suite/innodb/t/cross_ddl_partition_tables.test @@ -0,0 +1,46 @@ +--connect (con1,localhost,root,,) +--echo # Create database and tables +CREATE DATABASE testdb; +USE testdb; + +CREATE TABLE t1 ( id int ); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; + +CREATE TABLE t2 ( id int ); +INSERT INTO t2 SELECT * FROM t1; + +CREATE TABLE t3 ( + id INT +) +PARTITION BY RANGE (id) ( + PARTITION p0 VALUES LESS THAN (1000), + PARTITION p1 VALUES LESS THAN (2000), + PARTITION p2 VALUES LESS THAN (3000) +); +INSERT INTO t3 VALUES (800); +INSERT INTO t3 VALUES (1500); +INSERT INTO t3 VALUES (2300); + +BEGIN; +SELECT COUNT(*) FROM t1; + +--connect (con2,localhost,root,,) +--echo # Alter the partition table. +ALTER TABLE testdb.t3 ADD COLUMN name varchar(10); + +--connection con1 +--echo # SELECT COUNT(*) must fail as the table definition is changed. +--error ER_TABLE_DEF_CHANGED +SELECT COUNT(*) FROM testdb.t3; + +--echo # SELECT * must fail as the table definition is changed. +--error ER_TABLE_DEF_CHANGED +SELECT * FROM testdb.t3; + +--echo # Clean up +DROP DATABASE testdb; \ No newline at end of file diff --git a/mysql-test/suite/innodb/t/innodb_dirty_pages_at_shutdown.test b/mysql-test/suite/innodb/t/innodb_dirty_pages_at_shutdown.test new file mode 100644 index 000000000000..2aa1f4448bf9 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_dirty_pages_at_shutdown.test @@ -0,0 +1,27 @@ +--source include/have_debug_sync.inc +# This test checks the behavior of InnoDB when dirty pages are found +# after closing the redo log systems and page cleaners + +CREATE TABLE t1 (c1 INT); +INSERT INTO t1 VALUES (1); + +call mtr.add_suppression("\\[InnoDB\\] \\[FATAL\\] Page still fixed or dirty at shutdown."); +call mtr.add_suppression("\\[InnoDB\\] Assertion failure.*ib::fatal triggered"); +call mtr.add_suppression("Attempting backtrace"); + +SET GLOBAL DEBUG="+d,simulate_dirty_page_at_shutdown"; + +--echo # Shutdown the server +--source include/shutdown_mysqld.inc + +--echo # Search the server error logs for the FATAL message +--let SEARCH_PATTERN = Page still fixed or dirty at shutdown +--let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err +--source include/search_pattern.inc + +--echo # Start the server +--source include/start_mysqld.inc + +SET GLOBAL DEBUG="-d,simulate_dirty_page_at_shutdown"; + +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/instant_max_column_crash.test b/mysql-test/suite/innodb/t/instant_max_column_crash.test index b36fb6dbec24..9255e0ee61d1 100644 --- a/mysql-test/suite/innodb/t/instant_max_column_crash.test +++ b/mysql-test/suite/innodb/t/instant_max_column_crash.test @@ -1,1031 +1,39 @@ --source include/have_debug.inc --source include/have_innodb_min_16k.inc + --echo # --echo # Bug: #34378513 : Assertion failure: dict0mem.h:2482:pos < n_def thread 140243300361984 --echo # +--disable_query_log +# Procedure to create a table with given number of columns +DELIMITER |; + +CREATE PROCEDURE create_table(table_name varchar(50), n_cols INT) +BEGIN + DECLARE i INT DEFAULT 1; + SET @sql_text = CONCAT('CREATE TABLE ', table_name, ' ('); + WHILE (i <= n_cols) DO + SET @sql_text = CONCAT(@sql_text, CONCAT('col_', i), ' INTEGER DEFAULT NULL'); + set i = i + 1; + IF (i <= n_cols) THEN + SET @sql_text = CONCAT(@sql_text, ', '); + END IF; + END WHILE; + SET @sql_text = CONCAT(@sql_text, ")"); + PREPARE stmt FROM @sql_text; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; +END| + +DELIMITER ;| +--enable_query_log + --echo # Create table with 1017 columns -CREATE TABLE tb1 ( -col_1 INT DEFAULT NULL, -col_2 INT DEFAULT NULL, -col_3 INT DEFAULT NULL, -col_4 INT DEFAULT NULL, -col_5 INT DEFAULT NULL, -col_6 INT DEFAULT NULL, -col_7 INT DEFAULT NULL, -col_8 INT DEFAULT NULL, -col_9 INT DEFAULT NULL, -col_10 INT DEFAULT NULL, -col_11 INT DEFAULT NULL, -col_12 INT DEFAULT NULL, -col_13 INT DEFAULT NULL, -col_14 INT DEFAULT NULL, -col_15 INT DEFAULT NULL, -col_16 INT DEFAULT NULL, -col_17 INT DEFAULT NULL, -col_18 INT DEFAULT NULL, -col_19 INT DEFAULT NULL, -col_20 INT DEFAULT NULL, -col_21 INT DEFAULT NULL, -col_22 INT DEFAULT NULL, -col_23 INT DEFAULT NULL, -col_24 INT DEFAULT NULL, -col_25 INT DEFAULT NULL, -col_26 INT DEFAULT NULL, -col_27 INT DEFAULT NULL, -col_28 INT DEFAULT NULL, -col_29 INT DEFAULT NULL, -col_30 INT DEFAULT NULL, -col_31 INT DEFAULT NULL, -col_32 INT DEFAULT NULL, -col_33 INT DEFAULT NULL, -col_34 INT DEFAULT NULL, -col_35 INT DEFAULT NULL, -col_36 INT DEFAULT NULL, -col_37 INT DEFAULT NULL, -col_38 INT DEFAULT NULL, -col_39 INT DEFAULT NULL, -col_40 INT DEFAULT NULL, -col_41 INT DEFAULT NULL, -col_42 INT DEFAULT NULL, -col_43 INT DEFAULT NULL, -col_44 INT DEFAULT NULL, -col_45 INT DEFAULT NULL, -col_46 INT DEFAULT NULL, -col_47 INT DEFAULT NULL, -col_48 INT DEFAULT NULL, -col_49 INT DEFAULT NULL, -col_50 INT DEFAULT NULL, -col_51 INT DEFAULT NULL, -col_52 INT DEFAULT NULL, -col_53 INT DEFAULT NULL, -col_54 INT DEFAULT NULL, -col_55 INT DEFAULT NULL, -col_56 INT DEFAULT NULL, -col_57 INT DEFAULT NULL, -col_58 INT DEFAULT NULL, -col_59 INT DEFAULT NULL, -col_60 INT DEFAULT NULL, -col_61 INT DEFAULT NULL, -col_62 INT DEFAULT NULL, -col_63 INT DEFAULT NULL, -col_64 INT DEFAULT NULL, -col_65 INT DEFAULT NULL, -col_66 INT DEFAULT NULL, -col_67 INT DEFAULT NULL, -col_68 INT DEFAULT NULL, -col_69 INT DEFAULT NULL, -col_70 INT DEFAULT NULL, -col_71 INT DEFAULT NULL, -col_72 INT DEFAULT NULL, -col_73 INT DEFAULT NULL, -col_74 INT DEFAULT NULL, -col_75 INT DEFAULT NULL, -col_76 INT DEFAULT NULL, -col_77 INT DEFAULT NULL, -col_78 INT DEFAULT NULL, -col_79 INT DEFAULT NULL, -col_80 INT DEFAULT NULL, -col_81 INT DEFAULT NULL, -col_82 INT DEFAULT NULL, -col_83 INT DEFAULT NULL, -col_84 INT DEFAULT NULL, -col_85 INT DEFAULT NULL, -col_86 INT DEFAULT NULL, -col_87 INT DEFAULT NULL, -col_88 INT DEFAULT NULL, -col_89 INT DEFAULT NULL, -col_90 INT DEFAULT NULL, -col_91 INT DEFAULT NULL, -col_92 INT DEFAULT NULL, -col_93 INT DEFAULT NULL, -col_94 INT DEFAULT NULL, -col_95 INT DEFAULT NULL, -col_96 INT DEFAULT NULL, -col_97 INT DEFAULT NULL, -col_98 INT DEFAULT NULL, -col_99 INT DEFAULT NULL, -col_100 INT DEFAULT NULL, -col_101 INT DEFAULT NULL, -col_102 INT DEFAULT NULL, -col_103 INT DEFAULT NULL, -col_104 INT DEFAULT NULL, -col_105 INT DEFAULT NULL, -col_106 INT DEFAULT NULL, -col_107 INT DEFAULT NULL, -col_108 INT DEFAULT NULL, -col_109 INT DEFAULT NULL, -col_110 INT DEFAULT NULL, -col_111 INT DEFAULT NULL, -col_112 INT DEFAULT NULL, -col_113 INT DEFAULT NULL, -col_114 INT DEFAULT NULL, -col_115 INT DEFAULT NULL, -col_116 INT DEFAULT NULL, -col_117 INT DEFAULT NULL, -col_118 INT DEFAULT NULL, -col_119 INT DEFAULT NULL, -col_120 INT DEFAULT NULL, -col_121 INT DEFAULT NULL, -col_122 INT DEFAULT NULL, -col_123 INT DEFAULT NULL, -col_124 INT DEFAULT NULL, -col_125 INT DEFAULT NULL, -col_126 INT DEFAULT NULL, -col_127 INT DEFAULT NULL, -col_128 INT DEFAULT NULL, -col_129 INT DEFAULT NULL, -col_130 INT DEFAULT NULL, -col_131 INT DEFAULT NULL, -col_132 INT DEFAULT NULL, -col_133 INT DEFAULT NULL, -col_134 INT DEFAULT NULL, -col_135 INT DEFAULT NULL, -col_136 INT DEFAULT NULL, -col_137 INT DEFAULT NULL, -col_138 INT DEFAULT NULL, -col_139 INT DEFAULT NULL, -col_140 INT DEFAULT NULL, -col_141 INT DEFAULT NULL, -col_142 INT DEFAULT NULL, -col_143 INT DEFAULT NULL, -col_144 INT DEFAULT NULL, -col_145 INT DEFAULT NULL, -col_146 INT DEFAULT NULL, -col_147 INT DEFAULT NULL, -col_148 INT DEFAULT NULL, -col_149 INT DEFAULT NULL, -col_150 INT DEFAULT NULL, -col_151 INT DEFAULT NULL, -col_152 INT DEFAULT NULL, -col_153 INT DEFAULT NULL, -col_154 INT DEFAULT NULL, -col_155 INT DEFAULT NULL, -col_156 INT DEFAULT NULL, -col_157 INT DEFAULT NULL, -col_158 INT DEFAULT NULL, -col_159 INT DEFAULT NULL, -col_160 INT DEFAULT NULL, -col_161 INT DEFAULT NULL, -col_162 INT DEFAULT NULL, -col_163 INT DEFAULT NULL, -col_164 INT DEFAULT NULL, -col_165 INT DEFAULT NULL, -col_166 INT DEFAULT NULL, -col_167 INT DEFAULT NULL, -col_168 INT DEFAULT NULL, -col_169 INT DEFAULT NULL, -col_170 INT DEFAULT NULL, -col_171 INT DEFAULT NULL, -col_172 INT DEFAULT NULL, -col_173 INT DEFAULT NULL, -col_174 INT DEFAULT NULL, -col_175 INT DEFAULT NULL, -col_176 INT DEFAULT NULL, -col_177 INT DEFAULT NULL, -col_178 INT DEFAULT NULL, -col_179 INT DEFAULT NULL, -col_180 INT DEFAULT NULL, -col_181 INT DEFAULT NULL, -col_182 INT DEFAULT NULL, -col_183 INT DEFAULT NULL, -col_184 INT DEFAULT NULL, -col_185 INT DEFAULT NULL, -col_186 INT DEFAULT NULL, -col_187 INT DEFAULT NULL, -col_188 INT DEFAULT NULL, -col_189 INT DEFAULT NULL, -col_190 INT DEFAULT NULL, -col_191 INT DEFAULT NULL, -col_192 INT DEFAULT NULL, -col_193 INT DEFAULT NULL, -col_194 INT DEFAULT NULL, -col_195 INT DEFAULT NULL, -col_196 INT DEFAULT NULL, -col_197 INT DEFAULT NULL, -col_198 INT DEFAULT NULL, -col_199 INT DEFAULT NULL, -col_200 INT DEFAULT NULL, -col_201 INT DEFAULT NULL, -col_202 INT DEFAULT NULL, -col_203 INT DEFAULT NULL, -col_204 INT DEFAULT NULL, -col_205 INT DEFAULT NULL, -col_206 INT DEFAULT NULL, -col_207 INT DEFAULT NULL, -col_208 INT DEFAULT NULL, -col_209 INT DEFAULT NULL, -col_210 INT DEFAULT NULL, -col_211 INT DEFAULT NULL, -col_212 INT DEFAULT NULL, -col_213 INT DEFAULT NULL, -col_214 INT DEFAULT NULL, -col_215 INT DEFAULT NULL, -col_216 INT DEFAULT NULL, -col_217 INT DEFAULT NULL, -col_218 INT DEFAULT NULL, -col_219 INT DEFAULT NULL, -col_220 INT DEFAULT NULL, -col_221 INT DEFAULT NULL, -col_222 INT DEFAULT NULL, -col_223 INT DEFAULT NULL, -col_224 INT DEFAULT NULL, -col_225 INT DEFAULT NULL, -col_226 INT DEFAULT NULL, -col_227 INT DEFAULT NULL, -col_228 INT DEFAULT NULL, -col_229 INT DEFAULT NULL, -col_230 INT DEFAULT NULL, -col_231 INT DEFAULT NULL, -col_232 INT DEFAULT NULL, -col_233 INT DEFAULT NULL, -col_234 INT DEFAULT NULL, -col_235 INT DEFAULT NULL, -col_236 INT DEFAULT NULL, -col_237 INT DEFAULT NULL, -col_238 INT DEFAULT NULL, -col_239 INT DEFAULT NULL, -col_240 INT DEFAULT NULL, -col_241 INT DEFAULT NULL, -col_242 INT DEFAULT NULL, -col_243 INT DEFAULT NULL, -col_244 INT DEFAULT NULL, -col_245 INT DEFAULT NULL, -col_246 INT DEFAULT NULL, -col_247 INT DEFAULT NULL, -col_248 INT DEFAULT NULL, -col_249 INT DEFAULT NULL, -col_250 INT DEFAULT NULL, -col_251 INT DEFAULT NULL, -col_252 INT DEFAULT NULL, -col_253 INT DEFAULT NULL, -col_254 INT DEFAULT NULL, -col_255 INT DEFAULT NULL, -col_256 INT DEFAULT NULL, -col_257 INT DEFAULT NULL, -col_258 INT DEFAULT NULL, -col_259 INT DEFAULT NULL, -col_260 INT DEFAULT NULL, -col_261 INT DEFAULT NULL, -col_262 INT DEFAULT NULL, -col_263 INT DEFAULT NULL, -col_264 INT DEFAULT NULL, -col_265 INT DEFAULT NULL, -col_266 INT DEFAULT NULL, -col_267 INT DEFAULT NULL, -col_268 INT DEFAULT NULL, -col_269 INT DEFAULT NULL, -col_270 INT DEFAULT NULL, -col_271 INT DEFAULT NULL, -col_272 INT DEFAULT NULL, -col_273 INT DEFAULT NULL, -col_274 INT DEFAULT NULL, -col_275 INT DEFAULT NULL, -col_276 INT DEFAULT NULL, -col_277 INT DEFAULT NULL, -col_278 INT DEFAULT NULL, -col_279 INT DEFAULT NULL, -col_280 INT DEFAULT NULL, -col_281 INT DEFAULT NULL, -col_282 INT DEFAULT NULL, -col_283 INT DEFAULT NULL, -col_284 INT DEFAULT NULL, -col_285 INT DEFAULT NULL, -col_286 INT DEFAULT NULL, -col_287 INT DEFAULT NULL, -col_288 INT DEFAULT NULL, -col_289 INT DEFAULT NULL, -col_290 INT DEFAULT NULL, -col_291 INT DEFAULT NULL, -col_292 INT DEFAULT NULL, -col_293 INT DEFAULT NULL, -col_294 INT DEFAULT NULL, -col_295 INT DEFAULT NULL, -col_296 INT DEFAULT NULL, -col_297 INT DEFAULT NULL, -col_298 INT DEFAULT NULL, -col_299 INT DEFAULT NULL, -col_300 INT DEFAULT NULL, -col_301 INT DEFAULT NULL, -col_302 INT DEFAULT NULL, -col_303 INT DEFAULT NULL, -col_304 INT DEFAULT NULL, -col_305 INT DEFAULT NULL, -col_306 INT DEFAULT NULL, -col_307 INT DEFAULT NULL, -col_308 INT DEFAULT NULL, -col_309 INT DEFAULT NULL, -col_310 INT DEFAULT NULL, -col_311 INT DEFAULT NULL, -col_312 INT DEFAULT NULL, -col_313 INT DEFAULT NULL, -col_314 INT DEFAULT NULL, -col_315 INT DEFAULT NULL, -col_316 INT DEFAULT NULL, -col_317 INT DEFAULT NULL, -col_318 INT DEFAULT NULL, -col_319 INT DEFAULT NULL, -col_320 INT DEFAULT NULL, -col_321 INT DEFAULT NULL, -col_322 INT DEFAULT NULL, -col_323 INT DEFAULT NULL, -col_324 INT DEFAULT NULL, -col_325 INT DEFAULT NULL, -col_326 INT DEFAULT NULL, -col_327 INT DEFAULT NULL, -col_328 INT DEFAULT NULL, -col_329 INT DEFAULT NULL, -col_330 INT DEFAULT NULL, -col_331 INT DEFAULT NULL, -col_332 INT DEFAULT NULL, -col_333 INT DEFAULT NULL, -col_334 INT DEFAULT NULL, -col_335 INT DEFAULT NULL, -col_336 INT DEFAULT NULL, -col_337 INT DEFAULT NULL, -col_338 INT DEFAULT NULL, -col_339 INT DEFAULT NULL, -col_340 INT DEFAULT NULL, -col_341 INT DEFAULT NULL, -col_342 INT DEFAULT NULL, -col_343 INT DEFAULT NULL, -col_344 INT DEFAULT NULL, -col_345 INT DEFAULT NULL, -col_346 INT DEFAULT NULL, -col_347 INT DEFAULT NULL, -col_348 INT DEFAULT NULL, -col_349 INT DEFAULT NULL, -col_350 INT DEFAULT NULL, -col_351 INT DEFAULT NULL, -col_352 INT DEFAULT NULL, -col_353 INT DEFAULT NULL, -col_354 INT DEFAULT NULL, -col_355 INT DEFAULT NULL, -col_356 INT DEFAULT NULL, -col_357 INT DEFAULT NULL, -col_358 INT DEFAULT NULL, -col_359 INT DEFAULT NULL, -col_360 INT DEFAULT NULL, -col_361 INT DEFAULT NULL, -col_362 INT DEFAULT NULL, -col_363 INT DEFAULT NULL, -col_364 INT DEFAULT NULL, -col_365 INT DEFAULT NULL, -col_366 INT DEFAULT NULL, -col_367 INT DEFAULT NULL, -col_368 INT DEFAULT NULL, -col_369 INT DEFAULT NULL, -col_370 INT DEFAULT NULL, -col_371 INT DEFAULT NULL, -col_372 INT DEFAULT NULL, -col_373 INT DEFAULT NULL, -col_374 INT DEFAULT NULL, -col_375 INT DEFAULT NULL, -col_376 INT DEFAULT NULL, -col_377 INT DEFAULT NULL, -col_378 INT DEFAULT NULL, -col_379 INT DEFAULT NULL, -col_380 INT DEFAULT NULL, -col_381 INT DEFAULT NULL, -col_382 INT DEFAULT NULL, -col_383 INT DEFAULT NULL, -col_384 INT DEFAULT NULL, -col_385 INT DEFAULT NULL, -col_386 INT DEFAULT NULL, -col_387 INT DEFAULT NULL, -col_388 INT DEFAULT NULL, -col_389 INT DEFAULT NULL, -col_390 INT DEFAULT NULL, -col_391 INT DEFAULT NULL, -col_392 INT DEFAULT NULL, -col_393 INT DEFAULT NULL, -col_394 INT DEFAULT NULL, -col_395 INT DEFAULT NULL, -col_396 INT DEFAULT NULL, -col_397 INT DEFAULT NULL, -col_398 INT DEFAULT NULL, -col_399 INT DEFAULT NULL, -col_400 INT DEFAULT NULL, -col_401 INT DEFAULT NULL, -col_402 INT DEFAULT NULL, -col_403 INT DEFAULT NULL, -col_404 INT DEFAULT NULL, -col_405 INT DEFAULT NULL, -col_406 INT DEFAULT NULL, -col_407 INT DEFAULT NULL, -col_408 INT DEFAULT NULL, -col_409 INT DEFAULT NULL, -col_410 INT DEFAULT NULL, -col_411 INT DEFAULT NULL, -col_412 INT DEFAULT NULL, -col_413 INT DEFAULT NULL, -col_414 INT DEFAULT NULL, -col_415 INT DEFAULT NULL, -col_416 INT DEFAULT NULL, -col_417 INT DEFAULT NULL, -col_418 INT DEFAULT NULL, -col_419 INT DEFAULT NULL, -col_420 INT DEFAULT NULL, -col_421 INT DEFAULT NULL, -col_422 INT DEFAULT NULL, -col_423 INT DEFAULT NULL, -col_424 INT DEFAULT NULL, -col_425 INT DEFAULT NULL, -col_426 INT DEFAULT NULL, -col_427 INT DEFAULT NULL, -col_428 INT DEFAULT NULL, -col_429 INT DEFAULT NULL, -col_430 INT DEFAULT NULL, -col_431 INT DEFAULT NULL, -col_432 INT DEFAULT NULL, -col_433 INT DEFAULT NULL, -col_434 INT DEFAULT NULL, -col_435 INT DEFAULT NULL, -col_436 INT DEFAULT NULL, -col_437 INT DEFAULT NULL, -col_438 INT DEFAULT NULL, -col_439 INT DEFAULT NULL, -col_440 INT DEFAULT NULL, -col_441 INT DEFAULT NULL, -col_442 INT DEFAULT NULL, -col_443 INT DEFAULT NULL, -col_444 INT DEFAULT NULL, -col_445 INT DEFAULT NULL, -col_446 INT DEFAULT NULL, -col_447 INT DEFAULT NULL, -col_448 INT DEFAULT NULL, -col_449 INT DEFAULT NULL, -col_450 INT DEFAULT NULL, -col_451 INT DEFAULT NULL, -col_452 INT DEFAULT NULL, -col_453 INT DEFAULT NULL, -col_454 INT DEFAULT NULL, -col_455 INT DEFAULT NULL, -col_456 INT DEFAULT NULL, -col_457 INT DEFAULT NULL, -col_458 INT DEFAULT NULL, -col_459 INT DEFAULT NULL, -col_460 INT DEFAULT NULL, -col_461 INT DEFAULT NULL, -col_462 INT DEFAULT NULL, -col_463 INT DEFAULT NULL, -col_464 INT DEFAULT NULL, -col_465 INT DEFAULT NULL, -col_466 INT DEFAULT NULL, -col_467 INT DEFAULT NULL, -col_468 INT DEFAULT NULL, -col_469 INT DEFAULT NULL, -col_470 INT DEFAULT NULL, -col_471 INT DEFAULT NULL, -col_472 INT DEFAULT NULL, -col_473 INT DEFAULT NULL, -col_474 INT DEFAULT NULL, -col_475 INT DEFAULT NULL, -col_476 INT DEFAULT NULL, -col_477 INT DEFAULT NULL, -col_478 INT DEFAULT NULL, -col_479 INT DEFAULT NULL, -col_480 INT DEFAULT NULL, -col_481 INT DEFAULT NULL, -col_482 INT DEFAULT NULL, -col_483 INT DEFAULT NULL, -col_484 INT DEFAULT NULL, -col_485 INT DEFAULT NULL, -col_486 INT DEFAULT NULL, -col_487 INT DEFAULT NULL, -col_488 INT DEFAULT NULL, -col_489 INT DEFAULT NULL, -col_490 INT DEFAULT NULL, -col_491 INT DEFAULT NULL, -col_492 INT DEFAULT NULL, -col_493 INT DEFAULT NULL, -col_494 INT DEFAULT NULL, -col_495 INT DEFAULT NULL, -col_496 INT DEFAULT NULL, -col_497 INT DEFAULT NULL, -col_498 INT DEFAULT NULL, -col_499 INT DEFAULT NULL, -col_500 INT DEFAULT NULL, -col_501 INT DEFAULT NULL, -col_502 INT DEFAULT NULL, -col_503 INT DEFAULT NULL, -col_504 INT DEFAULT NULL, -col_505 INT DEFAULT NULL, -col_506 INT DEFAULT NULL, -col_507 INT DEFAULT NULL, -col_508 INT DEFAULT NULL, -col_509 INT DEFAULT NULL, -col_510 INT DEFAULT NULL, -col_511 INT DEFAULT NULL, -col_512 INT DEFAULT NULL, -col_513 INT DEFAULT NULL, -col_514 INT DEFAULT NULL, -col_515 INT DEFAULT NULL, -col_516 INT DEFAULT NULL, -col_517 INT DEFAULT NULL, -col_518 INT DEFAULT NULL, -col_519 INT DEFAULT NULL, -col_520 INT DEFAULT NULL, -col_521 INT DEFAULT NULL, -col_522 INT DEFAULT NULL, -col_523 INT DEFAULT NULL, -col_524 INT DEFAULT NULL, -col_525 INT DEFAULT NULL, -col_526 INT DEFAULT NULL, -col_527 INT DEFAULT NULL, -col_528 INT DEFAULT NULL, -col_529 INT DEFAULT NULL, -col_530 INT DEFAULT NULL, -col_531 INT DEFAULT NULL, -col_532 INT DEFAULT NULL, -col_533 INT DEFAULT NULL, -col_534 INT DEFAULT NULL, -col_535 INT DEFAULT NULL, -col_536 INT DEFAULT NULL, -col_537 INT DEFAULT NULL, -col_538 INT DEFAULT NULL, -col_539 INT DEFAULT NULL, -col_540 INT DEFAULT NULL, -col_541 INT DEFAULT NULL, -col_542 INT DEFAULT NULL, -col_543 INT DEFAULT NULL, -col_544 INT DEFAULT NULL, -col_545 INT DEFAULT NULL, -col_546 INT DEFAULT NULL, -col_547 INT DEFAULT NULL, -col_548 INT DEFAULT NULL, -col_549 INT DEFAULT NULL, -col_550 INT DEFAULT NULL, -col_551 INT DEFAULT NULL, -col_552 INT DEFAULT NULL, -col_553 INT DEFAULT NULL, -col_554 INT DEFAULT NULL, -col_555 INT DEFAULT NULL, -col_556 INT DEFAULT NULL, -col_557 INT DEFAULT NULL, -col_558 INT DEFAULT NULL, -col_559 INT DEFAULT NULL, -col_560 INT DEFAULT NULL, -col_561 INT DEFAULT NULL, -col_562 INT DEFAULT NULL, -col_563 INT DEFAULT NULL, -col_564 INT DEFAULT NULL, -col_565 INT DEFAULT NULL, -col_566 INT DEFAULT NULL, -col_567 INT DEFAULT NULL, -col_568 INT DEFAULT NULL, -col_569 INT DEFAULT NULL, -col_570 INT DEFAULT NULL, -col_571 INT DEFAULT NULL, -col_572 INT DEFAULT NULL, -col_573 INT DEFAULT NULL, -col_574 INT DEFAULT NULL, -col_575 INT DEFAULT NULL, -col_576 INT DEFAULT NULL, -col_577 INT DEFAULT NULL, -col_578 INT DEFAULT NULL, -col_579 INT DEFAULT NULL, -col_580 INT DEFAULT NULL, -col_581 INT DEFAULT NULL, -col_582 INT DEFAULT NULL, -col_583 INT DEFAULT NULL, -col_584 INT DEFAULT NULL, -col_585 INT DEFAULT NULL, -col_586 INT DEFAULT NULL, -col_587 INT DEFAULT NULL, -col_588 INT DEFAULT NULL, -col_589 INT DEFAULT NULL, -col_590 INT DEFAULT NULL, -col_591 INT DEFAULT NULL, -col_592 INT DEFAULT NULL, -col_593 INT DEFAULT NULL, -col_594 INT DEFAULT NULL, -col_595 INT DEFAULT NULL, -col_596 INT DEFAULT NULL, -col_597 INT DEFAULT NULL, -col_598 INT DEFAULT NULL, -col_599 INT DEFAULT NULL, -col_600 INT DEFAULT NULL, -col_601 INT DEFAULT NULL, -col_602 INT DEFAULT NULL, -col_603 INT DEFAULT NULL, -col_604 INT DEFAULT NULL, -col_605 INT DEFAULT NULL, -col_606 INT DEFAULT NULL, -col_607 INT DEFAULT NULL, -col_608 INT DEFAULT NULL, -col_609 INT DEFAULT NULL, -col_610 INT DEFAULT NULL, -col_611 INT DEFAULT NULL, -col_612 INT DEFAULT NULL, -col_613 INT DEFAULT NULL, -col_614 INT DEFAULT NULL, -col_615 INT DEFAULT NULL, -col_616 INT DEFAULT NULL, -col_617 INT DEFAULT NULL, -col_618 INT DEFAULT NULL, -col_619 INT DEFAULT NULL, -col_620 INT DEFAULT NULL, -col_621 INT DEFAULT NULL, -col_622 INT DEFAULT NULL, -col_623 INT DEFAULT NULL, -col_624 INT DEFAULT NULL, -col_625 INT DEFAULT NULL, -col_626 INT DEFAULT NULL, -col_627 INT DEFAULT NULL, -col_628 INT DEFAULT NULL, -col_629 INT DEFAULT NULL, -col_630 INT DEFAULT NULL, -col_631 INT DEFAULT NULL, -col_632 INT DEFAULT NULL, -col_633 INT DEFAULT NULL, -col_634 INT DEFAULT NULL, -col_635 INT DEFAULT NULL, -col_636 INT DEFAULT NULL, -col_637 INT DEFAULT NULL, -col_638 INT DEFAULT NULL, -col_639 INT DEFAULT NULL, -col_640 INT DEFAULT NULL, -col_641 INT DEFAULT NULL, -col_642 INT DEFAULT NULL, -col_643 INT DEFAULT NULL, -col_644 INT DEFAULT NULL, -col_645 INT DEFAULT NULL, -col_646 INT DEFAULT NULL, -col_647 INT DEFAULT NULL, -col_648 INT DEFAULT NULL, -col_649 INT DEFAULT NULL, -col_650 INT DEFAULT NULL, -col_651 INT DEFAULT NULL, -col_652 INT DEFAULT NULL, -col_653 INT DEFAULT NULL, -col_654 INT DEFAULT NULL, -col_655 INT DEFAULT NULL, -col_656 INT DEFAULT NULL, -col_657 INT DEFAULT NULL, -col_658 INT DEFAULT NULL, -col_659 INT DEFAULT NULL, -col_660 INT DEFAULT NULL, -col_661 INT DEFAULT NULL, -col_662 INT DEFAULT NULL, -col_663 INT DEFAULT NULL, -col_664 INT DEFAULT NULL, -col_665 INT DEFAULT NULL, -col_666 INT DEFAULT NULL, -col_667 INT DEFAULT NULL, -col_668 INT DEFAULT NULL, -col_669 INT DEFAULT NULL, -col_670 INT DEFAULT NULL, -col_671 INT DEFAULT NULL, -col_672 INT DEFAULT NULL, -col_673 INT DEFAULT NULL, -col_674 INT DEFAULT NULL, -col_675 INT DEFAULT NULL, -col_676 INT DEFAULT NULL, -col_677 INT DEFAULT NULL, -col_678 INT DEFAULT NULL, -col_679 INT DEFAULT NULL, -col_680 INT DEFAULT NULL, -col_681 INT DEFAULT NULL, -col_682 INT DEFAULT NULL, -col_683 INT DEFAULT NULL, -col_684 INT DEFAULT NULL, -col_685 INT DEFAULT NULL, -col_686 INT DEFAULT NULL, -col_687 INT DEFAULT NULL, -col_688 INT DEFAULT NULL, -col_689 INT DEFAULT NULL, -col_690 INT DEFAULT NULL, -col_691 INT DEFAULT NULL, -col_692 INT DEFAULT NULL, -col_693 INT DEFAULT NULL, -col_694 INT DEFAULT NULL, -col_695 INT DEFAULT NULL, -col_696 INT DEFAULT NULL, -col_697 INT DEFAULT NULL, -col_698 INT DEFAULT NULL, -col_699 INT DEFAULT NULL, -col_700 INT DEFAULT NULL, -col_701 INT DEFAULT NULL, -col_702 INT DEFAULT NULL, -col_703 INT DEFAULT NULL, -col_704 INT DEFAULT NULL, -col_705 INT DEFAULT NULL, -col_706 INT DEFAULT NULL, -col_707 INT DEFAULT NULL, -col_708 INT DEFAULT NULL, -col_709 INT DEFAULT NULL, -col_710 INT DEFAULT NULL, -col_711 INT DEFAULT NULL, -col_712 INT DEFAULT NULL, -col_713 INT DEFAULT NULL, -col_714 INT DEFAULT NULL, -col_715 INT DEFAULT NULL, -col_716 INT DEFAULT NULL, -col_717 INT DEFAULT NULL, -col_718 INT DEFAULT NULL, -col_719 INT DEFAULT NULL, -col_720 INT DEFAULT NULL, -col_721 INT DEFAULT NULL, -col_722 INT DEFAULT NULL, -col_723 INT DEFAULT NULL, -col_724 INT DEFAULT NULL, -col_725 INT DEFAULT NULL, -col_726 INT DEFAULT NULL, -col_727 INT DEFAULT NULL, -col_728 INT DEFAULT NULL, -col_729 INT DEFAULT NULL, -col_730 INT DEFAULT NULL, -col_731 INT DEFAULT NULL, -col_732 INT DEFAULT NULL, -col_733 INT DEFAULT NULL, -col_734 INT DEFAULT NULL, -col_735 INT DEFAULT NULL, -col_736 INT DEFAULT NULL, -col_737 INT DEFAULT NULL, -col_738 INT DEFAULT NULL, -col_739 INT DEFAULT NULL, -col_740 INT DEFAULT NULL, -col_741 INT DEFAULT NULL, -col_742 INT DEFAULT NULL, -col_743 INT DEFAULT NULL, -col_744 INT DEFAULT NULL, -col_745 INT DEFAULT NULL, -col_746 INT DEFAULT NULL, -col_747 INT DEFAULT NULL, -col_748 INT DEFAULT NULL, -col_749 INT DEFAULT NULL, -col_750 INT DEFAULT NULL, -col_751 INT DEFAULT NULL, -col_752 INT DEFAULT NULL, -col_753 INT DEFAULT NULL, -col_754 INT DEFAULT NULL, -col_755 INT DEFAULT NULL, -col_756 INT DEFAULT NULL, -col_757 INT DEFAULT NULL, -col_758 INT DEFAULT NULL, -col_759 INT DEFAULT NULL, -col_760 INT DEFAULT NULL, -col_761 INT DEFAULT NULL, -col_762 INT DEFAULT NULL, -col_763 INT DEFAULT NULL, -col_764 INT DEFAULT NULL, -col_765 INT DEFAULT NULL, -col_766 INT DEFAULT NULL, -col_767 INT DEFAULT NULL, -col_768 INT DEFAULT NULL, -col_769 INT DEFAULT NULL, -col_770 INT DEFAULT NULL, -col_771 INT DEFAULT NULL, -col_772 INT DEFAULT NULL, -col_773 INT DEFAULT NULL, -col_774 INT DEFAULT NULL, -col_775 INT DEFAULT NULL, -col_776 INT DEFAULT NULL, -col_777 INT DEFAULT NULL, -col_778 INT DEFAULT NULL, -col_779 INT DEFAULT NULL, -col_780 INT DEFAULT NULL, -col_781 INT DEFAULT NULL, -col_782 INT DEFAULT NULL, -col_783 INT DEFAULT NULL, -col_784 INT DEFAULT NULL, -col_785 INT DEFAULT NULL, -col_786 INT DEFAULT NULL, -col_787 INT DEFAULT NULL, -col_788 INT DEFAULT NULL, -col_789 INT DEFAULT NULL, -col_790 INT DEFAULT NULL, -col_791 INT DEFAULT NULL, -col_792 INT DEFAULT NULL, -col_793 INT DEFAULT NULL, -col_794 INT DEFAULT NULL, -col_795 INT DEFAULT NULL, -col_796 INT DEFAULT NULL, -col_797 INT DEFAULT NULL, -col_798 INT DEFAULT NULL, -col_799 INT DEFAULT NULL, -col_800 INT DEFAULT NULL, -col_801 INT DEFAULT NULL, -col_802 INT DEFAULT NULL, -col_803 INT DEFAULT NULL, -col_804 INT DEFAULT NULL, -col_805 INT DEFAULT NULL, -col_806 INT DEFAULT NULL, -col_807 INT DEFAULT NULL, -col_808 INT DEFAULT NULL, -col_809 INT DEFAULT NULL, -col_810 INT DEFAULT NULL, -col_811 INT DEFAULT NULL, -col_812 INT DEFAULT NULL, -col_813 INT DEFAULT NULL, -col_814 INT DEFAULT NULL, -col_815 INT DEFAULT NULL, -col_816 INT DEFAULT NULL, -col_817 INT DEFAULT NULL, -col_818 INT DEFAULT NULL, -col_819 INT DEFAULT NULL, -col_820 INT DEFAULT NULL, -col_821 INT DEFAULT NULL, -col_822 INT DEFAULT NULL, -col_823 INT DEFAULT NULL, -col_824 INT DEFAULT NULL, -col_825 INT DEFAULT NULL, -col_826 INT DEFAULT NULL, -col_827 INT DEFAULT NULL, -col_828 INT DEFAULT NULL, -col_829 INT DEFAULT NULL, -col_830 INT DEFAULT NULL, -col_831 INT DEFAULT NULL, -col_832 INT DEFAULT NULL, -col_833 INT DEFAULT NULL, -col_834 INT DEFAULT NULL, -col_835 INT DEFAULT NULL, -col_836 INT DEFAULT NULL, -col_837 INT DEFAULT NULL, -col_838 INT DEFAULT NULL, -col_839 INT DEFAULT NULL, -col_840 INT DEFAULT NULL, -col_841 INT DEFAULT NULL, -col_842 INT DEFAULT NULL, -col_843 INT DEFAULT NULL, -col_844 INT DEFAULT NULL, -col_845 INT DEFAULT NULL, -col_846 INT DEFAULT NULL, -col_847 INT DEFAULT NULL, -col_848 INT DEFAULT NULL, -col_849 INT DEFAULT NULL, -col_850 INT DEFAULT NULL, -col_851 INT DEFAULT NULL, -col_852 INT DEFAULT NULL, -col_853 INT DEFAULT NULL, -col_854 INT DEFAULT NULL, -col_855 INT DEFAULT NULL, -col_856 INT DEFAULT NULL, -col_857 INT DEFAULT NULL, -col_858 INT DEFAULT NULL, -col_859 INT DEFAULT NULL, -col_860 INT DEFAULT NULL, -col_861 INT DEFAULT NULL, -col_862 INT DEFAULT NULL, -col_863 INT DEFAULT NULL, -col_864 INT DEFAULT NULL, -col_865 INT DEFAULT NULL, -col_866 INT DEFAULT NULL, -col_867 INT DEFAULT NULL, -col_868 INT DEFAULT NULL, -col_869 INT DEFAULT NULL, -col_870 INT DEFAULT NULL, -col_871 INT DEFAULT NULL, -col_872 INT DEFAULT NULL, -col_873 INT DEFAULT NULL, -col_874 INT DEFAULT NULL, -col_875 INT DEFAULT NULL, -col_876 INT DEFAULT NULL, -col_877 INT DEFAULT NULL, -col_878 INT DEFAULT NULL, -col_879 INT DEFAULT NULL, -col_880 INT DEFAULT NULL, -col_881 INT DEFAULT NULL, -col_882 INT DEFAULT NULL, -col_883 INT DEFAULT NULL, -col_884 INT DEFAULT NULL, -col_885 INT DEFAULT NULL, -col_886 INT DEFAULT NULL, -col_887 INT DEFAULT NULL, -col_888 INT DEFAULT NULL, -col_889 INT DEFAULT NULL, -col_890 INT DEFAULT NULL, -col_891 INT DEFAULT NULL, -col_892 INT DEFAULT NULL, -col_893 INT DEFAULT NULL, -col_894 INT DEFAULT NULL, -col_895 INT DEFAULT NULL, -col_896 INT DEFAULT NULL, -col_897 INT DEFAULT NULL, -col_898 INT DEFAULT NULL, -col_899 INT DEFAULT NULL, -col_900 INT DEFAULT NULL, -col_901 INT DEFAULT NULL, -col_902 INT DEFAULT NULL, -col_903 INT DEFAULT NULL, -col_904 INT DEFAULT NULL, -col_905 INT DEFAULT NULL, -col_906 INT DEFAULT NULL, -col_907 INT DEFAULT NULL, -col_908 INT DEFAULT NULL, -col_909 INT DEFAULT NULL, -col_910 INT DEFAULT NULL, -col_911 INT DEFAULT NULL, -col_912 INT DEFAULT NULL, -col_913 INT DEFAULT NULL, -col_914 INT DEFAULT NULL, -col_915 INT DEFAULT NULL, -col_916 INT DEFAULT NULL, -col_917 INT DEFAULT NULL, -col_918 INT DEFAULT NULL, -col_919 INT DEFAULT NULL, -col_920 INT DEFAULT NULL, -col_921 INT DEFAULT NULL, -col_922 INT DEFAULT NULL, -col_923 INT DEFAULT NULL, -col_924 INT DEFAULT NULL, -col_925 INT DEFAULT NULL, -col_926 INT DEFAULT NULL, -col_927 INT DEFAULT NULL, -col_928 INT DEFAULT NULL, -col_929 INT DEFAULT NULL, -col_930 INT DEFAULT NULL, -col_931 INT DEFAULT NULL, -col_932 INT DEFAULT NULL, -col_933 INT DEFAULT NULL, -col_934 INT DEFAULT NULL, -col_935 INT DEFAULT NULL, -col_936 INT DEFAULT NULL, -col_937 INT DEFAULT NULL, -col_938 INT DEFAULT NULL, -col_939 INT DEFAULT NULL, -col_940 INT DEFAULT NULL, -col_941 INT DEFAULT NULL, -col_942 INT DEFAULT NULL, -col_943 INT DEFAULT NULL, -col_944 INT DEFAULT NULL, -col_945 INT DEFAULT NULL, -col_946 INT DEFAULT NULL, -col_947 INT DEFAULT NULL, -col_948 INT DEFAULT NULL, -col_949 INT DEFAULT NULL, -col_950 INT DEFAULT NULL, -col_951 INT DEFAULT NULL, -col_952 INT DEFAULT NULL, -col_953 INT DEFAULT NULL, -col_954 INT DEFAULT NULL, -col_955 INT DEFAULT NULL, -col_956 INT DEFAULT NULL, -col_957 INT DEFAULT NULL, -col_958 INT DEFAULT NULL, -col_959 INT DEFAULT NULL, -col_960 INT DEFAULT NULL, -col_961 INT DEFAULT NULL, -col_962 INT DEFAULT NULL, -col_963 INT DEFAULT NULL, -col_964 INT DEFAULT NULL, -col_965 INT DEFAULT NULL, -col_966 INT DEFAULT NULL, -col_967 INT DEFAULT NULL, -col_968 INT DEFAULT NULL, -col_969 INT DEFAULT NULL, -col_970 INT DEFAULT NULL, -col_971 INT DEFAULT NULL, -col_972 INT DEFAULT NULL, -col_973 INT DEFAULT NULL, -col_974 INT DEFAULT NULL, -col_975 INT DEFAULT NULL, -col_976 INT DEFAULT NULL, -col_977 INT DEFAULT NULL, -col_978 INT DEFAULT NULL, -col_979 INT DEFAULT NULL, -col_980 INT DEFAULT NULL, -col_981 INT DEFAULT NULL, -col_982 INT DEFAULT NULL, -col_983 INT DEFAULT NULL, -col_984 INT DEFAULT NULL, -col_985 INT DEFAULT NULL, -col_986 INT DEFAULT NULL, -col_987 INT DEFAULT NULL, -col_988 INT DEFAULT NULL, -col_989 INT DEFAULT NULL, -col_990 INT DEFAULT NULL, -col_991 INT DEFAULT NULL, -col_992 INT DEFAULT NULL, -col_993 INT DEFAULT NULL, -col_994 INT DEFAULT NULL, -col_995 INT DEFAULT NULL, -col_996 INT DEFAULT NULL, -col_997 INT DEFAULT NULL, -col_998 INT DEFAULT NULL, -col_999 INT DEFAULT NULL, -col_1000 INT DEFAULT NULL, -col_1001 INT DEFAULT NULL, -col_1002 INT DEFAULT NULL, -col_1003 INT DEFAULT NULL, -col_1004 INT DEFAULT NULL, -col_1005 INT DEFAULT NULL, -col_1006 INT DEFAULT NULL, -col_1007 INT DEFAULT NULL, -col_1008 INT DEFAULT NULL, -col_1009 INT DEFAULT NULL, -col_1010 INT DEFAULT NULL, -col_1011 INT DEFAULT NULL, -col_1012 INT DEFAULT NULL, -col_1013 INT DEFAULT NULL, -col_1014 INT DEFAULT NULL, -col_1015 INT DEFAULT NULL, -col_1016 INT DEFAULT NULL, -col_last INT DEFAULT NULL) ENGINE=InnoDB; +call create_table("tb1", 1017); --echo # Generate row version -INSERT INTO tb1 (col_last) VALUES (1); +INSERT INTO tb1 (col_1017) VALUES (1); --echo # Keep a copy for other scenarios CREATE TABLE t1 AS SELECT * FROM tb1; @@ -1033,55 +41,54 @@ CREATE TABLE t2 AS SELECT * FROM tb1; CREATE TABLE t3 AS SELECT * FROM tb1; CREATE TABLE t4 AS SELECT * FROM tb1; +--echo +--echo # 1017 (user cols) + 3 (system cols) = 1020 (MAX_FIELDS_ALLOWED) +--echo + --echo ######################################## --echo # Scenario 1: ADD/DROP single column: --echo ######################################## ---echo # REC_MAX_N_FIELDS = 1023 -- max number of fields allowed. ---echo # Step 1. DROP - ADD columns until (n_def + < REC_MAX_N_FIELDS) ---echo # Current: n_def = 1020 ( + 3(DB_ROW_ID + DB_TRX_ID + DB_ROLL_PTR) + ) +--echo # Current: n_def = (user columns + system columns + n_drop_cols) --echo # Current: n_def = 1020 (1017 + 3 + 0) -ALTER TABLE tb1 DROP COLUMN col_last, ALGORITHM=INSTANT; ---echo # Current: n_def = 1020 (1016 + 3 + 1) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; - -ALTER TABLE tb1 ADD COLUMN col_last INT, ALGORITHM=INSTANT; ---echo # Current: n_def = 1021 (1017 + 3 + 1) - -ALTER TABLE tb1 DROP COLUMN col_last, ALGORITHM=INSTANT; ---echo # Current: n_def = 1021 (1016 + 3 + 2) +--echo # ----------------------------------------------------------------------- +--echo # DROP - ADD columns till (n_def + n_col_added < MAX_FIELDS_ALLOWED) +--echo # ----------------------------------------------------------------------- -ALTER TABLE tb1 ADD COLUMN col_last INT, ALGORITHM=INSTANT; ---echo # Current: n_def = 1022 (1017 + 3 + 2) +--echo # DROP COLUMN should pass +ALTER TABLE tb1 DROP COLUMN col_1017, ALGORITHM=INSTANT; -ALTER TABLE tb1 DROP COLUMN col_last, ALGORITHM=INSTANT; ---echo # Current: n_def = 1022 (1016 + 3 + 3) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; +--echo # Current: n_def = 1020 (1016 + 3 + 1) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; ---echo # Step 2. Test that ADD with ALGORITHM=INSTANT is no longer allowed: ---echo # Current: n_def = 1022 (1016 + 3 + 3) ---echo # If we ADD 1 column: n_def = 1023 (1017 + 3 + 3) becomes REC_MAX_N_FIELDS -- not allowed +--echo # ADD COLUMN should fail --error ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS -ALTER TABLE tb1 ADD COLUMN col_last INT, ALGORITHM=INSTANT; ---echo # Current: n_def = 1022 (1016 + 3 + 3) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; +ALTER TABLE tb1 ADD COLUMN col_1017 INT, ALGORITHM=INSTANT; ---echo # Note that we can still DROP columns with INSTANT: +--echo # DROP COLUMN should still pass ALTER TABLE tb1 DROP COLUMN col_1016, ALGORITHM=INSTANT; ---echo # Current: n_def = 1022 (1015 + 3 + 4) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; ---echo # But we cannot ADD any more columns with INSTANT: ---echo # If we ADD 1 column: n_def = 1023 (1016 + 3 + 4) becomes REC_MAX_N_FIELDS -- not allowed +--echo # Current: n_def = 1020 (1015 + 3 + 2) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; + +--echo # ADD COLUMN should still fail --error ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS -ALTER TABLE tb1 ADD COLUMN col_1016 INT, ALGORITHM=INSTANT; +ALTER TABLE tb1 ADD COLUMN col_1017 INT, ALGORITHM=INSTANT; + +--echo # ----------------------------------------------------------------------- +--echo # Verify that ADD is possible without specifying ALGORITHM +--echo # (should fallback to INPLACE) +--echo # ----------------------------------------------------------------------- ---echo # Step 3. Verify that ADD is possible without specifying ALGORITHM (should fallback to INPLACE) -ALTER TABLE tb1 ADD COLUMN col_last INT; --echo # Table is rebuilt when ALGORITHM=INPLACE is used (internally) ---echo # Current: n_def = 1017 (1017) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; +ALTER TABLE tb1 ADD COLUMN col_1017 INT; + +--echo # Current: n_def = 1019 (1016 + 3) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/tb1"; --echo # Cleanup DROP TABLE tb1; @@ -1089,52 +96,61 @@ DROP TABLE tb1; --echo ######################################## --echo # Scenario 2: ADD/DROP two columns: --echo ######################################## ---echo # REC_MAX_N_FIELDS = 1023 -- max number of fields allowed. ---echo # Step 1. DROP - ADD columns until (n_def + < REC_MAX_N_FIELDS) ---echo # Current: n_def = 1020 ( + 3(DB_ROW_ID + DB_TRX_ID + DB_ROLL_PTR) + ) +--echo # Current: n_def = (user columns + system columns + n_drop_cols) --echo # Current: n_def = 1020 (1017 + 3 + 0) -ALTER TABLE t1 DROP COLUMN col_last, DROP COLUMN col_1016, ALGORITHM=INSTANT; ---echo # Current: n_def = 1020 (1015 + 3 + 2) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; +--echo # ----------------------------------------------------------------------- +--echo # DROP - ADD columns till (n_def + n_col_added < MAX_FIELDS_ALLOWED) +--echo # ----------------------------------------------------------------------- -ALTER TABLE t1 ADD COLUMN col_last INT, ADD COLUMN col_1016 INT, ALGORITHM=INSTANT; ---echo # Current: n_def = 1022 (1017 + 3 + 2) +--echo # DROP COLUMN for 2 columns should pass +ALTER TABLE t1 + DROP COLUMN col_1017, + DROP COLUMN col_1016, + ALGORITHM=INSTANT; -ALTER TABLE t1 DROP COLUMN col_last, DROP COLUMN col_1016, ALGORITHM=INSTANT; ---echo # Current: n_def = 1022 (1015 + 3 + 4) +--echo # Current: n_def = 1020 (1015 + 3 + 2) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; ---echo # Step 2. Test that ADD with ALGORITHM=INSTANT is no longer allowed: ---echo # Current: n_def = 1022 (1015 + 3 + 4) ---echo # If we ADD 2 columns: n_def = 1024 (1017 + 3 + 4) becomes > REC_MAX_N_FIELDS -- not allowed +--echo # ADD COLUMN should fail --error ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS -ALTER TABLE t1 ADD COLUMN col_last INT, ADD COLUMN col_1016 INT, ALGORITHM=INSTANT; ---echo # Current: n_def = 1022 (1015 + 3 + 4) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; - ---echo # If we ADD 1 column: n_def = 1023 (1016 + 3 + 4) becomes REC_MAX_N_FIELDS -- not allowed +ALTER TABLE t1 + ADD COLUMN col_1017 INT, + ADD COLUMN col_1016 INT, + ALGORITHM=INSTANT; + +--echo # DROP COLUMN for 2 columns should still pass +ALTER TABLE t1 + DROP COLUMN col_1015, + DROP COLUMN col_1014, + ALGORITHM=INSTANT; + +--echo # Current: n_def = 1020 (1013 + 3 + 4) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; + +--echo # ADD COLUMN should still fail --error ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS -ALTER TABLE t1 ADD COLUMN col_last INT, ALGORITHM=INSTANT; ---echo # Current: n_def = 1022 (1015 + 3 + 4) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; +ALTER TABLE t1 + ADD COLUMN col_1017 INT, + ADD COLUMN col_1016 INT, + ALGORITHM=INSTANT; ---echo # Note that we can still DROP columns with INSTANT: -ALTER TABLE t1 DROP COLUMN col_1015, DROP COLUMN col_1014, ALGORITHM=INSTANT; ---echo # Current: n_def = 1022 (1013 + 3 + 6) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; - ---echo # But we cannot ADD any more columns with INSTANT: ---echo # If we ADD 1 column: n_def = 1023 (1014 + 3 + 6) becomes REC_MAX_N_FIELDS -- not allowed ---error ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS -ALTER TABLE t1 ADD COLUMN col_1015 INT, ALGORITHM=INSTANT; ---echo # Current: n_def = 1022 (1013 + 3 + 6) +--echo # ----------------------------------------------------------------------- +--echo # Verify that ADD is possible without specifying ALGORITHM +--echo # (should fallback to INPLACE) +--echo # ----------------------------------------------------------------------- ---echo # Step 3. Verify that ADD is possible without specifying ALGORITHM (should fallback to INPLACE) -ALTER TABLE t1 ADD COLUMN col_1014 INT, ADD COLUMN col_1015 INT, ADD COLUMN col_1016 INT, ADD COLUMN col_last INT; --echo # Table is rebuilt when ALGORITHM=INPLACE is used (internally) ---echo # Current: n_def = 1017 (1017) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; +ALTER TABLE t1 + ADD COLUMN col_1017 INT, + ADD COLUMN col_1016 INT; + +--echo # Current: n_def = 1018 (1015 + 3) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t1"; --echo # Cleanup DROP TABLE t1; @@ -1142,28 +158,55 @@ DROP TABLE t1; --echo ######################################## --echo # Scenario 3: ADD/DROP multiple columns: --echo ######################################## ---echo # REC_MAX_N_FIELDS = 1023 -- max number of fields allowed. ---echo # ADD/DROP multiple columns and look for failures ---echo # Current: n_def = 1020 ( + 3(DB_ROW_ID + DB_TRX_ID + DB_ROLL_PTR) + ) +--echo # Current: n_def = (user columns + system columns + n_drop_cols) --echo # Current: n_def = 1020 (1017 + 3 + 0) -ALTER TABLE t2 DROP COLUMN col_1016, DROP COLUMN col_1015, DROP COLUMN col_1014, DROP COLUMN col_1013, DROP COLUMN col_1012, DROP COLUMN col_1011, ALGORITHM=INSTANT; ---echo # Current: n_def = 1020 (1011 + 3 + 6) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t2"; ---error ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS -ALTER TABLE t2 ADD COLUMN col_1011 INT, DROP COLUMN col_1010, ADD COLUMN col_1012 INT, ADD COLUMN col_1013 INT, DROP COLUMN col_1009, DROP COLUMN col_1008, ADD COLUMN col_1014 INT, ALGORITHM=INSTANT; ---echo # If operation was successful: n_def = 1027 (1015 + 3 + 9) > REC_MAX_N_FIELDS ---echo # Current: n_def = 1020 (1011 + 3 + 6) +--echo # ----------------------------------------------------------------------- +--echo # ADD/DROP multiple columns and look for failures +--echo # ----------------------------------------------------------------------- + +--echo # DROP multiple columns should pass +ALTER TABLE t2 + DROP COLUMN col_1016, + DROP COLUMN col_1015, + DROP COLUMN col_1014, + DROP COLUMN col_1013, + DROP COLUMN col_1012, + DROP COLUMN col_1011, + ALGORITHM=INSTANT; -ALTER TABLE t2 ADD COLUMN col_1015 INT, ADD COLUMN col_1016 INT, DROP COLUMN col_1010, ALGORITHM=INSTANT; ---echo # Current: n_def = 1022 (1012 + 3 + 7) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t2"; +--echo # Current: n_def = 1020 (1011 + 3 + 6) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t2"; +--echo # ADD COLUMN should fail +--error ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS +ALTER TABLE t2 + ADD COLUMN col_1011 INT, + DROP COLUMN col_1010, + ADD COLUMN col_1012 INT, + ADD COLUMN col_1013 INT, + DROP COLUMN col_1009, + DROP COLUMN col_1008, + ADD COLUMN col_1014 INT, + ALGORITHM=INSTANT; + +--echo # ----------------------------------------------------------------------- --echo # Fallback to inplace for failed query -ALTER TABLE t2 ADD COLUMN col_1011 INT, DROP COLUMN col_1007, ADD COLUMN col_1012 INT, ADD COLUMN col_1013 INT, DROP COLUMN col_1009, DROP COLUMN col_1008, ADD COLUMN col_1014 INT; ---echo # Current: n_def = 1017 (1017) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t2"; +--echo # ----------------------------------------------------------------------- +ALTER TABLE t2 + ADD COLUMN col_1011 INT, + DROP COLUMN col_1010, + ADD COLUMN col_1012 INT, + ADD COLUMN col_1013 INT, + DROP COLUMN col_1009, + DROP COLUMN col_1008, + ADD COLUMN col_1014 INT; + +--echo # Current: n_def = 1018 (1015 + 3 + 0) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t2"; --echo # Cleanup DROP TABLE t2; @@ -1171,35 +214,57 @@ DROP TABLE t2; --echo ######################################## --echo # Scenario 4: With other ALTER operations: --echo ######################################## ---echo # REC_MAX_N_FIELDS = 1023 -- max number of fields allowed. ---echo # ADD/DROP with other ALTER operations ---echo # Current: n_def = 1020 ( + 3(DB_ROW_ID + DB_TRX_ID + DB_ROLL_PTR) + ) +--echo # Current: n_def = (user columns + system columns + n_drop_cols) --echo # Current: n_def = 1020 (1017 + 3 + 0) -ALTER TABLE t3 DROP COLUMN col_1016, DROP COLUMN col_1015, DROP COLUMN col_1014, DROP COLUMN col_1013, DROP COLUMN col_1012, DROP COLUMN col_1011, DROP COLUMN col_1010, DROP COLUMN col_1009, ALGORITHM=INSTANT; ---echo Current: n_def = 1020 (1009 + 3 + 8) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; -ALTER TABLE t3 ADD COLUMN col_1009 INT, RENAME COLUMN col_last TO col_1017, RENAME COLUMN col_1007 TO col_1007_new, ADD COLUMN col_1011 INT, DROP COLUMN col_1008, ALGORITHM=INSTANT; ---echo Current: n_def = 1022 (1010 + 3 + 9) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; +--echo # ----------------------------------------------------------------------- +--echo # ADD/DROP with other ALTER operations +--echo # ----------------------------------------------------------------------- + +--echo # DROP COLUMN should pass +ALTER TABLE t3 + DROP COLUMN col_1016, + DROP COLUMN col_1015, + DROP COLUMN col_1014, + DROP COLUMN col_1013, + DROP COLUMN col_1012, + DROP COLUMN col_1011, + DROP COLUMN col_1010, + DROP COLUMN col_1009, + ALGORITHM=INSTANT; +--echo Current: n_def = 1020 (1009 + 3 + 8) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; + +--echo # ADD COLUMN with other operations should fail +--error ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS +ALTER TABLE t3 + ADD COLUMN col_1009 INT, + RENAME COLUMN col_1017 TO col_10177, + RENAME COLUMN col_1007 TO col_1007_new, + DROP COLUMN col_1008, + ALGORITHM=INSTANT; + +--echo # ADD COLUMN should fail --error ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS ALTER TABLE t3 ADD COLUMN col_1010 INT, ALGORITHM=INSTANT; ---echo Current: n_def = 1022 (1010 + 3 + 9) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; ---echo Similarly single column add/drop will fail +--echo # Similarly single column add/drop will fail --error ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS -ALTER TABLE t3 ADD COLUMN col_1010 INT, DROP COLUMN col_1009, ALGORITHM=INSTANT; ---echo Current: n_def = 1022 (1010 + 3 + 9) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; ---echo Fallback to inplace for failed query +ALTER TABLE t3 ADD COLUMN col_1010 INT, DROP COLUMN col_1008, ALGORITHM=INSTANT; +--echo # ----------------------------------------------------------------------- +--echo # Fallback to inplace for failed query +--echo # ----------------------------------------------------------------------- +--echo # ADD COLUMN should fallback to INPLACE and should pass ALTER TABLE t3 ADD COLUMN col_1010 INT; ---echo Current: n_def = 1017 (1017) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; + +--echo Current: n_def = 1013 (1010 + 3 + 0) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t3"; --echo # Cleanup DROP TABLE t3; @@ -1207,31 +272,67 @@ DROP TABLE t3; --echo ######################################## --echo # Scenario 5: ADD/DROP few columns: --echo ######################################## ---echo # REC_MAX_N_FIELDS = 1023 -- max number of fields allowed. ---echo # ADD/DROP few columns together ---echo # Current: n_def = 1020 ( + 3(DB_ROW_ID + DB_TRX_ID + DB_ROLL_PTR) + ) +--echo # Current: n_def = (user columns + system columns + n_drop_cols) --echo # Current: n_def = 1020 (1017 + 3 + 0) -ALTER TABLE t4 DROP COLUMN col_1016, DROP COLUMN col_1015, DROP COLUMN col_1014, DROP COLUMN col_1013, DROP COLUMN col_1012, DROP COLUMN col_1011, DROP COLUMN col_1010, DROP COLUMN col_1009, ALGORITHM=INSTANT; + +--echo # ----------------------------------------------------------------------- +--echo # ADD/DROP few columns together +--echo # ----------------------------------------------------------------------- + +--echo # DROP COLUMN should pass +ALTER TABLE t4 + DROP COLUMN col_1016, + DROP COLUMN col_1015, + DROP COLUMN col_1014, + DROP COLUMN col_1013, + DROP COLUMN col_1012, + DROP COLUMN col_1011, + DROP COLUMN col_1010, + DROP COLUMN col_1009, + ALGORITHM=INSTANT; + --echo Current: n_def = 1020 (1009 + 3 + 8) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t4"; +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t4"; -ALTER TABLE t4 ADD COLUMN col_1016 INT, DROP COLUMN col_1008, ALGORITHM=INSTANT; ---echo Current: n_def = 1021 (1009 + 3 + 9) +--echo # ADD COLUMN should fail +--error ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS +ALTER TABLE t4 + ADD COLUMN col_1016 INT, + DROP COLUMN col_1008, + ALGORITHM=INSTANT; -ALTER TABLE t4 ADD COLUMN col_1015 INT, DROP COLUMN col_1007, DROP COLUMN col_1006, ALGORITHM=INSTANT; ---echo Current: n_def = 1022 (1008 + 3 + 11) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t4"; +--echo # ADD COLUMN should fail +--error ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS +ALTER TABLE t4 + ADD COLUMN col_1015 INT, + DROP COLUMN col_1007, + DROP COLUMN col_1006, + ALGORITHM=INSTANT; +--echo # ADD COLUMN should fail --error ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS -ALTER TABLE t4 ADD COLUMN col_1014 INT, ADD COLUMN col_1013 INT, DROP COLUMN col_1005, ALGORITHM=INSTANT; ---echo Current: n_def = 1022 (1008 + 3 + 11) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t4"; +ALTER TABLE t4 + ADD COLUMN col_1014 INT, + ADD COLUMN col_1013 INT, + DROP COLUMN col_1005, +ALGORITHM=INSTANT; + +--echo # ----------------------------------------------------------------------- +--echo # Fallback to inplace for failed query +--echo # ----------------------------------------------------------------------- ---echo Fallback to inplace for failed query -ALTER TABLE t4 ADD COLUMN col_1014 INT, ADD COLUMN col_1013 INT, DROP COLUMN col_1005; ---echo Current: n_def = 1009 (1008 + 2 - 1 ) -SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t4"; +ALTER TABLE t4 + ADD COLUMN col_1014 INT, + ADD COLUMN col_1013 INT, + DROP COLUMN col_1005; + +--echo Current: n_def = 1013 (1010 + 3 + 0) +SELECT TOTAL_ROW_VERSIONS, N_COLS, CURRENT_COLUMN_COUNTS, INITIAL_COLUMN_COUNTS, +TOTAL_COLUMN_COUNTS FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME="test/t4"; --echo # Cleanup DROP TABLE t4; + +DROP PROCEDURE create_table; diff --git a/mysql-test/suite/ndb/my.cnf b/mysql-test/suite/ndb/my.cnf index fa753f42dff4..450d5ad4fd1c 100644 --- a/mysql-test/suite/ndb/my.cnf +++ b/mysql-test/suite/ndb/my.cnf @@ -75,6 +75,7 @@ skip-log-replica-updates [ENV] NDB_CONNECTSTRING= @mysql_cluster.1.ndb_connectstring +NDB_MGMD_PORT= @cluster_config.ndb_mgmd.1.1.PortNumber MASTER_MYSOCK= @mysqld.1.1.socket MASTER_MYPORT= @mysqld.1.1.port MASTER_MYPORT1= @mysqld.2.1.port diff --git a/mysql-test/suite/ndb/t/ndb_config_diff_default.test b/mysql-test/suite/ndb/t/ndb_config_diff_default.test index 42b6b6238f92..f4edd136b99a 100644 --- a/mysql-test/suite/ndb/t/ndb_config_diff_default.test +++ b/mysql-test/suite/ndb/t/ndb_config_diff_default.test @@ -1,7 +1,7 @@ source include/have_ndb.inc; -let $MGMPORT_REGEX = `select concat('/',substring_index(@@ndb_connectstring,':',-1),'//')`; -let $DYNPORT_REGEX = /42949([0-5][0-9]|6[0-6])[0-9][0-9][0-9]|4194[23][0-9][0-9]K//; +let $MGMPORT_REGEX = /\b$NDB_MGMD_PORT\b//; +let $DYNPORT_REGEX = /\b(42949([0-5][0-9]|6[0-6])[0-9][0-9][0-9]|4194[23][0-9][0-9]K)\b//; disable_query_log; eval select '$MYSQLTEST_VARDIR' into @vardir; enable_query_log; diff --git a/mysql-test/suite/rpl_nogtid/t/rpl_server_uuid.test b/mysql-test/suite/rpl_nogtid/t/rpl_server_uuid.test index b52d526299f7..f6d34954c37e 100644 --- a/mysql-test/suite/rpl_nogtid/t/rpl_server_uuid.test +++ b/mysql-test/suite/rpl_nogtid/t/rpl_server_uuid.test @@ -269,7 +269,7 @@ eval CHANGE REPLICATION SOURCE TO # Grep only after the message that the server_2 has connected to the master --let $assert_only_after=Start binlog_dump to source_thread_id\($replica_thread_id\) --let $assert_count= 1 ---let $assert_select=found a zombie dump thread with the same UUID +--let $assert_select=Upon reconnection with the replica, while initializing the dump thread for.*, an existing dump thread with the same.* was detected.* --let $assert_text= Found the expected line in master's error log for server 2 disconnection --source include/assert_grep.inc diff --git a/mysql-test/t/explain_dml.test b/mysql-test/t/explain_dml.test index 424ee5e78a0d..d54f4c31ee7a 100644 --- a/mysql-test/t/explain_dml.test +++ b/mysql-test/t/explain_dml.test @@ -79,7 +79,7 @@ INSERT DELAYED IGNORE INTO t1 PARTITION(p0, p1) (c1, c2) #INSERT .... SET EXPLAIN INSERT INTO t1 PARTITION(p0, p1) - SET c1 = (SELECT c1 from t2); + SET c1 = (SELECT c1 from t2 LIMIT 1); #REPLACE .... VALUES @@ -95,7 +95,7 @@ REPLACE DELAYED INTO t1 PARTITION(p0, p1) (c1, c2) #REPLACE .... SET EXPLAIN REPLACE INTO t1 PARTITION(p0, p1) - SET c1 = (SELECT c1 from t2); + SET c1 = (SELECT c1 from t2 LIMIT 1); #No effect on EXPLAIN FOR CONNECTION .... for both SINGLE/MULTI-TABLE DML let $QID= `SELECT CONNECTION_ID()`; diff --git a/mysql-test/t/mysqldump-tablespace-escape.test b/mysql-test/t/mysqldump-tablespace-escape.test index 0a23c154facc..a8e086090e2a 100644 --- a/mysql-test/t/mysqldump-tablespace-escape.test +++ b/mysql-test/t/mysqldump-tablespace-escape.test @@ -8,6 +8,7 @@ let $grep_file= $MYSQLTEST_VARDIR/tmp/bug36816986.sql; let $grep_output=boolean; CREATE DATABASE bug36816986; +USE bug36816986; --echo -- Run mysqldump with tablespace_injection_test. --exec $MYSQL_DUMP --debug="d,tablespace_injection_test" --result-file=$grep_file bug36816986 --all-tablespaces 2>&1 @@ -16,6 +17,109 @@ CREATE DATABASE bug36816986; let $grep_pattern=qr| ENGINE=\*/\nsystem touch foo|; --source include/grep_pattern.inc -# Cleanup +--echo The ` must be escaped: +let $grep_pattern=qr|CREATE TABLESPACE `T``N; /*`|; +--source include/grep_pattern.inc + --remove_file $grep_file DROP DATABASE bug36816986; + +--echo +--echo ####################################### +--echo + +--echo # +--echo # Bug#37607195 - fprintf_string not using the actual quote parameter +--echo # + +CREATE DATABASE bug37607195; +USE bug37607195; + +let $grep_file= $MYSQLTEST_VARDIR/tmp/bug37607195.sql; +let $grep_output=boolean; + +--echo Create a bunch of tables with numerous ` ' " \n etc. + +SET @@sql_mode='ANSI_QUOTES,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; + +CREATE TABLE "custo`mers" ( + "customer'_id" INT AUTO_INCREMENT PRIMARY KEY, + "fir`st_`na`me" VARCHAR(50) NOT NULL, + "last_'name" VARCHAR(50) NOT NULL, + "em`ail" VARCHAR(100) UNIQUE NOT NULL, + `pho"\ne` VARCHAR(15), + "created'_'at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + "updated'_'at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); + +CREATE TABLE "prod'ucts" ( + "product`_`id" INT AUTO_INCREMENT PRIMARY KEY, + "product'_`name" VARCHAR(100) NOT NULL, + "descri`p`t`i`o`n" TEXT, + "pr'i'ce" DECIMAL(10, 2) NOT NULL CHECK ("pr'i'ce" >= 0), + `stock"_"qua\ntity` INT DEFAULT 0, + `created'_'at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `updated"_'at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + INDEX ("product'_`name") +); + +CREATE TABLE "orders" ( + "order_id" INT AUTO_INCREMENT PRIMARY KEY, + "customer_id" INT NOT NULL, + "order_date" TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + "status" ENUM('Pending', 'Completed', 'Cancelled') NOT NULL, + "total\n" DECIMAL(10, 2) NOT NULL CHECK ("total\n" >= 0), + FOREIGN KEY (customer_id) REFERENCES "custo`mers"("customer'_id") ON DELETE CASCADE, + INDEX (order_date) +); + +CREATE TABLE `'order'_'items'` ( + `order'_'item_id` INT AUTO_INCREMENT PRIMARY KEY, + `'order'_'id'` INT NOT NULL, + `product'_'id` INT NOT NULL, + `qua\ntity` INT NOT NULL CHECK (`qua\ntity` > 0), + `p'rice` DECIMAL(10,2) NOT NULL CHECK (`p'rice` >= 0), + FOREIGN KEY (`'order'_'id'`) REFERENCES "orders"(order_id) ON DELETE CASCADE, + FOREIGN KEY (`product'_'id`) REFERENCES "prod'ucts"("product`_`id") ON DELETE CASCADE, + UNIQUE KEY (`'order'_'id'`, `product'_'id`) +); + +--exec $MYSQL_DUMP bug37607195 --init-command="SET @@sql_mode='ANSI_QUOTES,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'" --result-file=$grep_file 2>&1 + +--echo # Table 1: `'order'_'items'` +--echo # `qua\ntity` must be escaped +let $grep_pattern=qr| `qua\ntity` INT NOT NULL CHECK (`qua\ntity` > 0)|; +--source include/grep_pattern.inc + +--echo # Table 2: "custo`mers" +--echo # "custo`mers" must be escaped +let $grep_pattern=qr|CREATE TABLE `custo``mers`|; +--source include/grep_pattern.inc + +--echo # `pho"\ne` must be escaped +let $grep_pattern=qr|`pho"\ne` varchar(15) DEFAULT NULL|; +--source include/grep_pattern.inc + +--echo # Table 3: "orders" +--echo # `total\n` must be escaped +let $grep_pattern=qr|`total\n` decimal(10,2) NOT NULL|; +--source include/grep_pattern.inc + +--echo # FOREIGN KEY (`customer_id`) REFERENCES must be escaped +let $grep_pattern=qr|REFERENCES `custo``mers`|; +--source include/grep_pattern.inc + +--echo # Table 4: `prod'ucts` +--echo # "descri`p`t`i`o`n" TEXT must be escaped +let $grep_pattern=qr|`descri``p``t``i``o``n` text|; +--source include/grep_pattern.inc + +--echo # `stock"_"qua\ntity` must be escaped +let $grep_pattern=qr|`stock"_"qua\ntity` int DEFAULT '0'|; +--source include/grep_pattern.inc + +SET @@sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; + +# Cleanup +--remove_file $grep_file +DROP DATABASE bug37607195; diff --git a/mysql-test/t/partition_locking.test b/mysql-test/t/partition_locking.test index 7a13b4c226a9..7d9d8a1c4695 100644 --- a/mysql-test/t/partition_locking.test +++ b/mysql-test/t/partition_locking.test @@ -2938,6 +2938,11 @@ DROP TABLE t1, t2; --echo # --echo # Test subqueries/stored functions with UPDATE/DELETE/SELECT --echo # +# Bug#37560280: +# The EXPLAIN plan for queries with the sf_a_from_t1b_d() function call +# differs from the actual execution plan because constant folding +# is performed in the actual plan but not in EXPLAIN. + CREATE TABLE tq (id int PRIMARY KEY auto_increment, query varchar(255), not_select tinyint); CREATE TABLE tsq (id int PRIMARY KEY auto_increment, subquery varchar(255), can_be_locked tinyint); CREATE TABLE t1 (a int, b varchar(255), PRIMARY KEY (a), KEY (b)) diff --git a/mysql-test/t/partition_pruning.test b/mysql-test/t/partition_pruning.test index 34a3c087b640..fa4a51b4ebc4 100644 --- a/mysql-test/t/partition_pruning.test +++ b/mysql-test/t/partition_pruning.test @@ -2510,3 +2510,79 @@ SELECT * from t2 WHERE c2 IN ((SELECT c0 FROM t1 LIMIT 1),null); SELECT * from t2 WHERE c2 NOT IN ((SELECT c0 FROM t1 LIMIT 1),null); DROP TABLE t1, t2; + +--echo # +--echo # Bug#37397306 - looks like not use pruning when it inserts with now() function in 8.0 +--echo # + +CREATE TABLE t1 ( + f1 DATETIME NOT NULL, + f2 INT NOT NULL, + f3 DATE NOT NULL, + PRIMARY KEY (f1,f2) +) +PARTITION BY RANGE COLUMNS(f1) +( + PARTITION p01 VALUES LESS THAN ('1975-12-31 10:21:55'), + PARTITION p02 VALUES LESS THAN ('1976-12-31 10:21:55'), + PARTITION p03 VALUES LESS THAN ('2090-12-31 10:21:55') +); + +ANALYZE TABLE t1; +SET TIMESTAMP=UNIX_TIMESTAMP('2019-03-11 12:00:00'); +EXPLAIN INSERT INTO t1 (f1,f2,f3) VALUES (now(),10001,'1976-11-31'); +SET TIMESTAMP=UNIX_TIMESTAMP('1975-03-11 12:00:00'); +EXPLAIN INSERT INTO t1 (f1,f2,f3) VALUES (now(),10001,'2000-11-31'); + +SET TIMESTAMP=DEFAULT; +DROP TABLE t1; + +CREATE TABLE t1(a INTEGER PRIMARY KEY, b INTEGER) +PARTITION BY RANGE (a) +( + PARTITION p1 VALUES LESS THAN (10), + PARTITION p2 VALUES LESS THAN MAXVALUE +); + +ANALYZE TABLE t1; + +set @a=1,@b=22; +EXPLAIN INSERT INTO t1(a,b) VALUES (@a,@b); +EXPLAIN INSERT INTO t1 VALUES (@a, 1), (@b, 2); + +set @a=11,@b=22; +EXPLAIN INSERT INTO t1(a,b) VALUES (@a,@b); +EXPLAIN INSERT INTO t1 VALUES (@a, 1), (@b, 2); + +PREPARE s from "EXPLAIN INSERT INTO t1(a,b) VALUES (?,?)"; +set @a=1,@b=22; +EXECUTE s USING @a,@b; + +set @a=11,@b=22; +EXECUTE s USING @a,@b; + +PREPARE p from "EXPLAIN INSERT INTO t1(a,b) VALUES (?,1), (?,2)"; +set @a=1,@b=22; +EXECUTE p USING @a,@b; + +set @a=11,@b=22; +EXECUTE p USING @a,@b; + +DROP TABLE t1; + +CREATE TABLE t1 ( + id INT PRIMARY KEY, + f1 FLOAT +) +PARTITION BY RANGE (id) +( + PARTITION p0 VALUES LESS THAN (10), + PARTITION p1 VALUES LESS THAN MAXVALUE +); + +ANALYZE TABLE t1; + +EXPLAIN INSERT INTO t1 (id, f1) VALUES (1,RAND()); +EXPLAIN INSERT INTO t1 VALUES (20,RAND()); + +DROP TABLE t1; diff --git a/mysys/stacktrace.cc b/mysys/stacktrace.cc index 77db8c958c7b..415918285445 100644 --- a/mysys/stacktrace.cc +++ b/mysys/stacktrace.cc @@ -196,6 +196,10 @@ void my_safe_puts_stderr(const char *val, size_t max_len) { } #ifdef HAVE_EXT_BACKTRACE +static size_t my_write_stderr(const std::string_view &sv) { + return my_write_stderr(std::data(sv), std::size(sv)); +} + void my_print_stacktrace(const uchar *stack_bottom, ulong thread_stack) { my_safe_printf_stderr("stack_bottom = %p thread_stack 0x%lx\n", stack_bottom, thread_stack); @@ -206,6 +210,8 @@ void my_print_stacktrace(const uchar *stack_bottom, ulong thread_stack) { auto print_callback = [](void *cookie, uintptr_t pc, const char *filename, int lineno, const char *function) { auto idx = static_cast(cookie)->index++; + my_safe_printf_stderr(" #%d 0x%lx ", idx, (unsigned long)pc); + my_write_stderr(function == nullptr ? "" : function); if (filename != nullptr) { std::string_view filename_sv{filename}; constexpr std::string_view parent_dir{"../"}; @@ -218,13 +224,11 @@ void my_print_stacktrace(const uchar *stack_bottom, ulong thread_stack) { pos != std::string_view::npos) { filename_sv.remove_prefix(pos + std::size(mysql_dir)); } - my_safe_printf_stderr(" #%d 0x%lx %s at %s:%d\n", idx, (unsigned long)pc, - function == nullptr ? "" : function, - std::data(filename_sv), lineno); - } else { - my_safe_printf_stderr(" #%d 0x%lx %s\n", idx, (unsigned long)pc, - function == nullptr ? "" : function); + my_write_stderr(" at "); + my_write_stderr(filename_sv); + my_safe_printf_stderr(":%d", lineno); } + my_write_stderr("\n"); return 0; }; diff --git a/plugin/group_replication/include/certifier.h b/plugin/group_replication/include/certifier.h index 4dd6fdd577fb..d8a5f7e42d88 100644 --- a/plugin/group_replication/include/certifier.h +++ b/plugin/group_replication/include/certifier.h @@ -149,12 +149,8 @@ class Certifier_broadcast_thread { /** Terminate broadcast thread. - - @return the operation status - @retval 0 OK - @retval !=0 Error */ - int terminate(); + void terminate(); /** Broadcast thread worker method. @@ -241,15 +237,6 @@ class Certifier : public Certifier_interface { */ int initialize(ulonglong gtid_assignment_block_size); - /** - Terminate certifier. - - @return the operation status - @retval 0 OK - @retval !=0 Error - */ - int terminate(); - /** Handle view changes on certifier. */ diff --git a/plugin/group_replication/libmysqlgcs/src/bindings/xcom/gcs_message_stage_split.cc b/plugin/group_replication/libmysqlgcs/src/bindings/xcom/gcs_message_stage_split.cc index e7f97798ba48..e7510a3a6edb 100644 --- a/plugin/group_replication/libmysqlgcs/src/bindings/xcom/gcs_message_stage_split.cc +++ b/plugin/group_replication/libmysqlgcs/src/bindings/xcom/gcs_message_stage_split.cc @@ -28,7 +28,7 @@ #include // std::memcpy #include #include -#include "extra/lz4/my_xxhash.h" +#include "extra/xxhash/my_xxhash.h" #include "plugin/group_replication/libmysqlgcs/include/mysql/gcs/gcs_logging_system.h" #include "plugin/group_replication/libmysqlgcs/include/mysql/gcs/xplatform/byteorder.h" diff --git a/plugin/group_replication/src/certifier.cc b/plugin/group_replication/src/certifier.cc index 4c768244e51a..bc3483d368fa 100644 --- a/plugin/group_replication/src/certifier.cc +++ b/plugin/group_replication/src/certifier.cc @@ -84,8 +84,11 @@ int Certifier_broadcast_thread::initialize() { if ((mysql_thread_create(key_GR_THD_cert_broadcast, &broadcast_pthd, get_connection_attrib(), launch_broadcast_thread, (void *)this))) { - mysql_mutex_unlock(&broadcast_run_lock); /* purecov: inspected */ - return 1; /* purecov: inspected */ + /* purecov: begin inspected */ + mysql_mutex_unlock(&broadcast_run_lock); + LogPluginErr(ERROR_LEVEL, ER_GRP_RPL_CERT_BROADCAST_THREAD_CREATE_FAILED); + return 1; + /* purecov: end */ } broadcast_thd_state.set_created(); @@ -98,13 +101,13 @@ int Certifier_broadcast_thread::initialize() { return 0; } -int Certifier_broadcast_thread::terminate() { +void Certifier_broadcast_thread::terminate() { DBUG_TRACE; mysql_mutex_lock(&broadcast_run_lock); if (broadcast_thd_state.is_thread_dead()) { mysql_mutex_unlock(&broadcast_run_lock); - return 0; + return; } aborted = true; @@ -122,8 +125,6 @@ int Certifier_broadcast_thread::terminate() { mysql_cond_wait(&broadcast_run_cond, &broadcast_run_lock); } mysql_mutex_unlock(&broadcast_run_lock); - - return 0; } void Certifier_broadcast_thread::dispatcher() { @@ -143,6 +144,8 @@ void Certifier_broadcast_thread::dispatcher() { mysql_cond_broadcast(&broadcast_run_cond); mysql_mutex_unlock(&broadcast_run_lock); + LogPluginErr(SYSTEM_LEVEL, ER_GRP_RPL_CERT_BROADCAST_THREAD_STARTED); + while (!aborted) { // Broadcast Transaction identifiers every 30 seconds if (broadcast_counter % 30 == 0) { @@ -196,6 +199,8 @@ void Certifier_broadcast_thread::dispatcher() { mysql_cond_broadcast(&broadcast_run_cond); mysql_mutex_unlock(&broadcast_run_lock); + LogPluginErr(SYSTEM_LEVEL, ER_GRP_RPL_CERT_BROADCAST_THREAD_STOPPED); + my_thread_exit(nullptr); } @@ -306,6 +311,10 @@ Certifier::Certifier() Certifier::~Certifier() { mysql_mutex_lock(&LOCK_certification_info); initialized = false; + + broadcast_thread->terminate(); + delete broadcast_thread; + clear_certification_info(); delete certification_info_sid_map; @@ -316,7 +325,6 @@ Certifier::~Certifier() { delete group_gtid_extracted; delete group_gtid_sid_map; mysql_mutex_unlock(&LOCK_certification_info); - delete broadcast_thread; mysql_mutex_lock(&LOCK_members); clear_members(); @@ -640,15 +648,6 @@ int Certifier::initialize(ulonglong gtid_assignment_block_size) { return error; } -int Certifier::terminate() { - DBUG_TRACE; - int error = 0; - - if (is_initialized()) error = broadcast_thread->terminate(); - - return error; -} - void Certifier::update_parallel_applier_indexes( bool update_parallel_applier_last_committed_global, bool increment_parallel_applier_sequence_number) { diff --git a/plugin/group_replication/src/handlers/certification_handler.cc b/plugin/group_replication/src/handlers/certification_handler.cc index 736627b534ac..02de17c15e04 100644 --- a/plugin/group_replication/src/handlers/certification_handler.cc +++ b/plugin/group_replication/src/handlers/certification_handler.cc @@ -96,8 +96,6 @@ int Certification_handler::handle_action(Pipeline_action *action) { Handler_THD_setup_action *thd_conf_action = (Handler_THD_setup_action *)action; applier_module_thd = thd_conf_action->get_THD_object(); - } else if (action_type == HANDLER_STOP_ACTION) { - error = cert_module->terminate(); } if (error) return error; diff --git a/router/LICENSE.router b/router/LICENSE.router index 829903031977..877365025306 100644 --- a/router/LICENSE.router +++ b/router/LICENSE.router @@ -1,6 +1,6 @@ Licensing Information User Manual -MySQL Router 8.0.41 Community +MySQL Router 8.0.42 Community __________________________________________________________________ Introduction @@ -8,18 +8,18 @@ Introduction This License Information User Manual contains Oracle's product license and other licensing information, including licensing information for third-party software which may be included in this distribution of - MySQL Router 8.0.41 Community. + MySQL Router 8.0.42 Community. - Last updated: November 2024 + Last updated: March 2025 Licensing Information - This release of MySQL Router 8.0.41 Community is brought to you by the + This release of MySQL Router 8.0.42 Community is brought to you by the MySQL team at Oracle. This software is released under version 2 of the GNU General Public License (GPLv2), as set forth below, with the following additional permissions: - This distribution of MySQL Router 8.0.41 Community is designed to work + This distribution of MySQL Router 8.0.42 Community is designed to work with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in the license documentation. Without limiting your rights @@ -28,7 +28,7 @@ Licensing Information separately licensed software that they have either included with the program or referenced in the documentation. - Copyright (c) 2015, 2024, Oracle and/or its affiliates. + Copyright (c) 2015, 2025, Oracle and/or its affiliates. Election of GPLv2 diff --git a/router/cmake/set_rpath.cmake b/router/cmake/set_rpath.cmake index c15c8429e420..fcb9e8728c8c 100644 --- a/router/cmake/set_rpath.cmake +++ b/router/cmake/set_rpath.cmake @@ -76,6 +76,13 @@ IF(LINUX_INSTALL_RPATH_ORIGIN) ENDIF() LIST(REMOVE_DUPLICATES CMAKE_INSTALL_RPATH) +LIST(REMOVE_DUPLICATES ROUTER_INSTALL_RPATH) + +# We want all $ORIGIN/... before any /usr/bin or /usr/lib64 +IF(LINUX) + LIST(SORT CMAKE_INSTALL_RPATH) + LIST(SORT ROUTER_INSTALL_RPATH) +ENDIF() SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) diff --git a/share/messages_to_error_log.txt b/share/messages_to_error_log.txt index 7c5b196286fd..6c66a827361d 100644 --- a/share/messages_to_error_log.txt +++ b/share/messages_to_error_log.txt @@ -5781,8 +5781,8 @@ ER_IB_MSG_81 ER_IB_MSG_82 eng "%s" -ER_IB_MSG_83 - eng "%s" +ER_IB_ERR_PAGE_DIRTY_AT_SHUTDOWN + eng "Page still fixed or dirty at shutdown. %s" ER_IB_MSG_84 eng "%s" @@ -12316,6 +12316,15 @@ ER_CHECK_TABLE_FUNCTIONS ER_CHECK_TABLE_FUNCTIONS_DETAIL eng "%s" +ER_GRP_RPL_CERT_BROADCAST_THREAD_CREATE_FAILED + eng "Failed to create the Group Replication certifier broadcast thread (THD_certifier_broadcast)." + +ER_GRP_RPL_CERT_BROADCAST_THREAD_STARTED + eng "The Group Replication certifier broadcast thread (THD_certifier_broadcast) started." + +ER_GRP_RPL_CERT_BROADCAST_THREAD_STOPPED + eng "The Group Replication certifier broadcast thread (THD_certifier_broadcast) stopped." + # DO NOT add server-to-client messages here; # they go in messages_to_clients.txt # in the same directory as this file. diff --git a/sql/item.h b/sql/item.h index 56eb35b704f6..d96745367ed2 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2737,6 +2737,7 @@ class Item : public Parse_tree_node { Query_block *const m_root; friend class Item; + friend class Item_func_eq; friend class Item_sum; friend class Item_subselect; friend class Item_ref; @@ -3594,6 +3595,15 @@ inline bool WalkItem(Item *item, enum_walk walk, T &&functor) { reinterpret_cast(&functor)); } +/** + Overload for const 'item' and functor taking 'const Item*' argument. +*/ +template +inline bool WalkItem(const Item *item, enum_walk walk, T &&functor) { + auto to_const = [&](const Item *descendant) { return functor(descendant); }; + return WalkItem(const_cast(item), walk, to_const); +} + /** Same as WalkItem, but for Item::compile(). Use as e.g.: diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 29282a576877..57bfa408362b 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2437,6 +2437,22 @@ void Item_in_optimizer::update_used_tables() { } } +bool Item_func_eq::clean_up_after_removal(uchar *arg) { + Cleanup_after_removal_context *const ctx = + pointer_cast(arg); + + if (ctx->is_stopped(this)) return false; + + if (reference_count() > 1) { + (void)decrement_ref_count(); + ctx->stop_at(this); + } + + ctx->get_root()->prune_sj_exprs(this, nullptr); + + return false; +} + longlong Item_func_eq::val_int() { assert(fixed == 1); int value = cmp.compare(); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index dfdeb2f5cb88..3fc397c14c84 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1057,6 +1057,7 @@ class Item_func_eq final : public Item_eq_base { Item *negated_item() override; bool equality_substitution_analyzer(uchar **) override { return true; } Item *equality_substitution_transformer(uchar *arg) override; + bool clean_up_after_removal(uchar *arg) override; bool gc_subst_analyzer(uchar **) override { return true; } float get_filtering_effect(THD *thd, table_map filter_for_table, diff --git a/sql/item_func.cc b/sql/item_func.cc index 4b48b7302e17..1eeb28e4a32a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -354,8 +354,8 @@ bool Item_func::itemize(Parse_context *pc, Item **res) { if (Item_result_field::itemize(pc, res)) return true; const bool no_named_params = !may_have_named_parameters(); for (size_t i = 0; i < arg_count; i++) { - add_accum_properties(args[i]); if (args[i]->itemize(pc, &args[i])) return true; + add_accum_properties(args[i]); if (no_named_params && !args[i]->item_name.is_autogenerated()) { my_error(functype() == FUNC_SP ? ER_WRONG_PARAMETERS_TO_STORED_FCT : ER_WRONG_PARAMETERS_TO_NATIVE_FCT, @@ -5071,7 +5071,7 @@ longlong Item_source_pos_wait::val_int() { return 0; } - mi = channel_map.get_mi(channel_str->ptr()); + mi = channel_map.get_mi(channel_str->c_ptr_safe()); } else { if (channel_map.get_num_instances() > 1) { @@ -8192,6 +8192,8 @@ bool Item_func_sp::val_json(Json_wrapper *result) { bool Item_func_sp::execute() { THD *thd = current_thd; + assert(!thd->lex->is_explain() || thd->lex->is_explain_analyze); + Internal_error_handler_holder view_handler( thd, context->view_error_handler, context->view_error_handler_arg); diff --git a/sql/iterators/composite_iterators.cc b/sql/iterators/composite_iterators.cc index e87542f50a68..23bdc3107980 100644 --- a/sql/iterators/composite_iterators.cc +++ b/sql/iterators/composite_iterators.cc @@ -30,7 +30,7 @@ #include #include -#include "extra/lz4/my_xxhash.h" +#include "extra/xxhash/my_xxhash.h" #include "field_types.h" #include "mem_root_deque.h" #include "my_dbug.h" diff --git a/sql/iterators/hash_join_iterator.cc b/sql/iterators/hash_join_iterator.cc index 74b0c32dd855..c00f90d05827 100644 --- a/sql/iterators/hash_join_iterator.cc +++ b/sql/iterators/hash_join_iterator.cc @@ -32,7 +32,7 @@ #include #include -#include "extra/lz4/my_xxhash.h" +#include "extra/xxhash/my_xxhash.h" #include "field_types.h" #include "my_alloc.h" #include "my_bit.h" diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 010a2869ac5a..8fc560ef1958 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -459,6 +459,7 @@ bool partition_info::can_prune_insert( @param info COPY_INFO used for default values handling @param copy_default_values True if we should copy default values @param used_partitions Bitmap to set + @param tables_locked True if tables are locked @returns Operational status @retval false Success @@ -467,20 +468,41 @@ bool partition_info::can_prune_insert( so caller must check thd->is_error(). */ -bool partition_info::set_used_partition(THD *thd, - const mem_root_deque &fields, - const mem_root_deque &values, - COPY_INFO &info, - bool copy_default_values, - MY_BITMAP *used_partitions) { +bool partition_info::set_used_partition( + THD *thd, const mem_root_deque &fields, + const mem_root_deque &values, COPY_INFO &info, + bool copy_default_values, MY_BITMAP *used_partitions, bool tables_locked) { uint32 part_id; longlong func_value; assert(thd); - /* Only allow checking of constant values */ - for (Item *item : values) { - if (!item->const_item()) return true; + /* + In prepare phase, allow partition pruning from constant values. + In execution phase, allow partition pruning for values that are + const-for-execution. + */ + if (!fields.empty()) { + auto value_it = values.begin(); + for (Item *fld : fields) { + Item *value = *value_it++; + Item_field *field = fld->field_for_view_update(); + if (bitmap_is_set(&full_part_field_set, field->field->field_index())) { + if (!(value->const_item() || + (tables_locked && value->const_for_execution()))) + return true; + } + } + } else { + Field *field = nullptr; + for (Item *value : values) { + field = *table->field++; + if (bitmap_is_set(&full_part_field_set, field->field_index())) { + if (!(value->const_item() || + (tables_locked && value->const_for_execution()))) + return true; + } + } } if (copy_default_values) restore_record(table, s->default_values); diff --git a/sql/partition_info.h b/sql/partition_info.h index ecd67a6dc23e..330533efb1b6 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -511,7 +511,8 @@ class partition_info { void report_part_expr_error(bool use_subpart_expr); bool set_used_partition(THD *thd, const mem_root_deque &fields, const mem_root_deque &values, COPY_INFO &info, - bool copy_default_values, MY_BITMAP *used_partitions); + bool copy_default_values, MY_BITMAP *used_partitions, + bool tables_locked); /** PRUNE_NO - Unable to prune. PRUNE_DEFAULTS - Partitioning field is only set to diff --git a/sql/rpl_write_set_handler.cc b/sql/rpl_write_set_handler.cc index ea7851a0b3e1..612a758cf325 100644 --- a/sql/rpl_write_set_handler.cc +++ b/sql/rpl_write_set_handler.cc @@ -32,7 +32,7 @@ #include #include -#include "extra/lz4/my_xxhash.h" // IWYU pragma: keep +#include "extra/xxhash/my_xxhash.h" // IWYU pragma: keep #include "lex_string.h" #include "m_ctype.h" #include "my_base.h" diff --git a/sql/server_component/table_access_service.cc b/sql/server_component/table_access_service.cc index a2063c1a0092..683cb5d9d293 100644 --- a/sql/server_component/table_access_service.cc +++ b/sql/server_component/table_access_service.cc @@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "sql/sql_class.h" #include "sql/sql_lex.h" #include "sql/table.h" +#include "sql/table_trigger_dispatcher.h" #include "sql/transaction.h" #include "thr_lock.h" @@ -745,6 +746,38 @@ size_t Table_access_impl::add_table(const char *schema_name, return m_current_count++; } +/** + @brief Checks if access to the specified tables is supported + + Check if the table access service supports the requested operation + for the requested set of tables. + This currently includes: + * not writing to a table that has generated columns + * not writing to a table that has triggers + @warning This needs to be called after the tabes are opened. + + @param table_array The list of tables accessed + @retval true operation can continue + @retval false we should stop + */ +static bool is_access_to_tables_supported(Table_ref *table_array) { + for (Table_ref *tables = table_array; tables; tables = tables->next_global) { + if (tables->lock_descriptor().type == TL_WRITE && tables->table) { + TABLE *tb = tables->table; + /* We do not support writing to generated columns yet */ + if (tb->has_gcol()) return false; + /* We do not support writing to tables with triggers */ + if (tb->triggers && + (tb->triggers->has_update_triggers() || + tb->triggers->has_delete_triggers() || + tb->triggers->has_triggers(TRG_EVENT_INSERT, TRG_ACTION_BEFORE) || + tb->triggers->has_triggers(TRG_EVENT_INSERT, TRG_ACTION_AFTER))) + return false; + } + } + return true; +} + int Table_access_impl::begin() { /* Read lock must be acquired during entire open_and_lock_tables function @@ -781,6 +814,11 @@ int Table_access_impl::begin() { assert(!m_in_tx); m_in_tx = true; + + if (!is_access_to_tables_supported(m_table_array)) { + return TA_ERROR_OPEN; + } + return 0; } diff --git a/sql/set_var.cc b/sql/set_var.cc index bc37a5bd76af..bbca5b6c7d08 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1667,6 +1667,19 @@ int set_var::check(THD *thd) { } auto f = [this, thd](const System_variable_tracker &, sys_var *var) -> int { + if (var->is_readonly()) { + if (type != OPT_PERSIST_ONLY) { + my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->name.str, + "read only"); + return -1; + } + if (type == OPT_PERSIST_ONLY && var->is_non_persistent() && + !can_persist_non_persistent_var(thd, var, type)) { + my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->name.str, + "non persistent read only"); + return -1; + } + } if (var->check_update_type(value->result_type())) { my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name.str); return -1; diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index ba285e5aa4a0..1f1ba4404d40 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -182,8 +182,9 @@ void print_fatal_signal(int sig) { "Some pointers may be invalid and cause the dump to abort.\n"); my_safe_printf_stderr("Query (%p): ", thd->query().str); - my_safe_puts_stderr(thd->query().str, - std::min(size_t{1024}, thd->query().length)); + // 1024 * 1024 * 1024 is the limit for max_allowed_packet + my_safe_puts_stderr(thd->query().str, std::min(size_t{1024 * 1024 * 1024}, + thd->query().length)); my_safe_printf_stderr("Connection ID (thread ID): %u\n", thd->thread_id()); my_safe_printf_stderr("Status: %s\n\n", kreason); } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index ac7a2955dbcd..c39daa95ad18 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2535,8 +2535,16 @@ bool sp_head::execute_function(THD *thd, Item **argp, uint argcount, // Resetting THD::where to its default value thd->where = THD::DEFAULT_WHERE; - // Number of arguments has been checked during resolving - assert(argcount == m_root_parsing_ctx->context_var_count()); + /* + Re-validate the argument count to verify the Stored Function definition has + not changed since preparation. + */ + uint params = m_root_parsing_ctx->context_var_count(); + if (argcount != params) { + my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0), "FUNCTION", m_qname.str, params, + argcount); + return true; + } thd->swap_query_arena(call_arena, &backup_arena); @@ -2732,8 +2740,16 @@ bool sp_head::execute_procedure(THD *thd, mem_root_deque *args) { DBUG_TRACE; DBUG_PRINT("info", ("procedure %s", m_name.str)); - // Argument count has been validated in prepare function. - assert((args != nullptr ? args->size() : 0) == params); + /* + Re-validate the argument count to verify the Stored Procedure definition has + not changed since preparation. + */ + uint argcount = args != nullptr ? args->size() : 0; + if (argcount != params) { + my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0), "PROCEDURE", m_qname.str, params, + argcount); + return true; + } if (!parent_sp_runtime_ctx) { // Create a temporary old context. We need it to pass OUT-parameter values. diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 040db3695faa..972c536c147f 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1623,7 +1623,7 @@ bool Table_ref::optimize_derived(THD *thd) { // at execution time (in fact, it will get confused and crash if it has // already been materialized). if (!thd->lex->using_hypergraph_optimizer()) { - if (materializable_is_const() && + if (materializable_is_const(thd) && (create_materialized_table(thd) || materialize_derived(thd))) return true; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index d92eb4e2558c..5edd98a4225d 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -514,6 +514,29 @@ bool Sql_cmd_insert_values::execute_inner(THD *thd) { // Current error state inside and after the insert loop bool has_error = false; + const bool select_insert = insert_many_values.empty(); + + /* Prune after locking if pruning was not completed in prepare phase. */ + if (!select_insert && insert_table->part_info != nullptr && + !insert_table->part_info->is_pruning_completed) { + MY_BITMAP used_partitions; + bool prune_needs_default_values = false; + enum partition_info::enum_can_prune can_prune_partitions = + partition_info::PRUNE_NO; + + if (insert_table->part_info->can_prune_insert( + thd, duplicates, update, update_field_list, insert_field_list, + value_count == 0, &can_prune_partitions, + &prune_needs_default_values, &used_partitions)) + return true; /* purecov: inspected */ + if (can_prune_partitions != partition_info::PRUNE_NO) { + if (prune_partitions(thd, prune_needs_default_values, insert_field_list, + &used_partitions, insert_table, info, + &can_prune_partitions, + /*tables_locked*/ true)) + return true; + } + } { // Statement plan is available within these braces Modification_plan plan( @@ -1412,7 +1435,6 @@ bool Sql_cmd_insert_base::prepare_inner(THD *thd) { } if (!select_insert && insert_table->part_info) { - uint num_partitions = 0; enum partition_info::enum_can_prune can_prune_partitions = partition_info::PRUNE_NO; /* @@ -1440,6 +1462,7 @@ bool Sql_cmd_insert_base::prepare_inner(THD *thd) { return true; /* purecov: inspected */ MY_BITMAP used_partitions; bool prune_needs_default_values = false; + if (insert_table->part_info->can_prune_insert( thd, duplicates, update, update_field_list, insert_field_list, value_count == 0, &can_prune_partitions, @@ -1447,76 +1470,11 @@ bool Sql_cmd_insert_base::prepare_inner(THD *thd) { return true; /* purecov: inspected */ if (can_prune_partitions != partition_info::PRUNE_NO) { - auto its = insert_many_values.begin(); - num_partitions = insert_table->part_info->lock_partitions.n_bits; - uint counter = 1; - /* - Pruning probably possible, all partitions is unmarked for read/lock, - and we must now add them on row by row basis. - - Check the first INSERT value. - - PRUNE_DEFAULTS means the partitioning fields are only set to DEFAULT - values, so we only need to check the first INSERT value, since all the - rest will be in the same partition. - */ - if (insert_table->part_info->set_used_partition( - thd, insert_field_list, /*values=*/*(*its++), info, - prune_needs_default_values, &used_partitions)) { - can_prune_partitions = partition_info::PRUNE_NO; - // set_used_partition may fail. - if (thd->is_error()) return true; - } - - while (its != insert_many_values.end()) { - const mem_root_deque *values = *its++; - counter++; - - /* - We check pruning for each row until we will - use all partitions, Even if the number of rows is much higher than the - number of partitions. - TODO: Cache the calculated part_id and reuse in - ha_partition::write_row() if possible. - */ - if (can_prune_partitions == partition_info::PRUNE_YES) { - if (insert_table->part_info->set_used_partition( - thd, insert_field_list, *values, info, - prune_needs_default_values, &used_partitions)) { - can_prune_partitions = partition_info::PRUNE_NO; - // set_used_partition may fail. - if (thd->is_error()) return true; - } - if (!(counter % num_partitions)) { - /* - Check if we using all partitions in table after adding partition - for current row to the set of used partitions. Do it only from - time to time to avoid overhead from bitmap_is_set_all() call. - */ - if (bitmap_is_set_all(&used_partitions)) - can_prune_partitions = partition_info::PRUNE_NO; - } - } - } - } - - if (can_prune_partitions != partition_info::PRUNE_NO) { - /* - Only lock the partitions we will insert into. - And also only read from those partitions (duplicates etc.). - If explicit partition selection 'INSERT INTO t PARTITION (p1)' is used, - the new set of read/lock partitions is the intersection of read/lock - partitions and used partitions, i.e only the partitions that exists in - both sets will be marked for read/lock. - It is also safe for REPLACE, since all potentially conflicting records - always belong to the same partition as the one which we try to - insert a row. This is because ALL unique/primary keys must - include ALL partitioning columns. - */ - bitmap_intersect(&insert_table->part_info->read_partitions, - &used_partitions); - bitmap_intersect(&insert_table->part_info->lock_partitions, - &used_partitions); + if (prune_partitions(thd, prune_needs_default_values, insert_field_list, + &used_partitions, insert_table, info, + &can_prune_partitions, + /*tables_locked*/ false)) + return true; } } @@ -3358,3 +3316,87 @@ Sql_cmd_insert_select::eligible_secondary_storage_engine() const { return get_eligible_secondary_engine(); } + +/** + Perform partition pruning for INSERT query. +*/ +bool Sql_cmd_insert_base::prune_partitions( + THD *thd, bool prune_needs_default_values, + const mem_root_deque &insert_field_list, MY_BITMAP *used_partitions, + TABLE *const insert_table, COPY_INFO &info, + partition_info::enum_can_prune *can_prune_partitions, bool tables_locked) { + auto its = insert_many_values.begin(); + uint num_partitions = insert_table->part_info->lock_partitions.n_bits; + uint counter = 1; + /* + Pruning probably possible, all partitions are unmarked for read/lock, + and we must now add them on row by row basis. + + Check the first INSERT value. + + PRUNE_DEFAULTS means the partitioning fields are only set to DEFAULT + values, so we only need to check the first INSERT value, since all the + rest will be in the same partition. + */ + if (insert_table->part_info->set_used_partition( + thd, insert_field_list, /*values=*/*(*its++), info, + prune_needs_default_values, used_partitions, tables_locked)) { + *can_prune_partitions = partition_info::PRUNE_NO; + // set_used_partition may fail. + if (thd->is_error()) return true; + } + + while (its != insert_many_values.end()) { + const mem_root_deque *values = *its++; + counter++; + + /* + We check pruning for each row until we will + use all partitions, Even if the number of rows is much higher than the + number of partitions. + TODO: Cache the calculated part_id and reuse in + ha_partition::write_row() if possible. + */ + if (*can_prune_partitions == partition_info::PRUNE_YES) { + if (insert_table->part_info->set_used_partition( + thd, insert_field_list, *values, info, prune_needs_default_values, + used_partitions, tables_locked)) { + *can_prune_partitions = partition_info::PRUNE_NO; + // set_used_partition may fail. + if (thd->is_error()) return true; + } + if (!(counter % num_partitions)) { + /* + Check if we using all partitions in table after adding partition + for current row to the set of used partitions. Do it only from + time to time to avoid overhead from bitmap_is_set_all() call. + */ + if (bitmap_is_set_all(used_partitions)) { + *can_prune_partitions = partition_info::PRUNE_NO; + insert_table->part_info->is_pruning_completed = true; + } + } + } + } + + if (*can_prune_partitions != partition_info::PRUNE_NO) { + /* + Only lock the partitions we will insert into. + And also only read from those partitions (duplicates etc.). + If explicit partition selection 'INSERT INTO t PARTITION (p1)' is used, + the new set of read/lock partitions is the intersection of read/lock + partitions and used partitions, i.e only the partitions that exists in + both sets will be marked for read/lock. + It is also safe for REPLACE, since all potentially conflicting records + always belong to the same partition as the one which we try to + insert a row. This is because ALL unique/primary keys must + include ALL partitioning columns. + */ + bitmap_intersect(&insert_table->part_info->read_partitions, + used_partitions); + bitmap_intersect(&insert_table->part_info->lock_partitions, + used_partitions); + insert_table->part_info->is_pruning_completed = true; + } + return false; +} diff --git a/sql/sql_insert.h b/sql/sql_insert.h index c1518a067951..36129a73431e 100644 --- a/sql/sql_insert.h +++ b/sql/sql_insert.h @@ -226,6 +226,12 @@ class Sql_cmd_insert_base : public Sql_cmd_dml { bool check_privileges(THD *thd) override; bool prepare_inner(THD *thd) override; bool restore_cmd_properties(THD *thd) override; + bool prune_partitions(THD *thd, bool prune_needs_default_values, + const mem_root_deque &insert_field_list, + MY_BITMAP *used_partitions, TABLE *const insert_table, + COPY_INFO &info, + partition_info::enum_can_prune *can_prune_partitions, + bool tables_locked); private: bool resolve_update_expressions(THD *thd); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index b2e39db8ddf8..3b66a2b2a12f 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -726,6 +726,8 @@ class Query_expression { bool prepared; ///< All query blocks in query expression are prepared bool optimized; ///< All query blocks in query expression are optimized bool executed; ///< Query expression has been executed + ///< Explain mode: query expression refers stored function + bool m_has_stored_program{false}; /// Object to which the result for this query expression is sent. /// Not used if we materialize directly into a parent query expression's @@ -770,6 +772,8 @@ class Query_expression { /// multi-level ORDER, i.e. we have a "simple table". bool is_simple() const { return m_query_term->term_type() == QT_QUERY_BLOCK; } + bool has_stored_program() const { return m_has_stored_program; } + /// Values for Query_expression::cleaned enum enum_clean_state { UC_DIRTY, ///< Unit isn't cleaned @@ -1714,6 +1718,8 @@ class Query_block : public Query_term { */ bool accept(Select_lex_visitor *visitor); + void prune_sj_exprs(Item_func_eq *item, mem_root_deque *nest); + /** Cleanup this subtree (this Query_block and all nested Query_blockes and Query_expressions). @@ -2204,7 +2210,7 @@ class Query_block : public Query_term { /// Build semijoin condition for th query block bool build_sj_cond(THD *thd, NESTED_JOIN *nested_join, Query_block *subq_query_block, table_map outer_tables_map, - Item **sj_cond); + Item **sj_cond, bool *simple_const); bool decorrelate_condition(Semijoin_decorrelation &sj_decor, Table_ref *join_nest); @@ -4825,4 +4831,12 @@ bool accept_for_join(mem_root_deque *tables, Table_ref *nest_join(THD *thd, Query_block *select, Table_ref *embedding, mem_root_deque *jlist, size_t table_cnt, const char *legend); + +template +inline bool WalkQueryExpression(Query_expression *query_expr, enum_walk walk, + T &&functor) { + return query_expr->walk(&Item::walk_helper_thunk, walk, + reinterpret_cast(&functor)); +} + #endif /* SQL_LEX_INCLUDED */ diff --git a/sql/sql_optimizer.cc b/sql/sql_optimizer.cc index 7bdfdd37f418..01c6d848d127 100644 --- a/sql/sql_optimizer.cc +++ b/sql/sql_optimizer.cc @@ -5652,12 +5652,16 @@ bool JOIN::extract_const_tables() { 1. are dependent upon other tables, or 2. have no exact statistics, or 3. are full-text searched + 4. a derived table which has a stored function */ + const bool explain_mode = thd->lex->is_explain(); if ((table->s->system || table->file->stats.records <= 1 || all_partitions_pruned_away) && !tab->dependent && // 1 (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) && // 2 - !tl->is_fulltext_searched()) // 3 + !tl->is_fulltext_searched() && // 3 + !(explain_mode && tl->is_view_or_derived() && + tl->has_stored_program())) // 4 mark_const_table(tab, nullptr); break; } @@ -5811,6 +5815,7 @@ bool JOIN::extract_func_dependent_tables() { 6. are not going to be used, typically because they are streamed instead of materialized (see Query_expression::can_materialize_directly_into_result()). + 7. key evaluated in stored program in EXPLAIN mode */ if (eq_part.is_prefix(table->key_info[key].user_defined_key_parts) && !tl->is_fulltext_searched() && // 1 @@ -5818,7 +5823,9 @@ bool JOIN::extract_func_dependent_tables() { !(tl->embedding && tl->embedding->is_sj_or_aj_nest()) && // 3 !(tab->join_cond() && tab->join_cond()->is_expensive()) && // 4 !(table->file->ha_table_flags() & HA_BLOCK_CONST_TABLE) && // 5 - table->is_created()) { // 6 + table->is_created() && // 6 + !(thd->lex->is_explain() && + start_keyuse->val->has_stored_program())) { // 7 if (table->key_info[key].flags & HA_NOSAME) { if (const_ref == eq_part) { // Found everything for ref. ref_changed = true; @@ -6249,7 +6256,7 @@ static ha_rows get_quick_record_count(THD *thd, JOIN_TAB *tab, ha_rows limit, return 0; } DBUG_PRINT("warning", ("Couldn't use record count on const keypart")); - } else if (tl->is_table_function() || tl->materializable_is_const()) { + } else if (tl->is_table_function() || tl->materializable_is_const(thd)) { tl->fetch_number_of_rows(); return tl->table->file->stats.records; } @@ -9005,9 +9012,11 @@ static bool test_if_ref(THD *thd, Item_field *left_item, Item *right_item, (join_tab->type() != JT_REF_OR_NULL)) { Item *ref_item = part_of_refkey(field->table, &join_tab->ref(), field); if (ref_item != nullptr && ref_item->eq(right_item, true)) { - if (ref_lookup_subsumes_comparison(thd, field, right_item, - right_item->const_for_execution(), - redundant)) { + if (ref_lookup_subsumes_comparison( + thd, field, right_item, + right_item->const_for_execution() && + !(thd->lex->is_explain() && right_item->has_stored_program()), + redundant)) { return true; } } @@ -11456,6 +11465,13 @@ bool evaluate_during_optimization(const Item *item, const Query_block *select) { // If the Item does not access any tables, it can always be evaluated. if (item->const_item()) return true; + // Do not evaluate stored procedure in EXPLAIN + if (current_thd->lex->is_explain() && + WalkItem(item, enum_walk::PREFIX, [](const Item *curitem) { + return curitem->has_stored_program(); + })) + return false; + return !item->has_subquery() || (select->active_options() & OPTION_NO_SUBQUERY_DURING_OPTIMIZATION) == 0; } diff --git a/sql/sql_resolver.cc b/sql/sql_resolver.cc index 6c4c9e48e5ca..18a55f86e5d9 100644 --- a/sql/sql_resolver.cc +++ b/sql/sql_resolver.cc @@ -2442,20 +2442,19 @@ void Query_block::clear_sj_expressions(NESTED_JOIN *nested_join) { @param nested_join Join nest @param subq_query_block Query block for the subquery @param outer_tables_map Map of tables from original outer query block - @param[out] sj_cond Semi-join condition to be constructed - + @param[out] sj_cond Semi-join condition to be constructed + Contains non-equalities on input. + @param[out] simple_const true if the returned semi-join condition is + a simple true or false predicate, false otherwise. @return false if success, true if error */ bool Query_block::build_sj_cond(THD *thd, NESTED_JOIN *nested_join, Query_block *subq_query_block, - table_map outer_tables_map, Item **sj_cond) { - if (nested_join->sj_inner_exprs.empty()) { - // Semi-join materialization requires a key, push a constant integer item - Item *const_item = new Item_int(1); - if (const_item == nullptr) return true; - nested_join->sj_inner_exprs.push_back(const_item); - nested_join->sj_outer_exprs.push_back(const_item); - } + table_map outer_tables_map, Item **sj_cond, + bool *simple_const) { + *simple_const = false; + + Item *new_cond = nullptr; auto ii = nested_join->sj_inner_exprs.begin(); auto oi = nested_join->sj_outer_exprs.begin(); @@ -2502,13 +2501,8 @@ bool Query_block::build_sj_cond(THD *thd, NESTED_JOIN *nested_join, Remove the expression from inner/outer expression list if the const condition evaluates to true as Item_cond::fix_fields will remove the condition later. - Do the above if this is not the last expression in the list. - Semijoin processing expects at least one inner/outer expression - in the list if there is a sj_nest present. */ - if (nested_join->sj_inner_exprs.size() != 1) { - should_remove = true; - } + should_remove = true; } else { /* Remove all the expressions in inner/outer expression list if @@ -2520,11 +2514,10 @@ bool Query_block::build_sj_cond(THD *thd, NESTED_JOIN *nested_join, Item *new_item = new Item_func_false(); if (new_item == nullptr) return true; (*sj_cond) = new_item; - break; + *simple_const = true; + return false; } } - (*sj_cond) = and_items(*sj_cond, predicate); - if (*sj_cond == nullptr) return true; /* purecov: inspected */ /* If the selected expression has a reference to our query block, add it as a non-trivially correlated reference (to avoid materialization). @@ -2544,9 +2537,29 @@ bool Query_block::build_sj_cond(THD *thd, NESTED_JOIN *nested_join, ii = nested_join->sj_inner_exprs.erase(ii); oi = nested_join->sj_outer_exprs.erase(oi); } else { + new_cond = and_items(new_cond, predicate); + if (new_cond == nullptr) return true; /* purecov: inspected */ + ++ii, ++oi; } } + /* + Semijoin processing expects at least one inner/outer expression + in the list if there is a sj_nest present. This is required for semi-join + materialization and loose scan. + */ + if (nested_join->sj_inner_exprs.empty()) { + Item *const_item = new Item_int(1); + if (const_item == nullptr) return true; + nested_join->sj_inner_exprs.push_back(const_item); + nested_join->sj_outer_exprs.push_back(const_item); + new_cond = new Item_func_true(); + if (new_cond == nullptr) return true; + *simple_const = true; + } + (*sj_cond) = and_items(*sj_cond, new_cond); + if (*sj_cond == nullptr) return true; /* purecov: inspected */ + return false; } @@ -3302,8 +3315,9 @@ bool Query_block::convert_subquery_to_semijoin( }); // Build semijoin condition using the inner/outer expression list + bool simple_cond; if (build_sj_cond(thd, nested_join, subq_query_block, outer_tables_map, - &sj_cond)) + &sj_cond, &simple_cond)) return true; // Processing requires a non-empty semi-join condition: @@ -3358,8 +3372,10 @@ bool Query_block::convert_subquery_to_semijoin( // TODO fix QT_ DBUG_EXECUTE("where", print_where(thd, sj_cond, "SJ-COND", QT_ORDINARY);); - if (do_aj) { /* Condition remains attached to inner table, as for LEFT JOIN - */ + Item *cond = nullptr; + if (do_aj) { + // Condition remains attached to inner table, as for LEFT JOIN + cond = sj_cond; } else if (emb_tbl_nest) { // Inject semi-join condition into parent's join condition emb_tbl_nest->set_join_cond(and_items(emb_tbl_nest->join_cond(), sj_cond)); @@ -3369,37 +3385,28 @@ bool Query_block::convert_subquery_to_semijoin( emb_tbl_nest->join_cond()->fix_fields(thd, emb_tbl_nest->join_cond_ref())) return true; + cond = emb_tbl_nest->join_cond(); } else { // Inject semi-join condition into parent's WHERE condition m_where_cond = and_items(m_where_cond, sj_cond); if (m_where_cond == nullptr) return true; m_where_cond->apply_is_true(); if (m_where_cond->fix_fields(thd, &m_where_cond)) return true; + cond = m_where_cond; } - Item *cond = emb_tbl_nest ? emb_tbl_nest->join_cond() : m_where_cond; - if (cond && cond->const_item() && - !cond->walk(&Item::is_non_const_over_literals, enum_walk::POSTFIX, - nullptr)) { - bool cond_value = true; - if (simplify_const_condition(thd, &cond, false, &cond_value)) return true; - if (!cond_value) { - /* - Parent's condition is always FALSE. Thus: - (a) the value of the anti/semi-join condition has no influence on the - result - (b) we don't need to set up lookups (for loosescan or materialization) - (c) for a semi-join, the semi-join condition is already lost (it was - in parent's condition, which has been replaced with FALSE); the - outer/inner sj expressions are Items which point into the SJ - condition, so at 2nd execution they won't be fixed => clearing them - prevents a bug. - (d) for an anti-join, the join condition remains in - sj_nest->join_cond() and will possibly be evaluated. (c) doesn't hold, - but (a) and (b) do. - */ - clear_sj_expressions(nested_join); - } + /* + If the current semi-join or anti-join condition is always TRUE or + always FALSE: + (a) there is no need to set up lookups (for loosescan or materialization). + (b) if some predicates were eliminated as part of const value optimization, + their expressions are still in the inner/outer expression list + and must be removed. + (If a "simple condition" was added in build_sj_cond(), this is not necessary + since the expressions were constant values and are safe to keep.) + */ + if (cond != nullptr && cond->const_item() && !simple_cond) { + clear_sj_expressions(nested_join); } if (subq_query_block->ftfunc_list->elements && @@ -5231,6 +5238,43 @@ bool validate_gc_assignment(const mem_root_deque &fields, return false; } +/// Minion of prune_sj_exprs, q.v. +static void prune_sj_exprs_from_nest(Item_func_eq *item, Table_ref *nest) { + auto it1 = nest->nested_join->sj_outer_exprs.begin(); + auto it2 = nest->nested_join->sj_inner_exprs.begin(); + while (it1 != nest->nested_join->sj_outer_exprs.end() && + it2 != nest->nested_join->sj_inner_exprs.end()) { + Item *outer = *it1; + Item *inner = *it2; + if ((outer == item->arguments()[0] && inner == item->arguments()[1]) || + (outer == item->arguments()[1] && inner == item->arguments()[0])) { + nest->nested_join->sj_outer_exprs.erase(it1); + nest->nested_join->sj_inner_exprs.erase(it2); + break; + } + it1++; + it2++; + } +} + +/** + Recursively look for removed item inside any nested joins' + sj_{inner,outer}_exprs. If target for removal is found, remove such entries + because the corresponding equality condition has been eliminated. + + @param item the equality which is being removed. + @param nest the table nest (nullptr means top nest) +*/ +void Query_block::prune_sj_exprs(Item_func_eq *item, + mem_root_deque *nest) { + if (nest == nullptr) nest = &m_table_nest; + for (Table_ref *table : *nest) { + if (table->nested_join == nullptr) continue; + prune_sj_exprs_from_nest(item, table); + prune_sj_exprs(item, &table->nested_join->m_tables); + } +} + /** Delete unused columns from merged tables. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0d38a781d175..c86ff60d7bd0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2334,8 +2334,8 @@ bool init_ref_part(THD *thd, unsigned part_no, Item *val, bool *cond_guard, key_part_info, key_buff, nullable); if (unlikely(!s_key || thd->is_error())) return true; - if (used_tables & ~INNER_TABLE_BIT) { - /* Comparing against a non-constant. */ + if (used_tables & ~INNER_TABLE_BIT || + (thd->lex->is_explain() && val->has_stored_program())) { ref->key_copy[part_no] = s_key; } else { /* diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 8be63366c2b2..7c7e6f7d49ba 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -866,6 +866,18 @@ bool Query_expression::prepare(THD *thd, Query_result *sel_result, for (size_t i = 0; i < types.size(); i++) types[i]->set_nullable(nullable[i]); } + if (thd->lex->is_explain()) { + WalkQueryExpression(this, + enum_walk::SUBQUERY_POSTFIX, // Use SUBQUERY_POSTFIX to + // traverse subqueries + [this](Item *item) { + if (item->has_stored_program()) { + this->m_has_stored_program = true; + return true; // Stop walking + } + return false; // Continue walking + }); + } // Query blocks are prepared, update the state set_prepared(); diff --git a/sql/table.cc b/sql/table.cc index c34f519716ad..35ae4e79f63e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -6498,12 +6498,19 @@ bool Table_ref::is_mergeable() const { return derived->is_mergeable(); } -bool Table_ref::materializable_is_const() const { +bool Table_ref::has_stored_program() const { + assert(derived != nullptr); + return derived->has_stored_program(); +} + +bool Table_ref::materializable_is_const(THD *thd) const { assert(uses_materialization()); const Query_expression *unit = derived_query_expression(); + const bool explain_mode = thd->lex->is_explain(); return unit->query_result()->estimated_rowcount <= 1 && (unit->first_query_block()->active_options() & - OPTION_NO_SUBQUERY_DURING_OPTIMIZATION) == 0; + OPTION_NO_SUBQUERY_DURING_OPTIMIZATION) == 0 && + !(explain_mode && has_stored_program()); } /** diff --git a/sql/table.h b/sql/table.h index cd90d6d82d3f..9e467a8ffb62 100644 --- a/sql/table.h +++ b/sql/table.h @@ -3118,7 +3118,10 @@ class Table_ref { during execution. The hypergraph optimizer does not care about const tables, so such tables are not executed during optimization time when it is active. */ - bool materializable_is_const() const; + bool materializable_is_const(THD *thd) const; + + /// @returns true if this is a derived table containing a stored function. + bool has_stored_program() const; /// Return true if this is a derived table or view that is merged bool is_merged() const { return effective_algorithm == VIEW_ALGORITHM_MERGE; } diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index bcb0af66d632..5b40ce9652b2 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -68,6 +68,8 @@ this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include +#include #include "buf0checksum.h" #include "buf0dump.h" @@ -336,6 +338,65 @@ with small buffer pool size. */ bool srv_buf_pool_debug; #endif /* UNIV_DEBUG */ +namespace { +#ifndef UNIV_HOTBACKUP +const std::unordered_map buf_io_fix_str{ + {BUF_IO_NONE, "BUF_IO_NONE"}, + {BUF_IO_READ, "BUF_IO_READ"}, + {BUF_IO_WRITE, "BUF_IO_WRITE"}, + {BUF_IO_PIN, "BUF_IO_PIN"}, +}; + +const std::unordered_map buf_flush_str{ + {BUF_FLUSH_LRU, "BUF_FLUSH_LRU"}, + {BUF_FLUSH_LIST, "BUF_FLUSH_LIST"}, + {BUF_FLUSH_SINGLE_PAGE, "BUF_FLUSH_SINGLE_PAGE"}, + {BUF_FLUSH_N_TYPES, "BUF_FLUSH_N_TYPES"}}; + +/** Helper iostream operator presenting the io_fix value as human-readable +name of the enum. Used in error messages of Buf_io_fix_latching_rules. +@param[in,out] outs the output stream to which to print +@param[in] io_fix the value to be printed +@return always equals the stream passed as the outs argument +*/ +static std::ostream &operator<<(std::ostream &outs, const buf_io_fix io_fix) { + ut_a(buf_page_t::is_correct_io_fix_value(io_fix)); + return outs << buf_io_fix_str.at(io_fix); +} + +/** Helper ostream operator to print buf_page_state in human-readable name of +the enum. +@param[in,out] outs the output stream +@param[in] state the page state to be printed +@return same output stream passed as input */ +std::ostream &operator<<(std::ostream &outs, const buf_page_state &state) { + const std::string_view state_str = buf_page_state_str.at(state); + if (state_str.length() < 2) { + /* Compression pages states: invalid for buffer block pages */ + if (state == BUF_BLOCK_POOL_WATCH) { + return outs << "POOL_WATCH"; + } else if (state == BUF_BLOCK_ZIP_PAGE) { + return outs << "ZIP_PAGE"; + } else if (state == BUF_BLOCK_ZIP_DIRTY) { + return outs << "ZIP_DIRTY"; + } else { + ut_error; + } + } + return outs << state_str; +} + +/** Helper ostream operator to print buf_flush_t in human-readable name of the +enum. +@param[in,out] outs the output stream +@param[in] flush_type the flush_type to be printed +@return same output stream passed as input */ +std::ostream &operator<<(std::ostream &outs, const buf_flush_t &flush_type) { + return outs << buf_flush_str.at(flush_type); +} +#endif /* !UNIV_HOTBACKUP */ +} // namespace + #if defined UNIV_PFS_MUTEX || defined UNIV_PFS_RWLOCK #ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK @@ -1127,16 +1188,11 @@ buf_block_t *buf_pool_contains_zip(buf_pool_t *buf_pool, const void *data) { #endif /* UNIV_DEBUG */ /** Checks that all file pages in the buffer chunk are in a replaceable state. - @return address of a non-free block, or NULL if all freed */ -static const buf_block_t *buf_chunk_not_freed( - buf_chunk_t *chunk) /*!< in: chunk being checked */ -{ - buf_block_t *block; - ulint i; +@param[in] chunk The chunk to be checked */ +static void buf_assert_all_are_replaceable(buf_chunk_t *chunk) { + buf_block_t *block = chunk->blocks; - block = chunk->blocks; - - for (i = chunk->size; i--; block++) { + for (auto i = chunk->size; i--; block++) { switch (buf_block_get_state(block)) { case BUF_BLOCK_POOL_WATCH: case BUF_BLOCK_ZIP_PAGE: @@ -1154,18 +1210,16 @@ static const buf_block_t *buf_chunk_not_freed( break; case BUF_BLOCK_FILE_PAGE: buf_page_mutex_enter(block); - auto ready = buf_flush_ready_for_replace(&block->page); - buf_page_mutex_exit(block); - - if (!ready) { - return (block); + const auto &bpage = block->page; + if (!buf_flush_ready_for_replace(&bpage) || + DBUG_EVALUATE_IF("simulate_dirty_page_at_shutdown", true, false)) { + ib::fatal(UT_LOCATION_HERE, ER_IB_ERR_PAGE_DIRTY_AT_SHUTDOWN) + << *block; } - + buf_page_mutex_exit(block); break; } } - - return (nullptr); } /** Set buffer pool size variables @@ -5452,23 +5506,8 @@ void buf_page_free_stale_during_write(buf_page_t *bpage, ut_ad(!mutex_own(block_mutex)); ut_ad(!mutex_own(&buf_pool->LRU_list_mutex)); } -#ifdef UNIV_DEBUG -/** Helper iostream operator presenting the io_fix value as human-readable -name of the enum. Used in error messages of Buf_io_fix_latching_rules. -@param[in] outs the output stream to which to print -@param[in] io_fix the value to be printed -@return always equals the stream passed as the outs argument -*/ -static std::ostream &operator<<(std::ostream &outs, const buf_io_fix io_fix) { - ut_a(buf_page_t::is_correct_io_fix_value(io_fix)); - return outs << std::map{ - {BUF_IO_NONE, "BUF_IO_NONE"}, - {BUF_IO_READ, "BUF_IO_READ"}, - {BUF_IO_WRITE, "BUF_IO_WRITE"}, - {BUF_IO_PIN, "BUF_IO_PIN"}, - }[io_fix]; -} +#ifdef UNIV_DEBUG /* Possible io_buf states and transitions between them, with latches required for transition. @see buf_page_t::Latching_rules_helpers::get_owned_latches() for the meaning of @@ -5879,25 +5918,15 @@ bool buf_page_io_complete(buf_page_t *bpage, bool evict) { /** Asserts that all file pages in the buffer are in a replaceable state. @param[in] buf_pool buffer pool instance */ -static void buf_must_be_all_freed_instance(buf_pool_t *buf_pool) { - ulint i; - buf_chunk_t *chunk; - +static void buf_assert_all_are_replaceable(buf_pool_t *buf_pool) { ut_ad(buf_pool); - chunk = buf_pool->chunks; + buf_chunk_t *chunk = buf_pool->chunks; - for (i = buf_pool->n_chunks; i--; chunk++) { + for (auto i = buf_pool->n_chunks; i--; chunk++) { mutex_enter(&buf_pool->LRU_list_mutex); - - const buf_block_t *block = buf_chunk_not_freed(chunk); - + buf_assert_all_are_replaceable(chunk); mutex_exit(&buf_pool->LRU_list_mutex); - - if (block) { - ib::fatal(UT_LOCATION_HERE, ER_IB_MSG_83) - << "Page " << block->page.id << " still fixed or dirty"; - } } } @@ -5941,7 +5970,7 @@ static void buf_pool_invalidate_instance(buf_pool_t *buf_pool) { mutex_exit(&buf_pool->flush_state_mutex); - ut_d(buf_must_be_all_freed_instance(buf_pool)); + ut_d(buf_assert_all_are_replaceable(buf_pool)); while (buf_LRU_scan_and_free_block(buf_pool, true)) { } @@ -6728,14 +6757,9 @@ void buf_refresh_io_stats_all(void) { } } -/** Aborts the current process if there is any page in other state. */ -void buf_must_be_all_freed(void) { - for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t *buf_pool; - - buf_pool = buf_pool_from_array(i); - - buf_must_be_all_freed_instance(buf_pool); +void buf_assert_all_are_replaceable() { + for (size_t i = 0; i < srv_buf_pool_instances; i++) { + buf_assert_all_are_replaceable(buf_pool_from_array(i)); } } @@ -6876,3 +6900,78 @@ uint16_t buf_block_t::get_page_level() const { bool buf_block_t::is_empty() const { return page_rec_is_supremum(page_rec_get_next(page_get_infimum_rec(frame))); } + +#ifndef UNIV_HOTBACKUP +namespace { +/** Print the page's access_time as duration between first access and now, or +0.0 if never accessed +@param[in] access_time the time_point when page was first accessed +@return time elapsed since access_time */ +int64_t time_elapsed(std::chrono::steady_clock::time_point access_time) { + if (access_time == std::chrono::steady_clock::time_point{}) { + return 0; + } + return static_cast( + std::chrono::duration_cast( + std::chrono::steady_clock::now() - access_time) + .count()); +} +} // namespace + +std::ostream &operator<<(std::ostream &outs, const buf_page_t &page) { + /* Print in json format: "key":"value" */ + + ut_ad(mutex_own(buf_page_get_mutex(&page))); + ut_ad(buf_page_in_file(&page)); + + return outs << "{\"page\":{\"id\":\"" << page.id << "\",\"size\":\"" + << page.size << "\",\"page_type\":\"" + << reinterpret_cast(page).get_page_type_str() + << "\",\"was_stale\":" << page.was_stale() + << ",\"buf_fix_count\":" << page.buf_fix_count.load() + << ",\"io_fix\":\"" << page.get_io_fix_snapshot() + << "\",\"newest_lsn\":" << page.get_newest_lsn() + << ",\"oldest_lsn\":" << page.get_oldest_lsn() + << ",\"is_dirty\":" << page.is_dirty() << ",\"flush_type\":\"" + << page.flush_type + << "\",\"dblwr_batch_id\":" << page.get_dblwr_batch_id() + << ",\"old\":" << page.old + << ",\"first_accessed\":" << time_elapsed(page.access_time) +#ifdef UNIV_DEBUG + << ",\"file_page_was_freed\":" << page.file_page_was_freed + << ",\"someone_has_io_responsibility\":" + << page.someone_has_io_responsibility() + << ",\"current_thread_has_io_responsibility\":" + << page.current_thread_has_io_responsibility() + << ",\"in_flush_list\":" << page.in_flush_list + << ",\"in_free_list\":" << page.in_free_list + << ",\"in_LRU_list\":" << page.in_LRU_list + << ",\"in_page_hash\":" << page.in_page_hash + << ",\"in_zip_hash\":" << page.in_zip_hash +#endif /* UNIV_DEBUG */ + << "}}"; +} + +std::ostream &operator<<(std::ostream &outs, const buf_block_t &block) { + /* Print in json format: "key":"value" */ + + /* Block state corresponding to buf_page_state_str */ + outs << "{\"block\":{\"state\":\"" << buf_block_get_state(&block) + << "\",\"buf_pool_index\":" << unsigned{block.page.buf_pool_index}; + + if (buf_page_in_file(&block.page)) { + ut_ad(mutex_own(buf_page_get_mutex(&block.page))); + outs << ",\"page\":" << block.page; + } + + return outs << ",\"made_dirty_without_latch\":" + << block.made_dirty_with_no_latch + << ",\"modify_clock\":" << block.modify_clock +#ifdef UNIV_DEBUG + << ",\"in_unzip_LRU_list\":" << block.in_unzip_LRU_list + << ",\"in_withdraw_list\":" << block.in_withdraw_list + << ",\"rw_lock_t\":\"" << block.lock.to_string() << "\"" +#endif /* UNIV_DEBUG */ + << "}}"; +} +#endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 8dfe98b623e4..4402dba8518c 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -678,7 +678,7 @@ void buf_flush_insert_sorted_into_flush_list( buf_flush_list_mutex_exit(buf_pool); } -bool buf_flush_ready_for_replace(buf_page_t *bpage) { +bool buf_flush_ready_for_replace(const buf_page_t *bpage) { ut_d(auto buf_pool = buf_pool_from_bpage(bpage)); ut_ad(mutex_own(&buf_pool->LRU_list_mutex)); ut_ad(mutex_own(buf_page_get_mutex(bpage))); diff --git a/storage/innobase/dict/dict0dd.cc b/storage/innobase/dict/dict0dd.cc index 4959f356a9b1..b87e4963e513 100644 --- a/storage/innobase/dict/dict0dd.cc +++ b/storage/innobase/dict/dict0dd.cc @@ -440,7 +440,6 @@ int dd_table_open_on_dd_obj(THD *thd, dd::cache::Dictionary_client *client, TABLE_SHARE ts; TABLE table_def; - dd::Schema *schema; error = acquire_uncached_table(thd, client, &dd_table, tbl_name, &ts, &table_def); @@ -448,31 +447,39 @@ int dd_table_open_on_dd_obj(THD *thd, dd::cache::Dictionary_client *client, return (error); } - char tmp_name[MAX_FULL_NAME_LEN + 1]; - const char *tab_namep; - if (tbl_name) { - tab_namep = tbl_name; - } else { - char tmp_schema[MAX_DATABASE_NAME_LEN + 1]; - char tmp_tablename[MAX_TABLE_NAME_LEN + 1]; + const char *table_name = tbl_name; + char tmp_name[FN_REFLEN + 1]; + if (!tbl_name) { + dd::Schema *schema; error = client->acquire_uncached(dd_table.schema_id(), &schema); if (error != 0) { return error; } - tablename_to_filename(schema->name().c_str(), tmp_schema, - MAX_DATABASE_NAME_LEN + 1); - tablename_to_filename(dd_table.name().c_str(), tmp_tablename, - MAX_TABLE_NAME_LEN + 1); - snprintf(tmp_name, sizeof tmp_name, "%s/%s", tmp_schema, tmp_tablename); - tab_namep = tmp_name; + + bool truncated; + build_table_filename(tmp_name, sizeof(tmp_name) - 1, schema->name().c_str(), + dd_table.name().c_str(), nullptr, 0, &truncated); + + if (truncated) { + ut_d(ut_error); + ut_o(return DB_TOO_LONG_PATH); + } + table_name = tmp_name; + } + + char norm_name[FN_REFLEN]; + if (!normalize_table_name(norm_name, table_name)) { + ut_d(ut_error); + ut_o(return DB_TOO_LONG_PATH); } + if (dd_part == nullptr) { - table = dd_open_table(client, &table_def, tab_namep, &dd_table, thd); + table = dd_open_table(client, &table_def, norm_name, &dd_table, thd); if (table == nullptr) { error = HA_ERR_GENERIC; } } else { - table = dd_open_table(client, &table_def, tab_namep, dd_part, thd); + table = dd_open_table(client, &table_def, norm_name, dd_part, thd); } release_uncached_table(&ts, &table_def); return error; diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 33860746a0dc..42f8a81a8c3f 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -10572,7 +10572,7 @@ byte *fil_tablespace_redo_extend(byte *ptr, const byte *end, #if defined(UNIV_DEBUG) /* Validate that there are no pages in the buffer pool. */ - buf_must_be_all_freed(); + buf_assert_all_are_replaceable(); #endif /* UNIV_DEBUG */ /* Adjust the actual allocation size to take care of the allocation @@ -11056,7 +11056,6 @@ static bool fil_op_replay_rename(const page_id_t &page_id, } space_id_t Fil_system::get_tablespace_id(const std::string &filename) { - constexpr size_t read_size = UNIV_SECTOR_SIZE; pfs_os_file_t file; bool success; @@ -11089,19 +11088,23 @@ space_id_t Fil_system::get_tablespace_id(const std::string &filename) { space_id_t space_id = dict_sys_t::s_invalid_space_id; - auto buf = ut::make_unique_aligned(read_size, read_size); + auto buf = ut::make_unique_aligned(srv_page_size, srv_page_size); IORequest request(IORequest::READ); ulint bytes_read = 0; + /* Disable the warning if we try to read compressed tablespace which has + data less than the read size i.e., srv_page_size */ + request.disable_partial_io_warnings(); - dberr_t err = os_file_read_no_error_handling( - request, filename.c_str(), file, buf.get(), 0, read_size, &bytes_read); + dberr_t err = + os_file_read_no_error_handling(request, filename.c_str(), file, buf.get(), + 0, srv_page_size, &bytes_read); os_file_close(file); DBUG_EXECUTE_IF("invalid_header", bytes_read = 0;); - if (err != DB_SUCCESS || (bytes_read != read_size)) { + if (err != DB_SUCCESS || (bytes_read != srv_page_size)) { /* Reading from the first page failed, falling back to heavy duty method */ return find_space_id_reliably(); } diff --git a/storage/innobase/handler/ha_innopart.cc b/storage/innobase/handler/ha_innopart.cc index 4b660871ffcc..1a712955c77c 100644 --- a/storage/innobase/handler/ha_innopart.cc +++ b/storage/innobase/handler/ha_innopart.cc @@ -3212,6 +3212,12 @@ int ha_innopart::records(ha_rows *num_rows) { return (HA_ERR_NO_SUCH_TABLE); } + m_prebuilt->index_usable = m_prebuilt->index->is_usable(trx); + if (!m_prebuilt->index_usable) { + *num_rows = HA_POS_ERROR; + return HA_ERR_TABLE_DEF_CHANGED; + } + build_template(true); indexes.push_back(m_prebuilt->table->first_index()); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 1457b869d189..48a8b929b8c6 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1031,6 +1031,10 @@ enum_alter_inplace_result ha_innobase::check_if_supported_inplace_alter( ha_alter_info->handler_trivial_ctx = instant_type_to_int(Instant_Type::INSTANT_IMPOSSIBLE); + const bool is_instant_requested = + ha_alter_info->alter_info->requested_algorithm == + Alter_info::ALTER_TABLE_ALGORITHM_INSTANT; + if (!dict_table_is_partition(m_prebuilt->table)) { switch (instant_type) { case Instant_Type::INSTANT_IMPOSSIBLE: @@ -1047,9 +1051,9 @@ enum_alter_inplace_result ha_innobase::check_if_supported_inplace_alter( /* No records: prefer INPLACE to prevent bumping row version */ break; } else if (!((m_prebuilt->table->n_def + - get_num_cols_added(ha_alter_info)) < REC_MAX_N_FIELDS)) { - if (ha_alter_info->alter_info->requested_algorithm == - Alter_info::ALTER_TABLE_ALGORITHM_INSTANT) { + get_num_cols_added(ha_alter_info)) <= + REC_MAX_N_USER_FIELDS + DATA_N_SYS_COLS)) { + if (is_instant_requested) { my_error(ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS, MYF(0), m_prebuilt->table->name.m_name); return HA_ALTER_ERROR; @@ -1059,8 +1063,7 @@ enum_alter_inplace_result ha_innobase::check_if_supported_inplace_alter( } else if (!is_valid_row_version( m_prebuilt->table->current_row_version + 1)) { ut_ad(is_valid_row_version(m_prebuilt->table->current_row_version)); - if (ha_alter_info->alter_info->requested_algorithm == - Alter_info::ALTER_TABLE_ALGORITHM_INSTANT) { + if (is_instant_requested) { my_error(ER_INNODB_MAX_ROW_VERSION, MYF(0), m_prebuilt->table->name.m_name); return HA_ALTER_ERROR; @@ -1071,8 +1074,7 @@ enum_alter_inplace_result ha_innobase::check_if_supported_inplace_alter( } else if (!Instant_ddl_impl::is_instant_add_drop_possible( ha_alter_info, table, altered_table, m_prebuilt->table)) { - if (ha_alter_info->alter_info->requested_algorithm == - Alter_info::ALTER_TABLE_ALGORITHM_INSTANT) { + if (is_instant_requested) { /* Return error if either max possible row size already crosses max permissible row size or may cross it after add. */ my_error(ER_INNODB_INSTANT_ADD_DROP_NOT_SUPPORTED_MAX_SIZE, MYF(0)); @@ -10184,9 +10186,14 @@ enum_alter_inplace_result ha_innopart::check_if_supported_inplace_alter( Instant_Type instant_type = innopart_support_instant( ha_alter_info, m_tot_parts, m_part_share, this->table, altered_table); + ha_alter_info->handler_trivial_ctx = instant_type_to_int(Instant_Type::INSTANT_IMPOSSIBLE); + const bool is_instant_requested = + ha_alter_info->alter_info->requested_algorithm == + Alter_info::ALTER_TABLE_ALGORITHM_INSTANT; + switch (instant_type) { case Instant_Type::INSTANT_IMPOSSIBLE: break; @@ -10195,9 +10202,19 @@ enum_alter_inplace_result ha_innopart::check_if_supported_inplace_alter( Alter_info::ALTER_TABLE_ALGORITHM_INPLACE) { break; } else if (!((m_prebuilt->table->n_def + - get_num_cols_added(ha_alter_info)) < REC_MAX_N_FIELDS)) { - if (ha_alter_info->alter_info->requested_algorithm == - Alter_info::ALTER_TABLE_ALGORITHM_INSTANT) { + get_num_cols_added(ha_alter_info)) <= + REC_MAX_N_USER_FIELDS + DATA_N_SYS_COLS)) { + if (is_instant_requested) { + /* Following is the case when no more columns can be added to the + table becuase it has reached maximum allowed user columns */ + if (altered_table->s->fields > REC_MAX_N_USER_FIELDS) { + ha_alter_info->unsupported_reason = + innobase_get_err_msg(ER_TOO_MANY_FIELDS); + return HA_ALTER_INPLACE_NOT_SUPPORTED; + } + + /* In followin case, columns can't be added with INSTANT but if tried + with INPLACE/COPY, it is possible to add more columns */ my_error(ER_INNODB_INSTANT_ADD_NOT_SUPPORTED_MAX_FIELDS, MYF(0), m_prebuilt->table->name.m_name); return HA_ALTER_ERROR; @@ -10207,8 +10224,8 @@ enum_alter_inplace_result ha_innopart::check_if_supported_inplace_alter( } else if (!is_valid_row_version(m_prebuilt->table->current_row_version + 1)) { ut_ad(is_valid_row_version(m_prebuilt->table->current_row_version)); - if (ha_alter_info->alter_info->requested_algorithm == - Alter_info::ALTER_TABLE_ALGORITHM_INSTANT) { + + if (is_instant_requested) { my_error(ER_INNODB_MAX_ROW_VERSION, MYF(0), m_prebuilt->table->name.m_name); return HA_ALTER_ERROR; @@ -10217,8 +10234,7 @@ enum_alter_inplace_result ha_innopart::check_if_supported_inplace_alter( break; } else if (!Instant_ddl_impl::is_instant_add_drop_possible( ha_alter_info, table, altered_table, m_prebuilt->table)) { - if (ha_alter_info->alter_info->requested_algorithm == - Alter_info::ALTER_TABLE_ALGORITHM_INSTANT) { + if (is_instant_requested) { /* Return error if either max possible row size already crosses max permissible row size or may cross it after add. */ my_error(ER_INNODB_INSTANT_ADD_DROP_NOT_SUPPORTED_MAX_SIZE, MYF(0)); diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 9eb4d3bd4949..c7ed1f11db8f 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -39,6 +39,8 @@ this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include +#include #include "auth_acls.h" #include "btr0btr.h" @@ -118,6 +120,48 @@ constexpr uint64_t i_s_innodb_plugin_version = static_assert(I_S_PAGE_TYPE_LAST < (1 << I_S_PAGE_TYPE_BITS), "i_s_page_type[] is too large"); +namespace { +const char *state_str(buf_page_state state) { + const std::string_view state_str = buf_page_state_str.at(state); + if (state_str.length() == 0) { + return nullptr; + } + return state_str.data(); +} + +const std::unordered_map buf_io_fix_str{ + {BUF_IO_NONE, "IO_NONE"}, + {BUF_IO_READ, "IO_READ"}, + {BUF_IO_WRITE, "IO_WRITE"}, + {BUF_IO_PIN, "IO_PIN"}, +}; + +const char *io_fix_str(buf_io_fix io_fix) { + return buf_io_fix_str.at(io_fix).data(); +} + +const std::unordered_map + buf_lru_page_state_str{/* Compressed page */ + {BUF_BLOCK_ZIP_PAGE, "YES"}, + {BUF_BLOCK_ZIP_DIRTY, "YES"}, + /* Uncompressed page */ + {BUF_BLOCK_FILE_PAGE, "NO"}, + /* We should not see following states */ + {BUF_BLOCK_POOL_WATCH, ""}, + {BUF_BLOCK_READY_FOR_USE, ""}, + {BUF_BLOCK_NOT_USED, ""}, + {BUF_BLOCK_MEMORY, ""}, + {BUF_BLOCK_REMOVE_HASH, ""}}; + +const char *lru_page_state_str(buf_page_state lru_state) { + const std::string_view lru_state_str = buf_lru_page_state_str.at(lru_state); + if (lru_state_str.length() == 0) { + return nullptr; + } + return lru_state_str.data(); +} +} // namespace + /** Name string for File Page Types */ static buf_page_desc_t i_s_page_type[] = { {"ALLOCATED", FIL_PAGE_TYPE_ALLOCATED}, @@ -4261,13 +4305,9 @@ static int i_s_innodb_buffer_page_fill( const buf_page_info_t *page_info; char table_name[MAX_FULL_NAME_LEN + 1]; const char *table_name_end = nullptr; - const char *state_str; - enum buf_page_state state; page_info = info_array + i; - state_str = nullptr; - OK(fields[IDX_BUFFER_POOL_ID]->store(page_info->pool_id, true)); OK(fields[IDX_BUFFER_BLOCK_ID]->store(page_info->block_id, true)); @@ -4343,50 +4383,13 @@ static int i_s_innodb_buffer_page_fill( "BUF_PAGE_STATE_BITS > 3, please ensure that all " "1<(page_info->page_state); + OK(field_store_string( + fields[IDX_BUFFER_PAGE_STATE], + state_str(static_cast(page_info->page_state)))); - switch (state) { - /* First three states are for compression pages and - are not states we would get as we scan pages through - buffer blocks */ - case BUF_BLOCK_POOL_WATCH: - case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: - state_str = nullptr; - break; - case BUF_BLOCK_NOT_USED: - state_str = "NOT_USED"; - break; - case BUF_BLOCK_READY_FOR_USE: - state_str = "READY_FOR_USE"; - break; - case BUF_BLOCK_FILE_PAGE: - state_str = "FILE_PAGE"; - break; - case BUF_BLOCK_MEMORY: - state_str = "MEMORY"; - break; - case BUF_BLOCK_REMOVE_HASH: - state_str = "REMOVE_HASH"; - break; - }; - - OK(field_store_string(fields[IDX_BUFFER_PAGE_STATE], state_str)); - - switch (page_info->io_fix) { - case BUF_IO_NONE: - OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], "IO_NONE")); - break; - case BUF_IO_READ: - OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], "IO_READ")); - break; - case BUF_IO_WRITE: - OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], "IO_WRITE")); - break; - case BUF_IO_PIN: - OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], "IO_PIN")); - break; - } + OK(field_store_string( + fields[IDX_BUFFER_PAGE_IO_FIX], + io_fix_str(static_cast(page_info->io_fix)))); OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD], (page_info->is_old) ? "YES" : "NO")); @@ -4913,10 +4916,6 @@ static int i_s_innodb_buf_page_lru_fill( const buf_page_info_t *page_info; char table_name[MAX_FULL_NAME_LEN + 1]; const char *table_name_end = nullptr; - const char *state_str; - enum buf_page_state state; - - state_str = nullptr; page_info = info_array + i; @@ -4985,44 +4984,13 @@ static int i_s_innodb_buf_page_lru_fill( OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store( page_info->zip_ssize ? 512 << page_info->zip_ssize : 0, true)); - state = static_cast(page_info->page_state); - - switch (state) { - /* Compressed page */ - case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: - state_str = "YES"; - break; - /* Uncompressed page */ - case BUF_BLOCK_FILE_PAGE: - state_str = "NO"; - break; - /* We should not see following states */ - case BUF_BLOCK_POOL_WATCH: - case BUF_BLOCK_READY_FOR_USE: - case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_MEMORY: - case BUF_BLOCK_REMOVE_HASH: - state_str = nullptr; - break; - }; + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_STATE], + lru_page_state_str(static_cast( + page_info->page_state)))); - OK(field_store_string(fields[IDX_BUF_LRU_PAGE_STATE], state_str)); - - switch (page_info->io_fix) { - case BUF_IO_NONE: - OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], "IO_NONE")); - break; - case BUF_IO_READ: - OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], "IO_READ")); - break; - case BUF_IO_WRITE: - OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], "IO_WRITE")); - break; - case BUF_IO_PIN: - OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], "IO_PIN")); - break; - } + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_IO_FIX], + io_fix_str(static_cast(page_info->io_fix)))); OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD], (page_info->is_old) ? "YES" : "NO")); diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 5de6027dc9ad..f2902ac94f77 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -150,6 +150,18 @@ enum buf_page_state : uint8_t { BUF_BLOCK_REMOVE_HASH }; +const std::unordered_map buf_page_state_str{ + /* First three states are for compression pages and are not states we would + get as we scan pages through buffer blocks */ + {BUF_BLOCK_POOL_WATCH, ""}, + {BUF_BLOCK_ZIP_PAGE, ""}, + {BUF_BLOCK_ZIP_DIRTY, ""}, + {BUF_BLOCK_NOT_USED, "NOT_USED"}, + {BUF_BLOCK_READY_FOR_USE, "READY_FOR_USE"}, + {BUF_BLOCK_FILE_PAGE, "FILE_PAGE"}, + {BUF_BLOCK_MEMORY, "MEMORY"}, + {BUF_BLOCK_REMOVE_HASH, "REMOVE_HASH"}}; + /** This structure defines information we will fetch from each buffer pool. It will be used to print table IO stats */ struct buf_pool_info_t { @@ -675,7 +687,7 @@ double buf_get_modified_ratio_pct(void); void buf_refresh_io_stats_all(); /** Assert that all file pages in the buffer are in a replaceable state. */ -void buf_must_be_all_freed(void); +void buf_assert_all_are_replaceable(); /** Computes number of pending I/O read operations for the buffer pool. @return number of pending i/o reads */ @@ -1330,7 +1342,6 @@ class buf_page_t { Read under protection of rules described in @see Buf_io_fix_latching_rules */ copyable_atomic_t io_fix; -#ifdef UNIV_DEBUG public: /** Checks if io_fix has any of the known enum values. @param[in] io_fix the value to test @@ -1347,6 +1358,7 @@ class buf_page_t { return false; } +#ifdef UNIV_DEBUG private: /** Checks if io_fix has any of the known enum values. @return true iff io_fix has any of the known enum values @@ -1656,6 +1668,12 @@ class buf_page_t { bool in_zip_hash; #endif /* UNIV_DEBUG */ + /** Print page metadata in JSON format {"key":"value"}. Asserts that caller + holds page mutex and page if file page + @param[in,out] outs the output stream + @param[in] page the page whose metadata needs to be printed + @return same output stream */ + friend std::ostream &operator<<(std::ostream &outs, const buf_page_t &page); #endif /* !UNIV_HOTBACKUP */ }; @@ -1885,6 +1903,14 @@ struct buf_block_t { return (mach_read_from_2(frame + FIL_PAGE_TYPE)); } +#ifndef UNIV_HOTBACKUP + /** Print control block information in JSON format: {"key":"value"} + @param[in,out] outs the output stream + @param[in] block the control block whose information needs to be printed + @return same output stream */ + friend std::ostream &operator<<(std::ostream &outs, const buf_block_t &block); +#endif /* UNIV_HOTBACKUP */ + uint16_t get_page_level() const; bool is_leaf() const; bool is_root() const; diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h index ebb50ea032d7..7684eabf85be 100644 --- a/storage/innobase/include/buf0flu.h +++ b/storage/innobase/include/buf0flu.h @@ -180,7 +180,7 @@ LRU list and block mutexes. @param[in] bpage buffer control block, must be buf_page_in_file() and in the LRU list @return true if can replace immediately */ -bool buf_flush_ready_for_replace(buf_page_t *bpage); +bool buf_flush_ready_for_replace(const buf_page_t *bpage); #ifdef UNIV_DEBUG struct SYS_VAR; diff --git a/storage/innobase/include/ut0rnd.h b/storage/innobase/include/ut0rnd.h index 21e2df2c30da..839e0c9d5b85 100644 --- a/storage/innobase/include/ut0rnd.h +++ b/storage/innobase/include/ut0rnd.h @@ -183,7 +183,17 @@ static inline uint64_t random_from_interval(uint64_t low, uint64_t high) { } static inline uint64_t random_from_interval_fast(uint64_t low, uint64_t high) { - return random_from_interval_gen(low, high); + /* FIXME: To keep backward compatibility with the previous ut_rnd_interval(), + high value is not to be returned to keep same behavior for performance tuning + parameter. + (Bug#37212019: behavior related to innodb_spin_wait_delay changed in 8.0.30) + This function is not required accurate randomness, no real problems. */ + + if (low == high) { + return (low); + } + + return random_from_interval_gen(low, high - 1); } static inline uint64_t hash_uint64(uint64_t value) { diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 69278dcae923..e05bfd9718fb 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1119,44 +1119,41 @@ void row_upd_index_replace_new_col_vals_index_pos(dtuple_t *entry, bool order_only, mem_heap_t *heap) { DBUG_TRACE; - - ulint i; - ulint n_fields; - const page_size_t &page_size = dict_table_page_size(index->table); - ut_ad(index); ut_ad(!index->table->skip_alter_undo); dtuple_set_info_bits(entry, update->info_bits); - if (order_only) { - n_fields = dict_index_get_n_unique(index); - } else { - n_fields = dict_index_get_n_fields(index); - } + const ulint n_fields = order_only ? dict_index_get_n_unique(index) + : dict_index_get_n_fields(index); + for (ulint field_index = 0; field_index < n_fields; field_index++) { + ulint field_no; + bool is_virtual{false}; - for (i = 0; i < n_fields; i++) { - const dict_field_t *field; - const dict_col_t *col; - const upd_field_t *uf; + const dict_field_t *field = index->get_field(field_index); + const dict_col_t *col = field->col; - field = index->get_field(i); - col = field->col; - if (col->is_virtual()) { - const dict_v_col_t *vcol = reinterpret_cast(col); + if (col->is_instant_dropped()) { + dfield_t *field = dtuple_get_nth_field(entry, field_index); + field->reset(); + continue; + } - uf = upd_get_field_by_field_no(update, vcol->v_pos, true); + if (col->is_virtual()) { + is_virtual = true; + field_no = reinterpret_cast(col)->v_pos; } else { - uf = upd_get_field_by_field_no(update, i, false); + field_no = field_index; } - if (uf) { + if (auto uf = upd_get_field_by_field_no(update, field_no, is_virtual); uf) { upd_field_t *tmp = const_cast(uf); - dfield_t *dfield = dtuple_get_nth_field(entry, i); + dfield_t *dfield = dtuple_get_nth_field(entry, field_index); tmp->ext_in_old = dfield_is_ext(dfield); dfield_copy(&tmp->old_val, dfield); + const auto &page_size = dict_table_page_size(index->table); row_upd_index_replace_new_col_val(index, dfield, field, col, uf, heap, dict_index_is_sdi(index), page_size); } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 5f80ece974ab..1bd6db3e16e6 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2880,7 +2880,7 @@ static lsn_t srv_shutdown_log() { /* No redo log might be generated since now. */ log_background_threads_inactive_validate(); - buf_must_be_all_freed(); + buf_assert_all_are_replaceable(); const lsn_t lsn = log_get_lsn(*log_sys); @@ -2906,7 +2906,7 @@ static lsn_t srv_shutdown_log() { ut_a(err == DB_SUCCESS); } - buf_must_be_all_freed(); + buf_assert_all_are_replaceable(); ut_a(lsn == log_get_lsn(*log_sys)); if (srv_downgrade_logs) { diff --git a/storage/ndb/clusterj/clusterj-test/CMakeLists.txt b/storage/ndb/clusterj/clusterj-test/CMakeLists.txt index 8ccf778bb11c..5fc1f792cbf9 100644 --- a/storage/ndb/clusterj/clusterj-test/CMakeLists.txt +++ b/storage/ndb/clusterj/clusterj-test/CMakeLists.txt @@ -50,6 +50,7 @@ SET(JAVA_SOURCES ${CLUSTERJ_TESTSUITE_PREFIX}/BlobTest.java ${CLUSTERJ_TESTSUITE_PREFIX}/BulkDeleteTest.java ${CLUSTERJ_TESTSUITE_PREFIX}/Bug17200163Test.java + ${CLUSTERJ_TESTSUITE_PREFIX}/ByteBufferPoolTest.java ${CLUSTERJ_TESTSUITE_PREFIX}/CharsetTest.java ${CLUSTERJ_TESTSUITE_PREFIX}/ClearSmokeTest.java ${CLUSTERJ_TESTSUITE_PREFIX}/ConnectionPoolTest.java diff --git a/storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/BlobTest.java b/storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/BlobTest.java index 112cf7529a0a..e35554fb7d44 100644 --- a/storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/BlobTest.java +++ b/storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/BlobTest.java @@ -151,7 +151,7 @@ protected void createBlobInstances(int number) { * @param size the length of the returned byte[] * @return the byte[] filled with the pattern */ - protected byte[] getBlobBytes(int size) { + static byte[] getBlobBytes(int size) { byte[] result = new byte[size]; for (int i = 0; i < size; ++i) { result[i] = (byte)((i % 256) - 128); diff --git a/storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/ByteBufferPoolTest.java b/storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/ByteBufferPoolTest.java new file mode 100644 index 000000000000..3eceaf79cf3c --- /dev/null +++ b/storage/ndb/clusterj/clusterj-test/src/main/java/testsuite/clusterj/ByteBufferPoolTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2024, 2025 Oracle and/or its affiliates. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2.0, + * as published by the Free Software Foundation. + * + * This program is designed to work with certain software (including + * but not limited to OpenSSL) that is licensed under separate terms, + * as designated in a particular file or component or in included license + * documentation. The authors of MySQL hereby grant you an additional + * permission to link the program and your derivative works with the + * separately licensed software that they have either included with + * the program or referenced in the documentation. + * + * 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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +package testsuite.clusterj; + +import com.mysql.clusterj.ClusterJFatalUserException; +import com.mysql.clusterj.ClusterJHelper; +import com.mysql.clusterj.Constants; +import com.mysql.clusterj.Session; +import com.mysql.clusterj.SessionFactory; + +import java.util.Properties; + +import testsuite.clusterj.model.BlobTypes; + +public class ByteBufferPoolTest extends AbstractClusterJTest { + + @Override + protected void localSetUp() { + loadProperties(); + loadSchema(); + closeAllExistingSessionFactories(); + } + + @Override + protected void localTearDown() { + // Get a session for use in AbstractClusterJTest.tearDown() + createSessionFactory(); + createSession(); + addTearDownClasses(BlobTypes.class); + } + + public static void setPoolSizes(Properties p, String spec) { + p.put(Constants.PROPERTY_CLUSTER_BYTE_BUFFER_POOL_SIZES, spec); + } + + public static void printSizes(Properties p, String testName) { + System.out.println(testName + " Sizes: " + + p.get("com.mysql.clusterj.byte.buffer.pool.sizes")); + } + + protected void storeBlob(Session session, int id, int size) { + byte[] content = BlobTest.getBlobBytes(size); + BlobTypes instance = session.newInstance(BlobTypes.class); + instance.setId(id); + instance.setBlobbytes(content); + session.persist(instance); + } + + protected void storeOneBlob(SessionFactory factory, int id, int size) { + Session session = factory.getSession(); + storeBlob(session, id, size); + session.close(); + } + + + public void testDefaultPool() { + Properties properties = props; + printSizes(properties, "testDefaultPool"); + SessionFactory factory = ClusterJHelper.getSessionFactory(properties); + storeOneBlob(factory, 1, 10000); + factory.close(); + } + + public void testSmallPool() { + Properties properties = new Properties(); + properties.putAll(props); + setPoolSizes(properties, "512, 51200"); + printSizes(properties, "testSmallPool"); + assert sessionFactory == null; + SessionFactory factory = ClusterJHelper.getSessionFactory(properties); + System.out.println(" >> Expect WARNING ... requested: 65,000; maximum: 51,200. "); + storeOneBlob(factory, 2, 65000); + factory.close(); + } +} + diff --git a/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/BlobImpl.java b/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/BlobImpl.java index 9a481d96c4ca..627e2027a731 100644 --- a/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/BlobImpl.java +++ b/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/BlobImpl.java @@ -84,7 +84,7 @@ public void release() { this.operation = null; // return buffer to pool if (byteBufferForSetValue != null) { - this.byteBufferPool.returnBuffer(byteBufferForSetValueSize, byteBufferForSetValue); + this.byteBufferPool.returnBuffer(byteBufferForSetValue); } } @@ -119,7 +119,7 @@ public void readData(byte[] array, int length) { } finally { // return buffer to pool if (buffer != null) { - this.byteBufferPool.returnBuffer(length, buffer); + this.byteBufferPool.returnBuffer(buffer); } } } @@ -143,7 +143,7 @@ public void writeData(byte[] array) { } finally { // return buffer to pool if (buffer != null) { - this.byteBufferPool.returnBuffer(length, buffer); + this.byteBufferPool.returnBuffer(buffer); } } } @@ -160,7 +160,7 @@ public void setValue(byte[] array) { buffer.flip(); if (byteBufferForSetValue != null) { // free any existing buffer first (setValue was called again -- not likely) - byteBufferPool.returnBuffer(byteBufferForSetValueSize, byteBufferForSetValue); + byteBufferPool.returnBuffer(byteBufferForSetValue); } // the buffer will be returned to the pool when release is called byteBufferForSetValueSize = array.length; diff --git a/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/DbImpl.java b/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/DbImpl.java index 7d489939af2c..6af51cee09c5 100644 --- a/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/DbImpl.java +++ b/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/DbImpl.java @@ -278,7 +278,7 @@ public NdbTransaction enlist(String tableName, List keyParts) { // return the borrowed buffers for the partition key for (int i = 0; i < keyPartsSize; ++i) { KeyPart keyPart = keyParts.get(i); - bufferManager.returnPartitionKeyPartBuffer(keyPart.length, keyPart.buffer); + bufferManager.returnPartitionKeyPartBuffer(keyPart.buffer); } } } @@ -327,7 +327,7 @@ public class BufferManager { public static final int STRING_STORAGE_BUFFER_INITIAL_SIZE = 500; /** String storage buffer current size */ - private int stringStorageBufferCurrentSize = STRING_BYTE_BUFFER_INITIAL_SIZE; + private int stringStorageBufferCurrentSize = STRING_STORAGE_BUFFER_INITIAL_SIZE; /** Shared buffer for string output operations */ private ByteBuffer stringStorageBuffer; @@ -351,10 +351,10 @@ protected BufferManager(VariableByteBufferPoolImpl pool) { /** Release resources for this buffer manager. */ protected void release() { if (this.resultDataBuffer != null) { - pool.returnBuffer(resultDataBufferCurrentSize, this.resultDataBuffer); + pool.returnBuffer(this.resultDataBuffer); } - pool.returnBuffer(stringStorageBufferCurrentSize, stringStorageBuffer); - pool.returnBuffer(stringByteBufferCurrentSize, stringByteBuffer); + pool.returnBuffer(stringStorageBuffer); + pool.returnBuffer(stringByteBuffer); } /** Guarantee the size of the string storage buffer to be a minimum size. If the current @@ -367,7 +367,7 @@ public void guaranteeStringStorageBufferSize(int sizeNeeded) { if (logger.isDebugEnabled()) logger.debug(local.message("MSG_Reallocated_Byte_Buffer", "string storage", stringStorageBufferCurrentSize, sizeNeeded)); // return the existing shared buffer to the pool - pool.returnBuffer(stringStorageBufferCurrentSize, stringStorageBuffer); + pool.returnBuffer(stringStorageBuffer); stringStorageBuffer = pool.borrowBuffer(sizeNeeded); stringStorageBufferCurrentSize = sizeNeeded; } @@ -415,8 +415,8 @@ public ByteBuffer borrowBuffer(int length) { } /** Return a buffer */ - public void returnBuffer(int length, ByteBuffer buffer) { - pool.returnBuffer(length, buffer); + public void returnBuffer(ByteBuffer buffer) { + pool.returnBuffer(buffer); } /** Guarantee the size of the string byte buffer to be a minimum size. If the current @@ -426,7 +426,7 @@ public void returnBuffer(int length, ByteBuffer buffer) { */ protected void guaranteeStringByteBufferSize(int sizeNeeded) { if (sizeNeeded > stringByteBufferCurrentSize) { - pool.returnBuffer(stringByteBufferCurrentSize, stringByteBuffer); + pool.returnBuffer(stringByteBuffer); stringByteBufferCurrentSize = sizeNeeded; stringByteBuffer = pool.borrowBuffer(sizeNeeded); stringCharBuffer = stringByteBuffer.asCharBuffer(); @@ -458,7 +458,7 @@ public ByteBuffer getResultDataBuffer(int sizeNeeded) { "result data", resultDataBufferCurrentSize, sizeNeeded)); // return the existing result data buffer to the pool if (resultDataBuffer != null) { - pool.returnBuffer(resultDataBufferCurrentSize, resultDataBuffer); + pool.returnBuffer(resultDataBuffer); } resultDataBuffer = pool.borrowBuffer(sizeNeeded); resultDataBufferCurrentSize = sizeNeeded; @@ -474,8 +474,8 @@ public ByteBuffer borrowPartitionKeyPartBuffer(int length) { } /** Return a buffer used for a partition key part */ - public void returnPartitionKeyPartBuffer(int length, ByteBuffer buffer) { - pool.returnBuffer(length, buffer); + public void returnPartitionKeyPartBuffer(ByteBuffer buffer) { + pool.returnBuffer(buffer); } } diff --git a/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/IndexScanOperationImpl.java b/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/IndexScanOperationImpl.java index f2f109421600..93404be1a515 100644 --- a/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/IndexScanOperationImpl.java +++ b/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/IndexScanOperationImpl.java @@ -77,7 +77,7 @@ public void setBoundByte(Column storeColumn, BoundType type, byte value) { Utility.convertValue(buffer, storeColumn, value); int returnCode = ndbIndexScanOperation.setBound(storeColumn.getName(), convertBoundType(type), buffer); - bufferManager.returnBuffer(1, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbIndexScanOperation); } @@ -86,7 +86,7 @@ public void setBoundBytes(Column storeColumn, BoundType type, byte[] value) { Utility.convertValue(buffer, storeColumn, value); int returnCode = ndbIndexScanOperation.setBound(storeColumn.getName(), convertBoundType(type), buffer); - bufferManager.returnBuffer(value.length + 3, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbIndexScanOperation); } @@ -113,7 +113,7 @@ public void setBoundShort(Column storeColumn, BoundType type, short value) { Utility.convertValue(buffer, storeColumn, value); int returnCode = ndbIndexScanOperation.setBound(storeColumn.getName(), convertBoundType(type), buffer); - bufferManager.returnBuffer(2, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbIndexScanOperation); } @@ -122,7 +122,7 @@ public void setBoundInt(Column storeColumn, BoundType type, Integer value) { Utility.convertValue(buffer, storeColumn, value); int returnCode = ndbIndexScanOperation.setBound(storeColumn.getName(), convertBoundType(type), buffer); - bufferManager.returnBuffer(4, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbIndexScanOperation); } @@ -131,7 +131,7 @@ public void setBoundInt(Column storeColumn, BoundType type, int value) { Utility.convertValue(buffer, storeColumn, value); int returnCode = ndbIndexScanOperation.setBound(storeColumn.getName(), convertBoundType(type), buffer); - bufferManager.returnBuffer(4, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbIndexScanOperation); } @@ -140,7 +140,7 @@ public void setBoundLong(Column storeColumn, BoundType type, long value) { Utility.convertValue(buffer, storeColumn, value); int returnCode = ndbIndexScanOperation.setBound(storeColumn.getName(), convertBoundType(type), buffer); - bufferManager.returnBuffer(8, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbIndexScanOperation); } diff --git a/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/PartitionKeyImpl.java b/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/PartitionKeyImpl.java index 006b0348b136..9080fb703574 100644 --- a/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/PartitionKeyImpl.java +++ b/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/PartitionKeyImpl.java @@ -285,7 +285,7 @@ private KeyPartBuilderImpl(int length) { public void addKeyPart(BufferManager bufferManager) {} public void release() { if (this.bufferManager != null && this.buffer != null && this.length != 0) { - this.bufferManager.returnPartitionKeyPartBuffer(this.length, this.buffer); + this.bufferManager.returnPartitionKeyPartBuffer(this.buffer); } } } diff --git a/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/ScanFilterImpl.java b/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/ScanFilterImpl.java index c6d9713c3b40..25be1097bc4d 100644 --- a/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/ScanFilterImpl.java +++ b/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/ScanFilterImpl.java @@ -83,7 +83,7 @@ public void cmpBigInteger(BinaryCondition condition, Column storeColumn, BigInte Utility.convertValue(buffer, storeColumn, value); int returnCode = ndbScanFilter.cmp(convertCondition(condition), storeColumn.getColumnId(), buffer, buffer.limit()); - bufferManager.returnBuffer(100, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbScanFilter); } @@ -98,7 +98,7 @@ public void cmpByte(BinaryCondition condition, Column storeColumn, byte value) { Utility.convertValue(buffer, storeColumn, value); int returnCode = ndbScanFilter.cmp(convertCondition(condition), storeColumn.getColumnId(), buffer, buffer.limit()); - bufferManager.returnBuffer(4, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbScanFilter); } @@ -112,7 +112,7 @@ public void cmpBytes(BinaryCondition condition, Column storeColumn, byte[] value } int returnCode = ndbScanFilter.cmp(convertCondition(condition), storeColumn.getColumnId(), buffer, buffer.limit()); - bufferManager.returnBuffer(columnSpace, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbScanFilter); } @@ -121,7 +121,7 @@ public void cmpDecimal(BinaryCondition condition, Column storeColumn, BigDecimal Utility.convertValue(buffer, storeColumn, value); int returnCode = ndbScanFilter.cmp(convertCondition(condition), storeColumn.getColumnId(), buffer, buffer.limit()); - bufferManager.returnBuffer(100, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbScanFilter); } @@ -130,7 +130,7 @@ public void cmpDouble(BinaryCondition condition, Column storeColumn, double valu Utility.convertValue(buffer, storeColumn, value); int returnCode = ndbScanFilter.cmp(convertCondition(condition), storeColumn.getColumnId(), buffer, buffer.limit()); - bufferManager.returnBuffer(8, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbScanFilter); } @@ -139,7 +139,7 @@ public void cmpFloat(BinaryCondition condition, Column storeColumn, float value) Utility.convertValue(buffer, storeColumn, value); int returnCode = ndbScanFilter.cmp(convertCondition(condition), storeColumn.getColumnId(), buffer, buffer.limit()); - bufferManager.returnBuffer(4, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbScanFilter); } @@ -149,7 +149,7 @@ public void cmpShort(BinaryCondition condition, Column storeColumn, short value) Utility.convertValue(buffer, storeColumn, value); int returnCode = ndbScanFilter.cmp(convertCondition(condition), storeColumn.getColumnId(), buffer, buffer.limit()); - bufferManager.returnBuffer(4, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbScanFilter); } @@ -158,7 +158,7 @@ public void cmpInt(BinaryCondition condition, Column storeColumn, int value) { Utility.convertValue(buffer, storeColumn, value); int returnCode = ndbScanFilter.cmp(convertCondition(condition), storeColumn.getColumnId(), buffer, buffer.limit()); - bufferManager.returnBuffer(4, buffer); + bufferManager.returnBuffer(buffer); handleError(returnCode, ndbScanFilter); } diff --git a/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/VariableByteBufferPoolImpl.java b/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/VariableByteBufferPoolImpl.java index 20bac7f3ef97..c6567fe8f75a 100644 --- a/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/VariableByteBufferPoolImpl.java +++ b/storage/ndb/clusterj/clusterj-tie/src/main/java/com/mysql/clusterj/tie/VariableByteBufferPoolImpl.java @@ -33,6 +33,8 @@ import java.util.TreeMap; import java.util.concurrent.ConcurrentLinkedQueue; +import com.mysql.clusterj.ClusterJFatalInternalException; + import com.mysql.clusterj.core.util.I18NHelper; import com.mysql.clusterj.core.util.Logger; import com.mysql.clusterj.core.util.LoggerFactoryService; @@ -53,7 +55,7 @@ class VariableByteBufferPoolImpl { .getInstance(VariableByteBufferPoolImpl.class); /** The queues of ByteBuffer */ - TreeMap> queues; + final TreeMap> queues; /** The biggest size of any queue */ int biggest = 0; @@ -190,6 +192,7 @@ void initializeGuard(ByteBuffer buffer) { // the buffer has guard.length extra bytes in it, initialized with the guard bytes buffer.position(buffer.capacity() - guard.length); buffer.put(guard); + buffer.position(0); } /** Check the guard bytes which immediately follow the data in the buffer. */ @@ -211,7 +214,7 @@ void checkGuard(ByteBuffer buffer) { public VariableByteBufferPoolImpl(int[] bufferSizes) { queues = new TreeMap>(); for (int bufferSize: bufferSizes) { - queues.put(bufferSize + 1, new ConcurrentLinkedQueue()); + queues.put(bufferSize, new ConcurrentLinkedQueue()); if (biggest < bufferSize) { biggest = bufferSize; } @@ -219,24 +222,22 @@ public VariableByteBufferPoolImpl(int[] bufferSizes) { logger.info(local.message("MSG_ByteBuffer_Pools_Initialized", Arrays.toString(bufferSizes))); } - /** Borrow a buffer from the pool. The pool is the smallest that has buffers of the size needed. - * The buffer size is one less than the key because higherEntry is strictly higher. - * There is no method that returns the entry equal to or higher which is what we really want. - * If no buffer is in the pool, create a new one. + /** Borrow a buffer from the pool. The pool is the smallest that has buffers + * of the size needed. If no buffer is in the pool, create a new one. */ public ByteBuffer borrowBuffer(int sizeNeeded) { - Map.Entry> entry = queues.higherEntry(sizeNeeded); + Map.Entry> entry = queues.ceilingEntry(sizeNeeded); ByteBuffer buffer = null; if (entry == null) { // oh no, we need a bigger size than any buffer pool, so log a message and direct allocate a buffer if (logger.isDetailEnabled()) - logger.detail(local.message("MSG_Cannot_allocate_byte_buffer_from_pool", sizeNeeded, this.biggest)); + logger.warn(local.message("MSG_Cannot_allocate_byte_buffer_from_pool", sizeNeeded, this.biggest)); buffer = ByteBuffer.allocateDirect(sizeNeeded + guard.length); initializeGuard(buffer); return buffer; } ConcurrentLinkedQueuepool = entry.getValue(); - int bufferSize = entry.getKey() - 1; + int bufferSize = entry.getKey(); buffer = pool.poll(); if (buffer == null) { // no buffer currently in the pool, so allocate a new one @@ -249,24 +250,25 @@ public ByteBuffer borrowBuffer(int sizeNeeded) { return buffer; } - /** Return a buffer to the pool. The sizeNeeded is the original size requested, which - * is needed to decide which pool the buffer originally came from. If it did not come from - * a pool (requested size too big for an existing pool) then clean it. + /** Return a buffer to the pool. The appropriate pool is determined using + * buffer.capacity(). If the buffer did not come from a pool (because the + * requested size too big for any pool) then attempt to clean it. An + * exception in the try block would result from a buffer whose size is + * mismatched with all of the pools managed here. */ - public void returnBuffer(int sizeNeeded, ByteBuffer buffer) { - checkGuard(buffer); - Map.Entry> entry = this.queues.higherEntry(sizeNeeded); - // if this buffer came from a pool, return it - if (entry != null) { - int bufferSize = entry.getKey() - 1; - ConcurrentLinkedQueue pool = entry.getValue(); - pool.add(buffer); - } else { + public void returnBuffer(ByteBuffer buffer) { + int key = buffer.capacity() - guard.length; + if(key > biggest) { // mark this buffer as unusable in case we ever see it again buffer.limit(0); // clean (deallocate memory) the buffer clean(buffer); + } else { + try { + queues.get(key).add(buffer); + } catch(NullPointerException npe) { + throw new ClusterJFatalInternalException(npe); + } } } - } diff --git a/storage/ndb/include/kernel/signaldata/LqhTransConf.hpp b/storage/ndb/include/kernel/signaldata/LqhTransConf.hpp index ce1d0141fa33..164373b4bfd7 100644 --- a/storage/ndb/include/kernel/signaldata/LqhTransConf.hpp +++ b/storage/ndb/include/kernel/signaldata/LqhTransConf.hpp @@ -50,6 +50,7 @@ class LqhTransConf { public: static constexpr Uint32 SignalLength = 18; + static constexpr Uint32 MarkerSignalLength = 7; /** * Upgrade diff --git a/storage/ndb/src/common/debugger/signaldata/LqhTrans.cpp b/storage/ndb/src/common/debugger/signaldata/LqhTrans.cpp index 9f4b7014edc9..219ca359f84c 100644 --- a/storage/ndb/src/common/debugger/signaldata/LqhTrans.cpp +++ b/storage/ndb/src/common/debugger/signaldata/LqhTrans.cpp @@ -28,27 +28,26 @@ bool printLQH_TRANSCONF(FILE *output, const Uint32 *theData, Uint32 len, Uint16 /*receiverBlockNo*/) { - if (len < LqhTransConf::SignalLength) { - assert(false); - return false; - } - const LqhTransConf *const sig = (const LqhTransConf *)theData; - fprintf(output, " tcRef: %x\n", sig->tcRef); - fprintf(output, " lqhNodeId: %x\n", sig->lqhNodeId); - fprintf(output, " operationStatus: %x\n", sig->operationStatus); - fprintf(output, " transId1: %x\n", sig->transId1); - fprintf(output, " transId2: %x\n", sig->transId2); - fprintf(output, " apiRef: %x\n", sig->apiRef); - fprintf(output, " apiOpRec: %x\n", sig->apiOpRec); - fprintf(output, " lqhConnectPtr: %x\n", sig->lqhConnectPtr); - fprintf(output, " oldTcOpRec: %x\n", sig->oldTcOpRec); - fprintf(output, " requestInfo: %x\n", sig->requestInfo); - fprintf(output, " gci_hi: %x\n", sig->gci_hi); - fprintf(output, " gci_lo: %x\n", sig->gci_lo); - fprintf(output, " nextNodeId1: %x\n", sig->nextNodeId1); - fprintf(output, " nextNodeId2: %x\n", sig->nextNodeId2); - fprintf(output, " nextNodeId3: %x\n", sig->nextNodeId3); - fprintf(output, " tableId: %x\n", sig->tableId); + if (len >= LqhTransConf::MarkerSignalLength) { + fprintf(output, " tcRef: %x\n", sig->tcRef); + fprintf(output, " lqhNodeId: %x\n", sig->lqhNodeId); + fprintf(output, " operationStatus: %x\n", sig->operationStatus); + fprintf(output, " transId1: %x\n", sig->transId1); + fprintf(output, " transId2: %x\n", sig->transId2); + fprintf(output, " apiRef: %x\n", sig->apiRef); + fprintf(output, " apiOpRec: %x\n", sig->apiOpRec); + } + if (len >= LqhTransConf::SignalLength) { + fprintf(output, " lqhConnectPtr: %x\n", sig->lqhConnectPtr); + fprintf(output, " oldTcOpRec: %x\n", sig->oldTcOpRec); + fprintf(output, " requestInfo: %x\n", sig->requestInfo); + fprintf(output, " gci_hi: %x\n", sig->gci_hi); + fprintf(output, " gci_lo: %x\n", sig->gci_lo); + fprintf(output, " nextNodeId1: %x\n", sig->nextNodeId1); + fprintf(output, " nextNodeId2: %x\n", sig->nextNodeId2); + fprintf(output, " nextNodeId3: %x\n", sig->nextNodeId3); + fprintf(output, " tableId: %x\n", sig->tableId); + } return true; } diff --git a/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp index c071f29a111b..72a478c2996d 100644 --- a/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp +++ b/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp @@ -73,12 +73,6 @@ #define ZREPORT_MEMORY_USAGE 1000 -extern int simulate_error_during_shutdown; - -#ifdef ERROR_INSERT -extern int simulate_error_during_error_reporting; -#endif - // Index pages used by ACC instances Uint32 g_acc_pages_used[1 + MAX_NDBMT_LQH_WORKERS]; @@ -213,17 +207,20 @@ void Cmvmi::execNDB_TAMPER(Signal *signal) { ndbabort(); } +#ifdef ERROR_INSERT #ifndef _WIN32 if (ERROR_INSERTED(9996)) { - simulate_error_during_shutdown = SIGSEGV; + globalEmulatorData.theConfiguration->setShutdownHandlingFault( + Configuration::SHF_UNIX_SIGNAL, SIGSEGV); ndbabort(); } if (ERROR_INSERTED(9995)) { - simulate_error_during_shutdown = SIGSEGV; + globalEmulatorData.theConfiguration->setShutdownHandlingFault( + Configuration::SHF_UNIX_SIGNAL, SIGSEGV); kill(getpid(), SIGABRT); } - +#endif #endif } // execNDB_TAMPER() @@ -1935,11 +1932,16 @@ void Cmvmi::execDUMP_STATE_ORD(Signal *signal) { #ifdef ERROR_INSERT if (arg == DumpStateOrd::CmvmiSetErrorHandlingError) { Uint32 val = 0; + Uint32 extra = 0; if (signal->length() >= 2) { val = signal->theData[1]; + if (signal->length() >= 3) { + extra = signal->theData[2]; + } } - g_eventLogger->info("Cmvmi : Setting ErrorHandlingError to %u", val); - simulate_error_during_error_reporting = val; + g_eventLogger->info("Cmvmi : Setting ShutdownErrorHandling to %u %u", val, + extra); + globalEmulatorData.theConfiguration->setShutdownHandlingFault(val, extra); } #endif diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index abb47a434b9d..694adede4c2f 100644 --- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -24832,19 +24832,16 @@ void Dbdict::createFK_toCreateTrigger(Signal *signal, SchemaOpPtr op_ptr) { g_fkTriggerTmpl[createFKPtr.p->m_sub_create_trigger]; Uint32 tableId = RNIL; - Uint32 indexId = RNIL; Uint32 triggerId = RNIL; Uint32 triggerNo = RNIL; switch (createFKPtr.p->m_sub_create_trigger) { case 0: tableId = fk_ptr.p->m_parentTableId; - indexId = fk_ptr.p->m_parentIndexId; triggerId = fk_ptr.p->m_parentTriggerId; triggerNo = 0; break; case 1: tableId = fk_ptr.p->m_childTableId; - indexId = fk_ptr.p->m_childIndexId; triggerId = fk_ptr.p->m_childTriggerId; triggerNo = 1; break; @@ -29384,7 +29381,6 @@ void Dbdict::slave_writeSchema_conf(Signal *signal, Uint32 trans_key, SchemaTransPtr trans_ptr; ndbrequire(findSchemaTrans(trans_ptr, trans_key)); - bool release = false; if (!trans_ptr.p->m_isMaster) { switch (trans_ptr.p->m_state) { case SchemaTrans::TS_FLUSH_PREPARE: @@ -29414,7 +29410,6 @@ void Dbdict::slave_writeSchema_conf(Signal *signal, Uint32 trans_key, } case SchemaTrans::TS_ENDING: jam(); - release = true; break; default: jamLine(trans_ptr.p->m_state); @@ -31139,12 +31134,8 @@ void Dbdict::check_consistency_index(TableRecordPtr indexPtr) { ndbrequire(ok); check_consistency_table(tablePtr); - bool is_unique_index = false; switch (indexPtr.p->tableType) { case DictTabInfo::UniqueHashIndex: - jam(); - is_unique_index = true; - break; case DictTabInfo::OrderedIndex: jam(); break; diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 0135827e2cf3..afa75439c8db 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -13230,8 +13230,8 @@ void Dblqh::scanMarkers(Signal *signal, Uint32 tcNodeFail, lqhTransConf->transId2 = commitAckMarkerPtr.p->transid2; lqhTransConf->apiRef = commitAckMarkerPtr.p->apiRef; lqhTransConf->apiOpRec = commitAckMarkerPtr.p->apiOprec; - sendSignal(tcNodeFailPtr.p->newTcBlockref, GSN_LQH_TRANSCONF, signal, 7, - JBB); + sendSignal(tcNodeFailPtr.p->newTcBlockref, GSN_LQH_TRANSCONF, signal, + LqhTransConf::MarkerSignalLength, JBB); signal->theData[0] = ZSCAN_MARKERS; signal->theData[1] = tcNodeFailPtr.i; diff --git a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp index 1059f4c40d1c..3eb6a0ffa63b 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp +++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp @@ -1905,14 +1905,12 @@ void Dbtup::releaseFragment(Signal *signal, Uint32 tableId, tabPtr.i = tableId; ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec); Uint32 fragIndex = RNIL; - Uint32 fragId = RNIL; Uint32 i = 0; for (i = 0; i < NDB_ARRAY_SIZE(tabPtr.p->fragid); i++) { jam(); if (tabPtr.p->fragid[i] != RNIL) { jam(); fragIndex = tabPtr.p->fragrec[i]; - fragId = tabPtr.p->fragid[i]; break; } } diff --git a/storage/ndb/src/kernel/error/ErrorReporter.cpp b/storage/ndb/src/kernel/error/ErrorReporter.cpp index 03a3a8273569..4c40878ddbfd 100644 --- a/storage/ndb/src/kernel/error/ErrorReporter.cpp +++ b/storage/ndb/src/kernel/error/ErrorReporter.cpp @@ -61,10 +61,6 @@ static void dumpJam(FILE *jamStream, Uint32 thrdTheEmulatedJamIndex, const char *ndb_basename(const char *path); -#ifdef ERROR_INSERT -int simulate_error_during_error_reporting = 0; -#endif - static const char *formatTimeStampString(char *theDateTimeString, size_t len) { TimeModule DateTime; /* To create "theDateTimeString" */ DateTime.setTimeStamp(); @@ -411,12 +407,33 @@ int WriteMessage(int thrdMessageID, const char *thrdProblemData, fflush(stream); fclose(stream); +#ifdef ERROR_INSERT + if (globalEmulatorData.theConfiguration->getShutdownHandlingFault() == + Configuration::SHF_DELAY_WHILE_WRITING_ERRORLOG) { + Uint32 seconds = + globalEmulatorData.theConfiguration->getShutdownHandlingFaultExtra(); + if (seconds == 0) seconds = 300; + + fprintf(stderr, + "Stall for %us during error reporting before releasing lock\n", + seconds); + NdbSleep_SecSleep(seconds); + fprintf(stderr, "Stall finished\n"); + } +#endif + ErrorReporter::prepare_to_crash(false, (nst == NST_ErrorInsert)); #ifdef ERROR_INSERT - if (simulate_error_during_error_reporting == 1) { - fprintf(stderr, "Stall during error reporting after releasing lock\n"); - NdbSleep_MilliSleep(30000); + if (globalEmulatorData.theConfiguration->getShutdownHandlingFault() == + Configuration::SHF_DELAY_AFTER_WRITING_ERRORLOG) { + Uint32 seconds = + globalEmulatorData.theConfiguration->getShutdownHandlingFaultExtra(); + if (seconds == 0) seconds = 300; + fprintf(stderr, + "Stall for %us during error reporting after releasing lock\n", + seconds); + NdbSleep_SecSleep(seconds); } #endif diff --git a/storage/ndb/src/kernel/ndbd.cpp b/storage/ndb/src/kernel/ndbd.cpp index f07305695231..2a3d744533cc 100644 --- a/storage/ndb/src/kernel/ndbd.cpp +++ b/storage/ndb/src/kernel/ndbd.cpp @@ -879,11 +879,8 @@ void *async_log_func(void *args) { const size_t get_bytes = 512; char buf[get_bytes + 1]; size_t bytes; - int part_bytes = 0, bytes_printed = 0; while (!data->stop) { - part_bytes = 0; - bytes_printed = 0; if ((bytes = logBuf->get(buf, get_bytes))) { fwrite(buf, bytes, 1, f); fflush(f); @@ -1288,8 +1285,6 @@ extern bool opt_core; // instantiated and updated in NdbcntrMain.cpp extern Uint32 g_currentStartPhase; -int simulate_error_during_shutdown = 0; - void NdbShutdown(int error_code, NdbShutdownType type, NdbRestartType restartType) { if (type == NST_ErrorInsert) { @@ -1355,6 +1350,19 @@ void NdbShutdown(int error_code, NdbShutdownType type, * Very serious, don't attempt to free, just die!! */ g_eventLogger->info("Watchdog shutdown completed - %s", exitAbort); +#ifdef ERROR_INSERT + const Uint32 shf = + globalEmulatorData.theConfiguration->getShutdownHandlingFault(); + if (shf != 0) { + if (shf == Configuration::SHF_DELAY_AFTER_WRITING_ERRORLOG || + shf == Configuration::SHF_DELAY_WHILE_WRITING_ERRORLOG) { + g_eventLogger->info( + "ERROR_INSERT : Watchdog choosing restart rather than hard exit " + "for test pass"); + childExit(error_code, NRT_NoStart_Restart, g_currentStartPhase); + } + } +#endif if (opt_core) { childAbort(error_code, -1, g_currentStartPhase); } else { @@ -1362,11 +1370,18 @@ void NdbShutdown(int error_code, NdbShutdownType type, } } +#ifdef ERROR_INSERT #ifndef _WIN32 - if (simulate_error_during_shutdown) { - kill(getpid(), simulate_error_during_shutdown); + if (globalEmulatorData.theConfiguration->getShutdownHandlingFault() == + Configuration::SHF_UNIX_SIGNAL) { + const Uint32 sigId = + globalEmulatorData.theConfiguration->getShutdownHandlingFaultExtra(); + g_eventLogger->info("ERROR_INSERT : Raising unix signal %u to self", + sigId); + kill(getpid(), sigId); while (true) NdbSleep_MilliSleep(10); } +#endif #endif globalEmulatorData.theWatchDog->doStop(); diff --git a/storage/ndb/src/kernel/vm/Configuration.cpp b/storage/ndb/src/kernel/vm/Configuration.cpp index 1f9b76d4839c..ed7a190d4c03 100644 --- a/storage/ndb/src/kernel/vm/Configuration.cpp +++ b/storage/ndb/src/kernel/vm/Configuration.cpp @@ -358,6 +358,9 @@ void Configuration::setupConfiguration() { g_eventLogger->info("Mixology level set to 0x%x", _mixologyLevel); globalTransporterRegistry.setMixologyLevel(_mixologyLevel); } + + _shutdownHandlingFault = 0; + _shutdownHandlingFaultExtra = 0; #endif /** @@ -644,6 +647,19 @@ void Configuration::setRestartOnErrorInsert(int i) { Uint32 Configuration::getMixologyLevel() const { return _mixologyLevel; } void Configuration::setMixologyLevel(Uint32 l) { _mixologyLevel = l; } + +Uint32 Configuration::getShutdownHandlingFault() const { + return _shutdownHandlingFault; +}; +Uint32 Configuration::getShutdownHandlingFaultExtra() const { + return _shutdownHandlingFaultExtra; +}; + +void Configuration ::setShutdownHandlingFault(Uint32 v, Uint32 extra) { + _shutdownHandlingFault = v; + _shutdownHandlingFaultExtra = extra; +}; + #endif const ndb_mgm_configuration_iterator *Configuration::getOwnConfigIterator() diff --git a/storage/ndb/src/kernel/vm/Configuration.hpp b/storage/ndb/src/kernel/vm/Configuration.hpp index c852405ad4e6..309bdcc770c7 100644 --- a/storage/ndb/src/kernel/vm/Configuration.hpp +++ b/storage/ndb/src/kernel/vm/Configuration.hpp @@ -128,6 +128,23 @@ class Configuration { #ifdef ERROR_INSERT Uint32 getMixologyLevel() const; void setMixologyLevel(Uint32); + + enum { + SHF_NONE = 0, + /* Delays during crash handling */ + /* Extra specifies delay in seconds */ + SHF_DELAY_AFTER_WRITING_ERRORLOG = 1, + SHF_DELAY_WHILE_WRITING_ERRORLOG = 2, + + /* Unix signal during crash handling */ + /* Extra specifies signal number */ + SHF_UNIX_SIGNAL = 10 + } ShutdownHandlingFaults; + + Uint32 getShutdownHandlingFault() const; + Uint32 getShutdownHandlingFaultExtra() const; + + void setShutdownHandlingFault(Uint32 v, Uint32 extra = 0); #endif // Cluster configuration @@ -168,6 +185,8 @@ class Configuration { Uint32 _timeBetweenWatchDogCheckInitial; #ifdef ERROR_INSERT Uint32 _mixologyLevel; + Uint32 _shutdownHandlingFault; + Uint32 _shutdownHandlingFaultExtra; #endif Vector threadInfo; diff --git a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp b/storage/ndb/src/kernel/vm/SimulatedBlock.cpp index 5090c17bc3ad..d335c2284f05 100644 --- a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp +++ b/storage/ndb/src/kernel/vm/SimulatedBlock.cpp @@ -4964,6 +4964,8 @@ void ErrorReporter::prepare_to_crash(bool first_phase, (void)first_phase; (void)error_insert_crash; + globalData.incrementWatchDogCounter(22); // Handling node stop + static bool crash_handling_started = false; if (!first_phase) { if (crash_handling_started) { diff --git a/storage/ndb/src/kernel/vm/WatchDog.cpp b/storage/ndb/src/kernel/vm/WatchDog.cpp index 07570d4abc8d..b951aab7ca1c 100644 --- a/storage/ndb/src/kernel/vm/WatchDog.cpp +++ b/storage/ndb/src/kernel/vm/WatchDog.cpp @@ -188,6 +188,9 @@ static const char *get_action(char *buf, Uint32 IPValue) { case 21: action = "Initial value in mt_job_thread_main"; break; + case 22: + action = "Handling node stop"; + break; default: action = NULL; break; @@ -382,7 +385,14 @@ void WatchDog::run() { } } if ((elapsed[i] > 3 * theInterval) || killer) { - if (oldCounterValue[i] == 9) { + if (oldCounterValue[i] == 4 || // Print Job Buffers at crash + oldCounterValue[i] == 22) { // Handling node stop + /* Immediate exit without attempting to trace + * to avoid I/O stalls leaving process hanging + */ + NdbShutdown(NDBD_EXIT_WATCHDOG_TERMINATE, NST_Watchdog); + } + if (oldCounterValue[i] == 9) { // Allocating memory dump_memory_info(); } shutdownSystem(last_stuck_action); diff --git a/storage/ndb/src/kernel/vm/mt.cpp b/storage/ndb/src/kernel/vm/mt.cpp index c4cdf31a5e59..6134d860a89c 100644 --- a/storage/ndb/src/kernel/vm/mt.cpp +++ b/storage/ndb/src/kernel/vm/mt.cpp @@ -9264,6 +9264,13 @@ static bool crash_started = false; void ErrorReporter::prepare_to_crash(bool first_phase, bool error_insert_crash) { + { + thr_data *selfptr = NDB_THREAD_TLS_THREAD; + if (selfptr != NULL) { + selfptr->m_watchdog_counter = 22; + } + } + if (first_phase) { NdbMutex_Lock(&g_thr_repository->stop_for_crash_mutex); if (crash_started && error_insert_crash) { @@ -9493,9 +9500,25 @@ void FastScheduler::dumpSignalMemory(Uint32 thr_no, FILE *out) { signal.header.theReceiversBlockNumber &= NDBMT_BLOCK_MASK; const Uint32 *posptr = reinterpret_cast(s); - signal.m_sectionPtrI[0] = posptr[siglen + 0]; - signal.m_sectionPtrI[1] = posptr[siglen + 1]; - signal.m_sectionPtrI[2] = posptr[siglen + 2]; + signal.m_sectionPtrI[0] = RNIL; + signal.m_sectionPtrI[1] = RNIL; + signal.m_sectionPtrI[2] = RNIL; + switch (s->m_noOfSections) { + case 3: + signal.m_sectionPtrI[2] = posptr[siglen + 2]; + [[fallthrough]]; + case 2: + signal.m_sectionPtrI[1] = posptr[siglen + 1]; + [[fallthrough]]; + case 1: + signal.m_sectionPtrI[0] = posptr[siglen + 0]; + [[fallthrough]]; + case 0: + break; + default: + /* Out of range - ignore */ + break; + }; bool prioa = signalSequence[seq_end].prioa; /* Make sure to display clearly when there is a gap in the dump. */ diff --git a/storage/ndb/test/include/NDBT_Test.hpp b/storage/ndb/test/include/NDBT_Test.hpp index eda5449d37fd..3e62379b00ed 100644 --- a/storage/ndb/test/include/NDBT_Test.hpp +++ b/storage/ndb/test/include/NDBT_Test.hpp @@ -80,8 +80,8 @@ class NDBT_Context { void wait_timeout(int msec); // Wait until the property has been set to a certain value - bool getPropertyWait(const char *, Uint32); - const char *getPropertyWait(const char *, const char *); + bool getPropertyWait(const char *, Uint32 val); // returns false on success + const char *getPropertyWait(const char *, const char *val); // returns value void decProperty(const char *); void incProperty(const char *); @@ -464,20 +464,15 @@ class NDBT_TestSuite { bool m_checkErrorInsert; }; -#define NDBT_TESTSUITE(suitname) \ - class C##suitname : public NDBT_TestSuite { \ - public: \ - C##suitname() : NDBT_TestSuite(#suitname) { \ - NDBT_TestCaseImpl1 *pt; \ - pt = NULL; \ - NDBT_Step *pts; \ - pts = NULL; \ - NDBT_Verifier *ptv; \ - ptv = NULL; \ - NDBT_Initializer *pti; \ - pti = NULL; \ - NDBT_Finalizer *ptf; \ - ptf = NULL; +#define NDBT_TESTSUITE(suitname) \ + class C##suitname : public NDBT_TestSuite { \ + public: \ + C##suitname() : NDBT_TestSuite(#suitname) { \ + NDBT_TestCaseImpl1 *pt = nullptr; \ + [[maybe_unused]] NDBT_Step *pts = nullptr; \ + [[maybe_unused]] NDBT_Verifier *ptv = nullptr; \ + [[maybe_unused]] NDBT_Initializer *pti = nullptr; \ + [[maybe_unused]] NDBT_Finalizer *ptf = nullptr; // The default driver type to use for all tests in suite #define DRIVER(type) setDriverType(type) diff --git a/storage/ndb/test/include/NdbRestarter.hpp b/storage/ndb/test/include/NdbRestarter.hpp index 58698d26a90b..3648e5a1df79 100644 --- a/storage/ndb/test/include/NdbRestarter.hpp +++ b/storage/ndb/test/include/NdbRestarter.hpp @@ -48,13 +48,11 @@ class NdbRestarter { }; int restartOneDbNode(int _nodeId, bool initial = false, bool nostart = false, - bool abort = false, bool force = false, - bool captureError = false); + bool abort = false, bool force = false); - int restartOneDbNode2(int _nodeId, Uint32 flags, bool captureError = false) { + int restartOneDbNode2(int _nodeId, Uint32 flags) { return restartOneDbNode(_nodeId, flags & NRRF_INITIAL, flags & NRRF_NOSTART, - flags & NRRF_ABORT, flags & NRRF_FORCE, - captureError); + flags & NRRF_ABORT, flags & NRRF_FORCE); } int restartAll(bool initial = false, bool nostart = false, bool abort = false, @@ -68,8 +66,7 @@ class NdbRestarter { int restartAll3(bool initial = false, bool nostart = false, bool abort = false, bool force = false); - int restartNodes(int *nodes, int num_nodes, Uint32 flags, - bool captureError = false); + int restartNodes(int *nodes, int num_nodes, Uint32 flags); int startAll(); int startNodes(const int *_nodes, int _num_nodes); diff --git a/storage/ndb/test/ndbapi/ScanInterpretTest.hpp b/storage/ndb/test/ndbapi/ScanInterpretTest.hpp index 4d88cc1e1e0b..6c4ad944eabb 100644 --- a/storage/ndb/test/ndbapi/ScanInterpretTest.hpp +++ b/storage/ndb/test/ndbapi/ScanInterpretTest.hpp @@ -325,7 +325,6 @@ inline int ScanInterpretTest::scanReadVerify(Ndb *pNdb, int records, int eof; int rows = 0; - int rowsNoExist = 0; int rowsExist = 0; int existingRecordsNotFound = 0; int nonExistingRecordsFound = 0; @@ -357,7 +356,6 @@ inline int ScanInterpretTest::scanReadVerify(Ndb *pNdb, int records, return NDBT_FAILED; } } else { - rowsNoExist++; if (addRowToCheckTrans(pNdb, pNoExistTrans) != 0) { pNdb->closeTransaction(pTrans); pNdb->closeTransaction(pExistTrans); diff --git a/storage/ndb/test/ndbapi/bank/Bank.cpp b/storage/ndb/test/ndbapi/bank/Bank.cpp index c13013d20286..71d308bdc55f 100644 --- a/storage/ndb/test/ndbapi/bank/Bank.cpp +++ b/storage/ndb/test/ndbapi/bank/Bank.cpp @@ -693,12 +693,10 @@ int Bank::findLastGL(Uint64 &lastTime) { } int eof; - int rows = 0; eof = pOp->nextResult(); lastTime = 0; while (eof == 0) { - rows++; Uint64 t = timeRec->u_32_value(); if (t > lastTime) lastTime = t; @@ -1253,13 +1251,11 @@ int Bank::performValidateGL(Uint64 glTime) { } int eof; - int rows = 0; int countGlRecords = 0; int result = NDBT_OK; eof = pOp->nextResult(); while (eof == 0) { - rows++; Uint64 t = timeRec->u_64_value(); if (t == glTime) { @@ -1485,12 +1481,10 @@ int Bank::getOldestPurgedGL(const Uint32 accountType, Uint64 &oldest) { } int eof; - int rows = 0; eof = pOp->nextResult(); oldest = 0; while (eof == 0) { - rows++; Uint32 a = accountTypeRec->u_32_value(); Uint32 p = purgedRec->u_32_value(); @@ -1586,13 +1580,11 @@ int Bank::getOldestNotPurgedGL(Uint64 &oldest, Uint32 &accountTypeId, } int eof; - int rows = 0; eof = pOp->nextResult(); oldest = (Uint64)-1; found = false; while (eof == 0) { - rows++; Uint32 p = purgedRec->u_32_value(); if (p == 0) { found = true; @@ -1630,12 +1622,10 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType, * */ - int loop = 0; int found = 0; NdbConnection *pScanTrans = 0; do { int check; - loop++; pScanTrans = m_ndb.startTransaction(); if (pScanTrans == NULL) { const NdbError err = m_ndb.getNdbError(); @@ -1696,12 +1686,10 @@ int Bank::checkNoTransactionsOlderThan(const Uint32 accountType, } int eof; - int rows = 0; found = 0; eof = pOp->nextResult(); while (eof == 0) { - rows++; Uint32 a = accountTypeRec->u_32_value(); Uint32 t = timeRec->u_32_value(); @@ -1947,17 +1935,13 @@ int Bank::findTransactionsToPurge(const Uint64 glTime, const Uint32 accountType, } int eof; - int rows = 0; - int rowsFound = 0; eof = pOp->nextResult(); while (eof == 0) { - rows++; Uint64 t = timeRec->u_64_value(); Uint32 a = accountTypeRec->u_32_value(); if (a == accountType && t == glTime) { - rowsFound++; // One record found check = pOp->deleteCurrentTuple(pTrans); if (check == -1) { diff --git a/storage/ndb/test/ndbapi/bank/BankLoad.cpp b/storage/ndb/test/ndbapi/bank/BankLoad.cpp index 62b623829ca8..9bf211307414 100644 --- a/storage/ndb/test/ndbapi/bank/BankLoad.cpp +++ b/storage/ndb/test/ndbapi/bank/BankLoad.cpp @@ -345,11 +345,9 @@ int Bank::getBalanceForAccountType(const Uint32 accountType, Uint32 &balance) { } int eof; - int rows = 0; eof = pOp->nextResult(); while (eof == 0) { - rows++; Uint32 a = accountTypeRec->u_32_value(); Uint32 b = balanceRec->u_32_value(); diff --git a/storage/ndb/test/ndbapi/bench/ndb_async2.cpp b/storage/ndb/test/ndbapi/bench/ndb_async2.cpp index eed48383d087..62626296d68c 100644 --- a/storage/ndb/test/ndbapi/bench/ndb_async2.cpp +++ b/storage/ndb/test/ndbapi/bench/ndb_async2.cpp @@ -250,8 +250,6 @@ void start_T3(Ndb *pNDB, ThreadData *td, int async) { NdbSleep_MilliSleep(10); } - const NdbOperation *op; - if (td->ndbRecordSharedData) { char *rowPtr = (char *)&td->transactionData; const NdbRecord *record = td->ndbRecordSharedData->subscriberTableNdbRecord; @@ -264,11 +262,10 @@ void start_T3(Ndb *pNDB, ThreadData *td, int async) { SET_MASK(mask, IND_SUBSCRIBER_GROUP); SET_MASK(mask, IND_SUBSCRIBER_SESSIONS); - op = pCON->readTuple(record, rowPtr, record, rowPtr, NdbOperation::LM_Read, - mask); + pCON->readTuple(record, rowPtr, record, rowPtr, NdbOperation::LM_Read, + mask); } else { NdbOperation *MyOp = pCON->getNdbOperation(SUBSCRIBER_TABLE); - op = MyOp; CHECK_NULL(MyOp, "T3-1: getNdbOperation", td, pCON->getNdbError()); MyOp->readTuple(); @@ -305,8 +302,6 @@ void T3_Callback_1(int result, NdbConnection *pCON, void *threadData) { return; } // if - const NdbOperation *op = NULL; - if (td->ndbRecordSharedData) { char *rowPtr = (char *)&td->transactionData; const NdbRecord *record = @@ -316,11 +311,10 @@ void T3_Callback_1(int result, NdbConnection *pCON, void *threadData) { SET_MASK(mask, IND_GROUP_ALLOW_READ); - op = pCON->readTuple(record, rowPtr, record, rowPtr, NdbOperation::LM_Read, - mask); + pCON->readTuple(record, rowPtr, record, rowPtr, NdbOperation::LM_Read, + mask); } else { NdbOperation *MyOp = pCON->getNdbOperation(GROUP_TABLE); - op = MyOp; CHECK_NULL(MyOp, "T3-2: getNdbOperation", td, pCON->getNdbError()); MyOp->readTuple(); diff --git a/storage/ndb/test/ndbapi/flexBench.cpp b/storage/ndb/test/ndbapi/flexBench.cpp index 78bc269ad0ef..d6c1fc1adc4f 100644 --- a/storage/ndb/test/ndbapi/flexBench.cpp +++ b/storage/ndb/test/ndbapi/flexBench.cpp @@ -594,7 +594,6 @@ static void *flexBenchThread(void *pArg) { NdbConnection *pTrans = NULL; const NdbOperation **pOps = NULL; StartType tType; - StartType tSaveType; int *attrValue = NULL; int *attrRefValue = NULL; int check = 0; @@ -792,7 +791,6 @@ static void *flexBenchThread(void *pArg) { } // if tType = pThreadData->threadStart; - tSaveType = tType; pThreadData->threadStart = stIdle; // Start transaction, type of transaction diff --git a/storage/ndb/test/ndbapi/testBackup.cpp b/storage/ndb/test/ndbapi/testBackup.cpp index e37fb2cad3ef..6bf8b678e189 100644 --- a/storage/ndb/test/ndbapi/testBackup.cpp +++ b/storage/ndb/test/ndbapi/testBackup.cpp @@ -915,8 +915,6 @@ int runVerifyUndoData(NDBT_Context *ctx, NDBT_Step *step) { int records = ctx->getNumRecords(); Ndb *pNdb = GETNDB(step); int count = 0; - int num = 5; - if (records - 5 < 0) num = 1; const NdbDictionary::Table *tab = GETNDB(step)->getDictionary()->getTable(ctx->getTab()->getName()); diff --git a/storage/ndb/test/ndbapi/testBasic.cpp b/storage/ndb/test/ndbapi/testBasic.cpp index 5f0f4f43f9f4..ec0395449c5d 100644 --- a/storage/ndb/test/ndbapi/testBasic.cpp +++ b/storage/ndb/test/ndbapi/testBasic.cpp @@ -3162,6 +3162,7 @@ int runRefreshLocking(NDBT_Context *ctx, NDBT_Step *step) { case OP_LAST: abort(); } + if (res) g_err << " (Note: operation failed: " << res << ")" << endl; hugoOps.execute_Commit(ndb); diff --git a/storage/ndb/test/ndbapi/testBlobs.cpp b/storage/ndb/test/ndbapi/testBlobs.cpp index 8b18e165855f..1351a1ce39bc 100644 --- a/storage/ndb/test/ndbapi/testBlobs.cpp +++ b/storage/ndb/test/ndbapi/testBlobs.cpp @@ -4007,21 +4007,17 @@ static int testOpBatchLimits(OpTypes opType, unsigned numOps, int sz, /* Test RTs when executing certain number of ops of given * type, with size given */ - unsigned k = 0; + unsigned k; Uint32 opTimeoutRetries = g_opt.m_timeout_retries; do { CHK((g_con = g_ndb->startTransaction()) != 0); - unsigned r = 0; - for (; k < numOps;) { + for (k = 0; k < numOps; k++) { Tup &tup = g_tups[k]; setBvals(tup, sz); DBG(operationName(opType) << " pk1=" << hex << tup.m_pk1); CHK(setupOperation(g_opr, opType, tup) == 0); - - r++; - k++; } DBG("commit " diff --git a/storage/ndb/test/ndbapi/testDict.cpp b/storage/ndb/test/ndbapi/testDict.cpp index ca07a35a048c..fcc3fcd56212 100644 --- a/storage/ndb/test/ndbapi/testDict.cpp +++ b/storage/ndb/test/ndbapi/testDict.cpp @@ -117,27 +117,37 @@ void getNodeGroups(NdbRestarter &restarter) { char f_tablename[256]; -#define CHECK(b) \ - if (!(b)) { \ - g_err << "ERR: " << step->getName() << " failed on line " << __LINE__ \ - << endl; \ - result = NDBT_FAILED; \ - break; \ +#define DIAGNOSTIC0 \ + g_err << "ERR: " << step->getName() << " failed on line " << __LINE__ << endl + +#define DIAGNOSTIC1(c) \ + g_err << "ERR: " << step->getName() << " failed on line " << __LINE__ \ + << ": " << c << endl + +#define CHECK(b) \ + if (!(b)) { \ + DIAGNOSTIC0; \ + result = NDBT_FAILED; \ + break; \ } -#define CHECK2(b, c) \ - if (!(b)) { \ - g_err << "ERR: " << step->getName() << " failed on line " << __LINE__ \ - << ": " << c << endl; \ - result = NDBT_FAILED; \ - goto end; \ +#define CHECK1(b) \ + if (!(b)) { \ + DIAGNOSTIC0; \ + break; \ } -#define CHECK3(b, c) \ - if (!(b)) { \ - g_err << "ERR: " << step->getName() << " failed on line " << __LINE__ \ - << ": " << c << endl; \ - return NDBT_FAILED; \ +#define CHECK2(b, c) \ + if (!(b)) { \ + DIAGNOSTIC1(c); \ + result = NDBT_FAILED; \ + goto end; \ + } + +#define CHECK3(b, c) \ + if (!(b)) { \ + DIAGNOSTIC1(c); \ + return NDBT_FAILED; \ } int runLoadTable(NDBT_Context *ctx, NDBT_Step *step) { @@ -300,13 +310,9 @@ int runSetDropTableConcurrentLCP(NDBT_Context *ctx, NDBT_Step *step) { int runSetMinTimeBetweenLCP(NDBT_Context *ctx, NDBT_Step *step) { NdbRestarter restarter; - int result; int val = DumpStateOrd::DihMinTimeBetweenLCP; if (restarter.dumpStateAllNodes(&val, 1) != 0) { - do { - CHECK(0); - } while (0); - g_err << "Failed to set LCP to min value" << endl; + DIAGNOSTIC1("Failed to set LCP to min value"); return NDBT_FAILED; } return NDBT_OK; @@ -321,13 +327,9 @@ int runClearErrorInsert(NDBT_Context *ctx, NDBT_Step *step) { int runResetMinTimeBetweenLCP(NDBT_Context *ctx, NDBT_Step *step) { NdbRestarter restarter; - int result; int val2[] = {DumpStateOrd::DihMinTimeBetweenLCP, 0}; if (restarter.dumpStateAllNodes(val2, 2) != 0) { - do { - CHECK(0); - } while (0); - g_err << "Failed to set LCP to min value" << endl; + DIAGNOSTIC1("Failed to set LCP to min value"); return NDBT_FAILED; } return NDBT_OK; @@ -700,11 +702,7 @@ int runCreateAndDropWithData(NDBT_Context *ctx, NDBT_Step *step) { NdbRestarter restarter; int val = DumpStateOrd::DihMinTimeBetweenLCP; if (restarter.dumpStateAllNodes(&val, 1) != 0) { - int result; - do { - CHECK(0); - } while (0); - g_err << "Unable to change timebetween LCP" << endl; + DIAGNOSTIC1("Unable to change timebetween LCP"); return NDBT_FAILED; } @@ -4456,7 +4454,6 @@ static const NdbDictionary::Table *runBug48604createtable(NDBT_Context *ctx, Ndb *pNdb = GETNDB(step); NdbDictionary::Dictionary *pDic = pNdb->getDictionary(); const NdbDictionary::Table *pTab = 0; - int result = NDBT_OK; do { NdbDictionary::Table tab(tabName_Bug48604); { @@ -4471,8 +4468,8 @@ static const NdbDictionary::Table *runBug48604createtable(NDBT_Context *ctx, col.setNullable(false); tab.addColumn(col); } - CHECK(pDic->createTable(tab) == 0); - CHECK((pTab = pDic->getTable(tabName_Bug48604)) != 0); + CHECK1(pDic->createTable(tab) == 0); + CHECK1((pTab = pDic->getTable(tabName_Bug48604)) != 0); } while (0); return pTab; } @@ -4482,7 +4479,6 @@ static const NdbDictionary::Index *runBug48604createindex(NDBT_Context *ctx, Ndb *pNdb = GETNDB(step); NdbDictionary::Dictionary *pDic = pNdb->getDictionary(); const NdbDictionary::Index *pInd = 0; - int result = NDBT_OK; do { NdbDictionary::Index ind(indName_Bug48604); ind.setTable(tabName_Bug48604); @@ -4490,8 +4486,8 @@ static const NdbDictionary::Index *runBug48604createindex(NDBT_Context *ctx, ind.setLogging(false); ind.addColumn("b"); g_info << "index create.." << endl; - CHECK(pDic->createIndex(ind) == 0); - CHECK((pInd = pDic->getIndex(indName_Bug48604, tabName_Bug48604)) != 0); + CHECK1(pDic->createIndex(ind) == 0); + CHECK1((pInd = pDic->getIndex(indName_Bug48604, tabName_Bug48604)) != 0); g_info << "index created" << endl; return pInd; } while (0); @@ -9133,22 +9129,20 @@ int runBug13416603(NDBT_Context *ctx, NDBT_Step *step) { /** * Wait for one of the nodes to have died... */ - int count_started = 0; - int count_not_started = 0; - int count_nok = 0; + int count_not_started; + int count_nok; int down = 0; do { NdbSleep_MilliSleep(100); - count_started = count_not_started = count_nok = 0; + count_not_started = count_nok = 0; for (int i = 0; i < res.getNumDbNodes(); i++) { int n = res.getDbNodeId(i); if (res.getNodeStatus(n) == NDB_MGM_NODE_STATUS_NOT_STARTED) { count_not_started++; down = n; - } else if (res.getNodeStatus(n) == NDB_MGM_NODE_STATUS_STARTED) - count_started++; - else + } else if (res.getNodeStatus(n) != NDB_MGM_NODE_STATUS_STARTED) { count_nok++; + } } } while (count_not_started != 1); @@ -9443,7 +9437,6 @@ int runBug14645319(NDBT_Context *ctx, NDBT_Step *step) { int old_fragments = 0; int old_buckets = 0; - int new_fragments = 0; int new_buckets = 0; do { @@ -9498,7 +9491,6 @@ int runBug14645319(NDBT_Context *ctx, NDBT_Step *step) { result = pDic->getHashMap(new_hm, &new_tab); if (result != 0) break; - new_fragments = new_tab.getFragmentCount(); new_buckets = new_hm.getMapLen(); if (test.expected_buckets > 0 && new_buckets != test.expected_buckets) { diff --git a/storage/ndb/test/ndbapi/testFK.cpp b/storage/ndb/test/ndbapi/testFK.cpp index 5a6f33c9e88e..60b33629d396 100644 --- a/storage/ndb/test/ndbapi/testFK.cpp +++ b/storage/ndb/test/ndbapi/testFK.cpp @@ -1025,7 +1025,7 @@ static int runMixedCascade(NDBT_Context *ctx, NDBT_Step *step) { NdbOperation::OperationOptions::OO_DEFERRED_CONSTAINTS; } - const NdbOperation *pOp = 0, *pOp1 = 0; + const NdbOperation *pOp = nullptr, *pOp1 = nullptr; switch (ndb_rand_r(&seed) % 3) { case 0: pOp = pTrans->writeTuple(pRowRecord, (char *)pRow, pRowRecord, @@ -1034,6 +1034,7 @@ static int runMixedCascade(NDBT_Context *ctx, NDBT_Step *step) { if (result != 0) goto found_error; pOp1 = pTrans->writeTuple(pRowRecord1, (char *)pRow, pRowRecord1, (char *)pRow, 0, &opts, sizeof(opts)); + CHK_RET_FAILED(pOp1 != nullptr); break; case 1: pOp = pTrans->deleteTuple(pRowRecord, (char *)pRow, pRowRecord, @@ -1044,7 +1045,7 @@ static int runMixedCascade(NDBT_Context *ctx, NDBT_Step *step) { (char *)pRow, 0, &opts, sizeof(opts)); break; } - CHK_RET_FAILED(pOp != 0); + CHK_RET_FAILED(pOp != nullptr); result = pTrans->execute(NoCommit, AO_IgnoreError); if (result != 0) { goto found_error; diff --git a/storage/ndb/test/ndbapi/testIndex.cpp b/storage/ndb/test/ndbapi/testIndex.cpp index ccbd2ba4c9c5..2ab02b1a3571 100644 --- a/storage/ndb/test/ndbapi/testIndex.cpp +++ b/storage/ndb/test/ndbapi/testIndex.cpp @@ -3119,6 +3119,7 @@ int runRandomIndexScan(NDBT_Context *ctx, NDBT_Step *step) { << " scans using index " << iName << " and batchsize " << scanBatchSize << endl; + Uint32 rows = 0; for (Uint32 i = 0; i < iterations; i++) { // g_err << "Step " << step << " iteration " << i << endl; @@ -3140,7 +3141,6 @@ int runRandomIndexScan(NDBT_Context *ctx, NDBT_Step *step) { CHECKRET(trans->execute(ExecType::NoCommit) == 0); - Uint32 rows = 0; int rc = 0; while ((rc = pOp->nextResult()) == 0) { rows++; @@ -3152,6 +3152,7 @@ int runRandomIndexScan(NDBT_Context *ctx, NDBT_Step *step) { // g_err << "Found " << rows << " rows" << endl; } + g_err << "Found total " << rows << " rows" << endl; ctx->stopTest(); diff --git a/storage/ndb/test/ndbapi/testMgm.cpp b/storage/ndb/test/ndbapi/testMgm.cpp index 7a72b7f56ac6..b0073da22a0c 100644 --- a/storage/ndb/test/ndbapi/testMgm.cpp +++ b/storage/ndb/test/ndbapi/testMgm.cpp @@ -3209,8 +3209,7 @@ static int runGracefulStopRestartNodesInNG0(NDBT_Context *ctx, ctx->incProperty("ReplicasReady"); ctx->getPropertyWait("ReplicasReady", numReplicas); - int res = - restarter.restartOneDbNode(myNodeId, false, true, false, false, false); + int res = restarter.restartOneDbNode(myNodeId, false, true, false, false); ndbout_c("restart node %u result : %d", myNodeId, res); @@ -3220,6 +3219,10 @@ static int runGracefulStopRestartNodesInNG0(NDBT_Context *ctx, ndbout_c("ndb_mgm_restart failed %s %d", ndb_mgm_get_latest_error_msg(restarter.handle), ndb_mgm_get_latest_error(restarter.handle)); + if (res == -2) { + // Timeout, unknown state of restart + return NDBT_FAILED; + } } return NDBT_OK; diff --git a/storage/ndb/test/ndbapi/testNdbApi.cpp b/storage/ndb/test/ndbapi/testNdbApi.cpp index 24a1f1deb796..9c575dfa36e4 100644 --- a/storage/ndb/test/ndbapi/testNdbApi.cpp +++ b/storage/ndb/test/ndbapi/testNdbApi.cpp @@ -202,7 +202,6 @@ int runTestMaxTransaction(NDBT_Context *ctx, NDBT_Step *step) { } int runTestMaxOperations(NDBT_Context *ctx, NDBT_Step *step) { - Uint32 l = 1; int result = NDBT_OK; int maxOpsLimit = 1; const NdbDictionary::Table *pTab = ctx->getTab(); @@ -318,8 +317,6 @@ int runTestMaxOperations(NDBT_Context *ctx, NDBT_Step *step) { } hugoOps.closeTransaction(pNdb); - - l++; } maxOpsLimit = lower_max_ops; ndbout << "Found max operations limit " << maxOpsLimit << endl; diff --git a/storage/ndb/test/ndbapi/testNodeRestart.cpp b/storage/ndb/test/ndbapi/testNodeRestart.cpp index 04786bb333d9..a87b801630a6 100644 --- a/storage/ndb/test/ndbapi/testNodeRestart.cpp +++ b/storage/ndb/test/ndbapi/testNodeRestart.cpp @@ -1391,8 +1391,7 @@ int runBug16772(NDBT_Context *ctx, NDBT_Step *step) { /** initial */ false, /** nostart */ true, /** abort */ true, - /** force */ false, - /** capture error */ true) == 0) { + /** force */ false) == 0) { g_err << "Restart of node " << deadNodeId << " succeeded when it should " << "have failed"; return NDBT_FAILED; @@ -7659,8 +7658,7 @@ int runArbitrationWithApiNodeFailure(NDBT_Context *ctx, NDBT_Step *step) { * 3. kill master */ if (restarter.restartOneDbNode2( - master, NdbRestarter::NRRF_NOSTART | NdbRestarter::NRRF_ABORT, - true) == 0) { + master, NdbRestarter::NRRF_NOSTART | NdbRestarter::NRRF_ABORT) == 0) { g_err << "ERROR: Old master " << master << " reached not started state " << "before arbitration win" << endl; return NDBT_FAILED; @@ -7856,7 +7854,7 @@ int runTestStartNode(NDBT_Context *ctx, NDBT_Step *step) { ndbout << "Trigger restart of node " << nodeId << " which should fail" << endl; - if (restarter.restartOneDbNode(nodeId, false, true, true, false, true) == 0) { + if (restarter.restartOneDbNode(nodeId, false, true, true, false) == 0) { g_err << "ERROR: Restart of node " << nodeId << " succeeded instead of failing" << endl; return NDBT_FAILED; @@ -7886,7 +7884,7 @@ int runTestStartNode(NDBT_Context *ctx, NDBT_Step *step) { } ndbout << "Trigger restart of node " << nodeId << " which should fail" << endl; - if (restarter.restartOneDbNode(nodeId, false, true, true, false, true) == 0) { + if (restarter.restartOneDbNode(nodeId, false, true, true, false) == 0) { g_err << "ERROR: Restart of node " << nodeId << " succeeded instead of failing" << endl; return NDBT_FAILED; @@ -9048,56 +9046,64 @@ int runWatchdogSlowShutdown(NDBT_Context *ctx, NDBT_Step *step) { * 3 Trigger shutdown * * Expectation - * - Shutdown triggered, but slow + * - Shutdown triggered, but very slow * - Watchdog detects and also attempts shutdown * - No crash results, shutdown completes eventually */ NdbRestarter restarter; - /* 1 Set low watchdog threshold */ - { - const int dumpVals[] = {DumpStateOrd::CmvmiSetWatchdogInterval, 2000}; - CHECK((restarter.dumpStateAllNodes(dumpVals, 2) == NDBT_OK), - "Failed to set watchdog thresh"); - } - - /* 2 Use error insert to get error reporter to be slow - * during shutdown + /* Scenarios + * 1 : Stall during error reporting after releasing lock + * 2 : Stall during error reporting before releasing lock */ - { - const int dumpVals[] = {DumpStateOrd::CmvmiSetErrorHandlingError, 1}; - CHECK((restarter.dumpStateAllNodes(dumpVals, 2) == NDBT_OK), - "Failed to set error handling mode"); - } + for (int scenario = 1; scenario < 3; scenario++) { + g_err << "Scenario " << scenario << endl; + /* 1 Set low watchdog threshold */ + { + const int dumpVals[] = {DumpStateOrd::CmvmiSetWatchdogInterval, 2000}; + CHECK((restarter.dumpStateAllNodes(dumpVals, 2) == NDBT_OK), + "Failed to set watchdog thresh"); + } - /* 3 Trigger shutdown */ - const int nodeId = restarter.getNode(NdbRestarter::NS_RANDOM); - g_err << "Injecting crash in node " << nodeId << endl; - /* First request a 'NOSTART' restart on error insert */ - { - const int dumpVals[] = {DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1}; - CHECK((restarter.dumpStateOneNode(nodeId, dumpVals, 2) == NDBT_OK), - "Failed to request error insert restart"); - } + /* 2 Use error insert to get error reporter to be slow + * during shutdown + */ + { + int dumpVals[] = {DumpStateOrd::CmvmiSetErrorHandlingError, 0}; + dumpVals[1] = scenario; + CHECK((restarter.dumpStateAllNodes(dumpVals, 2) == NDBT_OK), + "Failed to set error handling mode"); + } - /* Next cause an error insert failure */ - CHECK((restarter.insertErrorInNode(nodeId, 9999) == NDBT_OK), - "Failed to request node crash"); + /* 3 Trigger shutdown */ + const int nodeId = restarter.getNode(NdbRestarter::NS_RANDOM); + g_err << "Injecting crash in node " << nodeId << endl; + /* First request a 'NOSTART' restart on error insert */ + { + const int dumpVals[] = {DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1}; + CHECK((restarter.dumpStateOneNode(nodeId, dumpVals, 2) == NDBT_OK), + "Failed to request error insert restart"); + } - /* Expect shutdown to be stalled, and shortly after, watchdog - * to detect this and act - */ - g_err << "Waiting for node " << nodeId << " to stop." << endl; - CHECK((restarter.waitNodesNoStart(&nodeId, 1) == NDBT_OK), - "Timeout waiting for node to stop"); + /* Next cause an error insert failure */ + CHECK((restarter.insertErrorInNode(nodeId, 9999) == NDBT_OK), + "Failed to request node crash"); + + /* Expect shutdown to be stalled, and shortly after, watchdog + * to detect this and act + */ + g_err << "Waiting for node " << nodeId << " to stop." << endl; + CHECK((restarter.waitNodesNoStart(&nodeId, 1) == NDBT_OK), + "Timeout waiting for node to stop"); - g_err << "Waiting for node " << nodeId << " to start." << endl; - CHECK((restarter.startNodes(&nodeId, 1) == NDBT_OK), - "Timeout waiting for node to start"); + g_err << "Waiting for node " << nodeId << " to start." << endl; + CHECK((restarter.startNodes(&nodeId, 1) == NDBT_OK), + "Timeout waiting for node to start"); - CHECK((restarter.waitClusterStarted() == NDBT_OK), - "Timeout waiting for cluster to start"); + CHECK((restarter.waitClusterStarted() == NDBT_OK), + "Timeout waiting for cluster to start"); + } g_err << "Success" << endl; return NDBT_OK; diff --git a/storage/ndb/test/ndbapi/test_event.cpp b/storage/ndb/test/ndbapi/test_event.cpp index 9079c32e23a8..fe9bee6a2b70 100644 --- a/storage/ndb/test/ndbapi/test_event.cpp +++ b/storage/ndb/test/ndbapi/test_event.cpp @@ -2912,7 +2912,6 @@ int errorInjectStalling(NDBT_Context *ctx, NDBT_Step *step) { if (res > 0) { NdbEventOperation *tmp; - int count = 0; while (connected && (tmp = ndb->nextEvent())) { if (tmp != pOp) { printf("Found stray NdbEventOperation\n"); @@ -2925,7 +2924,6 @@ int errorInjectStalling(NDBT_Context *ctx, NDBT_Step *step) { connected = false; break; default: - count++; break; } } @@ -5738,8 +5736,7 @@ int runTardyEventListener(NDBT_Context *ctx, NDBT_Step *step) { char buf[1024]; sprintf(buf, "%s_EVENT", table->getName()); - NdbEventOperation *pOp, *pCreate = 0; - pCreate = pOp = ndb->createEventOperation(buf); + NdbEventOperation *pOp = ndb->createEventOperation(buf); CHK(pOp != NULL, "Event operation creation failed"); CHK(pOp->execute() == 0, "Execute operation execution failed"); @@ -6803,6 +6800,10 @@ int runConsumeEpochs(NDBT_Context *ctx, NDBT_Step *step) { g_err << "NOTE: Unknown ops " << unknown_ops << endl; } + if (node_failures > 0) { + g_err << "NOTE: Node failures " << node_failures << endl; + } + if (round < no_of_err_ins) { g_err << "runConsumeEpochs: Not all " << no_of_err_ins << " error-insert rounds complete. Completed " << round << endl; diff --git a/storage/ndb/test/ndbapi/test_event_merge.cpp b/storage/ndb/test/ndbapi/test_event_merge.cpp index 16368a87efa4..8bab4973cad9 100644 --- a/storage/ndb/test/ndbapi/test_event_merge.cpp +++ b/storage/ndb/test/ndbapi/test_event_merge.cpp @@ -1577,7 +1577,6 @@ static int runops() { // move com chains with same gci under same gci entry static void mergeops(Run &r) { ll2("mergeops: " << r.tabname); - uint mergecnt = 0; Uint32 pk1; for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) { Op *tot_op = r.pk_op[pk1]; @@ -1603,7 +1602,6 @@ static void mergeops(Run &r) { Op *tmp_op = gci_op2; gci_op2 = gci_op2->next_gci; freeop(tmp_op); - mergecnt++; require(r.gciops != 0 && g_gciops != 0); r.gciops--; g_gciops--; diff --git a/storage/ndb/test/src/HugoAsynchTransactions.cpp b/storage/ndb/test/src/HugoAsynchTransactions.cpp index 0b4f066c2367..fbd07b413db3 100644 --- a/storage/ndb/test/src/HugoAsynchTransactions.cpp +++ b/storage/ndb/test/src/HugoAsynchTransactions.cpp @@ -162,7 +162,6 @@ int HugoAsynchTransactions::getNextWorkTask(int *startRecordId, int HugoAsynchTransactions::defineUpdateOpsForTask(TransactionInfo *tInfo) { int check = 0; - int a = 0; NdbTransaction *trans = tInfo->transaction; @@ -183,13 +182,13 @@ int HugoAsynchTransactions::defineUpdateOpsForTask(TransactionInfo *tInfo) { int updateVal = calc.getUpdatesValue(rows[recordId]) + 1; check = pOp->updateTuple(); - if (equalForRow(pOp, recordId) != 0) { + if (check != 0 || equalForRow(pOp, recordId) != 0) { NDB_ERR(trans->getNdbError()); trans->close(); return -1; } // Update the record - for (a = 0; a < tab.getNoOfColumns(); a++) { + for (int a = 0; a < tab.getNoOfColumns(); a++) { if (tab.getColumn(a)->getPrimaryKey() == false) { if (setValueForAttr(pOp, a, recordId, updateVal) != 0) { NDB_ERR(trans->getNdbError()); diff --git a/storage/ndb/test/src/NdbRestarter.cpp b/storage/ndb/test/src/NdbRestarter.cpp index 33bcb2988713..228519d8104e 100644 --- a/storage/ndb/test/src/NdbRestarter.cpp +++ b/storage/ndb/test/src/NdbRestarter.cpp @@ -72,59 +72,25 @@ int NdbRestarter::getDbNodeId(int _i) { } int NdbRestarter::restartOneDbNode(int _nodeId, bool inital, bool nostart, - bool abort, bool force, bool captureError) { + bool abort, bool force) { return restartNodes(&_nodeId, 1, (inital ? NRRF_INITIAL : 0) | (nostart ? NRRF_NOSTART : 0) | - (abort ? NRRF_ABORT : 0) | (force ? NRRF_FORCE : 0), - captureError); + (abort ? NRRF_ABORT : 0) | (force ? NRRF_FORCE : 0)); } -int NdbRestarter::restartNodes(int *nodes, int cnt, Uint32 flags, - bool captureError) { +int NdbRestarter::restartNodes(int *nodes, int cnt, Uint32 flags) { if (!isConnected()) return -1; - int ret = 0; int unused; - if ((ret = ndb_mgm_restart4(handle, cnt, nodes, (flags & NRRF_INITIAL), - (flags & NRRF_NOSTART), (flags & NRRF_ABORT), - (flags & NRRF_FORCE), &unused)) <= 0) { - /** - * ndb_mgm_restart4 returned error, one reason could - * be that the node have not stopped fast enough! - * Check status of the node to see if it's on the - * way down. If that's the case ignore the error. - * - * Bug #11757421 is a special case where the - * error code and description is required in - * the test case. The call to getStatus() - * overwrites the error and is thus avoided - * by adding an option to capture the error. - */ - - if (!captureError && getStatus() != 0) return -1; - - g_info << "ndb_mgm_restart4 returned with error, checking node state" - << endl; - - for (int j = 0; j < cnt; j++) { - int _nodeId = nodes[j]; - for (unsigned i = 0; i < ndbNodes.size(); i++) { - if (ndbNodes[i].node_id == _nodeId) { - g_info << _nodeId << ": status=" << ndbNodes[i].node_status << endl; - /* Node found check state */ - switch (ndbNodes[i].node_status) { - case NDB_MGM_NODE_STATUS_RESTARTING: - case NDB_MGM_NODE_STATUS_SHUTTING_DOWN: - break; - default: - MGMERR(handle); - g_err << "Could not stop node with id = " << _nodeId << endl; - return -1; - } - } - } - } + if (ndb_mgm_restart4(handle, cnt, nodes, (flags & NRRF_INITIAL), + (flags & NRRF_NOSTART), (flags & NRRF_ABORT), + (flags & NRRF_FORCE), &unused) <= 0) { + MGMERR(handle); + int err = ndb_mgm_get_latest_error(handle); + const bool timedout = (err == ETIMEDOUT); + if (timedout) return -2; + return -1; } if ((flags & NRRF_NOSTART) == 0) { diff --git a/storage/ndb/test/src/UtilTransactions.cpp b/storage/ndb/test/src/UtilTransactions.cpp index edb9116c82e5..45b20cdf7d7f 100644 --- a/storage/ndb/test/src/UtilTransactions.cpp +++ b/storage/ndb/test/src/UtilTransactions.cpp @@ -48,7 +48,6 @@ int UtilTransactions::clearTable(Ndb *pNdb, NdbScanOperation::ScanFlag flags, // them one by one int retryAttempt = 0; const int retryMax = 10; - int deletedRows = 0; int check; NdbScanOperation *pOp; NdbError err; @@ -112,7 +111,6 @@ int UtilTransactions::clearTable(Ndb *pNdb, NdbScanOperation::ScanFlag flags, NDB_ERR(err); goto failed; } - deletedRows++; } while ((check = pOp->nextResult(false)) == 0); if (check != -1) { @@ -695,11 +693,8 @@ int UtilTransactions::scanAndCompareUniqueIndex( } int eof; - int rows = 0; while ((eof = pOp->nextResult()) == 0) { - rows++; - // ndbout << row.c_str().c_str() << endl; if (readRowFromTableAndIndex(pNdb, pTrans, pIndex, row) != NDBT_OK) { @@ -1070,10 +1065,7 @@ int UtilTransactions::verifyOrderedIndex( } int eof = 0; - int rows = 0; while (check == 0 && (eof = pOp->nextResult()) == 0) { - rows++; - bool checkDestIndex = (destIndex != NULL); if (checkDestIndex && !findNulls) { /* Check for NULLs */ @@ -1175,7 +1167,6 @@ int UtilTransactions::verifyOrderedIndex( closeTransaction(pNdb); NdbSleep_MilliSleep(50); retryAttempt++; - rows--; continue; } NDB_ERR(err); diff --git a/storage/ndb/tools/restore/consumer_restore.cpp b/storage/ndb/tools/restore/consumer_restore.cpp index 858d868b0366..3698a0f23bc1 100644 --- a/storage/ndb/tools/restore/consumer_restore.cpp +++ b/storage/ndb/tools/restore/consumer_restore.cpp @@ -2577,8 +2577,8 @@ bool BackupRestore::table_compatible_check(TableS &tableS) { stagingTable->setFragmentData(0, 0); } - // if kernel is DD, staging will be too - bool kernel_is_dd = false; + // If table uses disk data, getTablespace() returns true, and staging + // table should use the same tablespace Uint32 ts_id = ~(Uint32)0; if (tab->getTablespace(&ts_id)) { // must be an initialization @@ -2596,7 +2596,6 @@ bool BackupRestore::table_compatible_check(TableS &tableS) { restoreLogger.log_info("Kernel table %s tablespace %s", tablename, ts_name); stagingTable->setTablespaceName(ts_name); - kernel_is_dd = true; } /* diff --git a/unittest/gunit/hash_join-t.cc b/unittest/gunit/hash_join-t.cc index 19de6a94f8d2..d2d35d21d7fe 100644 --- a/unittest/gunit/hash_join-t.cc +++ b/unittest/gunit/hash_join-t.cc @@ -33,7 +33,7 @@ #include // IWYU pragma: keep #include // IWYU pragma: keep -#include "extra/lz4/my_xxhash.h" +#include "extra/xxhash/my_xxhash.h" #include "my_alloc.h" #include "my_bitmap.h" #include "my_config.h" diff --git a/unittest/gunit/innodb/ut0rnd-t.cc b/unittest/gunit/innodb/ut0rnd-t.cc index 49fcd12eff0f..eaa52a5a6105 100644 --- a/unittest/gunit/innodb/ut0rnd-t.cc +++ b/unittest/gunit/innodb/ut0rnd-t.cc @@ -34,7 +34,7 @@ #include "storage/innobase/include/ut0crc32.h" #include "storage/innobase/include/ut0rnd.h" -#include "extra/lz4/my_xxhash.h" +#include "extra/xxhash/my_xxhash.h" namespace innodb_ut0rnd_unittest { @@ -369,7 +369,7 @@ static void test_interval_fast_distribution(uint64_t n) { const uint64_t max_score = 17000; for (uint64_t i = 0; i < max_count; i++) { - const auto value = ut::random_from_interval_fast(0, n - 1); + const auto value = ut::random_from_interval_fast(0, n); for (auto target : target_score) { if (value == target[0]) { target[1]++;