mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
Merge branch '11.4' into 11.8
This commit is contained in:
@@ -10908,7 +10908,7 @@ void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
|
||||
my_bind= (MYSQL_BIND*) my_malloc(PSI_NOT_INSTRUMENTED, num_fields * sizeof(MYSQL_BIND),
|
||||
MYF(MY_WME|MY_FAE|MY_ZEROFILL));
|
||||
length= (ulong*) my_malloc(PSI_NOT_INSTRUMENTED, num_fields * sizeof(ulong),
|
||||
MYF(MY_WME|MY_FAE));
|
||||
MYF(MY_WME|MY_FAE|MY_ZEROFILL));
|
||||
is_null= (my_bool*) my_malloc(PSI_NOT_INSTRUMENTED, num_fields * sizeof(my_bool),
|
||||
MYF(MY_WME|MY_FAE));
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@ MACRO(BUNDLE_PCRE2)
|
||||
ExternalProject_Add(
|
||||
pcre2
|
||||
PREFIX "${dir}"
|
||||
URL "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.47/pcre2-10.47.zip"
|
||||
URL_MD5 7906aec38f872b74f1b925122dde9069
|
||||
URL "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.49/pcre2-10.49.zip"
|
||||
URL_MD5 11e0345ad037d7b3f9342aa3251ac4a7
|
||||
INSTALL_COMMAND ""
|
||||
CMAKE_ARGS
|
||||
"-DCMAKE_WARN_DEPRECATED=FALSE"
|
||||
|
||||
@@ -102,6 +102,7 @@ if(WOLFSSL_INTELASM)
|
||||
if(MSVC_INTEL)
|
||||
target_sources(wolfssl PRIVATE
|
||||
${WOLFCRYPT_SRCDIR}/aes_asm.asm
|
||||
${WOLFCRYPT_SRCDIR}/aes_x86_64_asm.asm
|
||||
${WOLFCRYPT_SRCDIR}/aes_gcm_asm.asm
|
||||
${WOLFCRYPT_SRCDIR}/sp_x86_64_asm.asm
|
||||
)
|
||||
@@ -113,6 +114,7 @@ if(WOLFSSL_INTELASM)
|
||||
set(USE_INTEL_SPEEDUP 1)
|
||||
target_sources(wolfssl PRIVATE
|
||||
${WOLFCRYPT_SRCDIR}/aes_asm.S
|
||||
${WOLFCRYPT_SRCDIR}/aes_x86_64_asm.S
|
||||
${WOLFCRYPT_SRCDIR}/aes_gcm_asm.S
|
||||
${WOLFCRYPT_SRCDIR}/chacha_asm.S
|
||||
${WOLFCRYPT_SRCDIR}/fe_x25519_asm.S
|
||||
@@ -123,7 +125,8 @@ if(WOLFSSL_INTELASM)
|
||||
)
|
||||
target_compile_options(wolfssl PRIVATE -maes -msse4.2 -mpclmul)
|
||||
# Workaround 5.5.4 bug (user_settings.h not included into aes_asm.S)
|
||||
set_property(SOURCE ${WOLFCRYPT_SRCDIR}/aes_asm.S APPEND PROPERTY COMPILE_OPTIONS "-DWOLFSSL_X86_64_BUILD")
|
||||
set_property(SOURCE ${WOLFCRYPT_SRCDIR}/aes_asm.S
|
||||
${WOLFCRYPT_SRCDIR}/aes_x86_64_asm.S APPEND PROPERTY COMPILE_OPTIONS "-DWOLFSSL_X86_64_BUILD")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
Submodule extra/wolfssl/wolfssl updated: 1d363f3adc...3c5eead449
@@ -28,8 +28,6 @@ SET(HEADERS
|
||||
mariadb_capi_rename.h
|
||||
pack.h
|
||||
my_byteorder.h
|
||||
little_endian.h
|
||||
big_endian.h
|
||||
mysql_time.h
|
||||
ma_dyncol.h
|
||||
my_list.h
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
/*
|
||||
Data in big-endian format.
|
||||
*/
|
||||
#define float4store(T,A) do { *((T)+0)=(char) ((uchar *) &A)[3];\
|
||||
*((T)+1)=(char) ((uchar *) &A)[2];\
|
||||
*((T)+2)=(char) ((uchar *) &A)[1];\
|
||||
*((T)+3)=(char) ((uchar *) &A)[0]; } while(0)
|
||||
|
||||
#define float4get(V,M) do { float def_temp;\
|
||||
((uchar*) &def_temp)[0]=(M)[3];\
|
||||
((uchar*) &def_temp)[1]=(M)[2];\
|
||||
((uchar*) &def_temp)[2]=(M)[1];\
|
||||
((uchar*) &def_temp)[3]=(M)[0];\
|
||||
(V)=def_temp; } while(0)
|
||||
|
||||
#define float8store(T,V) do { *((T)+0)=(char) ((uchar *) &V)[7];\
|
||||
*((T)+1)=(char) ((uchar *) &V)[6];\
|
||||
*((T)+2)=(char) ((uchar *) &V)[5];\
|
||||
*((T)+3)=(char) ((uchar *) &V)[4];\
|
||||
*((T)+4)=(char) ((uchar *) &V)[3];\
|
||||
*((T)+5)=(char) ((uchar *) &V)[2];\
|
||||
*((T)+6)=(char) ((uchar *) &V)[1];\
|
||||
*((T)+7)=(char) ((uchar *) &V)[0]; } while(0)
|
||||
|
||||
#define float8get(V,M) do { double def_temp;\
|
||||
((uchar*) &def_temp)[0]=(M)[7];\
|
||||
((uchar*) &def_temp)[1]=(M)[6];\
|
||||
((uchar*) &def_temp)[2]=(M)[5];\
|
||||
((uchar*) &def_temp)[3]=(M)[4];\
|
||||
((uchar*) &def_temp)[4]=(M)[3];\
|
||||
((uchar*) &def_temp)[5]=(M)[2];\
|
||||
((uchar*) &def_temp)[6]=(M)[1];\
|
||||
((uchar*) &def_temp)[7]=(M)[0];\
|
||||
(V) = def_temp; } while(0)
|
||||
|
||||
#define ushortget(V,M) do { V = (uint16) (((uint16) ((uchar) (M)[1]))+\
|
||||
((uint16) ((uint16) (M)[0]) << 8)); } while(0)
|
||||
#define shortget(V,M) do { V = (short) (((short) ((uchar) (M)[1]))+\
|
||||
((short) ((short) (M)[0]) << 8)); } while(0)
|
||||
#define longget(V,M) do { int32 def_temp;\
|
||||
((uchar*) &def_temp)[0]=(M)[0];\
|
||||
((uchar*) &def_temp)[1]=(M)[1];\
|
||||
((uchar*) &def_temp)[2]=(M)[2];\
|
||||
((uchar*) &def_temp)[3]=(M)[3];\
|
||||
(V)=def_temp; } while(0)
|
||||
#define ulongget(V,M) do { uint32 def_temp;\
|
||||
((uchar*) &def_temp)[0]=(M)[0];\
|
||||
((uchar*) &def_temp)[1]=(M)[1];\
|
||||
((uchar*) &def_temp)[2]=(M)[2];\
|
||||
((uchar*) &def_temp)[3]=(M)[3];\
|
||||
(V)=def_temp; } while(0)
|
||||
#define shortstore(T,A) do { uint def_temp=(uint) (A) ;\
|
||||
*(((char*)T)+1)=(char)(def_temp); \
|
||||
*(((char*)T)+0)=(char)(def_temp >> 8); } while(0)
|
||||
#define longstore(T,A) do { *(((char*)T)+3)=((A));\
|
||||
*(((char*)T)+2)=(((A) >> 8));\
|
||||
*(((char*)T)+1)=(((A) >> 16));\
|
||||
*(((char*)T)+0)=(((A) >> 24)); } while(0)
|
||||
|
||||
#define floatget(V,M) memcpy(&V, (M), sizeof(float))
|
||||
/* Cast away type qualifiers (necessary as macro takes argument by value). */
|
||||
#define floatstore(T,V) memcpy((T), (void*) (&V), sizeof(float))
|
||||
#define doubleget(V,M) memcpy(&V, (M), sizeof(double))
|
||||
/* Cast away type qualifiers (necessary as macro takes argument by value). */
|
||||
#define doublestore(T,V) memcpy((T), (void*) &V, sizeof(double))
|
||||
#define longlongget(V,M) memcpy(&V, (M), sizeof(ulonglong))
|
||||
#define longlongstore(T,V) memcpy((T), &V, sizeof(ulonglong))
|
||||
@@ -1,75 +0,0 @@
|
||||
/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
/*
|
||||
Data in little-endian format.
|
||||
*/
|
||||
|
||||
#ifndef MY_BYTE_ORDER_ARCH_OPTIMIZED
|
||||
#define float4get(V,M) memcpy(&V, (M), sizeof(float))
|
||||
#define float4store(V,M) memcpy(V, (&M), sizeof(float))
|
||||
#define float8get(V,M) doubleget((V),(M))
|
||||
#define float8store(V,M) doublestore((V),(M))
|
||||
|
||||
/* Bi-endian hardware.... */
|
||||
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
|
||||
#define doublestore(T,V) do { *(((char*)T)+0)=(char) ((uchar *) &V)[4];\
|
||||
*(((char*)T)+1)=(char) ((uchar *) &V)[5];\
|
||||
*(((char*)T)+2)=(char) ((uchar *) &V)[6];\
|
||||
*(((char*)T)+3)=(char) ((uchar *) &V)[7];\
|
||||
*(((char*)T)+4)=(char) ((uchar *) &V)[0];\
|
||||
*(((char*)T)+5)=(char) ((uchar *) &V)[1];\
|
||||
*(((char*)T)+6)=(char) ((uchar *) &V)[2];\
|
||||
*(((char*)T)+7)=(char) ((uchar *) &V)[3]; }\
|
||||
while(0)
|
||||
#define doubleget(V,M) do { double def_temp;\
|
||||
((uchar*) &def_temp)[0]=(M)[4];\
|
||||
((uchar*) &def_temp)[1]=(M)[5];\
|
||||
((uchar*) &def_temp)[2]=(M)[6];\
|
||||
((uchar*) &def_temp)[3]=(M)[7];\
|
||||
((uchar*) &def_temp)[4]=(M)[0];\
|
||||
((uchar*) &def_temp)[5]=(M)[1];\
|
||||
((uchar*) &def_temp)[6]=(M)[2];\
|
||||
((uchar*) &def_temp)[7]=(M)[3];\
|
||||
(V) = def_temp; } while(0)
|
||||
#else /* Bi-endian hardware.... */
|
||||
|
||||
/* Cast away type qualifiers (necessary as macro takes argument by value). */
|
||||
#define doublestore(T,V) memcpy((T), (void*) &V, sizeof(double))
|
||||
#define doubleget(V,M) memcpy(&V, (M), sizeof(double))
|
||||
|
||||
#endif /* Bi-endian hardware.... */
|
||||
|
||||
#endif /* !MY_BYTE_ORDER_ARCH_OPTIMIZED */
|
||||
|
||||
#define ushortget(V,M) do { uchar *pM= (uchar*)(M);V = uint2korr(pM);} while(0)
|
||||
#define shortget(V,M) do { uchar *pM= (uchar*)(M);V = sint2korr(pM);} while(0)
|
||||
#define longget(V,M) do { uchar *pM= (uchar*)(M);V = sint4korr(pM);} while(0)
|
||||
#define ulongget(V,M) do { uchar *pM= (uchar*)(M);V = uint4korr(pM);} while(0)
|
||||
#define shortstore(T,V) int2store(T,V)
|
||||
#define longstore(T,V) int4store(T,V)
|
||||
|
||||
#ifndef floatstore
|
||||
/* Cast away type qualifiers (necessary as macro takes argument by value). */
|
||||
#define floatstore(T,V) memcpy((T), (void*) (&V), sizeof(float))
|
||||
#define floatget(V,M) memcpy(&V, (M), sizeof(float))
|
||||
#endif
|
||||
#ifndef doubleget
|
||||
#define doubleget(V,M) memcpy(&V, (M), sizeof(double))
|
||||
#define doublestore(T,V) memcpy((T), (void *) &V, sizeof(double))
|
||||
#endif /* doubleget */
|
||||
|
||||
#define longlongget(V,M) memcpy(&V, (M), sizeof(ulonglong))
|
||||
#define longlongstore(T,V) memcpy((T), &V, sizeof(ulonglong))
|
||||
@@ -280,15 +280,100 @@ static inline int32 int4net(const void *p)
|
||||
}
|
||||
|
||||
/*
|
||||
Some macros for reading doubles and floats (clean, do not assume alignment)
|
||||
These are defined in big_endian.h and little_endian.h
|
||||
Macros for reading and storing floating point numbers, and 16-bit and 32-bit
|
||||
integers in the native byte order. They have no alignment requirement.
|
||||
|
||||
The float4*() and float8*() macros use the little-endian byte order on any
|
||||
host. The mi_float*() macros in myisampack.h use the big-endian byte order.
|
||||
*/
|
||||
|
||||
/* Copy 4 or 8 bytes in the reverse order */
|
||||
#define MY_SWAPCPY4(DST,SRC) \
|
||||
do { \
|
||||
uint32 tmp_; \
|
||||
memcpy(&tmp_, (SRC), sizeof(tmp_)); \
|
||||
tmp_= MY_BSWAP32(tmp_); \
|
||||
memcpy((DST), &tmp_, sizeof(tmp_)); \
|
||||
} while(0)
|
||||
|
||||
#define MY_SWAPCPY8(DST,SRC) \
|
||||
do { \
|
||||
uint64 tmp_; \
|
||||
memcpy(&tmp_, (SRC), sizeof(tmp_)); \
|
||||
tmp_= MY_BSWAP64(tmp_); \
|
||||
memcpy((DST), &tmp_, sizeof(tmp_)); \
|
||||
} while(0)
|
||||
|
||||
/* Copy 4 or 8 bytes between the host order and the little/big-endian order */
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#include "big_endian.h"
|
||||
#define MY_COPY_LE4(DST,SRC) MY_SWAPCPY4(DST, SRC)
|
||||
#define MY_COPY_LE8(DST,SRC) MY_SWAPCPY8(DST, SRC)
|
||||
#define MY_COPY_BE4(DST,SRC) memcpy((DST), (SRC), 4)
|
||||
#define MY_COPY_BE8(DST,SRC) memcpy((DST), (SRC), 8)
|
||||
#else
|
||||
#include "little_endian.h"
|
||||
#define MY_COPY_LE4(DST,SRC) memcpy((DST), (SRC), 4)
|
||||
#define MY_COPY_LE8(DST,SRC) memcpy((DST), (SRC), 8)
|
||||
#define MY_COPY_BE4(DST,SRC) MY_SWAPCPY4(DST, SRC)
|
||||
#define MY_COPY_BE8(DST,SRC) MY_SWAPCPY8(DST, SRC)
|
||||
#endif
|
||||
|
||||
/* The "const void*" casts allow storing from volatile objects */
|
||||
#define float4store(T,A) MY_COPY_LE4((T), (const void*) &(A))
|
||||
#define float8store(T,V) MY_COPY_LE8((T), (const void*) &(V))
|
||||
|
||||
#define float4get(V,M) \
|
||||
do { \
|
||||
compile_time_assert(sizeof(V) == sizeof(float)); \
|
||||
MY_COPY_LE4(&(V), (M)); \
|
||||
} while(0)
|
||||
|
||||
#define float8get(V,M) \
|
||||
do { \
|
||||
compile_time_assert(sizeof(V) == sizeof(double)); \
|
||||
MY_COPY_LE8(&(V), (M)); \
|
||||
} while(0)
|
||||
|
||||
/* The following use the native byte order. */
|
||||
#define ushortget(V,M) \
|
||||
do { \
|
||||
uint16 tmp_; \
|
||||
memcpy(&tmp_, (M), sizeof(tmp_)); \
|
||||
(V)= tmp_; \
|
||||
} while(0)
|
||||
|
||||
#define shortget(V,M) \
|
||||
do { \
|
||||
int16 tmp_; \
|
||||
memcpy(&tmp_, (M), sizeof(tmp_)); \
|
||||
(V)= tmp_; \
|
||||
} while(0)
|
||||
|
||||
#define longget(V,M) \
|
||||
do { \
|
||||
int32 tmp_; \
|
||||
memcpy(&tmp_, (M), sizeof(tmp_)); \
|
||||
(V)= tmp_; \
|
||||
} while(0)
|
||||
|
||||
#define shortstore(T,A) \
|
||||
do { \
|
||||
uint16 tmp_= (uint16) (A); \
|
||||
memcpy((T), &tmp_, sizeof(tmp_)); \
|
||||
} while(0)
|
||||
|
||||
#define longstore(T,A) \
|
||||
do { \
|
||||
uint32 tmp_= (uint32) (A); \
|
||||
memcpy((T), &tmp_, sizeof(tmp_)); \
|
||||
} while(0)
|
||||
|
||||
#define floatget(V,M) memcpy(&(V), (M), sizeof(float))
|
||||
#define doubleget(V,M) memcpy(&(V), (M), sizeof(double))
|
||||
#define longlongget(V,M) memcpy(&(V), (M), sizeof(ulonglong))
|
||||
#define longlongstore(T,V) memcpy((T), (const void*) &(V), sizeof(ulonglong))
|
||||
#define floatstore(T,V) memcpy((T), (const void*) &(V), sizeof(float))
|
||||
#define doublestore(T,V) memcpy((T), (const void*) &(V), sizeof(double))
|
||||
|
||||
/* convenienve helpers */
|
||||
static inline float get_float(const void *from)
|
||||
{
|
||||
|
||||
@@ -141,96 +141,22 @@
|
||||
mi_int4store((uchar*) (T) + 0, def_temp4);\
|
||||
mi_int4store((uchar*) (T) + 4, def_temp3); }
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
/* Floating point numbers in MyISAM/Aria keys and in filesort keys are stored
|
||||
in big-endian byte order. */
|
||||
#define mi_float4store(T,A) MY_COPY_BE4((T), (const void*) &(A))
|
||||
#define mi_float8store(T,V) MY_COPY_BE8((T), (const void*) &(V))
|
||||
|
||||
#define mi_float4store(T,A) { ((uchar*) (T))[0]= ((uchar*) &A)[0];\
|
||||
((uchar*) (T))[1]= ((uchar*) &A)[1];\
|
||||
((uchar*) (T))[2]= ((uchar*) &A)[2];\
|
||||
((uchar*) (T))[3]= ((uchar*) &A)[3]; }
|
||||
#define mi_float4get(V,M) \
|
||||
do { \
|
||||
compile_time_assert(sizeof(V) == sizeof(float)); \
|
||||
MY_COPY_BE4(&(V), (M)); \
|
||||
} while(0)
|
||||
|
||||
#define mi_float4get(V,M) { float def_temp;\
|
||||
((uchar*) &def_temp)[0]= ((const uchar*) (M))[0];\
|
||||
((uchar*) &def_temp)[1]= ((const uchar*) (M))[1]; \
|
||||
((uchar*) &def_temp)[2]= ((const uchar*) (M))[2];\
|
||||
((uchar*) &def_temp)[3]= ((const uchar*) (M))[3];\
|
||||
(V)= def_temp; }
|
||||
|
||||
#define mi_float8store(T,V) { ((uchar*) (T))[0]= ((const uchar*) &V)[0];\
|
||||
((uchar*) (T))[1]= ((const uchar*) &V)[1];\
|
||||
((uchar*) (T))[2]= ((const uchar*) &V)[2];\
|
||||
((uchar*) (T))[3]= ((const uchar*) &V)[3];\
|
||||
((uchar*) (T))[4]= ((const uchar*) &V)[4];\
|
||||
((uchar*) (T))[5]= ((const uchar*) &V)[5];\
|
||||
((uchar*) (T))[6]= ((const uchar*) &V)[6];\
|
||||
((uchar*) (T))[7]= ((const uchar*) &V)[7]; }
|
||||
|
||||
#define mi_float8get(V,M) { double def_temp;\
|
||||
((uchar*) &def_temp)[0]= ((const uchar*) (M))[0];\
|
||||
((uchar*) &def_temp)[1]= ((const uchar*) (M))[1];\
|
||||
((uchar*) &def_temp)[2]= ((const uchar*) (M))[2];\
|
||||
((uchar*) &def_temp)[3]= ((const uchar*) (M))[3];\
|
||||
((uchar*) &def_temp)[4]= ((const uchar*) (M))[4];\
|
||||
((uchar*) &def_temp)[5]= ((const uchar*) (M))[5];\
|
||||
((uchar*) &def_temp)[6]= ((const uchar*) (M))[6];\
|
||||
((uchar*) &def_temp)[7]= ((const uchar*) (M))[7]; \
|
||||
(V)= def_temp; }
|
||||
#else
|
||||
|
||||
#define mi_float4store(T,A) { ((uchar*) (T))[0]= ((const uchar*) &A)[3];\
|
||||
((uchar*) (T))[1]= ((const uchar*) &A)[2];\
|
||||
((uchar*) (T))[2]= ((const uchar*) &A)[1];\
|
||||
((uchar*) (T))[3]= ((const uchar*) &A)[0]; }
|
||||
|
||||
#define mi_float4get(V,M) { float def_temp;\
|
||||
((uchar*) &def_temp)[0]= ((const uchar*) (M))[3];\
|
||||
((uchar*) &def_temp)[1]= ((const uchar*) (M))[2];\
|
||||
((uchar*) &def_temp)[2]= ((const uchar*) (M))[1];\
|
||||
((uchar*) &def_temp)[3]= ((const uchar*) (M))[0];\
|
||||
(V)= def_temp; }
|
||||
|
||||
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
|
||||
#define mi_float8store(T,V) { ((uchar*) (T))[0]= ((const uchar*) &V)[3];\
|
||||
((uchar*) (T))[1]= ((const uchar*) &V)[2];\
|
||||
((uchar*) (T))[2]= ((const uchar*) &V)[1];\
|
||||
((uchar*) (T))[3]= ((const uchar*) &V)[0];\
|
||||
((uchar*) (T))[4]= ((const uchar*) &V)[7];\
|
||||
((uchar*) (T))[5]= ((const uchar*) &V)[6];\
|
||||
((uchar*) (T))[6]= ((const uchar*) &V)[5];\
|
||||
((uchar*) (T))[7]= ((const uchar*) &V)[4];}
|
||||
|
||||
#define mi_float8get(V,M) { double def_temp;\
|
||||
((uchar*) &def_temp)[0]= ((const uchar*) (M))[3];\
|
||||
((uchar*) &def_temp)[1]= ((const uchar*) (M))[2];\
|
||||
((uchar*) &def_temp)[2]= ((const uchar*) (M))[1];\
|
||||
((uchar*) &def_temp)[3]= ((const uchar*) (M))[0];\
|
||||
((uchar*) &def_temp)[4]= ((const uchar*) (M))[7];\
|
||||
((uchar*) &def_temp)[5]= ((const uchar*) (M))[6];\
|
||||
((uchar*) &def_temp)[6]= ((const uchar*) (M))[5];\
|
||||
((uchar*) &def_temp)[7]= ((const uchar*) (M))[4];\
|
||||
(V)= def_temp; }
|
||||
|
||||
#else
|
||||
#define mi_float8store(T,V) { ((uchar*) (T))[0]= ((const uchar*) &V)[7];\
|
||||
((uchar*) (T))[1]= ((const uchar*) &V)[6];\
|
||||
((uchar*) (T))[2]= ((const uchar*) &V)[5];\
|
||||
((uchar*) (T))[3]= ((const uchar*) &V)[4];\
|
||||
((uchar*) (T))[4]= ((const uchar*) &V)[3];\
|
||||
((uchar*) (T))[5]= ((const uchar*) &V)[2];\
|
||||
((uchar*) (T))[6]= ((const uchar*) &V)[1];\
|
||||
((uchar*) (T))[7]= ((const uchar*) &V)[0];}
|
||||
|
||||
#define mi_float8get(V,M) { double def_temp;\
|
||||
((uchar*) &def_temp)[0]= ((const uchar*) (M))[7];\
|
||||
((uchar*) &def_temp)[1]= ((const uchar*) (M))[6];\
|
||||
((uchar*) &def_temp)[2]= ((const uchar*) (M))[5];\
|
||||
((uchar*) &def_temp)[3]= ((const uchar*) (M))[4];\
|
||||
((uchar*) &def_temp)[4]= ((const uchar*) (M))[3];\
|
||||
((uchar*) &def_temp)[5]= ((const uchar*) (M))[2];\
|
||||
((uchar*) &def_temp)[6]= ((const uchar*) (M))[1];\
|
||||
((uchar*) &def_temp)[7]= ((const uchar*) (M))[0];\
|
||||
(V)= def_temp; }
|
||||
#endif /* __FLOAT_WORD_ORDER */
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
#define mi_float8get(V,M) \
|
||||
do { \
|
||||
compile_time_assert(sizeof(V) == sizeof(double)); \
|
||||
MY_COPY_BE8(&(V), (M)); \
|
||||
} while(0)
|
||||
|
||||
/* Fix to avoid warnings when sizeof(ha_rows) == sizeof(long) */
|
||||
|
||||
|
||||
Submodule libmariadb updated: 8153da40fe...ae4495ef07
@@ -13,9 +13,18 @@ if(!`select $MTR_PARALLEL = 1`)
|
||||
# This is important for backward compatibility
|
||||
|
||||
# Emulate creating password in an interactive client session, with older clients
|
||||
# which communicates with the server using with something like cp850
|
||||
# which communicates with the server using with something like cp850.
|
||||
# Do not use chcp: the console codepage is shared by all parallel mtr workers.
|
||||
# 0x81 is 'ü' in cp850.
|
||||
|
||||
exec chcp 850 > NUL && echo CREATE USER 'u' IDENTIFIED by 'ü' | $MYSQL --default-character-set=cp850;
|
||||
--perl
|
||||
open(F, '>', "$ENV{MYSQL_TMP_DIR}/create_user_cp850.sql") or die;
|
||||
binmode F;
|
||||
print F "CREATE USER 'u' IDENTIFIED BY '\x81';\n";
|
||||
close F;
|
||||
EOF
|
||||
--exec $MYSQL --default-character-set=cp850 < $MYSQL_TMP_DIR/create_user_cp850.sql
|
||||
--remove_file $MYSQL_TMP_DIR/create_user_cp850.sql
|
||||
|
||||
|
||||
# Can't connect with UTF8
|
||||
|
||||
@@ -6427,6 +6427,12 @@ Warning 1292 Incorrect time value: '9430886' for column `test`.`t1`.`c2` at row
|
||||
Warning 1292 Incorrect time value: '9430816' for column `test`.`t1`.`c1` at row 2
|
||||
Warning 1292 Incorrect time value: '9430816' for column `test`.`t1`.`c2` at row 2
|
||||
drop table t1;
|
||||
#
|
||||
# MDEV-40616: MSAN - use-of-uninitialized-value in extract_date_time()
|
||||
#
|
||||
DO STR_TO_DATE(1, '%#');
|
||||
DO STR_TO_DATE(LOWER('q'), '%@');
|
||||
DO STR_TO_DATE(LOWER('.'), '%.');
|
||||
# End of 10.11 tests
|
||||
#
|
||||
# MDEV-34829 LOCALTIME returns a wrong data type
|
||||
|
||||
@@ -3281,6 +3281,14 @@ insert into t1 values (9430886, 9430886), (9430816, 9430816);
|
||||
select cast(c1 as time), cast(c2 as time) from t1;
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40616: MSAN - use-of-uninitialized-value in extract_date_time()
|
||||
--echo #
|
||||
|
||||
DO STR_TO_DATE(1, '%#');
|
||||
DO STR_TO_DATE(LOWER('q'), '%@');
|
||||
DO STR_TO_DATE(LOWER('.'), '%.');
|
||||
|
||||
--echo # End of 10.11 tests
|
||||
|
||||
--echo #
|
||||
|
||||
@@ -265,3 +265,102 @@ ERROR 70100: Query execution was interrupted
|
||||
DROP TABLE t1;
|
||||
disconnect con1;
|
||||
SET debug_sync='RESET';
|
||||
#
|
||||
# MDEV-31567 SIGSEGV in reinit_stmt_before_use | Prepared_statement::execute
|
||||
#
|
||||
# The first EXECUTE is killed after the one-time semi-join rewrite, but
|
||||
# before the nested selects save their WHERE. The statement must be
|
||||
# re-prepared, not run half-rewritten. The bug was reported with
|
||||
# max_statement_time, KILL QUERY at a sync point makes it deterministic.
|
||||
CREATE TABLE t (a INT);
|
||||
connect con1,localhost,root,,;
|
||||
PREPARE s FROM <62 nested IN subqueries>
|
||||
SET debug_sync='before_join_optimize SIGNAL parked WAIT_FOR go EXECUTE 1';
|
||||
EXECUTE s;
|
||||
connection default;
|
||||
SET debug_sync='now WAIT_FOR parked';
|
||||
KILL QUERY id;
|
||||
SET debug_sync='now SIGNAL go';
|
||||
connection con1;
|
||||
ERROR 70100: Query execution was interrupted
|
||||
SET debug_sync='RESET';
|
||||
EXECUTE s;
|
||||
a
|
||||
EXECUTE s;
|
||||
a
|
||||
DEALLOCATE PREPARE s;
|
||||
# The same with rows, the results must be correct
|
||||
INSERT INTO t VALUES (1),(2),(3);
|
||||
PREPARE s FROM <62 nested IN subqueries>
|
||||
SET debug_sync='before_join_optimize SIGNAL parked WAIT_FOR go EXECUTE 1';
|
||||
EXECUTE s;
|
||||
connection default;
|
||||
SET debug_sync='now WAIT_FOR parked';
|
||||
KILL QUERY id;
|
||||
SET debug_sync='now SIGNAL go';
|
||||
connection con1;
|
||||
ERROR 70100: Query execution was interrupted
|
||||
SET debug_sync='RESET';
|
||||
EXECUTE s;
|
||||
a
|
||||
1
|
||||
EXECUTE s;
|
||||
a
|
||||
1
|
||||
DEALLOCATE PREPARE s;
|
||||
# The same in a stored procedure
|
||||
CREATE PROCEDURE p() <62 nested IN subqueries>
|
||||
SET debug_sync='before_join_optimize SIGNAL parked WAIT_FOR go EXECUTE 1';
|
||||
CALL p();
|
||||
connection default;
|
||||
SET debug_sync='now WAIT_FOR parked';
|
||||
KILL QUERY id;
|
||||
SET debug_sync='now SIGNAL go';
|
||||
connection con1;
|
||||
ERROR 70100: Query execution was interrupted
|
||||
SET debug_sync='RESET';
|
||||
CALL p();
|
||||
a
|
||||
1
|
||||
CALL p();
|
||||
a
|
||||
1
|
||||
DROP PROCEDURE p;
|
||||
connection default;
|
||||
disconnect con1;
|
||||
# If the re-prepare fails, it must be tried again on the next EXECUTE
|
||||
CREATE USER u@localhost;
|
||||
GRANT SUPER ON *.* TO u@localhost;
|
||||
GRANT SELECT ON test.t TO u@localhost;
|
||||
connect con2,localhost,u,,test;
|
||||
PREPARE s FROM <62 nested IN subqueries>
|
||||
SET debug_sync='before_join_optimize SIGNAL parked WAIT_FOR go EXECUTE 1';
|
||||
EXECUTE s;
|
||||
connection default;
|
||||
SET debug_sync='now WAIT_FOR parked';
|
||||
KILL QUERY id;
|
||||
SET debug_sync='now SIGNAL go';
|
||||
REVOKE SELECT ON test.t FROM u@localhost;
|
||||
connection con2;
|
||||
ERROR 70100: Query execution was interrupted
|
||||
SET debug_sync='RESET';
|
||||
EXECUTE s;
|
||||
ERROR 42000: SELECT command denied to user 'u'@'localhost' for table `test`.`t`
|
||||
SHOW STATUS LIKE 'Com_stmt_reprepare';
|
||||
Variable_name Value
|
||||
Com_stmt_reprepare 1
|
||||
connection default;
|
||||
GRANT SELECT ON test.t TO u@localhost;
|
||||
connection con2;
|
||||
EXECUTE s;
|
||||
a
|
||||
1
|
||||
SHOW STATUS LIKE 'Com_stmt_reprepare';
|
||||
Variable_name Value
|
||||
Com_stmt_reprepare 2
|
||||
connection default;
|
||||
disconnect con2;
|
||||
DROP USER u@localhost;
|
||||
DROP TABLE t;
|
||||
SET debug_sync='RESET';
|
||||
# End of 11.4 tests
|
||||
|
||||
@@ -361,3 +361,120 @@ reap;
|
||||
DROP TABLE t1;
|
||||
disconnect con1;
|
||||
SET debug_sync='RESET';
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-31567 SIGSEGV in reinit_stmt_before_use | Prepared_statement::execute
|
||||
--echo #
|
||||
--echo # The first EXECUTE is killed after the one-time semi-join rewrite, but
|
||||
--echo # before the nested selects save their WHERE. The statement must be
|
||||
--echo # re-prepared, not run half-rewritten. The bug was reported with
|
||||
--echo # max_statement_time, KILL QUERY at a sync point makes it deterministic.
|
||||
CREATE TABLE t (a INT);
|
||||
let $q= 1;
|
||||
let $d= 62;
|
||||
while ($d)
|
||||
{
|
||||
let $q= SELECT a FROM t WHERE a IN ($q);
|
||||
dec $d;
|
||||
}
|
||||
connect (con1,localhost,root,,);
|
||||
let $id= `SELECT CONNECTION_ID()`;
|
||||
--echo PREPARE s FROM <62 nested IN subqueries>
|
||||
--disable_query_log
|
||||
eval PREPARE s FROM '$q';
|
||||
--enable_query_log
|
||||
SET debug_sync='before_join_optimize SIGNAL parked WAIT_FOR go EXECUTE 1';
|
||||
send EXECUTE s;
|
||||
connection default;
|
||||
SET debug_sync='now WAIT_FOR parked';
|
||||
replace_result $id id;
|
||||
eval KILL QUERY $id;
|
||||
SET debug_sync='now SIGNAL go';
|
||||
connection con1;
|
||||
--error ER_QUERY_INTERRUPTED
|
||||
reap;
|
||||
SET debug_sync='RESET';
|
||||
EXECUTE s;
|
||||
EXECUTE s;
|
||||
DEALLOCATE PREPARE s;
|
||||
|
||||
--echo # The same with rows, the results must be correct
|
||||
INSERT INTO t VALUES (1),(2),(3);
|
||||
--echo PREPARE s FROM <62 nested IN subqueries>
|
||||
--disable_query_log
|
||||
eval PREPARE s FROM '$q';
|
||||
--enable_query_log
|
||||
SET debug_sync='before_join_optimize SIGNAL parked WAIT_FOR go EXECUTE 1';
|
||||
send EXECUTE s;
|
||||
connection default;
|
||||
SET debug_sync='now WAIT_FOR parked';
|
||||
replace_result $id id;
|
||||
eval KILL QUERY $id;
|
||||
SET debug_sync='now SIGNAL go';
|
||||
connection con1;
|
||||
--error ER_QUERY_INTERRUPTED
|
||||
reap;
|
||||
SET debug_sync='RESET';
|
||||
EXECUTE s;
|
||||
EXECUTE s;
|
||||
DEALLOCATE PREPARE s;
|
||||
|
||||
--echo # The same in a stored procedure
|
||||
--echo CREATE PROCEDURE p() <62 nested IN subqueries>
|
||||
--disable_query_log
|
||||
eval CREATE PROCEDURE p() $q;
|
||||
--enable_query_log
|
||||
SET debug_sync='before_join_optimize SIGNAL parked WAIT_FOR go EXECUTE 1';
|
||||
send CALL p();
|
||||
connection default;
|
||||
SET debug_sync='now WAIT_FOR parked';
|
||||
replace_result $id id;
|
||||
eval KILL QUERY $id;
|
||||
SET debug_sync='now SIGNAL go';
|
||||
connection con1;
|
||||
--error ER_QUERY_INTERRUPTED
|
||||
reap;
|
||||
SET debug_sync='RESET';
|
||||
CALL p();
|
||||
CALL p();
|
||||
DROP PROCEDURE p;
|
||||
connection default;
|
||||
disconnect con1;
|
||||
|
||||
--echo # If the re-prepare fails, it must be tried again on the next EXECUTE
|
||||
CREATE USER u@localhost;
|
||||
GRANT SUPER ON *.* TO u@localhost;
|
||||
GRANT SELECT ON test.t TO u@localhost;
|
||||
connect (con2,localhost,u,,test);
|
||||
let $id= `SELECT CONNECTION_ID()`;
|
||||
--echo PREPARE s FROM <62 nested IN subqueries>
|
||||
--disable_query_log
|
||||
eval PREPARE s FROM '$q';
|
||||
--enable_query_log
|
||||
SET debug_sync='before_join_optimize SIGNAL parked WAIT_FOR go EXECUTE 1';
|
||||
send EXECUTE s;
|
||||
connection default;
|
||||
SET debug_sync='now WAIT_FOR parked';
|
||||
replace_result $id id;
|
||||
eval KILL QUERY $id;
|
||||
SET debug_sync='now SIGNAL go';
|
||||
REVOKE SELECT ON test.t FROM u@localhost;
|
||||
connection con2;
|
||||
--error ER_QUERY_INTERRUPTED
|
||||
reap;
|
||||
SET debug_sync='RESET';
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
EXECUTE s;
|
||||
SHOW STATUS LIKE 'Com_stmt_reprepare';
|
||||
connection default;
|
||||
GRANT SELECT ON test.t TO u@localhost;
|
||||
connection con2;
|
||||
EXECUTE s;
|
||||
SHOW STATUS LIKE 'Com_stmt_reprepare';
|
||||
connection default;
|
||||
disconnect con2;
|
||||
DROP USER u@localhost;
|
||||
DROP TABLE t;
|
||||
SET debug_sync='RESET';
|
||||
|
||||
--echo # End of 11.4 tests
|
||||
|
||||
@@ -236,3 +236,152 @@ DROP PROCEDURE forIterateBug;
|
||||
#
|
||||
# End of 10.4 tests
|
||||
#
|
||||
#
|
||||
# MDEV-37563 Crash on a FOR loop with a row comparison in the upper bound
|
||||
#
|
||||
CREATE OR REPLACE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE i INT;
|
||||
FOR i IN 0..((1,'b1')=(1,'b1')) DO
|
||||
SELECT i;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
CALL p1;
|
||||
i
|
||||
0
|
||||
i
|
||||
1
|
||||
CALL p1;
|
||||
i
|
||||
0
|
||||
i
|
||||
1
|
||||
DROP PROCEDURE p1;
|
||||
# The same for a cursor FOR loop parameter
|
||||
CREATE OR REPLACE PROCEDURE p2()
|
||||
BEGIN
|
||||
DECLARE c CURSOR (p INT) FOR SELECT p;
|
||||
FOR r IN c((1,'b1')=(1,'b1')) DO
|
||||
SELECT r.p;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
CALL p2;
|
||||
r.p
|
||||
1
|
||||
CALL p2;
|
||||
r.p
|
||||
1
|
||||
DROP PROCEDURE p2;
|
||||
# The same for a cursor FOR loop with more than one parameter
|
||||
CREATE OR REPLACE PROCEDURE p3()
|
||||
BEGIN
|
||||
DECLARE c CURSOR (a INT, b INT) FOR SELECT a, b;
|
||||
FOR r IN c(1, (1,'b1')=(1,'b1')) DO
|
||||
SELECT r.a, r.b;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
CALL p3;
|
||||
r.a r.b
|
||||
1 1
|
||||
CALL p3;
|
||||
r.a r.b
|
||||
1 1
|
||||
DROP PROCEDURE p3;
|
||||
# The same with a row comparison in more than one parameter
|
||||
CREATE OR REPLACE PROCEDURE p4()
|
||||
BEGIN
|
||||
DECLARE c CURSOR (p1 INT, p2 INT, p3 INT) FOR SELECT p1, p2, p3;
|
||||
FOR r IN c((1,'a')=(1,'a'), 7, (2,'b')=(2,'c')) DO
|
||||
SELECT r.p1, r.p2, r.p3;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
CALL p4;
|
||||
r.p1 r.p2 r.p3
|
||||
1 7 0
|
||||
CALL p4;
|
||||
r.p1 r.p2 r.p3
|
||||
1 7 0
|
||||
DROP PROCEDURE p4;
|
||||
# The same with a row comparison in a derived table of the lower bound
|
||||
CREATE OR REPLACE PROCEDURE p5()
|
||||
BEGIN
|
||||
FOR i IN 0+(SELECT z FROM (SELECT (1,'b1')=(1,'b1') AS z) dt)..2 DO
|
||||
SELECT i;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
CALL p5;
|
||||
i
|
||||
1
|
||||
i
|
||||
2
|
||||
CALL p5;
|
||||
i
|
||||
1
|
||||
i
|
||||
2
|
||||
DROP PROCEDURE p5;
|
||||
# The same for a REVERSE loop, whose target bound is the left one
|
||||
CREATE OR REPLACE PROCEDURE p6()
|
||||
BEGIN
|
||||
FOR i IN REVERSE 0+((1,'b1')=(1,'b1'))..2 DO
|
||||
SELECT i;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
CALL p6;
|
||||
i
|
||||
2
|
||||
i
|
||||
1
|
||||
CALL p6;
|
||||
i
|
||||
2
|
||||
i
|
||||
1
|
||||
DROP PROCEDURE p6;
|
||||
# A trigger re-parses the upper bound after ALTER TABLE
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE TABLE t2 (b INT);
|
||||
INSERT INTO t2 VALUES (1);
|
||||
CREATE TRIGGER tr BEFORE INSERT ON t1 FOR EACH ROW
|
||||
BEGIN
|
||||
FOR i IN 0..(SELECT NEW.a + COUNT(*) FROM t2) DO
|
||||
SET @x= i;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
INSERT INTO t1 VALUES (1);
|
||||
ALTER TABLE t2 ADD COLUMN c INT;
|
||||
INSERT INTO t1 VALUES (2);
|
||||
INSERT INTO t1 VALUES (3);
|
||||
SELECT @x;
|
||||
@x
|
||||
4
|
||||
DROP TABLE t1, t2;
|
||||
# A trigger with NEW fields in more than one cursor parameter
|
||||
CREATE TABLE t1 (a INT, b INT);
|
||||
CREATE TRIGGER tr BEFORE INSERT ON t1 FOR EACH ROW
|
||||
BEGIN
|
||||
DECLARE c CURSOR (p1 INT, p2 INT) FOR SELECT p1, p2;
|
||||
FOR r IN c(NEW.a, NEW.b + ((NEW.a,'x')=(NEW.a,'x'))) DO
|
||||
SET @x= CONCAT(r.p1, ',', r.p2);
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
INSERT INTO t1 VALUES (1, 10);
|
||||
SELECT @x;
|
||||
@x
|
||||
1,11
|
||||
INSERT INTO t1 VALUES (2, 20);
|
||||
SELECT @x;
|
||||
@x
|
||||
2,21
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 11.4 tests
|
||||
#
|
||||
|
||||
@@ -248,3 +248,145 @@ DROP PROCEDURE forIterateBug;
|
||||
--echo #
|
||||
--echo # End of 10.4 tests
|
||||
--echo #
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-37563 Crash on a FOR loop with a row comparison in the upper bound
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE OR REPLACE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE i INT;
|
||||
FOR i IN 0..((1,'b1')=(1,'b1')) DO
|
||||
SELECT i;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p1;
|
||||
CALL p1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
--echo # The same for a cursor FOR loop parameter
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE OR REPLACE PROCEDURE p2()
|
||||
BEGIN
|
||||
DECLARE c CURSOR (p INT) FOR SELECT p;
|
||||
FOR r IN c((1,'b1')=(1,'b1')) DO
|
||||
SELECT r.p;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p2;
|
||||
CALL p2;
|
||||
DROP PROCEDURE p2;
|
||||
|
||||
--echo # The same for a cursor FOR loop with more than one parameter
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE OR REPLACE PROCEDURE p3()
|
||||
BEGIN
|
||||
DECLARE c CURSOR (a INT, b INT) FOR SELECT a, b;
|
||||
FOR r IN c(1, (1,'b1')=(1,'b1')) DO
|
||||
SELECT r.a, r.b;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p3;
|
||||
CALL p3;
|
||||
DROP PROCEDURE p3;
|
||||
|
||||
--echo # The same with a row comparison in more than one parameter
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE OR REPLACE PROCEDURE p4()
|
||||
BEGIN
|
||||
DECLARE c CURSOR (p1 INT, p2 INT, p3 INT) FOR SELECT p1, p2, p3;
|
||||
FOR r IN c((1,'a')=(1,'a'), 7, (2,'b')=(2,'c')) DO
|
||||
SELECT r.p1, r.p2, r.p3;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p4;
|
||||
CALL p4;
|
||||
DROP PROCEDURE p4;
|
||||
|
||||
--echo # The same with a row comparison in a derived table of the lower bound
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE OR REPLACE PROCEDURE p5()
|
||||
BEGIN
|
||||
FOR i IN 0+(SELECT z FROM (SELECT (1,'b1')=(1,'b1') AS z) dt)..2 DO
|
||||
SELECT i;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p5;
|
||||
CALL p5;
|
||||
DROP PROCEDURE p5;
|
||||
|
||||
--echo # The same for a REVERSE loop, whose target bound is the left one
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE OR REPLACE PROCEDURE p6()
|
||||
BEGIN
|
||||
FOR i IN REVERSE 0+((1,'b1')=(1,'b1'))..2 DO
|
||||
SELECT i;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
CALL p6;
|
||||
CALL p6;
|
||||
DROP PROCEDURE p6;
|
||||
|
||||
--echo # A trigger re-parses the upper bound after ALTER TABLE
|
||||
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE TABLE t2 (b INT);
|
||||
INSERT INTO t2 VALUES (1);
|
||||
DELIMITER $$;
|
||||
CREATE TRIGGER tr BEFORE INSERT ON t1 FOR EACH ROW
|
||||
BEGIN
|
||||
FOR i IN 0..(SELECT NEW.a + COUNT(*) FROM t2) DO
|
||||
SET @x= i;
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
INSERT INTO t1 VALUES (1);
|
||||
ALTER TABLE t2 ADD COLUMN c INT;
|
||||
INSERT INTO t1 VALUES (2);
|
||||
INSERT INTO t1 VALUES (3);
|
||||
SELECT @x;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
--echo # A trigger with NEW fields in more than one cursor parameter
|
||||
|
||||
CREATE TABLE t1 (a INT, b INT);
|
||||
DELIMITER $$;
|
||||
CREATE TRIGGER tr BEFORE INSERT ON t1 FOR EACH ROW
|
||||
BEGIN
|
||||
DECLARE c CURSOR (p1 INT, p2 INT) FOR SELECT p1, p2;
|
||||
FOR r IN c(NEW.a, NEW.b + ((NEW.a,'x')=(NEW.a,'x'))) DO
|
||||
SET @x= CONCAT(r.p1, ',', r.p2);
|
||||
END FOR;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
INSERT INTO t1 VALUES (1, 10);
|
||||
SELECT @x;
|
||||
INSERT INTO t1 VALUES (2, 20);
|
||||
SELECT @x;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # End of 11.4 tests
|
||||
--echo #
|
||||
|
||||
@@ -2093,3 +2093,43 @@ drop user 'root
|
||||
definer_host=localhost
|
||||
suid=1'@localhost;
|
||||
# End of 10.6 tests
|
||||
#
|
||||
# MDEV-22374: VIEW with security definer require FILE privilege from
|
||||
# definer not invoker in case of INTO OUTFILE
|
||||
#
|
||||
create user test@localhost;
|
||||
grant select on test.* to test@localhost;
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2);
|
||||
create definer=test@localhost sql security definer view v1 as select * from t1;
|
||||
# FILE privilege should be checked for the invoker, not the view definer
|
||||
select * into outfile 'MYSQLTEST_VARDIR/tmp/mdev22374.txt' from t1;
|
||||
select * from v1;
|
||||
a
|
||||
1
|
||||
2
|
||||
select * into outfile 'MYSQLTEST_VARDIR/tmp/mdev22374.txt' from (select count(*) from v1) as dv1;
|
||||
select * into outfile 'MYSQLTEST_VARDIR/tmp/mdev22374.txt' from (select * from v1) as dv1;
|
||||
select * into outfile 'MYSQLTEST_VARDIR/tmp/mdev22374.txt' from v1;
|
||||
drop view v1;
|
||||
# Invoker without FILE privilege can not use the definer's one
|
||||
create definer=root@localhost sql security definer view v1 as select * from t1;
|
||||
connect con1, localhost, test;
|
||||
select * into outfile 'MYSQLTEST_VARDIR/tmp/mdev22374.txt' from t1;
|
||||
ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
|
||||
select * from v1;
|
||||
a
|
||||
1
|
||||
2
|
||||
select * into outfile 'MYSQLTEST_VARDIR/tmp/mdev22374.txt' from (select count(*) from v1) as dv1;
|
||||
ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
|
||||
select * into outfile 'MYSQLTEST_VARDIR/tmp/mdev22374.txt' from (select * from v1) as dv1;
|
||||
ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
|
||||
select * into outfile 'MYSQLTEST_VARDIR/tmp/mdev22374.txt' from v1;
|
||||
ERROR 42000: Access denied; you need (at least one of) the FILE privilege(s) for this operation
|
||||
disconnect con1;
|
||||
connection default;
|
||||
drop view v1;
|
||||
drop table t1;
|
||||
drop user test@localhost;
|
||||
# End of 10.11 tests
|
||||
|
||||
@@ -2347,5 +2347,57 @@ suid=1'@localhost;
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-22374: VIEW with security definer require FILE privilege from
|
||||
--echo # definer not invoker in case of INTO OUTFILE
|
||||
--echo #
|
||||
|
||||
create user test@localhost;
|
||||
grant select on test.* to test@localhost;
|
||||
create table t1 (a int);
|
||||
insert into t1 values (1),(2);
|
||||
create definer=test@localhost sql security definer view v1 as select * from t1;
|
||||
|
||||
--echo # FILE privilege should be checked for the invoker, not the view definer
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--eval select * into outfile '$MYSQLTEST_VARDIR/tmp/mdev22374.txt' from t1
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/mdev22374.txt
|
||||
select * from v1;
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--eval select * into outfile '$MYSQLTEST_VARDIR/tmp/mdev22374.txt' from (select count(*) from v1) as dv1
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/mdev22374.txt
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--eval select * into outfile '$MYSQLTEST_VARDIR/tmp/mdev22374.txt' from (select * from v1) as dv1
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/mdev22374.txt
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--eval select * into outfile '$MYSQLTEST_VARDIR/tmp/mdev22374.txt' from v1
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/mdev22374.txt
|
||||
drop view v1;
|
||||
|
||||
--echo # Invoker without FILE privilege can not use the definer's one
|
||||
create definer=root@localhost sql security definer view v1 as select * from t1;
|
||||
connect con1, localhost, test;
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
--eval select * into outfile '$MYSQLTEST_VARDIR/tmp/mdev22374.txt' from t1
|
||||
select * from v1;
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
--eval select * into outfile '$MYSQLTEST_VARDIR/tmp/mdev22374.txt' from (select count(*) from v1) as dv1
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
--eval select * into outfile '$MYSQLTEST_VARDIR/tmp/mdev22374.txt' from (select * from v1) as dv1
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
--eval select * into outfile '$MYSQLTEST_VARDIR/tmp/mdev22374.txt' from v1
|
||||
disconnect con1;
|
||||
connection default;
|
||||
|
||||
drop view v1;
|
||||
drop table t1;
|
||||
drop user test@localhost;
|
||||
|
||||
--echo # End of 10.11 tests
|
||||
|
||||
# Wait till we reached the initial number of concurrent sessions
|
||||
--source include/wait_until_count_sessions.inc
|
||||
|
||||
42
mysql-test/suite/galera/r/MDEV-40727.result
Normal file
42
mysql-test/suite/galera/r/MDEV-40727.result
Normal file
@@ -0,0 +1,42 @@
|
||||
connection node_2;
|
||||
connection node_1;
|
||||
connection node_1;
|
||||
connection node_2;
|
||||
# Take node_2 down first: a per-table DATA/INDEX DIRECTORY names an
|
||||
# absolute host path, and mtr runs both nodes on the same host, so
|
||||
# creating the tables while node_2 is a live cluster member would
|
||||
# replicate the same CREATE TABLE to node_2 and make it race node_1
|
||||
# for the same external path. Node_2 must only ever receive these
|
||||
# tables as SST-transferred files, not as replicated DDL.
|
||||
connection node_2;
|
||||
connection node_1;
|
||||
CALL mtr.add_suppression("InnoDB: File .* was not found");
|
||||
CREATE TABLE t_aria (f1 INT PRIMARY KEY, f2 VARCHAR(100))
|
||||
ENGINE=Aria
|
||||
DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/MDEV-40727_aria_data'
|
||||
INDEX DIRECTORY='MYSQLTEST_VARDIR/tmp/MDEV-40727_aria_index';
|
||||
CREATE TABLE t_innodb (f1 INT PRIMARY KEY, f2 VARCHAR(100))
|
||||
ENGINE=InnoDB
|
||||
DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/MDEV-40727_innodb_data';
|
||||
INSERT INTO t_aria VALUES (1, 'aria_row_1'), (2, 'aria_row_2');
|
||||
INSERT INTO t_innodb VALUES (1, 'innodb_row_1'), (2, 'innodb_row_2');
|
||||
# Clean node_2's data directory so that a restart forces a full SST.
|
||||
connection node_2;
|
||||
SET SESSION wsrep_sync_wait = 15;
|
||||
# Check that every table in database test, not only t_aria and
|
||||
# t_innodb, has identical content on node_2 after the SST.
|
||||
connection node_1;
|
||||
connection node_2;
|
||||
connection node_1;
|
||||
connection node_2;
|
||||
connection node_1;
|
||||
connection node_2;
|
||||
connection node_2;
|
||||
# Confirm the donor's rsync SST script flushed the filesystems
|
||||
# holding the Aria and InnoDB per-table directories, not only the
|
||||
# data directory itself.
|
||||
FOUND 1 /Synced filesystem: MYSQLTEST_VARDIR/tmp/MDEV-40727_aria_data/ in mysqld.1.err
|
||||
FOUND 1 /Synced filesystem: MYSQLTEST_VARDIR/tmp/MDEV-40727_aria_index/ in mysqld.1.err
|
||||
FOUND 1 /Synced filesystem: MYSQLTEST_VARDIR/tmp/MDEV-40727_innodb_data/test/ in mysqld.1.err
|
||||
connection node_1;
|
||||
DROP TABLE t_aria, t_innodb;
|
||||
10
mysql-test/suite/galera/t/MDEV-40727.cnf
Normal file
10
mysql-test/suite/galera/t/MDEV-40727.cnf
Normal file
@@ -0,0 +1,10 @@
|
||||
!include ../galera_2nodes.cnf
|
||||
|
||||
[mysqld]
|
||||
wsrep_sst_method=rsync
|
||||
|
||||
[mysqld.1]
|
||||
wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.wait_prim_timeout=PT60S;gcache.size=10M'
|
||||
|
||||
[mysqld.2]
|
||||
wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.wait_prim_timeout=PT60S;gcache.size=10M'
|
||||
142
mysql-test/suite/galera/t/MDEV-40727.test
Normal file
142
mysql-test/suite/galera/t/MDEV-40727.test
Normal file
@@ -0,0 +1,142 @@
|
||||
--source include/big_test.inc
|
||||
--source include/galera_cluster.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_aria.inc
|
||||
|
||||
#
|
||||
# MDEV-40727 rsync SST donor stalls in a whole-host sync()
|
||||
#
|
||||
# The rsync SST donor flushes, to disk, every filesystem that the
|
||||
# transfer reads from, before the transfer starts. That flush must
|
||||
# also reach a filesystem holding a table placed outside the data
|
||||
# directory by a per-table DATA DIRECTORY or INDEX DIRECTORY option.
|
||||
# MyISAM and Aria place an OS symlink to the table file one level
|
||||
# below the database directory; InnoDB instead leaves a small '.isl'
|
||||
# file next to the tablespace, holding the real path as plain text -
|
||||
# no OS symlink at all. This test forces a full SST and checks the
|
||||
# donor's log for both cases.
|
||||
#
|
||||
# The per-database-directory transfer also needs to dereference these
|
||||
# symlinks (--copy-links, not --links): the rsync daemon on the joiner
|
||||
# cannot recreate an absolute symlink target as-is, so a MyISAM or
|
||||
# Aria table placed by DATA DIRECTORY or INDEX DIRECTORY would
|
||||
# otherwise come out unreadable after every rsync SST. This test
|
||||
# checksums every table in database test on both nodes after the SST
|
||||
# to check that all of them, not only t_aria and t_innodb, transferred
|
||||
# with identical content.
|
||||
#
|
||||
|
||||
--let $aria_data_dir = $MYSQLTEST_VARDIR/tmp/MDEV-40727_aria_data
|
||||
--let $aria_index_dir = $MYSQLTEST_VARDIR/tmp/MDEV-40727_aria_index
|
||||
--let $innodb_data_dir = $MYSQLTEST_VARDIR/tmp/MDEV-40727_innodb_data
|
||||
|
||||
--let $node_1=node_1
|
||||
--let $node_2=node_2
|
||||
--source include/auto_increment_offset_save.inc
|
||||
|
||||
--echo # Take node_2 down first: a per-table DATA/INDEX DIRECTORY names an
|
||||
--echo # absolute host path, and mtr runs both nodes on the same host, so
|
||||
--echo # creating the tables while node_2 is a live cluster member would
|
||||
--echo # replicate the same CREATE TABLE to node_2 and make it race node_1
|
||||
--echo # for the same external path. Node_2 must only ever receive these
|
||||
--echo # tables as SST-transferred files, not as replicated DDL.
|
||||
|
||||
--connection node_2
|
||||
--source include/shutdown_mysqld.inc
|
||||
|
||||
--connection node_1
|
||||
--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
|
||||
--source include/wait_condition.inc
|
||||
|
||||
# Dropping a table whose tablespace lives under a per-table DATA
|
||||
# DIRECTORY logs this message; it is not a query failure.
|
||||
CALL mtr.add_suppression("InnoDB: File .* was not found");
|
||||
|
||||
--exec rm -rf $aria_data_dir $aria_index_dir $innodb_data_dir
|
||||
--exec mkdir -p $aria_data_dir $aria_index_dir $innodb_data_dir
|
||||
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
eval CREATE TABLE t_aria (f1 INT PRIMARY KEY, f2 VARCHAR(100))
|
||||
ENGINE=Aria
|
||||
DATA DIRECTORY='$aria_data_dir'
|
||||
INDEX DIRECTORY='$aria_index_dir';
|
||||
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
eval CREATE TABLE t_innodb (f1 INT PRIMARY KEY, f2 VARCHAR(100))
|
||||
ENGINE=InnoDB
|
||||
DATA DIRECTORY='$innodb_data_dir';
|
||||
|
||||
INSERT INTO t_aria VALUES (1, 'aria_row_1'), (2, 'aria_row_2');
|
||||
INSERT INTO t_innodb VALUES (1, 'innodb_row_1'), (2, 'innodb_row_2');
|
||||
|
||||
--echo # Clean node_2's data directory so that a restart forces a full SST.
|
||||
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/mtr
|
||||
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/performance_schema
|
||||
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/test
|
||||
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data/mysql
|
||||
--remove_files_wildcard $MYSQLTEST_VARDIR/mysqld.2/data
|
||||
|
||||
--connection node_2
|
||||
--source include/start_mysqld.inc
|
||||
|
||||
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
|
||||
--source include/wait_condition.inc
|
||||
|
||||
SET SESSION wsrep_sync_wait = 15;
|
||||
|
||||
--echo # Check that every table in database test, not only t_aria and
|
||||
--echo # t_innodb, has identical content on node_2 after the SST.
|
||||
|
||||
--connection node_1
|
||||
--let $n_tables_node1 = `SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test'`
|
||||
|
||||
--connection node_2
|
||||
--let $n_tables_node2 = `SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'test'`
|
||||
|
||||
if ($n_tables_node1 != $n_tables_node2)
|
||||
{
|
||||
--die Database test has a different number of tables on node_1 and node_2 after SST
|
||||
}
|
||||
|
||||
--let $ctr = 1
|
||||
while ($ctr <= $n_tables_node1)
|
||||
{
|
||||
--connection node_1
|
||||
--let $tbl = query_get_value(SELECT table_name FROM information_schema.tables WHERE table_schema = 'test' ORDER BY table_name, table_name, $ctr)
|
||||
--let $checksum_node1 = query_get_value(CHECKSUM TABLE test.$tbl, Checksum, 1)
|
||||
|
||||
--connection node_2
|
||||
--let $checksum_node2 = query_get_value(CHECKSUM TABLE test.$tbl, Checksum, 1)
|
||||
|
||||
if ($checksum_node1 != $checksum_node2)
|
||||
{
|
||||
--die Table test.$tbl differs between node_1 and node_2 after SST
|
||||
}
|
||||
--inc $ctr
|
||||
}
|
||||
|
||||
--connection node_2
|
||||
|
||||
--echo # Confirm the donor's rsync SST script flushed the filesystems
|
||||
--echo # holding the Aria and InnoDB per-table directories, not only the
|
||||
--echo # data directory itself.
|
||||
|
||||
--let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err
|
||||
--let SEARCH_PATTERN = Synced filesystem: $aria_data_dir
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--let SEARCH_PATTERN = Synced filesystem: $aria_index_dir
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--let SEARCH_PATTERN = Synced filesystem: $innodb_data_dir/test
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
--connection node_1
|
||||
DROP TABLE t_aria, t_innodb;
|
||||
|
||||
--exec rm -rf $aria_data_dir $aria_index_dir $innodb_data_dir
|
||||
|
||||
--source include/auto_increment_offset_restore.inc
|
||||
@@ -171,11 +171,121 @@ check_pid_and_port()
|
||||
check_pid "$pid_file" && [ "$CHECK_PID" -eq "$pid" ]
|
||||
}
|
||||
|
||||
# Resolves a directory to its physical path, with symlinks expanded.
|
||||
# A relative path is interpreted against the data directory, which is
|
||||
# how the server itself resolves these options. Prints nothing when the
|
||||
# directory cannot be reached.
|
||||
resolve_dir()
|
||||
{
|
||||
case "$1" in
|
||||
/*) (cd -P "$1" 2>/dev/null && pwd -P) || : ;;
|
||||
*) (cd -P "$DATA_DIR" 2>/dev/null && \
|
||||
cd -P "$1" 2>/dev/null && pwd -P) || : ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Flushes the filesystems that hold the files to be transferred.
|
||||
# A bare 'sync' flushes every mounted filesystem on the host and can
|
||||
# block for minutes on I/O unrelated to the SST, while the donor holds
|
||||
# the global read lock. 'sync -f' is limited to a single filesystem,
|
||||
# but it is not available on every platform.
|
||||
sync_filesystems()
|
||||
{
|
||||
local NL=$'\n'
|
||||
local data_fs candidates synced dir path target isl
|
||||
|
||||
# 'sync -f' (syncfs) is a GNU coreutils extension. The Darwin and
|
||||
# FreeBSD 'sync' ignores its operands, flushes everything and still
|
||||
# exits with zero status, so a functional probe alone cannot detect
|
||||
# it and every call below would become a whole-host sync - worse
|
||||
# than the single sync being replaced. Gate on the platform first.
|
||||
if [ "$OS" != 'Linux' ]; then
|
||||
sync
|
||||
return
|
||||
fi
|
||||
|
||||
# The data directory itself may be a symlink. Resolve it to the
|
||||
# physical path.
|
||||
data_fs=$(resolve_dir "$DATA_DIR")
|
||||
[ -n "$data_fs" ] || data_fs="$DATA_DIR"
|
||||
|
||||
if ! sync -f "$data_fs" 2>/dev/null; then
|
||||
sync
|
||||
return
|
||||
fi
|
||||
|
||||
# The InnoDB and Aria directories are resolved by create_dirs() and
|
||||
# default to the data directory, but each of them may be placed on
|
||||
# a filesystem of its own, and the transfer reads from all of them.
|
||||
# Binlogs may likewise reside elsewhere: a relative binlog path is
|
||||
# taken relative to the data directory, but it can still escape it
|
||||
# or be a mount point of its own.
|
||||
candidates="$ib_home_dir$NL$ib_log_dir$NL$ib_undo_dir$NL$ar_log_dir"
|
||||
candidates="$candidates$NL$binlog_dir$NL"
|
||||
|
||||
# Database directories may be symlinks to other filesystems, and so
|
||||
# may an individual table file placed one level deeper by a
|
||||
# per-table DATA DIRECTORY or INDEX DIRECTORY (MyISAM, Aria). The
|
||||
# transfer follows both, so flush them as well.
|
||||
candidates="$candidates$(find "$data_fs" -mindepth 1 -maxdepth 2 \
|
||||
-type l 2>/dev/null || :)$NL"
|
||||
|
||||
# InnoDB's per-table DATA DIRECTORY does not create an OS symlink:
|
||||
# it leaves a small '.isl' file next to the tablespace, holding the
|
||||
# real file's path as plain text. Flush the filesystem it names too.
|
||||
while IFS= read -r isl; do
|
||||
[ -n "$isl" ] || continue
|
||||
target=$(sed -e '1q' -e 's/[[:space:]]*$//' "$isl" 2>/dev/null) || continue
|
||||
[ -n "$target" ] || continue
|
||||
candidates="$candidates$(dirname "$target")$NL"
|
||||
done <<< "$(find "$data_fs" -mindepth 2 -maxdepth 2 -type f \
|
||||
-name '*.isl' 2>/dev/null || :)"
|
||||
|
||||
# Paths already flushed, newline delimited on both sides so that a
|
||||
# membership test cannot match a partial path component.
|
||||
synced="$NL$data_fs$NL"
|
||||
|
||||
while IFS= read -r dir; do
|
||||
[ -n "$dir" ] || continue
|
||||
if [ -L "$dir" ]; then
|
||||
# readlink -f gives the physical path whether the link
|
||||
# points to a directory (a symlinked database directory)
|
||||
# or to a file (a symlinked per-table data/index file);
|
||||
# 'cd -P', which resolve_dir() relies on, only works for
|
||||
# the former.
|
||||
target=$(readlink -f "$dir" 2>/dev/null) || continue
|
||||
[ -e "$target" ] || continue
|
||||
if [ -d "$target" ]; then
|
||||
path=$target
|
||||
else
|
||||
path=$(dirname "$target")
|
||||
fi
|
||||
else
|
||||
# resolve_dir() prints nothing unless the path is a
|
||||
# reachable directory, so it doubles as the existence
|
||||
# check. Testing $dir directly would resolve a relative
|
||||
# path against the current directory rather than against
|
||||
# the data directory.
|
||||
path=$(resolve_dir "$dir")
|
||||
fi
|
||||
[ -n "$path" ] || continue
|
||||
case "$synced" in
|
||||
*"$NL$path$NL"*) continue ;;
|
||||
esac
|
||||
sync -f "$path" || :
|
||||
wsrep_log_info "Synced filesystem: $path"
|
||||
synced="$synced$path$NL"
|
||||
done <<< "$candidates"
|
||||
}
|
||||
|
||||
get_binlog
|
||||
|
||||
if [ -n "$WSREP_SST_OPT_BINLOG" ]; then
|
||||
binlog_dir=$(dirname "$WSREP_SST_OPT_BINLOG")
|
||||
binlog_base=$(basename "$WSREP_SST_OPT_BINLOG")
|
||||
else
|
||||
binlog_dir=""
|
||||
binlog_base=""
|
||||
fi
|
||||
|
||||
BINLOG_TAR_FILE="$DATA_DIR/wsrep_sst_binlog.tar"
|
||||
@@ -383,7 +493,7 @@ EOF
|
||||
STATE=$(cat "$FLUSHED")
|
||||
rm "$FLUSHED"
|
||||
|
||||
sync
|
||||
sync_filesystems
|
||||
|
||||
wsrep_log_info "Tables flushed"
|
||||
|
||||
@@ -621,11 +731,19 @@ FILTER="-f '- /lost+found'
|
||||
findopt='-L'
|
||||
[ "$OS" = 'FreeBSD' ] && findopt="$findopt -E"
|
||||
|
||||
# --copy-links, not --links: a per-table DATA DIRECTORY or INDEX
|
||||
# DIRECTORY (MyISAM, Aria) places a real OS symlink here, and
|
||||
# the rsync daemon on the joiner cannot recreate an absolute
|
||||
# symlink target as-is (with 'use chroot = no', it either
|
||||
# rewrites the target into a dangling '/rsyncd-munged/...'
|
||||
# path, or, with symlink munging turned off, still drops the
|
||||
# target's leading '/'). Dereferencing the symlink and copying
|
||||
# the file it points to avoids depending on either behavior.
|
||||
find $findopt . -maxdepth 1 -mindepth 1 -type d -not -name 'lost+found' \
|
||||
-not -name '.zfs' -not -name .snapshot -print0 \
|
||||
| xargs -I{} -0 -P $backup_threads \
|
||||
rsync ${STUNNEL:+--rsh="$STUNNEL"} \
|
||||
--owner --group --perms --links --specials --ignore-times \
|
||||
--owner --group --perms --copy-links --specials --ignore-times \
|
||||
--inplace --recursive --delete --quiet $WHOLE_FILE_OPT \
|
||||
-f '- $ib_home_dir/ib_lru_dump' \
|
||||
-f '- $ib_home_dir/ibdata*' \
|
||||
|
||||
@@ -2454,20 +2454,7 @@ void change_double_for_sort(double nr,uchar *to)
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
memcpy(tmp, &nr, sizeof(nr));
|
||||
#else
|
||||
{
|
||||
uchar *ptr= (uchar*) &nr;
|
||||
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
|
||||
tmp[0]= ptr[3]; tmp[1]=ptr[2]; tmp[2]= ptr[1]; tmp[3]=ptr[0];
|
||||
tmp[4]= ptr[7]; tmp[5]=ptr[6]; tmp[6]= ptr[5]; tmp[7]=ptr[4];
|
||||
#else
|
||||
tmp[0]= ptr[7]; tmp[1]=ptr[6]; tmp[2]= ptr[5]; tmp[3]=ptr[4];
|
||||
tmp[4]= ptr[3]; tmp[5]=ptr[2]; tmp[6]= ptr[1]; tmp[7]=ptr[0];
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
mi_float8store(tmp, nr);
|
||||
if (tmp[0] & 128) /* Negative */
|
||||
{ /* make complement */
|
||||
uint i;
|
||||
|
||||
@@ -333,15 +333,15 @@ static bool extract_date_time(THD *thd, DATE_TIME_FORMAT *format,
|
||||
|
||||
/* Conversion specifiers that match classes of characters */
|
||||
case '.':
|
||||
while (my_ispunct(cs, *val) && val != val_end)
|
||||
while (val < val_end && my_ispunct(cs, *val))
|
||||
val++;
|
||||
break;
|
||||
case '@':
|
||||
while (my_isalpha(cs, *val) && val != val_end)
|
||||
while (val < val_end && my_isalpha(cs, *val))
|
||||
val++;
|
||||
break;
|
||||
case '#':
|
||||
while (my_isdigit(cs, *val) && val != val_end)
|
||||
while (val < val_end && my_isdigit(cs, *val))
|
||||
val++;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -6141,6 +6141,7 @@ int mysqld_main(int argc, char **argv)
|
||||
my_report_svc_status(SERVICE_START_PENDING, NO_ERROR, slow_start_timeout);
|
||||
#endif
|
||||
|
||||
vio_check_ssl_init();
|
||||
if (init_server_components())
|
||||
unireg_abort(1);
|
||||
|
||||
|
||||
@@ -3220,6 +3220,73 @@ int sp_head::add_instr(sp_instr_cursor_copy_struct *instr)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
In a trigger, add_instr() also takes the NEW and OLD fields in
|
||||
m_cur_instr_trig_field_items. Rebuild this list from THD::free_list
|
||||
after a split, so the fields go with their items.
|
||||
*/
|
||||
|
||||
static void set_trig_field_items(THD *thd, sp_head *sp)
|
||||
{
|
||||
if (sp->m_handler->type() != SP_TYPE_TRIGGER)
|
||||
return;
|
||||
sp->m_cur_instr_trig_field_items.empty();
|
||||
for (Item *item= thd->free_list; item; item= item->next)
|
||||
{
|
||||
if (item->type() == Item::TRIGGER_FIELD_ITEM)
|
||||
{
|
||||
Item_trigger_field *field= static_cast<Item_trigger_field*>(item);
|
||||
sp->m_cur_instr_trig_field_items.insert(field, &field->next_trg_field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Move the items of an expression from an item list to THD::free_list.
|
||||
|
||||
The list starts with the newest item, and the parser creates the parts
|
||||
of an item before the item itself. So the first item in the list that
|
||||
walk() finds in expr, and all items after it, belong to expr, even
|
||||
those walk() does not visit, like the LIMIT of a subquery.
|
||||
|
||||
@param thd Thread handle
|
||||
@param list Item list to take the items from
|
||||
@param expr Root of the oldest expression that has items in list
|
||||
*/
|
||||
|
||||
void sp_head::move_expr_items_to_free_list(THD *thd, Item **list, Item *expr)
|
||||
{
|
||||
DBUG_ASSERT(!thd->free_list || thd->free_list == *list);
|
||||
Item **pos= list;
|
||||
while (*pos && !expr->walk(&Item::find_item_processor, true, *pos))
|
||||
pos= &(*pos)->next;
|
||||
DBUG_ASSERT(*pos); // expr itself is always found
|
||||
thd->free_list= *pos;
|
||||
*pos= NULL;
|
||||
set_trig_field_items(thd, this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Put an item list back on THD::free_list, so that the next added
|
||||
instruction owns the items, or on an error the routine frees them.
|
||||
*/
|
||||
|
||||
void sp_head::add_to_free_list(THD *thd, Item *items)
|
||||
{
|
||||
if (items)
|
||||
{
|
||||
Item *last= items;
|
||||
while (last->next)
|
||||
last= last->next;
|
||||
last->next= thd->free_list;
|
||||
thd->free_list= items;
|
||||
}
|
||||
set_trig_field_items(thd, this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Add instruction to SP.
|
||||
|
||||
@@ -3981,6 +4048,15 @@ sp_head::add_set_for_loop_cursor_param_variables(THD *thd,
|
||||
Item_args *parameters)
|
||||
{
|
||||
DBUG_ASSERT(param_spcont->context_var_count() == parameters->argument_count());
|
||||
/*
|
||||
All parameters were parsed as one expression, so THD::free_list holds:
|
||||
|
||||
[items of no parameter] [items of arg N-1] ... [items of arg 0]
|
||||
|
||||
Give each sp_instr_set the items of the argument it evaluates.
|
||||
*/
|
||||
Item *rest= thd->free_list;
|
||||
thd->free_list= NULL;
|
||||
for (uint idx= 0; idx < parameters->argument_count(); idx ++)
|
||||
{
|
||||
/*
|
||||
@@ -3990,13 +4066,29 @@ sp_head::add_set_for_loop_cursor_param_variables(THD *thd,
|
||||
*/
|
||||
bool last= idx + 1 == parameters->argument_count();
|
||||
sp_variable *spvar= param_spcont->get_context_variable(idx);
|
||||
/*
|
||||
The last instruction also takes the Item_func_sp of the cursor call
|
||||
and anything that belongs to no argument.
|
||||
*/
|
||||
if (last)
|
||||
{
|
||||
add_to_free_list(thd, rest);
|
||||
rest= NULL;
|
||||
}
|
||||
else
|
||||
move_expr_items_to_free_list(thd, &rest, parameters->arguments()[idx]);
|
||||
if (set_local_variable(thd, param_spcont,
|
||||
&sp_rcontext_handler_local,
|
||||
spvar, parameters->arguments()[idx],
|
||||
param_lex, last,
|
||||
param_lex->get_expr_str()))
|
||||
{
|
||||
add_to_free_list(thd, rest);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* With no parameters, nothing took the items */
|
||||
add_to_free_list(thd, rest);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -403,6 +403,9 @@ public:
|
||||
int
|
||||
add_instr(sp_instr_cursor_copy_struct *instr);
|
||||
|
||||
void move_expr_items_to_free_list(THD *thd, Item **list, Item *expr);
|
||||
void add_to_free_list(THD *thd, Item *items);
|
||||
|
||||
bool
|
||||
add_instr_jump(THD *thd, sp_pcontext *spcont);
|
||||
|
||||
|
||||
@@ -495,7 +495,10 @@ int sp_lex_keeper::validate_lex_and_exec_core(THD *thd, uint *nextp,
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (instr->is_invalid() || m_lex->needs_reprepare)
|
||||
if (!instr->is_invalid() && m_lex->needs_reprepare)
|
||||
instr->invalidate();
|
||||
|
||||
if (instr->is_invalid())
|
||||
{
|
||||
thd->clear_error();
|
||||
free_lex(thd);
|
||||
|
||||
@@ -7419,12 +7419,34 @@ bool LEX::sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop,
|
||||
my_error(ER_SP_UNDECLARED_VAR, MYF(0), item->full_name());
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
Both bounds were parsed before any instruction was added, so give each
|
||||
bound instruction only the items of its own bound. The left bound was
|
||||
parsed first, so split there; with REVERSE the index is the right bound.
|
||||
Splitting here, not in the grammar, keeps the items on THD::free_list,
|
||||
so a parse error cannot leak them.
|
||||
*/
|
||||
Item *rest= thd->free_list;
|
||||
sphead->move_expr_items_to_free_list(thd, &rest, bounds.m_direction > 0 ?
|
||||
bounds.m_index->get_item() :
|
||||
bounds.m_target_bound->get_item());
|
||||
if (bounds.m_direction < 0)
|
||||
{
|
||||
Item *left= thd->free_list;
|
||||
thd->free_list= NULL;
|
||||
sphead->add_to_free_list(thd, rest);
|
||||
rest= left;
|
||||
}
|
||||
if (!(loop->m_index=
|
||||
bounds.m_index->sp_add_for_loop_variable(thd, index,
|
||||
bounds.m_index->get_item(),
|
||||
bounds.m_index->get_expr_str())
|
||||
))
|
||||
{
|
||||
sphead->add_to_free_list(thd, rest);
|
||||
return true;
|
||||
}
|
||||
sphead->add_to_free_list(thd, rest);
|
||||
if (unlikely(!(loop->m_target_bound=
|
||||
bounds.m_target_bound->
|
||||
sp_add_for_loop_target_bound(thd,
|
||||
|
||||
@@ -3177,9 +3177,9 @@ public:
|
||||
Explain_query *explain;
|
||||
|
||||
/*
|
||||
If true, query optimizer has encountered an unrecoverable error when doing
|
||||
If true, query optimizer has encountered an error when doing
|
||||
once-per-statement optimization and it is not safe to re-execute this
|
||||
statement.
|
||||
statement without re-preparing it.
|
||||
*/
|
||||
bool needs_reprepare{false};
|
||||
|
||||
|
||||
@@ -4434,13 +4434,12 @@ Prepared_statement::execute_loop(String *expanded_query,
|
||||
*/
|
||||
DBUG_ASSERT(thd->free_list == NULL);
|
||||
|
||||
if (lex->needs_reprepare)
|
||||
if (lex->needs_reprepare && state != Query_arena::STMT_ERROR)
|
||||
{
|
||||
/*
|
||||
Something has happened on previous execution that requires us to
|
||||
re-prepare before we try to execute.
|
||||
*/
|
||||
lex->needs_reprepare= false;
|
||||
goto start_with_reprepare;
|
||||
}
|
||||
|
||||
@@ -4615,7 +4614,6 @@ Prepared_statement::execute_bulk_loop(String *expanded_query,
|
||||
Something has happened on previous execution that requires us to
|
||||
re-prepare before we try to execute.
|
||||
*/
|
||||
lex->needs_reprepare= false;
|
||||
error= reprepare();
|
||||
if (error)
|
||||
goto err;
|
||||
|
||||
@@ -2020,7 +2020,13 @@ int JOIN::optimize()
|
||||
if (optimization_state != JOIN::NOT_OPTIMIZED)
|
||||
return FALSE;
|
||||
optimization_state= JOIN::OPTIMIZATION_IN_PROGRESS;
|
||||
bool first_optimization= select_lex->first_cond_optimization;
|
||||
res= optimize_inner();
|
||||
if (unlikely(res) && first_optimization)
|
||||
{
|
||||
/* A failed first optimization may leave the statement half-done */
|
||||
thd->lex->needs_reprepare= true;
|
||||
}
|
||||
}
|
||||
if (!with_two_phase_optimization)
|
||||
{
|
||||
|
||||
@@ -108,6 +108,8 @@ ExternalProject_Add(duckdb_build
|
||||
"-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}"
|
||||
"-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_EXE_LINKER_FLAGS}"
|
||||
"-DCMAKE_MODULE_LINKER_FLAGS=${CMAKE_MODULE_LINKER_FLAGS}"
|
||||
"-DCMAKE_C_LINKER_LAUNCHER=${CMAKE_C_LINKER_LAUNCHER}"
|
||||
"-DCMAKE_CXX_LINKER_LAUNCHER=${CMAKE_CXX_LINKER_LAUNCHER}"
|
||||
-DENABLE_SANITIZER=${ADDRESS_SANITIZER}
|
||||
-DENABLE_UBSAN=${UB_SANITIZER}
|
||||
-DOVERRIDE_GIT_DESCRIBE=${_DUCKDB_GIT_DESCRIBE}
|
||||
|
||||
@@ -554,19 +554,7 @@ mach_double_read(
|
||||
const byte* b) /*!< in: pointer to memory from where to read */
|
||||
{
|
||||
double d;
|
||||
ulint i;
|
||||
byte* ptr;
|
||||
|
||||
ptr = (byte*) &d;
|
||||
|
||||
for (i = 0; i < sizeof(double); i++) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
ptr[sizeof(double) - i - 1] = b[i];
|
||||
#else
|
||||
ptr[i] = b[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
float8get(d, b);
|
||||
return(d);
|
||||
}
|
||||
|
||||
@@ -579,18 +567,7 @@ mach_double_write(
|
||||
byte* b, /*!< in: pointer to memory where to write */
|
||||
double d) /*!< in: double */
|
||||
{
|
||||
ulint i;
|
||||
byte* ptr;
|
||||
|
||||
ptr = (byte*) &d;
|
||||
|
||||
for (i = 0; i < sizeof(double); i++) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
b[i] = ptr[sizeof(double) - i - 1];
|
||||
#else
|
||||
b[i] = ptr[i];
|
||||
#endif
|
||||
}
|
||||
float8store(b, d);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
@@ -603,19 +580,7 @@ mach_float_read(
|
||||
const byte* b) /*!< in: pointer to memory from where to read */
|
||||
{
|
||||
float d;
|
||||
ulint i;
|
||||
byte* ptr;
|
||||
|
||||
ptr = (byte*) &d;
|
||||
|
||||
for (i = 0; i < sizeof(float); i++) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
ptr[sizeof(float) - i - 1] = b[i];
|
||||
#else
|
||||
ptr[i] = b[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
float4get(d, b);
|
||||
return(d);
|
||||
}
|
||||
|
||||
@@ -628,18 +593,7 @@ mach_float_write(
|
||||
byte* b, /*!< in: pointer to memory where to write */
|
||||
float d) /*!< in: float */
|
||||
{
|
||||
ulint i;
|
||||
byte* ptr;
|
||||
|
||||
ptr = (byte*) &d;
|
||||
|
||||
for (i = 0; i < sizeof(float); i++) {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
b[i] = ptr[sizeof(float) - i - 1];
|
||||
#else
|
||||
b[i] = ptr[i];
|
||||
#endif
|
||||
}
|
||||
float4store(b, d);
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
|
||||
@@ -549,8 +549,7 @@ typedef uint64 ULLong;
|
||||
|
||||
typedef union { double d; ULong L[2]; } U;
|
||||
|
||||
#if defined(WORDS_BIGENDIAN) || (defined(__FLOAT_WORD_ORDER) && \
|
||||
(__FLOAT_WORD_ORDER == __BIG_ENDIAN))
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define word0(x) (x)->L[0]
|
||||
#define word1(x) (x)->L[1]
|
||||
#else
|
||||
|
||||
@@ -83,6 +83,81 @@ void test_byte_order()
|
||||
TEST(mi_int8store, mi_uint8korr, ulonglong, 0x0807060504030201,
|
||||
ARRAY_8(8, 7, 6, 5, 4, 3, 2, 1));
|
||||
|
||||
/*
|
||||
Floating point macros. The stored bytes are IEEE 754, little-endian
|
||||
(float4store etc.) or big-endian (the mi_ variants), on any host.
|
||||
*/
|
||||
#define TEST_FLOAT(STORE_NAME, LOAD_NAME, TYPE, VALUE, BYTES) \
|
||||
{ \
|
||||
TYPE value= VALUE, loaded; \
|
||||
uchar bytes[]= BYTES; \
|
||||
STORE_NAME(aligned, value); \
|
||||
ok(!memcmp(aligned, bytes, sizeof(bytes)), "aligned\t\t" #STORE_NAME); \
|
||||
LOAD_NAME(loaded, aligned); \
|
||||
ok(!memcmp(&loaded, &value, sizeof(value)), "aligned\t\t" #LOAD_NAME); \
|
||||
STORE_NAME(not_aligned, value); \
|
||||
ok(!memcmp(not_aligned, bytes, sizeof(bytes)), \
|
||||
"not aligned\t" #STORE_NAME); \
|
||||
LOAD_NAME(loaded, not_aligned); \
|
||||
ok(!memcmp(&loaded, &value, sizeof(value)), "not aligned\t" #LOAD_NAME); \
|
||||
}
|
||||
|
||||
TEST_FLOAT(float4store, float4get, float, 1.0f, ARRAY_4(0, 0, 0x80, 0x3f));
|
||||
TEST_FLOAT(float8store, float8get, double, 1.0,
|
||||
ARRAY_8(0, 0, 0, 0, 0, 0, 0xf0, 0x3f));
|
||||
TEST_FLOAT(float8store, float8get, double, -0.0,
|
||||
ARRAY_8(0, 0, 0, 0, 0, 0, 0, 0x80));
|
||||
TEST_FLOAT(mi_float4store, mi_float4get, float, 1.0f,
|
||||
ARRAY_4(0x3f, 0x80, 0, 0));
|
||||
TEST_FLOAT(mi_float4store, mi_float4get, float, -2.0f,
|
||||
ARRAY_4(0xc0, 0, 0, 0));
|
||||
TEST_FLOAT(mi_float8store, mi_float8get, double, 1.0,
|
||||
ARRAY_8(0x3f, 0xf0, 0, 0, 0, 0, 0, 0));
|
||||
TEST_FLOAT(mi_float8store, mi_float8get, double, -2.0,
|
||||
ARRAY_8(0xc0, 0, 0, 0, 0, 0, 0, 0));
|
||||
|
||||
{
|
||||
/* The bits of a NaN must be preserved, too */
|
||||
ulonglong bits= 0x7ff8000000000001ULL;
|
||||
uchar bytes[]= ARRAY_8(1, 0, 0, 0, 0, 0, 0xf8, 0x7f);
|
||||
double nan, loaded;
|
||||
memcpy(&nan, &bits, sizeof(nan));
|
||||
float8store(aligned, nan);
|
||||
ok(!memcmp(aligned, bytes, sizeof(bytes)), "NaN\t\tfloat8store");
|
||||
float8get(loaded, aligned);
|
||||
ok(!memcmp(&loaded, &nan, sizeof(nan)), "NaN\t\tfloat8get");
|
||||
}
|
||||
|
||||
/* Native byte order integers, including sign and zero extension on read */
|
||||
#define TEST_NATIVE(P, NAME) \
|
||||
{ \
|
||||
int16 s= -2; \
|
||||
uint16 us= 0xfffe; \
|
||||
int32 l= -70000; \
|
||||
int16 s_loaded; \
|
||||
int i_loaded; \
|
||||
int32 l_loaded; \
|
||||
longlong ll_loaded; \
|
||||
shortstore(P, s); \
|
||||
shortget(s_loaded, P); \
|
||||
ok(s_loaded == s, NAME "\tshortstore/shortget"); \
|
||||
shortget(i_loaded, P); \
|
||||
ok(i_loaded == -2, NAME "\tshortget sign extension"); \
|
||||
shortstore(P, us); \
|
||||
ushortget(i_loaded, P); \
|
||||
ok(i_loaded == 0xfffe, NAME "\tushortget zero extension"); \
|
||||
longstore(P, l); \
|
||||
longget(l_loaded, P); \
|
||||
ok(l_loaded == l, NAME "\tlongstore/longget"); \
|
||||
longget(ll_loaded, P); \
|
||||
ok(ll_loaded == -70000, NAME "\tlongget sign extension"); \
|
||||
}
|
||||
|
||||
TEST_NATIVE(aligned, "aligned");
|
||||
TEST_NATIVE(not_aligned, "not aligned");
|
||||
|
||||
#undef TEST_NATIVE
|
||||
#undef TEST_FLOAT
|
||||
#undef ARRAY_8
|
||||
#undef ARRAY_7
|
||||
#undef ARRAY_6
|
||||
@@ -96,7 +171,7 @@ void test_byte_order()
|
||||
|
||||
int main(int argc __attribute__((unused)), char **argv __attribute__((unused)))
|
||||
{
|
||||
plan(68);
|
||||
plan(108);
|
||||
test_byte_order();
|
||||
return exit_status();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SET(HEIDISQL_VERSION "12.20")
|
||||
SET(HEIDISQL_VERSION "12.21")
|
||||
SET(HEIDISQL_BASE_NAME "HeidiSQL_${HEIDISQL_VERSION}_64_Portable")
|
||||
SET(HEIDISQL_ZIP "${HEIDISQL_BASE_NAME}.zip")
|
||||
SET(HEIDISQL_URL "https://github.com/HeidiSQL/HeidiSQL/releases/download/v${HEIDISQL_VERSION}/${HEIDISQL_ZIP}")
|
||||
@@ -7,7 +7,7 @@ SET(HEIDISQL_DOWNLOAD_DIR ${THIRD_PARTY_DOWNLOAD_LOCATION}/${HEIDISQL_BASE_NAME}
|
||||
MAKE_DIRECTORY(${HEIDISQL_DOWNLOAD_DIR})
|
||||
MESSAGE(STATUS "Downloading ${HEIDISQL_URL} to ${HEIDISQL_DOWNLOAD_DIR}/${HEIDISQL_ZIP}")
|
||||
FILE(DOWNLOAD ${HEIDISQL_URL} ${HEIDISQL_DOWNLOAD_DIR}/${HEIDISQL_ZIP} TIMEOUT 300
|
||||
SHOW_PROGRESS EXPECTED_HASH SHA256=d84742736e4508c206c28c58018bbd934319c941dc9d68ff4673737a3f4df731)
|
||||
SHOW_PROGRESS EXPECTED_HASH SHA256=fecb76a69e29a53ea05b1d57fc2f7b7aaed5b8f889556c6eca545e2a800df1ab)
|
||||
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E chdir ${HEIDISQL_DOWNLOAD_DIR}
|
||||
${CMAKE_COMMAND} -E tar xfz ${HEIDISQL_DOWNLOAD_DIR}/${HEIDISQL_ZIP})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user